--- /dev/null
+++ b/ext/apc/apc_bin.c
@@ -0,0 +1,987 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_bin.c 303383 2010-09-15 08:15:58Z dmitry $ */
+
+/* Creates a binary architecture specific output to a string or file containing
+ * the current cache contents for both fies and user variables.  This is accomplished
+ * via the apc_copy_* functions and "swizzling" pointer values to a position
+ * independent value, and unswizzling them on restoration.
+ */
+
+#include "apc_globals.h"
+#include "apc_bin.h"
+#include "apc_zend.h"
+#include "apc_sma.h"
+#include "apc_pool.h"
+#include "ext/standard/md5.h"
+#include "ext/standard/crc32.h"
+
+extern apc_cache_t* apc_cache;
+extern apc_cache_t* apc_user_cache;
+
+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); /* this is hacky */
+
+#define APC_BINDUMP_DEBUG 0
+
+
+#if APC_BINDUMP_DEBUG
+
+#define SWIZZLE(bd, ptr)  \
+    do { \
+        if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
+            printf("SWIZZLE: %x ~> ", ptr); \
+            ptr = (void*)((long)(ptr) - (long)(bd)); \
+            printf("%x in %s on line %d", ptr, __FILE__, __LINE__); \
+        } else if((long)ptr > bd->size) { /* not swizzled */ \
+            apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \
+        } \
+        printf("\n"); \
+    } while(0);
+
+#define UNSWIZZLE(bd, ptr)  \
+    do { \
+      printf("UNSWIZZLE: %x -> ", ptr); \
+      ptr = (void*)((long)(ptr) + (long)(bd)); \
+      printf("%x in %s on line %d \n", ptr, __FILE__, __LINE__); \
+    } while(0);
+
+#else    /* !APC_BINDUMP_DEBUG */
+
+#define SWIZZLE(bd, ptr) \
+    do { \
+        if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
+            ptr = (void*)((long)(ptr) - (long)(bd)); \
+        } else if((ulong)ptr > bd->size) { /* not swizzled */ \
+            apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \
+        } \
+    } while(0);
+
+#define UNSWIZZLE(bd, ptr) \
+    do { \
+      ptr = (void*)((long)(ptr) + (long)(bd)); \
+    } while(0);
+
+#endif
+
+
+static void *apc_bd_alloc(size_t size TSRMLS_DC);
+static void apc_bd_free(void *ptr TSRMLS_DC);
+static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC);
+
+typedef void (*apc_swizzle_cb_t)(apc_bd_t *bd, zend_llist *ll, void *ptr TSRMLS_DC);
+
+#if APC_BINDUMP_DEBUG
+#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, __FILE__, __LINE__ TSRMLS_CC)
+#else
+#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, NULL, 0 TSRMLS_CC)
+#endif
+
+static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC);
+static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC);
+static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC);
+static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC);
+static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC);
+static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC);
+static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC);
+static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC);
+static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC);
+
+static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC);
+static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC);
+
+
+/* {{{ apc_bd_alloc
+ *  callback for copy_* functions */
+static void *apc_bd_alloc(size_t size TSRMLS_DC) {
+    return apc_bd_alloc_ex(NULL, size TSRMLS_CC);
+} /* }}} */
+
+
+/* {{{ apc_bd_free
+ *  callback for copy_* functions */
+static void apc_bd_free(void *ptr TSRMLS_DC) {
+    size_t *size;
+    if(zend_hash_index_find(&APCG(apc_bd_alloc_list), (ulong)ptr, (void**)&size) == FAILURE) {
+        apc_error("apc_bd_free could not free pointer (not found in list: %x)" TSRMLS_CC, ptr);
+    }
+    APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) - *size);
+    zend_hash_index_del(&APCG(apc_bd_alloc_list), (ulong)ptr);
+} /* }}} */
+
+
+/* {{{ apc_bd_alloc_ex
+ *  set ranges or allocate a block of data from an already (e)malloc'd range.
+ *  if ptr_new is not NULL, it will reset the pointer to start at ptr_new,
+ *  with a range of size.  If ptr_new is NULL, returns the next available
+ *  block of given size.
+ */
+static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC) {
+    void *rval;
+
+    rval = APCG(apc_bd_alloc_ptr);
+    if(ptr_new != NULL) {  /* reset ptrs */
+      APCG(apc_bd_alloc_ptr) = ptr_new;
+      APCG(apc_bd_alloc_ubptr) = (void*)((unsigned char *) ptr_new + size);
+    } else {  /* alloc block */
+      APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) + size);
+#if APC_BINDUMP_DEBUG
+      apc_notice("apc_bd_alloc: rval: 0x%x  ptr: 0x%x  ubptr: 0x%x  size: %d" TSRMLS_CC, rval, APCG(apc_bd_alloc_ptr), APCG(apc_bd_alloc_ubptr), size);
+#endif
+      if(APCG(apc_bd_alloc_ptr) > APCG(apc_bd_alloc_ubptr)) {
+          apc_error("Exceeded bounds check in apc_bd_alloc_ex by %d bytes." TSRMLS_CC, (unsigned char *) APCG(apc_bd_alloc_ptr) - (unsigned char *) APCG(apc_bd_alloc_ubptr));
+      }
+      zend_hash_index_update(&APCG(apc_bd_alloc_list), (ulong)rval, &size, sizeof(size_t), NULL);
+    }
+
+    return rval;
+} /* }}} */
+
+
+/* {{{ _apc_swizzle_ptr */
+static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC) {
+    if(*ptr) {
+        if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) {
+            zend_llist_add_element(ll, &ptr);
+#if APC_BINDUMP_DEBUG
+            printf("[%06d] apc_swizzle_ptr: %x -> %x ", zend_llist_count(ll), ptr, *ptr);
+            printf(" in %s on line %d \n", file, line);
+#endif
+        } else if((ulong)ptr > bd->size) {
+            apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, *ptr, ((long)bd + bd->size), file, line); \
+        }
+    }
+} /* }}} */
+
+
+/* {{{ apc_swizzle_op_array */
+static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC) {
+    uint i;
+
+#ifdef ZEND_ENGINE_2
+    apc_swizzle_arg_info_array(bd, ll, op_array->arg_info, op_array->num_args TSRMLS_CC);
+    apc_swizzle_ptr(bd, ll, &op_array->arg_info);
+#else
+    if (op_array->arg_types) {
+        apc_swizzle_ptr(bd, ll, &op_array->arg_types);
+    }
+#endif
+
+    apc_swizzle_ptr(bd, ll, &op_array->function_name);
+    apc_swizzle_ptr(bd, ll, &op_array->filename);
+    apc_swizzle_ptr(bd, ll, &op_array->refcount);
+
+    /* swizzle op_array */
+    for(i=0; i < op_array->last; i++) {
+#ifndef ZEND_ENGINE_2_4
+        if(op_array->opcodes[i].result.op_type == IS_CONST) {
+            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].result.u.constant TSRMLS_CC);
+        }
+        if(op_array->opcodes[i].op1.op_type == IS_CONST) {
+            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op1.u.constant TSRMLS_CC);
+        }
+        if(op_array->opcodes[i].op2.op_type == IS_CONST) {
+            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op2.u.constant TSRMLS_CC);
+        }
+#endif
+        switch (op_array->opcodes[i].opcode) {
+            case ZEND_JMP:
+#ifdef ZEND_ENGINE_2_4
+                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.jmp_addr);
+#else
+                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.u.jmp_addr);
+#endif
+            case ZEND_JMPZ:
+            case ZEND_JMPNZ:
+            case ZEND_JMPZ_EX:
+            case ZEND_JMPNZ_EX:
+#ifdef ZEND_ENGINE_2_4
+                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.jmp_addr);
+#else
+                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.u.jmp_addr);
+#endif
+        }
+    }
+    apc_swizzle_ptr(bd, ll, &op_array->opcodes);
+
+    /* break-continue array ptr */
+    if(op_array->brk_cont_array) {
+        apc_swizzle_ptr(bd, ll, &op_array->brk_cont_array);
+    }
+
+    /* static voriables */
+    if(op_array->static_variables) {
+        apc_swizzle_hashtable(bd, ll, op_array->static_variables, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+        apc_swizzle_ptr(bd, ll, &op_array->static_variables);
+    }
+
+#ifdef ZEND_ENGINE_2
+    /* try-catch */
+    if(op_array->try_catch_array) {
+        apc_swizzle_ptr(bd, ll, &op_array->try_catch_array);
+    }
+#endif
+
+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
+    /* vars */
+    if(op_array->vars) {
+        for(i=0; (signed int) i < op_array->last_var; i++) {
+            apc_swizzle_ptr(bd, ll, &op_array->vars[i].name);
+        }
+        apc_swizzle_ptr(bd, ll, &op_array->vars);
+    }
+#endif
+
+#ifdef ZEND_ENGINE_2
+    /* doc comment */
+    if(op_array->doc_comment) {
+        apc_swizzle_ptr(bd, ll, &op_array->doc_comment);
+    }
+#endif
+
+} /* }}} */
+
+
+/* {{{ apc_swizzle_function */
+static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC) {
+    apc_swizzle_op_array(bd, ll, &func->op_array TSRMLS_CC);
+#ifdef ZEND_ENGINE_2
+    if(func->common.scope) {
+        apc_swizzle_ptr(bd, ll, &func->common.scope);
+    }
+#endif
+} /* }}} */
+
+
+/* {{{ apc_swizzle_class_entry */
+static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC) {
+
+    uint i;
+
+    if(ce->name) {
+        apc_swizzle_ptr(bd, ll, &ce->name);
+    }
+
+    if (ce->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(ce)) {
+        apc_swizzle_ptr(bd, ll, &ZEND_CE_DOC_COMMENT(ce));
+    }
+
+#ifndef ZEND_ENGINE_2
+    apc_swizzle_ptr(bd, ll, &ce->refcount);
+#endif
+
+    apc_swizzle_hashtable(bd, ll, &ce->function_table, (apc_swizzle_cb_t)apc_swizzle_function, 0 TSRMLS_CC);
+#ifdef ZEND_ENGINE_2_4
+    if (ce->default_properties_table) {
+        int i;
+
+        for (i = 0; i < ce->default_properties_count; i++) {
+            if (ce->default_properties_table[i]) {
+                apc_swizzle_ptr(bd, ll, &ce->default_properties_table[i]);
+                apc_swizzle_zval(bd, ll, ce->default_properties_table[i] TSRMLS_CC);
+            }
+        }
+    }
+#else
+    apc_swizzle_hashtable(bd, ll, &ce->default_properties, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+#endif
+
+#ifdef ZEND_ENGINE_2
+    apc_swizzle_hashtable(bd, ll, &ce->properties_info, (apc_swizzle_cb_t)apc_swizzle_property_info, 0 TSRMLS_CC);
+#endif
+
+#ifdef ZEND_ENGINE_2_4
+    if (ce->default_static_members_table) {
+        int i;
+
+        for (i = 0; i < ce->default_static_members_count; i++) {
+            if (ce->default_static_members_table[i]) {
+                apc_swizzle_ptr(bd, ll, &ce->default_static_members_table[i]);
+                apc_swizzle_zval(bd, ll, ce->default_static_members_table[i] TSRMLS_CC);
+            }
+        }
+    }
+    ce->static_members_table = ce->default_static_members_table;
+#else
+    apc_swizzle_hashtable(bd, ll, &ce->default_static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+
+    if(ce->static_members != &ce->default_static_members) {
+        apc_swizzle_hashtable(bd, ll, ce->static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+    } else {
+        apc_swizzle_ptr(bd, ll, &ce->static_members);
+    }
+#endif
+
+    apc_swizzle_hashtable(bd, ll, &ce->constants_table, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+
+    if(ce->type == ZEND_INTERNAL_CLASS &&  ZEND_CE_BUILTIN_FUNCTIONS(ce)) {
+        for(i=0; ZEND_CE_BUILTIN_FUNCTIONS(ce)[i].fname; i++) {
+            apc_swizzle_function_entry(bd, ll, &ZEND_CE_BUILTIN_FUNCTIONS(ce)[i] TSRMLS_CC);
+        }
+    }
+
+    apc_swizzle_ptr(bd, ll, &ce->constructor);
+    apc_swizzle_ptr(bd, ll, &ce->destructor);
+    apc_swizzle_ptr(bd, ll, &ce->clone);
+    apc_swizzle_ptr(bd, ll, &ce->__get);
+    apc_swizzle_ptr(bd, ll, &ce->__set);
+    apc_swizzle_ptr(bd, ll, &ce->__unset);
+    apc_swizzle_ptr(bd, ll, &ce->__isset);
+    apc_swizzle_ptr(bd, ll, &ce->__call);
+    apc_swizzle_ptr(bd, ll, &ce->serialize_func);
+    apc_swizzle_ptr(bd, ll, &ce->unserialize_func);
+
+#ifdef ZEND_ENGINE_2_2
+    apc_swizzle_ptr(bd, ll, &ce->__tostring);
+#endif
+
+    if (ce->type == ZEND_USER_CLASS) {
+        apc_swizzle_ptr(bd, ll, &ZEND_CE_FILENAME(ce));
+    }
+} /* }}} */
+
+
+/* {{{ apc_swizzle_property_info */
+static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC) {
+    apc_swizzle_ptr(bd, ll, &pi->name);
+    apc_swizzle_ptr(bd, ll, &pi->doc_comment);
+
+#ifdef ZEND_ENGINE_2_2
+    apc_swizzle_ptr(bd, ll, &pi->ce);
+#endif
+} /* }}} */
+
+
+/* {{{ apc_swizzle_function_entry */
+static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC) {
+    apc_swizzle_ptr(bd, ll, &fe->fname);
+    apc_swizzle_arg_info_array(bd, ll, fe->arg_info, fe->num_args TSRMLS_CC);
+    apc_swizzle_ptr(bd, ll, &fe->arg_info);
+} /* }}} */
+
+
+/* {{{ apc_swizzle_arg_info_array */
+static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC) {
+    if(arg_info_array) {
+        uint i;
+
+        for(i=0; i < num_args; i++) {
+            apc_swizzle_ptr(bd, ll, &arg_info_array[i].name);
+            apc_swizzle_ptr(bd, ll, &arg_info_array[i].class_name);
+        }
+    }
+
+} /* }}} */
+
+
+/* {{{ apc_swizzle_hashtable */
+static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC) {
+    uint i;
+    Bucket **bp, **bp_prev;
+
+    bp = &ht->pListHead;
+    while(*bp) {
+        bp_prev = bp;
+        bp = &(*bp)->pListNext;
+        if(is_ptr) {
+            swizzle_cb(bd, ll, *(void**)(*bp_prev)->pData TSRMLS_CC);
+            apc_swizzle_ptr(bd, ll, (*bp_prev)->pData);
+        } else {
+            swizzle_cb(bd, ll, (void**)(*bp_prev)->pData TSRMLS_CC);
+        }
+        apc_swizzle_ptr(bd, ll, &(*bp_prev)->pData);
+        if((*bp_prev)->pDataPtr) {
+            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pDataPtr);
+        }
+        if((*bp_prev)->pListLast) {
+            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pListLast);
+        }
+        if((*bp_prev)->pNext) {
+            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pNext);
+        }
+        if((*bp_prev)->pLast) {
+            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pLast);
+        }
+        apc_swizzle_ptr(bd, ll, bp_prev);
+    }
+    for(i=0; i < ht->nTableSize; i++) {
+        if(ht->arBuckets[i]) {
+            apc_swizzle_ptr(bd, ll, &ht->arBuckets[i]);
+        }
+    }
+    apc_swizzle_ptr(bd, ll, &ht->pListTail);
+
+    apc_swizzle_ptr(bd, ll, &ht->arBuckets);
+} /* }}} */
+
+
+/* {{{ apc_swizzle_zval */
+static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC) {
+
+    if(APCG(copied_zvals).nTableSize) {
+        if(zend_hash_index_exists(&APCG(copied_zvals), (ulong)zv)) {
+          return;
+        }
+        zend_hash_index_update(&APCG(copied_zvals), (ulong)zv, (void**)&zv, sizeof(zval*), NULL);
+    }
+
+    switch(zv->type & ~IS_CONSTANT_INDEX) {
+        case IS_NULL:
+        case IS_LONG:
+        case IS_DOUBLE:
+        case IS_BOOL:
+        case IS_RESOURCE:
+            /* nothing to do */
+            break;
+        case IS_CONSTANT:
+        case IS_STRING:
+            apc_swizzle_ptr(bd, ll, &zv->value.str.val);
+            break;
+        case IS_ARRAY:
+        case IS_CONSTANT_ARRAY:
+            apc_swizzle_hashtable(bd, ll, zv->value.ht, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
+            apc_swizzle_ptr(bd, ll, &zv->value.ht);
+            break;
+        case IS_OBJECT:
+            break;
+        default:
+            assert(0); /* shouldn't happen */
+    }
+} /* }}} */
+
+
+/* {{{ apc_swizzle_bd */
+static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC) {
+    int count, i;
+    PHP_MD5_CTX context;
+    unsigned char digest[16];
+    register php_uint32 crc;
+    php_uint32 crcinit = 0;
+    char *crc_p;
+    void ***ptr;
+    void ***ptr_list;
+
+    count = zend_llist_count(ll);
+    ptr_list = emalloc(count * sizeof(void**));
+    ptr = zend_llist_get_first(ll);
+    for(i=0; i < count; i++) {
+#if APC_BINDUMP_DEBUG
+        printf("[%06d] ", i+1);
+#endif
+        SWIZZLE(bd, **ptr); /* swizzle ptr */
+        if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) {  /* exclude ptrs that aren't actually included in the ptr list */
+#if APC_BINDUMP_DEBUG
+            printf("[------] ");
+#endif
+            SWIZZLE(bd, *ptr);  /* swizzle ptr list */
+            ptr_list[i] = *ptr;
+        }
+        ptr = zend_llist_get_next(ll);
+    }
+    SWIZZLE(bd, bd->entries);
+
+    if(count > 0) {
+        bd = erealloc(bd, bd->size + (count * sizeof(void**)));
+        bd->num_swizzled_ptrs = count;
+        bd->swizzled_ptrs = (void***)((unsigned char *)bd + bd->size -2);   /* extra -1 for null termination */
+        bd->size += count * sizeof(void**);
+        memcpy(bd->swizzled_ptrs, ptr_list, count * sizeof(void**));
+        SWIZZLE(bd, bd->swizzled_ptrs);
+    } else {
+        bd->num_swizzled_ptrs = 0;
+        bd->swizzled_ptrs = NULL;
+    }
+    ((char*)bd)[bd->size-1] = 0;  /* silence null termination for zval strings */
+    efree(ptr_list);
+    bd->swizzled = 1;
+
+    /* Generate MD5/CRC32 checksum */
+    for(i=0; i<16; i++) { bd->md5[i] = 0; }
+    bd->crc=0;
+    PHP_MD5Init(&context);
+    PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
+    PHP_MD5Final(digest, &context);
+    crc = crcinit^0xFFFFFFFF;
+    crc_p = (char*)bd;
+    for(i=bd->size; i--; ++crc_p) {
+      crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
+    }
+    memcpy(bd->md5, digest, 16);
+    bd->crc = crc;
+
+    return bd;
+} /* }}} */
+
+
+/* {{{ apc_unswizzle_bd */
+static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC) {
+    int i;
+    unsigned char md5_orig[16];
+    unsigned char digest[16];
+    PHP_MD5_CTX context;
+    register php_uint32 crc;
+    php_uint32 crcinit = 0;
+    php_uint32 crc_orig;
+    char *crc_p;
+
+    /* Verify the md5 or crc32 before we unswizzle */
+    memcpy(md5_orig, bd->md5, 16);
+    for(i=0; i<16; i++) { bd->md5[i] = 0; }
+    crc_orig = bd->crc;
+    bd->crc=0;
+    if(flags & APC_BIN_VERIFY_MD5) {
+        PHP_MD5Init(&context);
+        PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
+        PHP_MD5Final(digest, &context);
+        if(memcmp(md5_orig, digest, 16)) {
+            apc_error("MD5 checksum of binary dump failed." TSRMLS_CC);
+            memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
+            return -1;
+        }
+    }
+    if(flags & APC_BIN_VERIFY_CRC32) {
+        crc = crcinit^0xFFFFFFFF;
+        crc_p = (char*)bd;
+        for(i=bd->size; i--; ++crc_p) {
+          crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
+        }
+        if(crc_orig != crc) {
+            apc_error("CRC32 checksum of binary dump failed." TSRMLS_CC);
+            bd->crc = crc_orig;
+            return -1;
+        }
+    }
+    memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
+    bd->crc = crc_orig;
+
+    UNSWIZZLE(bd, bd->entries);
+    UNSWIZZLE(bd, bd->swizzled_ptrs);
+    for(i=0; i < bd->num_swizzled_ptrs; i++) {
+        if(bd->swizzled_ptrs[i]) {
+            UNSWIZZLE(bd, bd->swizzled_ptrs[i]);
+            if(*bd->swizzled_ptrs[i] && (*bd->swizzled_ptrs[i] < (void*)bd)) {
+                UNSWIZZLE(bd, *bd->swizzled_ptrs[i]);
+            }
+        }
+    }
+
+    bd->swizzled=0;
+
+    return 0;
+} /* }}} */
+
+
+/* {{{ apc_bin_checkfilter */
+static int apc_bin_checkfilter(HashTable *filter, const char *key, uint key_len) {
+    zval **zptr;
+
+    if(filter == NULL) {
+        return 1;
+    }
+
+    if(zend_hash_find(filter, (char*)key, key_len, (void**)&zptr) == SUCCESS) {
+        if(Z_TYPE_PP(zptr) == IS_LONG && Z_LVAL_PP(zptr) == 0) {
+            return 0;
+        }
+    } else {
+        return 0;
+    }
+
+
+    return 1;
+} /* }}} */
+
+/* {{{ apc_bin_fixup_op_array */
+static inline void apc_bin_fixup_op_array(zend_op_array *op_array) {
+    ulong i;
+    for (i = 0; i < op_array->last; i++) {
+        op_array->opcodes[i].handler = zend_opcode_handlers[APC_OPCODE_HANDLER_DECODE(&op_array->opcodes[i])];
+    }
+}
+/* }}} */
+
+/* {{{ apc_bin_fixup_class_entry */
+static inline void apc_bin_fixup_class_entry(zend_class_entry *ce) {
+    zend_function *fe;
+    HashPosition hpos;
+
+    /* fixup the opcodes in each method */
+    zend_hash_internal_pointer_reset_ex(&ce->function_table, &hpos);
+    while(zend_hash_get_current_data_ex(&ce->function_table, (void**)&fe, &hpos) == SUCCESS) {
+        apc_bin_fixup_op_array(&fe->op_array);
+        zend_hash_move_forward_ex(&ce->function_table, &hpos);
+    }
+
+    /* fixup hashtable destructor pointers */
+    ce->function_table.pDestructor = (dtor_func_t)zend_function_dtor;
+#ifndef ZEND_ENGINE_2_4
+    ce->default_properties.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
+#endif
+    ce->properties_info.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
+#ifndef ZEND_ENGINE_2_4
+    ce->default_static_members.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
+    if (ce->static_members) {
+        ce->static_members->pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
+    }
+#endif
+    ce->constants_table.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
+}
+/* }}} */
+
+/* {{{ apc_bin_dump */
+apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC) {
+
+    int i;
+    uint fcount;
+    slot_t *sp;
+    apc_bd_entry_t *ep;
+    int count=0;
+    apc_bd_t *bd;
+    zend_llist ll;
+    zend_function *efp, *sfp;
+    long size=0;
+    apc_context_t ctxt;
+    void *pool_ptr;
+
+    zend_llist_init(&ll, sizeof(void*), NULL, 0);
+    zend_hash_init(&APCG(apc_bd_alloc_list), 0, NULL, NULL, 0);
+
+    /* flip the hash for faster filter checking */
+    files = apc_flip_hash(files);
+    user_vars = apc_flip_hash(user_vars);
+
+    /* get size and entry counts */
+    for(i=0; i < apc_user_cache->num_slots; i++) {
+        sp = apc_user_cache->slots[i];
+        for(; sp != NULL; sp = sp->next) {
+            if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) {
+                size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
+                size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
+                count++;
+            }
+        }
+    }
+    for(i=0; i < apc_cache->num_slots; i++) {
+        sp = apc_cache->slots[i];
+        for(; sp != NULL; sp = sp->next) {
+            if(sp->key.type == APC_CACHE_KEY_FPFILE) {
+                if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
+                    size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
+                    size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
+                    count++;
+                }
+            } else {
+                /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load */
+                apc_warning("Excluding some files from apc_bin_dump[file].  Cached files must be included using full path with apc.stat=0." TSRMLS_CC);
+            }
+        }
+    }
+
+    size += sizeof(apc_bd_t) +1;  /* +1 for null termination */
+    bd = emalloc(size);
+    bd->size = size;
+    pool_ptr = emalloc(sizeof(apc_pool));
+    apc_bd_alloc_ex(pool_ptr, sizeof(apc_pool) TSRMLS_CC);
+    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_bd_alloc, apc_bd_free, NULL, NULL TSRMLS_CC);  /* ideally the pool wouldn't be alloc'd as part of this */
+    if (!ctxt.pool) { /* TODO need to cleanup */
+        apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+        return NULL;
+    }
+    ctxt.copy = APC_COPY_IN_USER;  /* avoid stupid ALLOC_ZVAL calls here, hack */
+    apc_bd_alloc_ex((void*)((long)bd + sizeof(apc_bd_t)), bd->size - sizeof(apc_bd_t) -1 TSRMLS_CC);
+    bd->num_entries = count;
+    bd->entries = apc_bd_alloc_ex(NULL, sizeof(apc_bd_entry_t) * count TSRMLS_CC);
+
+    /* User entries */
+    zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
+    count = 0;
+    for(i=0; i < apc_user_cache->num_slots; i++) {
+        sp = apc_user_cache->slots[i];
+        for(; sp != NULL; sp = sp->next) {
+            if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) {
+                ep = &bd->entries[count];
+                ep->type = sp->value->type;
+                ep->val.user.info = apc_bd_alloc(sp->value->data.user.info_len TSRMLS_CC);
+                memcpy(ep->val.user.info, sp->value->data.user.info, sp->value->data.user.info_len);
+                ep->val.user.info_len = sp->value->data.user.info_len;
+                ep->val.user.val = apc_copy_zval(NULL, sp->value->data.user.val, &ctxt TSRMLS_CC);
+                ep->val.user.ttl = sp->value->data.user.ttl;
+
+                /* swizzle pointers */
+                apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.info);
+                zend_hash_clean(&APCG(copied_zvals));
+                apc_swizzle_zval(bd, &ll, bd->entries[count].val.user.val TSRMLS_CC);
+                apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.val);
+
+                count++;
+            }
+        }
+    }
+    zend_hash_destroy(&APCG(copied_zvals));
+    APCG(copied_zvals).nTableSize=0;
+
+    /* File entries */
+    for(i=0; i < apc_cache->num_slots; i++) {
+        for(sp=apc_cache->slots[i]; sp != NULL; sp = sp->next) {
+            if(sp->key.type == APC_CACHE_KEY_FPFILE) {
+                if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
+                    ep = &bd->entries[count];
+                    ep->type = sp->key.type;
+                    ep->val.file.filename = apc_bd_alloc(strlen(sp->value->data.file.filename) + 1 TSRMLS_CC);
+                    strcpy(ep->val.file.filename, sp->value->data.file.filename);
+                    ep->val.file.op_array = apc_copy_op_array(NULL, sp->value->data.file.op_array, &ctxt TSRMLS_CC);
+
+                    for(ep->num_functions=0; sp->value->data.file.functions[ep->num_functions].function != NULL;) { ep->num_functions++; }
+                    ep->val.file.functions = apc_bd_alloc(sizeof(apc_function_t) * ep->num_functions TSRMLS_CC);
+                    for(fcount=0; fcount < ep->num_functions; fcount++) {
+                        memcpy(&ep->val.file.functions[fcount], &sp->value->data.file.functions[fcount], sizeof(apc_function_t));
+                        ep->val.file.functions[fcount].name = apc_xmemcpy(sp->value->data.file.functions[fcount].name, sp->value->data.file.functions[fcount].name_len+1, apc_bd_alloc TSRMLS_CC);
+                        ep->val.file.functions[fcount].name_len = sp->value->data.file.functions[fcount].name_len;
+                        ep->val.file.functions[fcount].function = apc_bd_alloc(sizeof(zend_function) TSRMLS_CC);
+                        efp = ep->val.file.functions[fcount].function;
+                        sfp = sp->value->data.file.functions[fcount].function;
+                        switch(sfp->type) {
+                            case ZEND_INTERNAL_FUNCTION:
+                            case ZEND_OVERLOADED_FUNCTION:
+                                efp->op_array = sfp->op_array;
+                                break;
+                            case ZEND_USER_FUNCTION:
+                            case ZEND_EVAL_CODE:
+                                apc_copy_op_array(&efp->op_array, &sfp->op_array, &ctxt TSRMLS_CC);
+                                break;
+                            default:
+                                assert(0);
+                        }
+#ifdef ZEND_ENGINE_2
+                        efp->common.prototype = NULL;
+                        efp->common.fn_flags = sfp->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
+#endif
+                        apc_swizzle_ptr(bd, &ll, &ep->val.file.functions[fcount].name);
+                        apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions[fcount].function);
+                        apc_swizzle_op_array(bd, &ll, &efp->op_array TSRMLS_CC);
+                    }
+
+
+                    for(ep->num_classes=0; sp->value->data.file.classes[ep->num_classes].class_entry != NULL;) { ep->num_classes++; }
+                    ep->val.file.classes = apc_bd_alloc(sizeof(apc_class_t) * ep->num_classes TSRMLS_CC);
+                    for(fcount=0; fcount < ep->num_classes; fcount++) {
+                        ep->val.file.classes[fcount].name = apc_xmemcpy(sp->value->data.file.classes[fcount].name, sp->value->data.file.classes[fcount].name_len + 1, apc_bd_alloc TSRMLS_CC);
+                        ep->val.file.classes[fcount].name_len = sp->value->data.file.classes[fcount].name_len;
+                        ep->val.file.classes[fcount].class_entry = apc_copy_class_entry(NULL, sp->value->data.file.classes[fcount].class_entry, &ctxt TSRMLS_CC);
+                        ep->val.file.classes[fcount].parent_name = apc_xstrdup(sp->value->data.file.classes[fcount].parent_name, apc_bd_alloc TSRMLS_CC);
+
+                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].name);
+                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].parent_name);
+                        apc_swizzle_class_entry(bd, &ll, ep->val.file.classes[fcount].class_entry TSRMLS_CC);
+                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].class_entry);
+                    }
+
+                    apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.filename);
+                    apc_swizzle_op_array(bd, &ll, bd->entries[count].val.file.op_array TSRMLS_CC);
+                    apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.op_array);
+                    apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions);
+                    apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.classes);
+
+                    count++;
+                } else {
+                    /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load */
+                }
+            }
+        }
+    }
+
+    /* append swizzle pointer list to bd */
+    bd = apc_swizzle_bd(bd, &ll TSRMLS_CC);
+    zend_llist_destroy(&ll);
+    zend_hash_destroy(&APCG(apc_bd_alloc_list));
+
+    if(files) {
+        zend_hash_destroy(files);
+        efree(files);
+    }
+    if(user_vars) {
+        zend_hash_destroy(user_vars);
+        efree(user_vars);
+    }
+
+    efree(pool_ptr);
+
+    return bd;
+} /* }}} */
+
+
+/* {{{ apc_bin_load */
+int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC) {
+
+    apc_bd_entry_t *ep;
+    uint i, i2;
+    int ret;
+    time_t t;
+    zend_op_array *alloc_op_array = NULL;
+    apc_function_t *alloc_functions = NULL;
+    apc_class_t *alloc_classes = NULL;
+    apc_cache_entry_t *cache_entry;
+    apc_cache_key_t cache_key;
+    apc_context_t ctxt;
+
+    if (bd->swizzled) {
+        if(apc_unswizzle_bd(bd, flags TSRMLS_CC) < 0) {
+            return -1;
+        }
+    }
+
+    t = apc_time();
+
+    for(i = 0; i < bd->num_entries; i++) {
+        ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+        if (!ctxt.pool) { /* TODO need to cleanup previous pools */
+            apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+            goto failure;
+        }
+        ep = &bd->entries[i];
+        switch (ep->type) {
+            case APC_CACHE_KEY_FILE:
+                /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load (or something else perhaps?) */
+                break;
+            case APC_CACHE_KEY_FPFILE:
+                ctxt.copy = APC_COPY_IN_OPCODE;
+
+                HANDLE_BLOCK_INTERRUPTIONS();
+#if NONBLOCKING_LOCK_AVAILABLE
+                if(APCG(write_lock)) {
+                    if(!apc_cache_write_lock(apc_cache TSRMLS_CC)) {
+                        HANDLE_UNBLOCK_INTERRUPTIONS();
+                        return -1;
+                    }
+                }
+#endif
+                if(! (alloc_op_array = apc_copy_op_array(NULL, ep->val.file.op_array, &ctxt TSRMLS_CC))) {
+                    goto failure;
+                }
+                apc_bin_fixup_op_array(alloc_op_array);
+
+                if(! (alloc_functions = apc_sma_malloc(sizeof(apc_function_t) * (ep->num_functions + 1) TSRMLS_CC))) {
+                    goto failure;
+                }
+                for(i2=0; i2 < ep->num_functions; i2++) {
+                    if(! (alloc_functions[i2].name = apc_xmemcpy(ep->val.file.functions[i2].name, ep->val.file.functions[i2].name_len + 1, apc_sma_malloc TSRMLS_CC))) {
+                        goto failure;
+                    }
+                    alloc_functions[i2].name_len = ep->val.file.functions[i2].name_len;
+                    if(! (alloc_functions[i2].function = apc_sma_malloc(sizeof(zend_function) TSRMLS_CC))) {
+                        goto failure;
+                    }
+                    switch(ep->val.file.functions[i2].function->type) {
+                        case ZEND_INTERNAL_FUNCTION:
+                        case ZEND_OVERLOADED_FUNCTION:
+                            alloc_functions[i2].function->op_array = ep->val.file.functions[i2].function->op_array;
+                            break;
+                        case ZEND_USER_FUNCTION:
+                        case ZEND_EVAL_CODE:
+                            if (!apc_copy_op_array(&alloc_functions[i2].function->op_array, &ep->val.file.functions[i2].function->op_array, &ctxt TSRMLS_CC)) {
+                                goto failure;
+                            }
+                            apc_bin_fixup_op_array(&alloc_functions[i2].function->op_array);
+                            break;
+                        default:
+                            assert(0);
+                    }
+#ifdef ZEND_ENGINE_2
+                    alloc_functions[i2].function->common.prototype=NULL;
+                    alloc_functions[i2].function->common.fn_flags=ep->val.file.functions[i2].function->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
+#endif
+                }
+                alloc_functions[i2].name = NULL;
+                alloc_functions[i2].function = NULL;
+
+                if(! (alloc_classes = apc_sma_malloc(sizeof(apc_class_t) * (ep->num_classes + 1) TSRMLS_CC))) {
+                    goto failure;
+                }
+                for(i2=0; i2 < ep->num_classes; i2++) {
+                    if(! (alloc_classes[i2].name = apc_xmemcpy(ep->val.file.classes[i2].name, ep->val.file.classes[i2].name_len+1, apc_sma_malloc TSRMLS_CC))) {
+                        goto failure;
+                    }
+                    alloc_classes[i2].name_len = ep->val.file.classes[i2].name_len;
+                    if(! (alloc_classes[i2].class_entry = apc_copy_class_entry(NULL, ep->val.file.classes[i2].class_entry, &ctxt TSRMLS_CC))) {
+                        goto failure;
+                    }
+                    apc_bin_fixup_class_entry(alloc_classes[i2].class_entry);
+                    if(! (alloc_classes[i2].parent_name = apc_xstrdup(ep->val.file.classes[i2].parent_name, apc_sma_malloc TSRMLS_CC))) {
+                        if(ep->val.file.classes[i2].parent_name != NULL) {
+                            goto failure;
+                        }
+                    }
+                }
+                alloc_classes[i2].name = NULL;
+                alloc_classes[i2].class_entry = NULL;
+
+                if(!(cache_entry = apc_cache_make_file_entry(ep->val.file.filename, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
+                    goto failure;
+                }
+
+                if (!apc_cache_make_file_key(&cache_key, ep->val.file.filename, PG(include_path), t TSRMLS_CC)) {
+                    goto failure;
+                }
+
+                if ((ret = apc_cache_insert(apc_cache, cache_key, cache_entry, &ctxt, t TSRMLS_CC)) != 1) {
+                    if(ret==-1) {
+                        goto failure;
+                    }
+                }
+
+#if NONBLOCKING_LOCK_AVAILABLE
+                if(APCG(write_lock)) {
+                    apc_cache_write_unlock(apc_cache TSRMLS_CC);
+                }
+#endif
+                HANDLE_UNBLOCK_INTERRUPTIONS();
+
+                break;
+            case APC_CACHE_KEY_USER:
+                ctxt.copy = APC_COPY_IN_USER;
+                _apc_store(ep->val.user.info, ep->val.user.info_len, ep->val.user.val, ep->val.user.ttl, 0 TSRMLS_CC);
+                break;
+            default:
+                break;
+       }
+    }
+
+    return 0;
+
+failure:
+    apc_pool_destroy(ctxt.pool TSRMLS_CC);
+    apc_warning("Unable to allocate memory for apc binary load/dump functionality." TSRMLS_CC);
+#if NONBLOCKING_LOCK_AVAILABLE
+    if(APCG(write_lock)) {
+        apc_cache_write_unlock(apc_cache TSRMLS_CC);
+    }
+#endif
+    HANDLE_UNBLOCK_INTERRUPTIONS();
+    return -1;
+} /* }}} */
+
+
+/*
+ * 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
+ */
--- /dev/null
+++ b/ext/apc/apc_bin.h
@@ -0,0 +1,63 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_bin.h 300979 2010-07-04 10:15:05Z kalle $ */
+
+#ifndef APC_BINDUMP_H
+#define APC_BINDUMP_H
+
+#include "apc.h"
+#include "apc_php.h"
+#include "ext/standard/basic_functions.h"
+
+/* APC binload flags */
+#define APC_BIN_VERIFY_MD5    1 << 0
+#define APC_BIN_VERIFY_CRC32  1 << 1
+
+typedef struct _apc_bd_entry_t {
+    unsigned char type;
+    uint num_functions;
+    uint num_classes;
+    apc_cache_entry_value_t val;
+} apc_bd_entry_t;
+
+typedef struct _apc_bd_t {
+    unsigned int size;
+    int swizzled;
+    unsigned char md5[16];
+    php_uint32 crc;
+    unsigned int num_entries;
+    apc_bd_entry_t *entries;
+    int num_swizzled_ptrs;
+    void ***swizzled_ptrs;
+} apc_bd_t;
+
+apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC);
+int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC);
+
+#endif
+
+/*
+ * 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
+ */
--- /dev/null
+++ b/ext/apc/apc.c
@@ -0,0 +1,636 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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.c 305003 2010-10-31 19:45:10Z gopalv $ */
+
+#include "apc.h"
+#include "apc_zend.h"
+#include "apc_cache.h"
+#include "php.h"
+
+#if HAVE_PCRE || HAVE_BUNDLED_PCRE
+/*  Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
+#   if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
+#       include "apc_php_pcre.h"
+#   else
+#       include "ext/pcre/php_pcre.h"
+#   endif
+#   include "ext/standard/php_smart_str.h"
+#endif
+
+#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
+
+/* {{{ memory allocation wrappers */
+
+void* apc_emalloc(size_t n TSRMLS_DC)
+{
+    void* p = malloc(n);
+    if (p == NULL) {
+        apc_error("apc_emalloc: malloc failed to allocate %u bytes:" TSRMLS_CC, n);
+    }
+    return p;
+}
+
+void* apc_erealloc(void* p, size_t n TSRMLS_DC)
+{
+    p = realloc(p, n);
+    if (p == NULL) {
+        apc_error("apc_erealloc: realloc failed to allocate %u bytes:" TSRMLS_CC, n);
+    }
+    return p;
+}
+
+void apc_efree(void* p TSRMLS_DC)
+{
+    if (p == NULL) {
+        apc_error("apc_efree: attempt to free null pointer" TSRMLS_CC);
+    }
+    free(p);
+}
+
+char* apc_estrdup(const char* s TSRMLS_DC)
+{
+    int len;
+    char* dup;
+
+    if (s == NULL) {
+        return NULL;
+    }
+    len = strlen(s);
+    dup = (char*) malloc(len+1);
+    if (dup == NULL) {
+        apc_error("apc_estrdup: malloc failed to allocate %u bytes:" TSRMLS_CC, len+1);
+    }
+    memcpy(dup, s, len);
+    dup[len] = '\0';
+    return dup;
+}
+
+void* apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC)
+{
+    return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f TSRMLS_CC) : NULL;
+}
+
+void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC)
+{
+    void* q;
+
+    if (p != NULL && (q = f(n TSRMLS_CC)) != NULL) {
+        memcpy(q, p, n);
+        return q;
+    }
+    return NULL;
+}
+
+/* }}} */
+
+/* {{{ console display functions */
+#ifdef ZTS
+# define APC_PRINT_FUNCTION_PARAMETER TSRMLS_C
+#else
+# define APC_PRINT_FUNCTION_PARAMETER format
+#endif
+
+#define APC_PRINT_FUNCTION(name, verbosity)					\
+	void apc_##name(const char *format TSRMLS_DC, ...)			\
+	{									\
+		va_list args;							\
+										\
+		va_start(args, APC_PRINT_FUNCTION_PARAMETER);			\
+		php_verror(NULL, "", verbosity, format, args TSRMLS_CC);	\
+		va_end(args);							\
+	}
+
+APC_PRINT_FUNCTION(error, E_ERROR)
+APC_PRINT_FUNCTION(warning, E_WARNING)
+APC_PRINT_FUNCTION(notice, E_NOTICE)
+
+#ifdef __DEBUG_APC__
+APC_PRINT_FUNCTION(debug, E_NOTICE)
+#else
+void apc_debug(const char *format TSRMLS_DC, ...) {}
+#endif
+/* }}} */
+
+/* {{{ string and text manipulation */
+
+char* apc_append(const char* s, const char* t TSRMLS_DC)
+{
+    int slen;
+    int tlen;
+    char* p;
+
+    slen = strlen(s);
+    tlen = strlen(t);
+
+    p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char) TSRMLS_CC);
+    memcpy(p, s, slen);
+    memcpy(p + slen, t, tlen + 1);
+
+    return p;
+}
+
+char* apc_substr(const char* s, int start, int length TSRMLS_DC)
+{
+    char* substr;
+    int src_len = strlen(s);
+
+    /* bring start into range */
+    if (start < 0) {
+        start = 0;
+    }
+    else if (start >= src_len) {
+        start = src_len - 1;
+    }
+
+    /* bring length into range */
+    if (length < 0 || src_len - start < length) {
+        length = src_len - start;
+    }
+
+    /* create the substring */
+    substr = apc_xmemcpy(s + start, length + 1, apc_emalloc TSRMLS_CC);
+    substr[length] = '\0';
+    return substr;
+}
+
+char** apc_tokenize(const char* s, char delim TSRMLS_DC)
+{
+    char** tokens;      /* array of tokens, NULL terminated */
+    int size;           /* size of tokens array */
+    int n;              /* index of next token in tokens array */
+    int cur;            /* current position in input string */
+    int end;            /* final legal position in input string */
+    int next;           /* position of next delimiter in input */
+
+    if (!s) {
+        return NULL;
+    }
+
+    size = 2;
+    n    = 0;
+    cur  = 0;
+    end  = strlen(s) - 1;
+
+    tokens = (char**) apc_emalloc(size * sizeof(char*) TSRMLS_CC);
+    tokens[n] = NULL;
+
+    while (cur <= end) {
+        /* search for the next delimiter */
+        char* p = strchr(s + cur, delim);
+        next = p ? p-s : end+1;
+
+        /* resize token array if necessary */
+        if (n == size-1) {
+            size *= 2;
+            tokens = (char**) apc_erealloc(tokens, size * sizeof(char*) TSRMLS_CC);
+        }
+
+        /* save the current token */
+        tokens[n] = apc_substr(s, cur, next-cur TSRMLS_CC);
+
+        tokens[++n] = NULL;
+        cur = next + 1;
+    }
+
+    return tokens;
+}
+
+/* }}} */
+
+
+/* {{{ apc_win32_restat */
+#ifdef PHP_WIN32
+static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
+{
+    HANDLE hFile;
+    BY_HANDLE_FILE_INFORMATION hInfo;
+
+    hFile = CreateFile(fileinfo->fullpath, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+    if (!hFile) {
+        apc_debug("Cannot create a file HANDLE for %s\n" TSRMLS_CC, fileinfo->fullpath);
+        return -1;
+    }
+
+    if (!GetFileInformationByHandle(hFile, &hInfo)) {
+        apc_debug("Cannot get file information from handle\n" TSRMLS_CC);
+        CloseHandle(hFile);
+        return -1;
+    }
+
+    CloseHandle(hFile);
+
+    fileinfo->st_buf.sb.st_dev = hInfo.dwVolumeSerialNumber;
+    fileinfo->st_buf.sb.st_ino = (((apc_ino_t)(hInfo.nFileIndexHigh) << 32) | (apc_ino_t) hInfo.nFileIndexLow);
+
+    return 0;
+}
+#else
+static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
+{
+	return 0;
+}
+#endif
+/* }}} */
+
+/* {{{ apc_search_paths */
+/* similar to php_stream_stat_path */
+#define APC_URL_STAT(wrapper, filename, pstatbuf) \
+    ((wrapper)->wops->url_stat((wrapper), (filename), PHP_STREAM_URL_STAT_QUIET, (pstatbuf), NULL TSRMLS_CC))
+
+/* copy out to path_buf if path_for_open isn't the same as filename */
+#define COPY_IF_CHANGED(p) \
+    (char*) (((p) == filename) ? filename : \
+            (strlcpy((char*)fileinfo->path_buf, (p), sizeof(fileinfo->path_buf))) \
+                    ? (fileinfo->path_buf) : NULL)
+
+/* len checks can be skipped here because filename is NUL terminated */
+#define IS_RELATIVE_PATH(filename, len) \
+        ((filename) && (filename[0] == '.' && \
+            (IS_SLASH(filename[1]) || \
+                (filename[1] == '.' && \
+                    IS_SLASH(filename[2])))))
+    
+
+int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC)
+{
+    char** paths = NULL;
+    char *exec_fname;
+    int exec_fname_length;
+    int found = 0;
+    int i;
+    php_stream_wrapper *wrapper = NULL;
+    char *path_for_open = NULL;
+
+    assert(filename && fileinfo);
+
+
+    wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC);
+
+    if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) {
+        return -1;
+    }
+
+    if(wrapper != &php_plain_files_wrapper) {
+        if(APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
+            fileinfo->fullpath = COPY_IF_CHANGED(path_for_open);
+            return apc_restat(fileinfo TSRMLS_CC);
+        }
+        return -1; /* cannot stat */
+    }
+
+    if (IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) && 
+            APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
+        fileinfo->fullpath = COPY_IF_CHANGED(path_for_open);
+        return apc_restat(fileinfo TSRMLS_CC);
+    }
+
+    if (!IS_RELATIVE_PATH(path_for_open, strlen(path_for_open))) {
+        paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR TSRMLS_CC);
+        if (!paths)
+            return -1;
+
+        /* for each directory in paths, look for filename inside */
+        for (i = 0; paths[i]; i++) {
+            snprintf(fileinfo->path_buf, sizeof(fileinfo->path_buf), "%s%c%s", paths[i], DEFAULT_SLASH, path_for_open);
+            if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
+                fileinfo->fullpath = (char*) fileinfo->path_buf;
+                found = 1;
+                break;
+            }
+        }
+    }
+
+    /* check in path of the calling scripts' current working directory */
+    /* modified from main/streams/plain_wrapper.c */
+    if(!found && zend_is_executing(TSRMLS_C)) {
+        exec_fname = zend_get_executed_filename(TSRMLS_C);
+        exec_fname_length = strlen(exec_fname);
+        while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
+        if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
+            /* not: [no active file] or no path */
+            memcpy(fileinfo->path_buf, exec_fname, exec_fname_length);
+            fileinfo->path_buf[exec_fname_length] = DEFAULT_SLASH;
+            strlcpy(fileinfo->path_buf +exec_fname_length +1, path_for_open,sizeof(fileinfo->path_buf)-exec_fname_length-1);
+            /* apc_warning("filename: %s, exec_fname: %s, fileinfo->path_buf: %s" TSRMLS_CC, path_for_open, exec_fname, fileinfo->path_buf); */
+            if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
+                fileinfo->fullpath = (char*) fileinfo->path_buf;
+                found = 1;
+            }
+        }
+    }
+
+    if(paths) {
+        /* free the value returned by apc_tokenize */
+        for (i = 0; paths[i]; i++) {
+            apc_efree(paths[i] TSRMLS_CC);
+        }
+        apc_efree(paths TSRMLS_CC);
+    }
+
+    return found ? apc_restat(fileinfo TSRMLS_CC) : -1;
+}
+
+/* }}} */
+
+/* {{{ regular expression wrapper functions */
+
+#if (HAVE_PCRE || HAVE_BUNDLED_PCRE)
+typedef struct {
+    pcre *preg;
+    pcre *nreg;
+} apc_regex;
+
+#define APC_ADD_PATTERN(match, pat) do {\
+    if(match.len > 1) {\
+        smart_str_appendc(&match, '|');\
+    }\
+    smart_str_appendc(&match, '(');\
+    while(*pat) {\
+        if(*pat == '/') smart_str_appendc(&match, '\\');\
+        \
+        smart_str_appendc(&match, *(pat++));\
+    }\
+    smart_str_appendc(&match, ')');\
+} while(0)
+
+#define APC_COMPILE_PATTERN(re, match) do {\
+    if(match.len > 2) { /* more than just "//" */\
+        if (((re) = pcre_get_compiled_regex(match.c, NULL, NULL TSRMLS_CC)) == NULL) {\
+            apc_warning("apc_regex_compile_array: invalid expression '%s'" TSRMLS_CC, match.c); \
+            smart_str_free(&match);\
+            return NULL;\
+        }\
+    } else { \
+        (re) = NULL;\
+    }\
+} while(0)
+
+void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
+{
+    apc_regex* regs;
+    int npat;
+    smart_str pmatch = {0,};
+    smart_str nmatch = {0,};
+    char* pattern;
+
+    if (!patterns)
+        return NULL;
+
+    regs = (apc_regex*) apc_emalloc(sizeof(apc_regex) TSRMLS_CC);
+
+    smart_str_appendc(&pmatch, '/');
+    smart_str_appendc(&nmatch, '/');
+
+    for (npat = 0; patterns[npat] != NULL; npat++) {
+        pattern = patterns[npat];
+        if(pattern[0] == '+') {
+            pattern += sizeof(char);
+            APC_ADD_PATTERN(pmatch, pattern);
+        } else {
+            if(pattern[0] == '-') pattern += sizeof(char);
+            APC_ADD_PATTERN(nmatch, pattern);
+        }
+    }
+    smart_str_appendc(&pmatch, '/');
+    smart_str_appendc(&nmatch, '/');
+
+    smart_str_0(&nmatch);
+    smart_str_0(&pmatch);
+
+    APC_COMPILE_PATTERN(regs->preg, pmatch);
+    APC_COMPILE_PATTERN(regs->nreg, nmatch);
+
+    smart_str_free(&pmatch);
+    smart_str_free(&nmatch);
+
+    return (void*) regs;
+}
+
+void apc_regex_destroy_array(void* p TSRMLS_DC)
+{
+    if (p != NULL) {
+        apc_regex* regs = (apc_regex*) p;
+        apc_efree(regs TSRMLS_CC);
+    }
+}
+
+#define APC_MATCH_PATTERN(re, input, output) do {\
+    if (re && pcre_exec(re, NULL, (input), strlen(input), 0, 0, NULL, 0) >= 0) {\
+        return (output);\
+    }\
+} while(0)
+
+
+int apc_regex_match_array(void* p, const char* input)
+{
+    apc_regex* regs;
+
+    if (!p)
+        return 0;
+
+    regs = (apc_regex*) p;
+
+    APC_MATCH_PATTERN(regs->preg, input, APC_POSITIVE_MATCH);
+    APC_MATCH_PATTERN(regs->nreg, input, APC_NEGATIVE_MATCH);
+
+    return 0;
+}
+#else /* no pcre */
+void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
+{
+    if(patterns && patterns[0] != NULL) {
+        apc_warning("pcre missing, disabling filters" TSRMLS_CC);
+    }
+    return NULL;
+}
+void apc_regex_destroy_array(void* p)
+{
+    /* nothing */
+}
+int apc_regex_match_array(void* p, const char* input)
+{
+    return 0;
+}
+#endif
+/* }}} */
+
+/* {{{ crc32 implementation */
+
+/* this table was generated by crc32gen() */
+static unsigned int crc32tab[] = {
+    /*   0 */  0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
+    /*   4 */  0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
+    /*   8 */  0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
+    /*  12 */  0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
+    /*  16 */  0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
+    /*  20 */  0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
+    /*  24 */  0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
+    /*  28 */  0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
+    /*  32 */  0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
+    /*  36 */  0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
+    /*  40 */  0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
+    /*  44 */  0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
+    /*  48 */  0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
+    /*  52 */  0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
+    /*  56 */  0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
+    /*  60 */  0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
+    /*  64 */  0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
+    /*  68 */  0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
+    /*  72 */  0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
+    /*  76 */  0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
+    /*  80 */  0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
+    /*  84 */  0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
+    /*  88 */  0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
+    /*  92 */  0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
+    /*  96 */  0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
+    /* 100 */  0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
+    /* 104 */  0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
+    /* 108 */  0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
+    /* 112 */  0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
+    /* 116 */  0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
+    /* 120 */  0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
+    /* 124 */  0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
+    /* 128 */  0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
+    /* 132 */  0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
+    /* 136 */  0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
+    /* 140 */  0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
+    /* 144 */  0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
+    /* 148 */  0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
+    /* 152 */  0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
+    /* 156 */  0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
+    /* 160 */  0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
+    /* 164 */  0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
+    /* 168 */  0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
+    /* 172 */  0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
+    /* 176 */  0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
+    /* 180 */  0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
+    /* 184 */  0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
+    /* 188 */  0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
+    /* 192 */  0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
+    /* 196 */  0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
+    /* 200 */  0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
+    /* 204 */  0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
+    /* 208 */  0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
+    /* 212 */  0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
+    /* 216 */  0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
+    /* 220 */  0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
+    /* 224 */  0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
+    /* 228 */  0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
+    /* 232 */  0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
+    /* 236 */  0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
+    /* 240 */  0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
+    /* 244 */  0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
+    /* 248 */  0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
+    /* 252 */  0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
+};
+
+unsigned int apc_crc32(const char* buf, int len)
+{
+    int i;
+    int k;
+    unsigned int crc;
+
+    /* preconditioning */
+    crc = 0xFFFFFFFF;
+
+    for (i = 0; i < len; i++) {
+        k = (crc ^ buf[i]) & 0x000000FF;
+        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
+    }
+
+    /* postconditioning */
+    return ~crc;
+}
+
+/* crc32gen: generate the nth (0..255) crc32 table value */
+#if 0
+static unsigned long crc32gen(int n)
+{
+    int i;
+    unsigned long crc;
+
+    crc = n;
+    for (i = 8; i >= 0; i--) {
+        if (crc & 1) {
+            crc = (crc >> 1) ^ 0xEDB88320;
+        }
+        else {
+            crc >>= 1;
+        }
+    }
+    return crc;
+}
+#endif
+
+/* }}} */
+
+
+/* {{{ apc_flip_hash() */
+HashTable* apc_flip_hash(HashTable *hash) {
+    zval **entry, *data;
+    HashTable *new_hash;
+    HashPosition pos;
+
+    if(hash == NULL) return hash;
+
+    MAKE_STD_ZVAL(data);
+    ZVAL_LONG(data, 1);
+    
+    new_hash = emalloc(sizeof(HashTable));
+    zend_hash_init(new_hash, hash->nTableSize, NULL, ZVAL_PTR_DTOR, 0);
+
+    zend_hash_internal_pointer_reset_ex(hash, &pos);
+    while (zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) {
+        if(Z_TYPE_PP(entry) == IS_STRING) {
+            zend_hash_update(new_hash, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) +1, &data, sizeof(data), NULL);
+        } else {
+            zend_hash_index_update(new_hash, Z_LVAL_PP(entry), &data, sizeof(data), NULL);
+        }
+        Z_ADDREF_P(data);
+        zend_hash_move_forward_ex(hash, &pos);
+    }
+    zval_ptr_dtor(&data);
+
+    return new_hash;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_cache.c
@@ -0,0 +1,1295 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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_cache.c 305771 2010-11-26 12:57:16Z gopalv $ */
+
+#include "apc_cache.h"
+#include "apc_zend.h"
+#include "apc_sma.h"
+#include "apc_globals.h"
+#include "SAPI.h"
+
+/* TODO: rehash when load factor exceeds threshold */
+
+#define CHECK(p) { if ((p) == NULL) return NULL; }
+
+/* {{{ key_equals */
+#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
+/* }}} */
+
+static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC);
+
+/* {{{ hash */
+static unsigned int hash(apc_cache_key_t key)
+{
+    return (unsigned int)(key.data.file.device + key.data.file.inode);
+}
+/* }}} */
+
+/* {{{ string_nhash_8 */
+#define string_nhash_8(s,len) (unsigned int)(zend_inline_hash_func(s, len))
+/* }}} */
+
+/* {{{ make_prime */
+static int const primes[] = {
+  257, /*   256 */
+  521, /*   512 */
+ 1031, /*  1024 */
+ 2053, /*  2048 */
+ 3079, /*  3072 */
+ 4099, /*  4096 */
+ 5147, /*  5120 */
+ 6151, /*  6144 */
+ 7177, /*  7168 */
+ 8209, /*  8192 */
+ 9221, /*  9216 */
+10243, /* 10240 */
+#if 0
+11273, /* 11264 */
+12289, /* 12288 */
+13313, /* 13312 */
+14341, /* 14336 */
+15361, /* 15360 */
+16411, /* 16384 */
+17417, /* 17408 */
+18433, /* 18432 */
+19457, /* 19456 */
+#endif
+0      /* sentinel */
+};
+
+static int make_prime(int n)
+{
+    int *k = (int*)primes; 
+    while(*k) {
+        if((*k) > n) return *k;
+        k++;
+    }
+    return *(k-1);
+}
+/* }}} */
+
+/* {{{ make_slot */
+slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t TSRMLS_DC)
+{
+    slot_t* p = apc_pool_alloc(value->pool, sizeof(slot_t));
+
+    if (!p) return NULL;
+
+    if(value->type == APC_CACHE_ENTRY_USER) {
+        char *identifier = (char*) apc_pmemcpy(key.data.user.identifier, key.data.user.identifier_len, value->pool TSRMLS_CC);
+        if (!identifier) {
+            return NULL;
+        }
+        key.data.user.identifier = identifier;
+    } else if(key.type == APC_CACHE_KEY_FPFILE) {
+        char *fullpath = (char*) apc_pstrdup(key.data.fpfile.fullpath, value->pool TSRMLS_CC);
+        if (!fullpath) {
+            return NULL;
+        }
+        key.data.fpfile.fullpath = fullpath;
+    }
+    p->key = key;
+    p->value = value;
+    p->next = next;
+    p->num_hits = 0;
+    p->creation_time = t;
+    p->access_time = t;
+    p->deletion_time = 0;
+    return p;
+}
+/* }}} */
+
+/* {{{ free_slot */
+static void free_slot(slot_t* slot TSRMLS_DC)
+{
+    apc_pool_destroy(slot->value->pool TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ remove_slot */
+static void remove_slot(apc_cache_t* cache, slot_t** slot TSRMLS_DC)
+{
+    slot_t* dead = *slot;
+    *slot = (*slot)->next;
+
+    cache->header->mem_size -= dead->value->mem_size;
+    cache->header->num_entries--;
+    if (dead->value->ref_count <= 0) {
+        free_slot(dead TSRMLS_CC);
+    }
+    else {
+        dead->next = cache->header->deleted_list;
+        dead->deletion_time = time(0);
+        cache->header->deleted_list = dead;
+    }
+}
+/* }}} */
+
+/* {{{ process_pending_removals */
+static void process_pending_removals(apc_cache_t* cache TSRMLS_DC)
+{
+    slot_t** slot;
+    time_t now;
+
+    /* This function scans the list of removed cache entries and deletes any
+     * entry whose reference count is zero (indicating that it is no longer
+     * being executed) or that has been on the pending list for more than
+     * cache->gc_ttl seconds (we issue a warning in the latter case).
+     */
+
+    if (!cache->header->deleted_list)
+        return;
+
+    slot = &cache->header->deleted_list;
+    now = time(0);
+
+    while (*slot != NULL) {
+        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
+
+        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
+            slot_t* dead = *slot;
+
+            if (dead->value->ref_count > 0) {
+                switch(dead->value->type) {
+                    case APC_CACHE_ENTRY_FILE:
+                        apc_warning("GC cache entry '%s' (dev=%d ino=%d) was on gc-list for %d seconds" TSRMLS_CC, 
+                            dead->value->data.file.filename, dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
+                        break;
+                    case APC_CACHE_ENTRY_USER:
+                        apc_warning("GC cache entry '%s'was on gc-list for %d seconds" TSRMLS_CC, dead->value->data.user.info, gc_sec);
+                        break;
+                }
+            }
+            *slot = dead->next;
+            free_slot(dead TSRMLS_CC);
+        }
+        else {
+            slot = &(*slot)->next;
+        }
+    }
+}
+/* }}} */
+
+/* {{{ prevent_garbage_collection */
+static void prevent_garbage_collection(apc_cache_entry_t* entry)
+{
+    /* set reference counts on zend objects to an arbitrarily high value to
+     * prevent garbage collection after execution */
+
+    enum { BIG_VALUE = 1000 };
+
+    if(entry->data.file.op_array) {
+        entry->data.file.op_array->refcount[0] = BIG_VALUE;
+    }
+    if (entry->data.file.functions) {
+        int i;
+        apc_function_t* fns = entry->data.file.functions;
+        for (i=0; fns[i].function != NULL; i++) {
+            *(fns[i].function->op_array.refcount) = BIG_VALUE;
+        }
+    }
+    if (entry->data.file.classes) {
+        int i;
+        apc_class_t* classes = entry->data.file.classes;
+        for (i=0; classes[i].class_entry != NULL; i++) {
+            classes[i].class_entry->refcount = BIG_VALUE;
+        }
+    }
+}
+/* }}} */
+
+/* {{{ apc_cache_create */
+apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC)
+{
+    apc_cache_t* cache;
+    int cache_size;
+    int num_slots;
+
+    num_slots = make_prime(size_hint > 0 ? size_hint : 2000);
+
+    cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t) TSRMLS_CC);
+    cache_size = sizeof(cache_header_t) + num_slots*sizeof(slot_t*);
+
+    cache->shmaddr = apc_sma_malloc(cache_size TSRMLS_CC);
+    if(!cache->shmaddr) {
+        apc_error("Unable to allocate shared memory for cache structures.  (Perhaps your shared memory size isn't large enough?). " TSRMLS_CC);
+    }
+    memset(cache->shmaddr, 0, cache_size);
+
+    cache->header = (cache_header_t*) cache->shmaddr;
+    cache->header->num_hits = 0;
+    cache->header->num_misses = 0;
+    cache->header->deleted_list = NULL;
+    cache->header->start_time = time(NULL);
+    cache->header->expunges = 0;
+    cache->header->busy = 0;
+
+    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(cache_header_t));
+    cache->num_slots = num_slots;
+    cache->gc_ttl = gc_ttl;
+    cache->ttl = ttl;
+    CREATE_LOCK(cache->header->lock);
+#if NONBLOCKING_LOCK_AVAILABLE
+    CREATE_LOCK(cache->header->wrlock);
+#endif
+    memset(cache->slots, 0, sizeof(slot_t*)*num_slots);
+    cache->expunge_cb = apc_cache_expunge;
+    cache->has_lock = 0;
+
+    return cache;
+}
+/* }}} */
+
+/* {{{ apc_cache_destroy */
+void apc_cache_destroy(apc_cache_t* cache TSRMLS_DC)
+{
+    DESTROY_LOCK(cache->header->lock);
+#ifdef NONBLOCKING_LOCK_AVAILABLE
+    DESTROY_LOCK(cache->header->wrlock);
+#endif
+    apc_efree(cache TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_cache_clear */
+void apc_cache_clear(apc_cache_t* cache TSRMLS_DC)
+{
+    int i;
+
+    if(!cache) return;
+
+    CACHE_LOCK(cache);
+    cache->header->busy = 1;
+    cache->header->num_hits = 0;
+    cache->header->num_misses = 0;
+    cache->header->start_time = time(NULL);
+    cache->header->expunges = 0;
+
+    for (i = 0; i < cache->num_slots; i++) {
+        slot_t* p = cache->slots[i];
+        while (p) {
+            remove_slot(cache, &p TSRMLS_CC);
+        }
+        cache->slots[i] = NULL;
+    }
+
+    memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
+
+    cache->header->busy = 0;
+    CACHE_UNLOCK(cache);
+}
+/* }}} */
+
+/* {{{ apc_cache_expunge */
+static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC)
+{
+    int i;
+    time_t t;
+
+    t = apc_time();
+
+    if(!cache) return;
+
+    if(!cache->ttl) {
+        /*
+         * If cache->ttl is not set, we wipe out the entire cache when
+         * we run out of space.
+         */
+        CACHE_SAFE_LOCK(cache);
+        if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) {
+            /* probably a queued up expunge, we don't need to do this */
+            CACHE_SAFE_UNLOCK(cache);
+            return;
+        }
+        cache->header->busy = 1;
+        cache->header->expunges++;
+clear_all:
+        for (i = 0; i < cache->num_slots; i++) {
+            slot_t* p = cache->slots[i];
+            while (p) {
+                remove_slot(cache, &p TSRMLS_CC);
+            }
+            cache->slots[i] = NULL;
+        }
+        memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
+        cache->header->busy = 0;
+        CACHE_SAFE_UNLOCK(cache);
+    } else {
+        slot_t **p;
+        /*
+         * If the ttl for the cache is set we walk through and delete stale 
+         * entries.  For the user cache that is slightly confusing since
+         * we have the individual entry ttl's we can look at, but that would be
+         * too much work.  So if you want the user cache expunged, set a high
+         * default apc.user_ttl and still provide a specific ttl for each entry
+         * on insert
+         */
+
+        CACHE_SAFE_LOCK(cache);
+        if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) {
+            /* probably a queued up expunge, we don't need to do this */
+            CACHE_SAFE_UNLOCK(cache);
+            return;
+        }
+        cache->header->busy = 1;
+        cache->header->expunges++;
+        for (i = 0; i < cache->num_slots; i++) {
+            p = &cache->slots[i];
+            while(*p) {
+                /*
+                 * For the user cache we look at the individual entry ttl values
+                 * and if not set fall back to the default ttl for the user cache
+                 */
+                if((*p)->value->type == APC_CACHE_ENTRY_USER) {
+                    if((*p)->value->data.user.ttl) {
+                        if((time_t) ((*p)->creation_time + (*p)->value->data.user.ttl) < t) {
+                            remove_slot(cache, p TSRMLS_CC);
+                            continue;
+                        }
+                    } else if(cache->ttl) {
+                        if((*p)->creation_time + cache->ttl < t) {
+                            remove_slot(cache, p TSRMLS_CC);
+                            continue;
+                        }
+                    }
+                } else if((*p)->access_time < (t - cache->ttl)) {
+                    remove_slot(cache, p TSRMLS_CC);
+                    continue;
+                }
+                p = &(*p)->next;
+            }
+        }
+
+        if (!apc_sma_get_avail_size(size)) {
+            /* TODO: re-do this to remove goto across locked sections */
+            goto clear_all;
+        }
+        memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
+        cache->header->busy = 0;
+        CACHE_SAFE_UNLOCK(cache);
+    }
+}
+/* }}} */
+
+/* {{{ apc_cache_insert */
+static inline int _apc_cache_insert(apc_cache_t* cache,
+                     apc_cache_key_t key,
+                     apc_cache_entry_t* value,
+                     apc_context_t* ctxt,
+                     time_t t
+                     TSRMLS_DC)
+{
+    slot_t** slot;
+
+    if (!value) {
+        return 0;
+    }
+
+    apc_debug("Inserting [%s]\n" TSRMLS_CC, value->data.file.filename);
+
+    process_pending_removals(cache TSRMLS_CC);
+
+    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
+    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
+
+    while(*slot) {
+      if(key.type == (*slot)->key.type) {
+        if(key.type == APC_CACHE_KEY_FILE) {
+            if(key_equals((*slot)->key.data.file, key.data.file)) {
+                /* If existing slot for the same device+inode is different, remove it and insert the new version */
+                if (ctxt->force_update || (*slot)->key.mtime != key.mtime) {
+                    remove_slot(cache, slot TSRMLS_CC);
+                    break;
+                }
+                return 0;
+            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
+                remove_slot(cache, slot TSRMLS_CC);
+                continue;
+            }
+        } else {   /* APC_CACHE_KEY_FPFILE */
+            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
+                /* Hrm.. it's already here, remove it and insert new one */
+                remove_slot(cache, slot TSRMLS_CC);
+                break;
+            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
+                remove_slot(cache, slot TSRMLS_CC);
+                continue;
+            }
+        }
+      }
+      slot = &(*slot)->next;
+    }
+
+    if ((*slot = make_slot(key, value, *slot, t TSRMLS_CC)) == NULL) {
+        return -1;
+    }
+
+    value->mem_size = ctxt->pool->size;
+    cache->header->mem_size += ctxt->pool->size;
+    cache->header->num_entries++;
+    cache->header->num_inserts++;
+
+    return 1;
+}
+/* }}} */
+
+/* {{{ apc_cache_insert */
+int apc_cache_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t *ctxt, time_t t TSRMLS_DC)
+{
+    int rval;
+    CACHE_LOCK(cache);
+    rval = _apc_cache_insert(cache, key, value, ctxt, t TSRMLS_CC);
+    CACHE_UNLOCK(cache);
+    return rval;
+}
+/* }}} */
+
+/* {{{ apc_cache_insert */
+int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys, apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries TSRMLS_DC)
+{
+    int *rval;
+    int i;
+
+    rval = emalloc(sizeof(int) * num_entries);
+    CACHE_LOCK(cache);
+    for (i=0; i < num_entries; i++) {
+        if (values[i]) {
+            ctxt->pool = values[i]->pool;
+            rval[i] = _apc_cache_insert(cache, keys[i], values[i], ctxt, t TSRMLS_CC);
+        }
+    }
+    CACHE_UNLOCK(cache);
+    return rval;
+}
+/* }}} */
+
+
+/* {{{ apc_cache_user_insert */
+int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC)
+{
+    slot_t** slot;
+    unsigned int keylen = key.data.user.identifier_len;
+    unsigned int h = string_nhash_8(key.data.user.identifier, keylen);
+    apc_keyid_t *lastkey = &cache->header->lastkey;
+    
+    if (!value) {
+        return 0;
+    }
+    
+    if(apc_cache_busy(cache)) {
+        /* cache cleanup in progress, do not wait */ 
+        return 0;
+    }
+
+    if(apc_cache_is_last_key(cache, &key, h, t TSRMLS_CC)) {
+        /* potential cache slam */
+        printf("Last key warning for it!");
+        return 0;
+    }
+
+    CACHE_LOCK(cache);
+
+    memset(lastkey, 0, sizeof(apc_keyid_t));
+
+    lastkey->h = h;
+    lastkey->keylen = keylen;
+    lastkey->mtime = t;
+#ifdef ZTS
+    lastkey->tid = tsrm_thread_id();
+#else
+    lastkey->pid = getpid();
+#endif
+    
+    /* we do not reset lastkey after the insert. Whether it is inserted 
+     * or not, another insert in the same second is always a bad idea. 
+     */
+
+    process_pending_removals(cache TSRMLS_CC);
+    
+    slot = &cache->slots[h % cache->num_slots];
+
+    while (*slot) {
+        if (((*slot)->key.data.user.identifier_len == key.data.user.identifier_len) &&
+            (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, keylen))) {
+            /* 
+             * At this point we have found the user cache entry.  If we are doing 
+             * an exclusive insert (apc_add) we are going to bail right away if
+             * the user entry already exists and it has no ttl, or
+             * there is a ttl and the entry has not timed out yet.
+             */
+            if(exclusive && (  !(*slot)->value->data.user.ttl ||
+                              ( (*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) 
+                            ) ) {
+                goto fail;
+            }
+            remove_slot(cache, slot TSRMLS_CC);
+            break;
+        } else 
+        /* 
+         * This is a bit nasty.  The idea here is to do runtime cleanup of the linked list of
+         * slot entries so we don't always have to skip past a bunch of stale entries.  We check
+         * for staleness here and get rid of them by first checking to see if the cache has a global
+         * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
+         * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
+         */
+        if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || 
+           ((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
+            remove_slot(cache, slot TSRMLS_CC);
+            continue;
+        }
+        slot = &(*slot)->next;
+    }
+
+    if ((*slot = make_slot(key, value, *slot, t TSRMLS_CC)) == NULL) {
+        goto fail;
+    } 
+    
+    value->mem_size = ctxt->pool->size;
+    cache->header->mem_size += ctxt->pool->size;
+
+    cache->header->num_entries++;
+    cache->header->num_inserts++;
+
+    CACHE_UNLOCK(cache);
+
+    return 1;
+
+fail:
+    CACHE_UNLOCK(cache);
+
+    return 0;
+}
+/* }}} */
+
+/* {{{ apc_cache_find_slot */
+slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC)
+{
+    slot_t** slot;
+    volatile slot_t* retval = NULL;
+
+    CACHE_LOCK(cache);
+    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
+    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
+
+    while (*slot) {
+      if(key.type == (*slot)->key.type) {
+        if(key.type == APC_CACHE_KEY_FILE) {
+            if(key_equals((*slot)->key.data.file, key.data.file)) {
+                if((*slot)->key.mtime != key.mtime) {
+                    remove_slot(cache, slot TSRMLS_CC);
+                    cache->header->num_misses++;
+                    CACHE_UNLOCK(cache);
+                    return NULL;
+                }
+                (*slot)->num_hits++;
+                (*slot)->value->ref_count++;
+                (*slot)->access_time = t;
+                prevent_garbage_collection((*slot)->value);
+                cache->header->num_hits++;
+                retval = *slot;
+                CACHE_UNLOCK(cache);
+                return (slot_t*)retval;
+            }
+        } else {  /* APC_CACHE_KEY_FPFILE */
+            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
+                /* TTL Check ? */
+                (*slot)->num_hits++;
+                (*slot)->value->ref_count++;
+                (*slot)->access_time = t;
+                prevent_garbage_collection((*slot)->value);
+                cache->header->num_hits++;
+                retval = *slot;
+                CACHE_UNLOCK(cache);
+                return (slot_t*)retval;
+            }
+        }
+      }
+      slot = &(*slot)->next;
+    }
+    cache->header->num_misses++;
+    CACHE_UNLOCK(cache);
+    return NULL;
+}
+/* }}} */
+
+/* {{{ apc_cache_find */
+apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC)
+{
+    slot_t * slot = apc_cache_find_slot(cache, key, t TSRMLS_CC);
+    return (slot) ? slot->value : NULL;
+}
+/* }}} */
+
+/* {{{ apc_cache_user_find */
+apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC)
+{
+    slot_t** slot;
+    volatile apc_cache_entry_t* value = NULL;
+
+    if(apc_cache_busy(cache))
+    {
+        /* cache cleanup in progress */ 
+        return NULL;
+    }
+
+    CACHE_LOCK(cache);
+
+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
+
+    while (*slot) {
+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
+            /* Check to make sure this entry isn't expired by a hard TTL */
+            if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
+                remove_slot(cache, slot TSRMLS_CC);
+                cache->header->num_misses++;
+                CACHE_UNLOCK(cache);
+                return NULL;
+            }
+            /* Otherwise we are fine, increase counters and return the cache entry */
+            (*slot)->num_hits++;
+            (*slot)->value->ref_count++;
+            (*slot)->access_time = t;
+
+            cache->header->num_hits++;
+            value = (*slot)->value;
+            CACHE_UNLOCK(cache);
+            return (apc_cache_entry_t*)value;
+        }
+        slot = &(*slot)->next;
+    }
+ 
+    cache->header->num_misses++;
+    CACHE_UNLOCK(cache);
+    return NULL;
+}
+/* }}} */
+
+/* {{{ apc_cache_user_exists */
+apc_cache_entry_t* apc_cache_user_exists(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC)
+{
+    slot_t** slot;
+    volatile apc_cache_entry_t* value = NULL;
+
+    if(apc_cache_busy(cache))
+    {
+        /* cache cleanup in progress */ 
+        return NULL;
+    }
+
+    CACHE_LOCK(cache);
+
+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
+
+    while (*slot) {
+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
+            /* Check to make sure this entry isn't expired by a hard TTL */
+            if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
+                CACHE_UNLOCK(cache);
+                return NULL;
+            }
+            /* Return the cache entry ptr */
+            value = (*slot)->value;
+            CACHE_UNLOCK(cache);
+            return (apc_cache_entry_t*)value;
+        }
+        slot = &(*slot)->next;
+    }
+    CACHE_UNLOCK(cache);
+    return NULL;
+}
+/* }}} */
+
+/* {{{ apc_cache_user_update */
+int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, apc_cache_updater_t updater, void* data TSRMLS_DC)
+{
+    slot_t** slot;
+    int retval;
+
+    if(apc_cache_busy(cache))
+    {
+        /* cache cleanup in progress */ 
+        return 0;
+    }
+
+    CACHE_LOCK(cache);
+
+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
+
+    while (*slot) {
+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
+            retval = updater(cache, (*slot)->value, data);
+            (*slot)->key.mtime = apc_time();
+            CACHE_UNLOCK(cache);
+            return retval;
+        }
+        slot = &(*slot)->next;
+    }
+    CACHE_UNLOCK(cache);
+    return 0;
+}
+/* }}} */
+
+/* {{{ apc_cache_user_delete */
+int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC)
+{
+    slot_t** slot;
+
+    CACHE_LOCK(cache);
+
+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
+
+    while (*slot) {
+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
+            remove_slot(cache, slot TSRMLS_CC);
+            CACHE_UNLOCK(cache);
+            return 1;
+        }
+        slot = &(*slot)->next;
+    }
+
+    CACHE_UNLOCK(cache);
+    return 0;
+}
+/* }}} */
+
+/* {{{ apc_cache_delete */
+int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC)
+{
+    slot_t** slot;
+    time_t t;
+    apc_cache_key_t key;
+
+    t = apc_time();
+
+    /* try to create a cache key; if we fail, give up on caching */
+    if (!apc_cache_make_file_key(&key, filename, PG(include_path), t TSRMLS_CC)) {
+        apc_warning("Could not stat file %s, unable to delete from cache." TSRMLS_CC, filename);
+        return -1;
+    }
+
+    CACHE_LOCK(cache);
+
+    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
+    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
+
+    while(*slot) {
+      if(key.type == (*slot)->key.type) {
+        if(key.type == APC_CACHE_KEY_FILE) {
+            if(key_equals((*slot)->key.data.file, key.data.file)) {
+                remove_slot(cache, slot TSRMLS_CC);
+                CACHE_UNLOCK(cache);
+                return 1;
+            }
+        } else {   /* APC_CACHE_KEY_FPFILE */
+            if(((*slot)->key.data.fpfile.fullpath_len == key.data.fpfile.fullpath_len) &&
+                (!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1))) {
+                remove_slot(cache, slot TSRMLS_CC);
+                CACHE_UNLOCK(cache);
+                return 1;
+            }
+        }
+      }
+      slot = &(*slot)->next;
+    }
+    
+    memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
+    
+    CACHE_UNLOCK(cache);
+    return 0;
+
+}
+/* }}} */
+
+/* {{{ apc_cache_release */
+void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry TSRMLS_DC)
+{
+    CACHE_LOCK(cache);
+    entry->ref_count--;
+    CACHE_UNLOCK(cache);
+}
+/* }}} */
+
+/* {{{ apc_cache_make_file_key */
+int apc_cache_make_file_key(apc_cache_key_t* key,
+                       const char* filename,
+                       const char* include_path,
+                       time_t t
+                       TSRMLS_DC)
+{
+    struct stat *tmp_buf=NULL;
+    struct apc_fileinfo_t *fileinfo = NULL;
+    int len;
+
+    assert(key != NULL);
+
+    if (!filename || !SG(request_info).path_translated) {
+        apc_debug("No filename and no path_translated - bailing\n" TSRMLS_CC);
+        goto cleanup;
+    }
+
+    len = strlen(filename);
+    if(APCG(fpstat)==0) {
+        if(IS_ABSOLUTE_PATH(filename,len)) {
+            key->data.fpfile.fullpath = filename;
+            key->data.fpfile.fullpath_len = len;
+            key->mtime = t;
+            key->type = APC_CACHE_KEY_FPFILE;
+            goto success;
+        } else if(APCG(canonicalize)) {
+
+            fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
+
+            if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) {
+                apc_warning("apc failed to locate %s - bailing" TSRMLS_CC, filename);
+                goto cleanup;
+            }
+
+            if(!VCWD_REALPATH(fileinfo->fullpath, APCG(canon_path))) {
+                apc_warning("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename);
+                goto cleanup;
+            }
+
+            key->data.fpfile.fullpath = APCG(canon_path);
+            key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
+            key->mtime = t;
+            key->type = APC_CACHE_KEY_FPFILE;
+            goto success;
+        }
+        /* fall through to stat mode */
+    }
+
+    fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
+
+    assert(fileinfo != NULL);
+
+    if(!strcmp(SG(request_info).path_translated, 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(filename, include_path, fileinfo TSRMLS_CC) != 0) {
+            apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC, filename,SG(request_info).path_translated);
+            goto cleanup;
+        }
+    }
+
+    if(APCG(max_file_size) < fileinfo->st_buf.sb.st_size) {
+        apc_debug("File is too big %s (%d - %ld) - bailing\n" TSRMLS_CC, filename,t,fileinfo->st_buf.sb.st_size);
+        goto cleanup;
+    }
+
+    /*
+     * 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.  This is now
+     * configurable, but the default is still 2 seconds.
+     */
+    if(APCG(file_update_protection) && (t - fileinfo->st_buf.sb.st_mtime < APCG(file_update_protection)) && !APCG(force_file_update)) {
+        apc_debug("File is too new %s (%d - %d) - bailing\n" TSRMLS_CC,filename,t,fileinfo->st_buf.sb.st_mtime);
+        goto cleanup;
+    }
+
+    key->data.file.device = fileinfo->st_buf.sb.st_dev;
+    key->data.file.inode  = fileinfo->st_buf.sb.st_ino;
+
+    /*
+     * If working with content management systems that like to munge the mtime, 
+     * it might be appropriate to key off of the ctime to be immune to systems
+     * that try to backdate a template.  If the mtime is set to something older
+     * than the previous mtime of a template we will obviously never see this
+     * "older" template.  At some point the Smarty templating system did this.
+     * I generally disagree with using the ctime here because you lose the 
+     * ability to warm up new content by saving it to a temporary file, hitting
+     * it once to cache it and then renaming it into its permanent location so
+     * set the apc.stat_ctime=true to enable this check.
+     */
+    if(APCG(stat_ctime)) {
+        key->mtime  = (fileinfo->st_buf.sb.st_ctime > fileinfo->st_buf.sb.st_mtime) ? fileinfo->st_buf.sb.st_ctime : fileinfo->st_buf.sb.st_mtime; 
+    } else {
+        key->mtime = fileinfo->st_buf.sb.st_mtime;
+    }
+    key->type = APC_CACHE_KEY_FILE;
+
+success: 
+
+    if(fileinfo != NULL) {
+        apc_php_free(fileinfo TSRMLS_CC);
+    }
+
+    return 1;
+
+cleanup:
+    
+    if(fileinfo != NULL) {
+        apc_php_free(fileinfo TSRMLS_CC);
+    }
+
+    return 0;
+}
+/* }}} */
+
+/* {{{ apc_cache_make_user_key */
+int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
+{
+    assert(key != NULL);
+
+    if (!identifier)
+        return 0;
+
+    key->data.user.identifier = identifier;
+    key->data.user.identifier_len = identifier_len;
+    key->mtime = t;
+    key->type = APC_CACHE_KEY_USER;
+    return 1;
+}
+/* }}} */
+
+/* {{{ apc_cache_make_file_entry */
+apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
+                                        zend_op_array* op_array,
+                                        apc_function_t* functions,
+                                        apc_class_t* classes,
+                                        apc_context_t* ctxt
+                                        TSRMLS_DC)
+{
+    apc_cache_entry_t* entry;
+    apc_pool* pool = ctxt->pool;
+
+    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
+    if (!entry) return NULL;
+
+    entry->data.file.filename  = apc_pstrdup(filename, pool TSRMLS_CC);
+    if(!entry->data.file.filename) {
+        apc_debug("apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n" TSRMLS_CC);
+        return NULL;
+    }
+    apc_debug("apc_cache_make_file_entry: entry->data.file.filename is [%s]\n" TSRMLS_CC,entry->data.file.filename);
+    entry->data.file.op_array  = op_array;
+    entry->data.file.functions = functions;
+    entry->data.file.classes   = classes;
+
+    entry->data.file.halt_offset = apc_file_halt_offset(filename TSRMLS_CC);
+
+    entry->type = APC_CACHE_ENTRY_FILE;
+    entry->ref_count = 0;
+    entry->mem_size = 0;
+    entry->pool = pool;
+    return entry;
+}
+/* }}} */
+
+/* {{{ apc_cache_store_zval */
+zval* apc_cache_store_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    if (Z_TYPE_P(src) == IS_ARRAY) {
+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
+        zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
+        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
+        zend_hash_destroy(&APCG(copied_zvals));
+        APCG(copied_zvals).nTableSize=0;
+    } else {
+        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
+    }
+
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_cache_fetch_zval */
+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    if (Z_TYPE_P(src) == IS_ARRAY) {
+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
+        zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
+        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
+        zend_hash_destroy(&APCG(copied_zvals));
+        APCG(copied_zvals).nTableSize=0;
+    } else {
+        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
+    }
+
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_cache_make_user_entry */
+apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, apc_context_t* ctxt, const unsigned int ttl TSRMLS_DC)
+{
+    apc_cache_entry_t* entry;
+    apc_pool* pool = ctxt->pool;
+
+    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
+    if (!entry) return NULL;
+
+    entry->data.user.info = apc_pmemcpy(info, info_len, pool TSRMLS_CC);
+    entry->data.user.info_len = info_len;
+    if(!entry->data.user.info) {
+        return NULL;
+    }
+    entry->data.user.val = apc_cache_store_zval(NULL, val, ctxt TSRMLS_CC);
+    if(!entry->data.user.val) {
+        return NULL;
+    }
+    INIT_PZVAL(entry->data.user.val);
+    entry->data.user.ttl = ttl;
+    entry->type = APC_CACHE_ENTRY_USER;
+    entry->ref_count = 0;
+    entry->mem_size = 0;
+    entry->pool = pool;
+    return entry;
+}
+/* }}} */
+
+/* {{{ apc_cache_info */
+apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited TSRMLS_DC)
+{
+    apc_cache_info_t* info;
+    slot_t* p;
+    int i;
+
+    if(!cache) return NULL;
+
+    CACHE_LOCK(cache);
+
+    info = (apc_cache_info_t*) apc_php_malloc(sizeof(apc_cache_info_t) TSRMLS_CC);
+    if(!info) {
+        CACHE_UNLOCK(cache);
+        return NULL;
+    }
+    info->num_slots = cache->num_slots;
+    info->ttl = cache->ttl;
+    info->num_hits = cache->header->num_hits;
+    info->num_misses = cache->header->num_misses;
+    info->list = NULL;
+    info->deleted_list = NULL;
+    info->start_time = cache->header->start_time;
+    info->expunges = cache->header->expunges;
+    info->mem_size = cache->header->mem_size;
+    info->num_entries = cache->header->num_entries;
+    info->num_inserts = cache->header->num_inserts;
+
+    if(!limited) {
+        /* For each hashtable slot */
+        for (i = 0; i < info->num_slots; i++) {
+            p = cache->slots[i];
+            for (; p != NULL; p = p->next) {
+                apc_cache_link_t* link = (apc_cache_link_t*) apc_php_malloc(sizeof(apc_cache_link_t) TSRMLS_CC);
+
+                if(p->value->type == APC_CACHE_ENTRY_FILE) {
+                    if(p->key.type == APC_CACHE_KEY_FILE) {
+                        link->data.file.device = p->key.data.file.device;
+                        link->data.file.inode = p->key.data.file.inode;
+                        link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_php_malloc TSRMLS_CC);
+                    } else { /* This is a no-stat fullpath file entry */
+                        link->data.file.device = 0;
+                        link->data.file.inode = 0;
+                        link->data.file.filename = apc_xstrdup(p->key.data.fpfile.fullpath, apc_php_malloc TSRMLS_CC);
+                    }
+                    link->type = APC_CACHE_ENTRY_FILE;
+                    if (APCG(file_md5)) {
+                      link->data.file.md5 = emalloc(sizeof(p->key.md5));
+                      memcpy(link->data.file.md5, p->key.md5, 16);
+                    } else {
+                      link->data.file.md5 = NULL;
+                    }
+                } else if(p->value->type == APC_CACHE_ENTRY_USER) {
+                    link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len+1, apc_php_malloc TSRMLS_CC);
+                    link->data.user.ttl = p->value->data.user.ttl;
+                    link->type = APC_CACHE_ENTRY_USER;
+                }
+                link->num_hits = p->num_hits;
+                link->mtime = p->key.mtime;
+                link->creation_time = p->creation_time;
+                link->deletion_time = p->deletion_time;
+                link->access_time = p->access_time;
+                link->ref_count = p->value->ref_count;
+                link->mem_size = p->value->mem_size;
+                link->next = info->list;
+                info->list = link;
+            }
+        }
+
+        /* For each slot pending deletion */
+        for (p = cache->header->deleted_list; p != NULL; p = p->next) {
+            apc_cache_link_t* link = (apc_cache_link_t*) apc_php_malloc(sizeof(apc_cache_link_t) TSRMLS_CC);
+
+            if(p->value->type == APC_CACHE_ENTRY_FILE) {
+                if(p->key.type == APC_CACHE_KEY_FILE) {
+                    link->data.file.device = p->key.data.file.device;
+                    link->data.file.inode = p->key.data.file.inode;
+                    link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_php_malloc TSRMLS_CC);
+                } else { /* This is a no-stat fullpath file entry */
+                    link->data.file.device = 0;
+                    link->data.file.inode = 0;
+                    link->data.file.filename = apc_xstrdup(p->key.data.fpfile.fullpath, apc_php_malloc TSRMLS_CC);
+                }
+                link->type = APC_CACHE_ENTRY_FILE;
+                if (APCG(file_md5)) {
+                  link->data.file.md5 = emalloc(sizeof(p->key.md5));
+                  memcpy(link->data.file.md5, p->key.md5, 16);
+                } else {
+                  link->data.file.md5 = NULL;
+                }
+            } else if(p->value->type == APC_CACHE_ENTRY_USER) {
+                link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len+1, apc_php_malloc TSRMLS_CC);
+                link->data.user.ttl = p->value->data.user.ttl;
+                link->type = APC_CACHE_ENTRY_USER;
+            }
+            link->num_hits = p->num_hits;
+            link->mtime = p->key.mtime;
+            link->creation_time = p->creation_time;
+            link->deletion_time = p->deletion_time;
+            link->access_time = p->access_time;
+            link->ref_count = p->value->ref_count;
+            link->mem_size = p->value->mem_size;
+            link->next = info->deleted_list;
+            info->deleted_list = link;
+        }
+    }
+
+    CACHE_UNLOCK(cache);
+    return info;
+}
+/* }}} */
+
+/* {{{ apc_cache_free_info */
+void apc_cache_free_info(apc_cache_info_t* info TSRMLS_DC)
+{
+    apc_cache_link_t* p = info->list;
+    apc_cache_link_t* q = NULL;
+    while (p != NULL) {
+        q = p;
+        p = p->next;
+        if(q->type == APC_CACHE_ENTRY_FILE) {
+            if(q->data.file.md5) {
+                efree(q->data.file.md5);
+            }
+            apc_php_free(q->data.file.filename TSRMLS_CC);
+        }
+        else if(q->type == APC_CACHE_ENTRY_USER) apc_php_free(q->data.user.info TSRMLS_CC);
+        apc_php_free(q TSRMLS_CC);
+    }
+    p = info->deleted_list;
+    while (p != NULL) {
+        q = p;
+        p = p->next;
+        if(q->type == APC_CACHE_ENTRY_FILE) {
+            if(q->data.file.md5) {
+                efree(q->data.file.md5);
+            }
+            apc_php_free(q->data.file.filename TSRMLS_CC);
+        }
+        else if(q->type == APC_CACHE_ENTRY_USER) apc_php_free(q->data.user.info TSRMLS_CC);
+        apc_php_free(q TSRMLS_CC);
+    }
+    apc_php_free(info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_cache_unlock */
+void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC)
+{
+    CACHE_UNLOCK(cache);
+}
+/* }}} */
+
+/* {{{ apc_cache_busy */
+zend_bool apc_cache_busy(apc_cache_t* cache)
+{
+    return cache->header->busy;
+}
+/* }}} */
+
+/* {{{ apc_cache_is_last_key */
+zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, unsigned int h, time_t t TSRMLS_DC)
+{
+    apc_keyid_t *lastkey = &cache->header->lastkey;
+    unsigned int keylen = key->data.user.identifier_len;
+#ifdef ZTS
+    THREAD_T tid = tsrm_thread_id();
+    #define FROM_DIFFERENT_THREAD(k) (memcmp(&((k)->tid), &tid, sizeof(THREAD_T))!=0)
+#else
+    pid_t pid = getpid();
+    #define FROM_DIFFERENT_THREAD(k) (pid != (k)->pid) 
+#endif
+
+
+    if(!h) h = string_nhash_8(key->data.user.identifier, keylen);
+
+    /* unlocked reads, but we're not shooting for 100% success with this */
+    if(lastkey->h == h && keylen == lastkey->keylen) {
+        if(lastkey->mtime == t && FROM_DIFFERENT_THREAD(lastkey)) {
+            /* potential cache slam */
+            if(APCG(slam_defense)) {
+                apc_warning("Potential cache slam averted for key '%s'" TSRMLS_CC, key->data.user.identifier);
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+/* }}} */
+
+#if NONBLOCKING_LOCK_AVAILABLE
+/* {{{ apc_cache_write_lock */
+zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC)
+{
+    return apc_lck_nb_lock(cache->header->wrlock);
+}
+/* }}} */
+
+/* {{{ apc_cache_write_unlock */
+void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC)
+{
+    apc_lck_unlock(cache->header->wrlock);
+}
+/* }}} */
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_cache.h
@@ -0,0 +1,403 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>                             |
+  +----------------------------------------------------------------------+
+
+   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_cache.h 305258 2010-11-10 19:02:06Z gopalv $ */
+
+#ifndef APC_CACHE_H
+#define APC_CACHE_H
+
+/*
+ * This module defines the shared memory file cache. Basically all of the
+ * logic for storing and retrieving cache entries lives here.
+ */
+
+#include "apc.h"
+#include "apc_compile.h"
+#include "apc_lock.h"
+#include "apc_pool.h"
+#include "apc_main.h"
+#include "TSRM.h"
+
+#define APC_CACHE_ENTRY_FILE   1
+#define APC_CACHE_ENTRY_USER   2
+
+#define APC_CACHE_KEY_FILE     1
+#define APC_CACHE_KEY_USER     2
+#define APC_CACHE_KEY_FPFILE   3
+
+#ifdef PHP_WIN32
+typedef unsigned __int64 apc_ino_t;
+typedef unsigned __int64 apc_dev_t;
+#else
+typedef ino_t apc_ino_t;
+typedef dev_t apc_dev_t;
+#endif
+
+/* {{{ cache locking macros */
+#define CACHE_LOCK(cache)        { LOCK(cache->header->lock);   cache->has_lock = 1; }
+#define CACHE_UNLOCK(cache)      { UNLOCK(cache->header->lock); cache->has_lock = 0; }
+#define CACHE_SAFE_LOCK(cache)   { if ((++cache->has_lock) == 1) LOCK(cache->header->lock); }
+#define CACHE_SAFE_UNLOCK(cache) { if ((--cache->has_lock) == 0) UNLOCK(cache->header->lock); }
+/* }}} */
+
+/* {{{ struct definition: apc_cache_key_t */
+#define T apc_cache_t*
+typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
+
+typedef union _apc_cache_key_data_t {
+    struct {
+        apc_dev_t device;             /* the filesystem device */
+        apc_ino_t inode;              /* the filesystem inode */
+    } file;
+    struct {
+        const char *identifier;
+        int identifier_len;
+    } user;
+    struct {
+        const char *fullpath;
+        int fullpath_len;
+    } fpfile;
+} apc_cache_key_data_t;
+
+typedef struct apc_cache_key_t apc_cache_key_t;
+struct apc_cache_key_t {
+    apc_cache_key_data_t data;
+    time_t mtime;                 /* the mtime of this cached entry */
+    unsigned char type;
+    unsigned char md5[16];        /* md5 hash of the source file */
+};
+
+
+typedef struct apc_keyid_t apc_keyid_t;
+
+struct apc_keyid_t {
+    unsigned int h;
+    unsigned int keylen;
+    time_t mtime;
+#ifdef ZTS
+    THREAD_T tid;
+#else
+    pid_t pid;
+#endif
+};
+/* }}} */
+
+/* {{{ struct definition: apc_cache_entry_t */
+typedef union _apc_cache_entry_value_t {
+    struct {
+        char *filename;             /* absolute path to source file */
+        zend_op_array* op_array;    /* op_array allocated in shared memory */
+        apc_function_t* functions;  /* array of apc_function_t's */
+        apc_class_t* classes;       /* array of apc_class_t's */
+        long halt_offset;           /* value of __COMPILER_HALT_OFFSET__ for the file */
+    } file;
+    struct {
+        char *info;
+        int info_len;
+        zval *val;
+        unsigned int ttl;
+    } user;
+} apc_cache_entry_value_t;
+
+typedef struct apc_cache_entry_t apc_cache_entry_t;
+struct apc_cache_entry_t {
+    apc_cache_entry_value_t data;
+    unsigned char type;
+    int ref_count;
+    size_t mem_size;
+    apc_pool *pool;
+};
+/* }}} */
+
+/*
+ * apc_cache_create creates the shared memory compiler cache. This function
+ * should be called just once (ideally in the web server parent process, e.g.
+ * in apache), otherwise you will end up with multiple caches (which won't
+ * necessarily break anything). Returns a pointer to the cache object.
+ *
+ * size_hint is a "hint" at the total number of source files that will be
+ * cached. It determines the physical size of the hash table. Passing 0 for
+ * this argument will use a reasonable default value.
+ *
+ * gc_ttl is the maximum time a cache entry may speed on the garbage
+ * collection list. This is basically a work around for the inherent
+ * unreliability of our reference counting mechanism (see apc_cache_release).
+ *
+ * ttl is the maximum time a cache entry can idle in a slot in case the slot
+ * is needed.  This helps in cleaning up the cache and ensuring that entries 
+ * hit frequently stay cached and ones not hit very often eventually disappear.
+ */
+extern T apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC);
+
+/*
+ * apc_cache_destroy releases any OS resources associated with a cache object.
+ * Under apache, this function can be safely called by the child processes
+ * when they exit.
+ */
+extern void apc_cache_destroy(T cache TSRMLS_DC);
+
+/*
+ * apc_cache_clear empties a cache. This can safely be called at any time,
+ * even while other server processes are executing cached source files.
+ */
+extern void apc_cache_clear(T cache TSRMLS_DC);
+
+/*
+ * apc_cache_insert adds an entry to the cache, using a filename as a key.
+ * Internally, the filename is translated to a canonical representation, so
+ * that relative and absolute filenames will map to a single key. Returns
+ * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
+ * returned, the caller must free the cache entry by calling
+ * apc_cache_free_entry (see below).
+ *
+ * key is the value created by apc_cache_make_file_key for file keys.
+ *
+ * value is a cache entry returned by apc_cache_make_entry (see below).
+ */
+extern int apc_cache_insert(T cache, apc_cache_key_t key,
+                            apc_cache_entry_t* value, apc_context_t* ctxt, time_t t TSRMLS_DC);
+
+extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
+                            apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC);
+
+extern int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys,
+                            apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries TSRMLS_DC);
+
+/*
+ * apc_cache_find searches for a cache entry by filename, and returns a
+ * pointer to the entry if found, NULL otherwise.
+ *
+ * key is a value created by apc_cache_make_file_key for file keys.
+ */
+extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t TSRMLS_DC);
+
+/*
+ * apc_cache_user_find searches for a cache entry by its hashed identifier,
+ * and returns a pointer to the entry if found, NULL otherwise.
+ *
+ */
+extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
+
+/*
+ * apc_cache_user_exists searches for a cache entry by its hashed identifier,
+ * and returns a pointer to the entry if found, NULL otherwise.  This is a
+ * quick non-locking version of apc_cache_user_find that does not modify the
+ * shared memory segment in any way.
+ *
+ */
+extern apc_cache_entry_t* apc_cache_user_exists(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
+
+/*
+ * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it.
+ */
+extern int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC);
+extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC);
+
+/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
+ * zval from it.
+ *
+ */
+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC);
+
+/*
+ * apc_cache_release decrements the reference count associated with a cache
+ * entry. Calling apc_cache_find automatically increments the reference count,
+ * and this function must be called post-execution to return the count to its
+ * original value. Failing to do so will prevent the entry from being
+ * garbage-collected.
+ *
+ * entry is the cache entry whose ref count you want to decrement.
+ */
+extern void apc_cache_release(T cache, apc_cache_entry_t* entry TSRMLS_DC);
+
+/*
+ * apc_cache_make_file_key creates a key object given a relative or absolute
+ * filename and an optional list of auxillary paths to search. include_path is
+ * searched if the filename cannot be found relative to the current working
+ * directory.
+ *
+ * key points to caller-allocated storage (must not be null).
+ *
+ * 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,
+                                   time_t t
+                                   TSRMLS_DC);
+
+/*
+ * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
+ * and the compilation results returned by the PHP compiler.
+ */
+extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
+                                                    zend_op_array* op_array,
+                                                    apc_function_t* functions,
+                                                    apc_class_t* classes,
+                                                    apc_context_t* ctxt
+						    TSRMLS_DC);
+
+
+zend_bool apc_compile_cache_entry(apc_cache_key_t key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array_pp, apc_cache_entry_t** cache_entry_pp TSRMLS_DC);
+
+/*
+ * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
+ * and the zval to be stored.
+ */
+extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, apc_context_t* ctxt, const unsigned int ttl TSRMLS_DC);
+
+extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
+
+/* {{{ struct definition: apc_cache_link_data_t */
+typedef union _apc_cache_link_data_t {
+    struct {
+        char *filename;
+        apc_ino_t device;
+        apc_dev_t inode;
+        unsigned char *md5;
+    } file;
+    struct {
+        char *info;
+        unsigned int ttl;
+    } user;
+} apc_cache_link_data_t;
+/* }}} */
+
+/* {{{ struct definition: apc_cache_link_t */
+typedef struct apc_cache_link_t apc_cache_link_t;
+struct apc_cache_link_t {
+    apc_cache_link_data_t data;
+    unsigned char type;
+    unsigned long num_hits;
+    time_t mtime;
+    time_t creation_time;
+    time_t deletion_time;
+    time_t access_time;
+    int ref_count;
+    size_t mem_size;
+    apc_cache_link_t* next;
+};
+/* }}} */
+
+
+/* {{{ struct definition: apc_cache_info_t */
+typedef struct apc_cache_info_t apc_cache_info_t;
+struct apc_cache_info_t {
+    int num_slots;
+    unsigned long num_hits;
+    unsigned long num_misses;
+    unsigned long num_inserts;
+    unsigned long expunges;
+    int ttl;
+    apc_cache_link_t* list;
+    apc_cache_link_t* deleted_list;
+    time_t start_time;
+    int num_entries;
+    size_t mem_size;
+};
+/* }}} */
+
+/* {{{ struct definition: slot_t */
+typedef struct slot_t slot_t;
+struct slot_t {
+    apc_cache_key_t key;        /* slot key */
+    apc_cache_entry_t* value;   /* slot value */
+    slot_t* next;               /* next slot in linked list */
+    unsigned long num_hits;     /* number of hits to this bucket */
+    time_t creation_time;       /* time slot was initialized */
+    time_t deletion_time;       /* time slot was removed from cache */
+    time_t access_time;         /* time slot was last accessed */
+};
+/* }}} */
+
+/* {{{ struct definition: cache_header_t
+   Any values that must be shared among processes should go in here. */
+typedef struct cache_header_t cache_header_t;
+struct cache_header_t {
+    apc_lck_t lock;             /* read/write lock (exclusive blocking cache lock) */
+    apc_lck_t wrlock;           /* write lock (non-blocking used to prevent cache slams) */
+    unsigned long num_hits;     /* total successful hits in cache */
+    unsigned long num_misses;   /* total unsuccessful hits in cache */
+    unsigned long num_inserts;  /* total successful inserts in cache */
+    unsigned long expunges;     /* total number of expunges */
+    slot_t* deleted_list;       /* linked list of to-be-deleted slots */
+    time_t start_time;          /* time the above counters were reset */
+    zend_bool busy;             /* Flag to tell clients when we are busy cleaning the cache */
+    int num_entries;            /* Statistic on the number of entries */
+    size_t mem_size;            /* Statistic on the memory size used by this cache */
+    apc_keyid_t lastkey;        /* the key that is being inserted (user cache) */
+};
+/* }}} */
+
+typedef void (*apc_expunge_cb_t)(T cache, size_t n TSRMLS_DC); 
+
+/* {{{ struct definition: apc_cache_t */
+struct apc_cache_t {
+    void* shmaddr;                /* process (local) address of shared cache */
+    cache_header_t* header;       /* cache header (stored in SHM) */
+    slot_t** slots;               /* array of cache slots (stored in SHM) */
+    int num_slots;                /* number of slots in cache */
+    int gc_ttl;                   /* maximum time on GC list for a slot */
+    int ttl;                      /* if slot is needed and entry's access time is older than this ttl, remove it */
+    apc_expunge_cb_t expunge_cb;  /* cache specific expunge callback to free up sma memory */
+    uint has_lock;                /* flag for possible recursive locks within the same process */
+};
+/* }}} */
+
+extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited TSRMLS_DC);
+extern void apc_cache_free_info(apc_cache_info_t* info TSRMLS_DC);
+extern void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC);
+extern zend_bool apc_cache_busy(apc_cache_t* cache);
+extern zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC);
+extern void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC);
+extern zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, unsigned int h, time_t t TSRMLS_DC);
+
+/* used by apc_rfc1867 to update data in-place - not to be used elsewhere */
+
+typedef int (*apc_cache_updater_t)(apc_cache_t*, apc_cache_entry_t*, void* data);
+extern int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen,
+                                    apc_cache_updater_t updater, void* data TSRMLS_DC);
+
+
+#undef T
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_compile.c
@@ -0,0 +1,2102 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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_compile.c 303796 2010-09-27 17:14:18Z gopalv $ */
+
+#include "apc_compile.h"
+#include "apc_globals.h"
+#include "apc_zend.h"
+#include "apc_string.h"
+#include "ext/standard/php_var.h"
+#include "ext/standard/php_smart_str.h"
+
+#ifndef IS_CONSTANT_TYPE_MASK
+#define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
+#endif
+
+typedef void* (*ht_copy_fun_t)(void*, void*, apc_context_t* TSRMLS_DC);
+//typedef void  (*ht_free_fun_t)(void*, apc_context_t*);
+typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
+
+typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
+
+#define CHECK(p) { if ((p) == NULL) return NULL; }
+
+/* {{{ internal function declarations */
+
+static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC);
+
+/*
+ * The "copy" functions perform deep-copies on a particular data structure
+ * (passed as the second argument). They also optionally allocate space for
+ * the destination data structure if the first argument is null.
+ */
+static zval** my_copy_zval_ptr(zval**, const zval**, apc_context_t* TSRMLS_DC);
+static zval* my_copy_zval(zval*, const zval*, apc_context_t* TSRMLS_DC);
+static znode* my_copy_znode(znode*, znode*, apc_context_t* TSRMLS_DC);
+static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_context_t* TSRMLS_DC);
+static zend_function* my_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC);
+static zend_function_entry* my_copy_function_entry(zend_function_entry*, const zend_function_entry*, apc_context_t* TSRMLS_DC);
+static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_context_t* TSRMLS_DC);
+static HashTable* my_copy_hashtable_ex(HashTable*, HashTable* TSRMLS_DC, ht_copy_fun_t, int, apc_context_t*, ht_check_copy_fun_t, ...);
+#define my_copy_hashtable( dst, src, copy_fn, holds_ptr, ctxt) \
+    my_copy_hashtable_ex(dst, src TSRMLS_CC, copy_fn, holds_ptr, ctxt, NULL)
+static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* TSRMLS_DC);
+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* TSRMLS_DC);
+static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, const zend_arg_info*, uint, apc_context_t* TSRMLS_DC);
+static zend_arg_info* my_copy_arg_info(zend_arg_info*, const zend_arg_info*, apc_context_t* TSRMLS_DC);
+
+/*
+ * The "fixup" functions need for ZEND_ENGINE_2
+ */
+static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
+static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
+/* my_fixup_function_for_execution is the same as my_fixup_function
+ * but named differently for clarity
+ */
+#define my_fixup_function_for_execution my_fixup_function
+
+#ifdef ZEND_ENGINE_2_2
+static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
+#define my_fixup_property_info_for_execution my_fixup_property_info
+#endif
+
+/*
+ * These functions return "1" if the member/function is
+ * defined/overridden in the 'current' class and not inherited.
+ */
+static int my_check_copy_function(Bucket* src, va_list args);
+static int my_check_copy_default_property(Bucket* p, va_list args);
+static int my_check_copy_property_info(Bucket* src, va_list args);
+static int my_check_copy_static_member(Bucket* src, va_list args);
+static int my_check_copy_constant(Bucket* src, va_list args);
+
+/* }}} */
+
+/* {{{ check_op_array_integrity */
+#if 0
+static void check_op_array_integrity(zend_op_array* src)
+{
+    int i, j;
+
+    /* These sorts of checks really aren't particularly effective, but they
+     * can provide a welcome sanity check when debugging. Just don't enable
+     * for production use!  */
+
+    assert(src->refcount != NULL);
+    assert(src->opcodes != NULL);
+    assert(src->last > 0);
+
+    for (i = 0; i < src->last; i++) {
+        zend_op* op = &src->opcodes[i];
+        znode* nodes[] = { &op->result, &op->op1, &op->op2 };
+        for (j = 0; j < 3; j++) {
+            assert(nodes[j]->op_type == IS_CONST ||
+                   nodes[j]->op_type == IS_VAR ||
+                   nodes[j]->op_type == IS_TMP_VAR ||
+                   nodes[j]->op_type == IS_UNUSED);
+
+            if (nodes[j]->op_type == IS_CONST) {
+                int type = nodes[j]->u.constant.type;
+                assert(type == IS_RESOURCE ||
+                       type == IS_BOOL ||
+                       type == IS_LONG ||
+                       type == IS_DOUBLE ||
+                       type == IS_NULL ||
+                       type == IS_CONSTANT ||
+                       type == IS_STRING ||
+                       type == FLAG_IS_BC ||
+                       type == IS_ARRAY ||
+                       type == IS_CONSTANT_ARRAY ||
+                       type == IS_OBJECT);
+            }
+        }
+    }
+}
+#endif
+/* }}} */
+
+/* {{{ my_bitwise_copy_function */
+static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_function*) apc_pool_alloc(pool, sizeof(src[0])));
+    }
+
+    /* We only need to do a bitwise copy */
+    memcpy(dst, src, sizeof(src[0]));
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_zval_ptr */
+static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_context_t* ctxt TSRMLS_DC)
+{
+    zval* dst_new;
+    apc_pool* pool = ctxt->pool;
+    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zval**) apc_pool_alloc(pool, sizeof(zval*)));
+    }
+
+    if(usegc) {
+        ALLOC_ZVAL(dst[0]);
+        CHECK(dst[0]);
+    } else {
+        CHECK((dst[0] = (zval*) apc_pool_alloc(pool, sizeof(zval))));
+    }
+
+    CHECK((dst_new = my_copy_zval(*dst, *src, ctxt TSRMLS_CC)));
+
+    if(dst_new != *dst) {
+        if(usegc) {
+            FREE_ZVAL(dst[0]);
+        }
+        *dst = dst_new;
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_serialize_object */
+static zval* my_serialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    smart_str buf = {0};
+    php_serialize_data_t var_hash;
+    apc_pool* pool = ctxt->pool;
+
+    PHP_VAR_SERIALIZE_INIT(var_hash);
+    php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
+    PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+    if(buf.c) {
+        dst->type = src->type & ~IS_CONSTANT_INDEX;
+        dst->value.str.len = buf.len;
+        CHECK(dst->value.str.val = apc_pmemcpy(buf.c, (buf.len + 1), pool TSRMLS_CC));
+        dst->type = src->type;
+        smart_str_free(&buf);
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_unserialize_object */
+static zval* my_unserialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    php_unserialize_data_t var_hash;
+    const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
+
+    PHP_VAR_UNSERIALIZE_INIT(var_hash);
+    if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
+        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+        zval_dtor(dst);
+        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
+        dst->type = IS_NULL;
+    }
+    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+    return dst;
+}
+/* }}} */
+
+static char *apc_string_pmemcpy(char *str, size_t len, apc_pool* pool TSRMLS_DC)
+{	
+#ifdef ZEND_ENGINE_2_4
+    if (pool->type != APC_UNPOOL) {
+        char * ret = apc_new_interned_string(str, len TSRMLS_CC);
+        if (ret) {
+            return ret;
+        }
+    }
+#endif
+    return apc_pmemcpy(str, len, pool TSRMLS_CC);
+}
+
+/* {{{ my_copy_zval */
+static zval* my_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    zval **tmp;
+    apc_pool* pool = ctxt->pool;
+
+    assert(dst != NULL);
+    assert(src != NULL);
+
+    memcpy(dst, src, sizeof(src[0]));
+
+    if(APCG(copied_zvals).nTableSize) {
+        if(zend_hash_index_find(&APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
+            if(Z_ISREF_P((zval*)src)) {
+                Z_SET_ISREF_PP(tmp);
+            }
+            Z_ADDREF_PP(tmp);
+            return *tmp;
+        }
+
+        zend_hash_index_update(&APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
+    }
+
+
+    if(ctxt->copy == APC_COPY_OUT_USER || ctxt->copy == APC_COPY_IN_USER) {
+        /* deep copies are refcount(1), but moved up for recursive 
+         * arrays,  which end up being add_ref'd during its copy. */
+        Z_SET_REFCOUNT_P(dst, 1);
+        Z_UNSET_ISREF_P(dst);
+    } else {
+        /* code uses refcount=2 for consts */
+        Z_SET_REFCOUNT_P(dst, Z_REFCOUNT_P((zval*)src));
+        Z_SET_ISREF_TO_P(dst, Z_ISREF_P((zval*)src));
+    }
+
+    switch (src->type & IS_CONSTANT_TYPE_MASK) {
+    case IS_RESOURCE:
+    case IS_BOOL:
+    case IS_LONG:
+    case IS_DOUBLE:
+    case IS_NULL:
+        break;
+
+    case IS_CONSTANT:
+    case IS_STRING:
+        if (src->value.str.val) {
+            CHECK(dst->value.str.val = apc_string_pmemcpy(src->value.str.val,
+                                                   src->value.str.len+1,
+                                                   pool TSRMLS_CC));
+        }
+        break;
+
+    case IS_ARRAY:
+    case IS_CONSTANT_ARRAY:
+
+        CHECK(dst->value.ht =
+            my_copy_hashtable(NULL,
+                              src->value.ht,
+                              (ht_copy_fun_t) my_copy_zval_ptr,
+                              1,
+                              ctxt));
+        break;
+
+    case IS_OBJECT:
+    
+        dst->type = IS_NULL;
+        if(ctxt->copy == APC_COPY_IN_USER) {
+            dst = my_serialize_object(dst, src, ctxt TSRMLS_CC);
+        } else if(ctxt->copy == APC_COPY_OUT_USER) {
+            dst = my_unserialize_object(dst, src, ctxt TSRMLS_CC);
+        }
+        break;
+
+    default:
+        assert(0);
+    }
+
+    return dst;
+}
+/* }}} */
+
+#ifdef ZEND_ENGINE_2_4
+/* {{{ my_copy_znode */
+static void my_check_znode(zend_uchar op_type, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(op_type == IS_CONST ||
+           op_type == IS_VAR ||
+           op_type == IS_CV ||
+           op_type == IS_TMP_VAR ||
+           op_type == IS_UNUSED);
+}
+/* }}} */
+
+/* {{{ my_copy_zend_op */
+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(dst != NULL);
+    assert(src != NULL);
+
+    memcpy(dst, src, sizeof(src[0]));
+
+    my_check_znode(dst->result_type & ~EXT_TYPE_UNUSED, ctxt TSRMLS_CC);
+    my_check_znode(dst->op1_type, ctxt TSRMLS_CC);
+    my_check_znode(dst->op2_type, ctxt TSRMLS_CC);
+
+    return dst;
+}
+/* }}} */
+#else
+/* {{{ my_copy_znode */
+static znode* my_copy_znode(znode* dst, znode* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(dst != NULL);
+    assert(src != NULL);
+
+    memcpy(dst, src, sizeof(src[0]));
+
+#ifdef IS_CV
+    assert(dst ->op_type == IS_CONST ||
+           dst ->op_type == IS_VAR ||
+           dst ->op_type == IS_CV ||
+           dst ->op_type == IS_TMP_VAR ||
+           dst ->op_type == IS_UNUSED);
+#else
+    assert(dst ->op_type == IS_CONST ||
+           dst ->op_type == IS_VAR ||
+           dst ->op_type == IS_TMP_VAR ||
+           dst ->op_type == IS_UNUSED);
+#endif
+
+    if (src->op_type == IS_CONST) {
+        if(!my_copy_zval(&dst->u.constant, &src->u.constant, ctxt TSRMLS_CC)) {
+            return NULL;
+        }
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_zend_op */
+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(dst != NULL);
+    assert(src != NULL);
+
+    memcpy(dst, src, sizeof(src[0]));
+
+    CHECK(my_copy_znode(&dst->result, &src->result, ctxt TSRMLS_CC));
+    CHECK(my_copy_znode(&dst->op1, &src->op1, ctxt TSRMLS_CC));
+    CHECK(my_copy_znode(&dst->op2, &src->op2, ctxt TSRMLS_CC));
+
+    return dst;
+}
+/* }}} */
+#endif
+
+/* {{{ my_copy_function */
+static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(src != NULL);
+
+    CHECK(dst = my_bitwise_copy_function(dst, src, ctxt TSRMLS_CC));
+
+    switch (src->type) {
+    case ZEND_INTERNAL_FUNCTION:
+    case ZEND_OVERLOADED_FUNCTION:
+        /* shallow copy because op_array is internal */
+        dst->op_array = src->op_array;
+        break;
+
+    case ZEND_USER_FUNCTION:
+    case ZEND_EVAL_CODE:
+        CHECK(apc_copy_op_array(&dst->op_array,
+                                &src->op_array,
+                                ctxt TSRMLS_CC));
+        break;
+
+    default:
+        assert(0);
+    }
+    /*
+     * op_array bitwise copying overwrites what ever you modified
+     * before apc_copy_op_array - which is why this code is outside 
+     * my_bitwise_copy_function.
+     */
+
+    /* zend_do_inheritance will re-look this up, because the pointers
+     * in prototype are from a function table of another class. It just
+     * helps if that one is from EG(class_table).
+     */
+    dst->common.prototype = NULL;
+
+    /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
+     * have to carry around a prototype. Thankfully zend_do_inheritance
+     * sets this properly as well
+     */
+    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
+
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_function_entry */
+static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, const zend_function_entry* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_function_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0])));
+    }
+
+    /* Start with a bitwise copy */
+    memcpy(dst, src, sizeof(src[0]));
+
+    dst->fname = NULL;
+    dst->arg_info = NULL;
+
+    if (src->fname) {
+        CHECK((dst->fname = apc_pstrdup(src->fname, ctxt->pool TSRMLS_CC)));
+    }
+
+    if (src->arg_info) {
+        CHECK((dst->arg_info = my_copy_arg_info_array(NULL,
+                                                src->arg_info,
+                                                src->num_args,
+                                                ctxt TSRMLS_CC)));
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_property_info */
+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_property_info*) apc_pool_alloc(pool, sizeof(*src)));
+    }
+
+    /* Start with a bitwise copy */
+    memcpy(dst, src, sizeof(*src));
+
+    dst->name = NULL;
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
+    dst->doc_comment = NULL;
+#endif
+
+    if (src->name) {
+        /* private members are stored inside property_info as a mangled
+         * string of the form:
+         *      \0<classname>\0<membername>\0
+         */
+        CHECK((dst->name = apc_string_pmemcpy(src->name, src->name_length+1, pool TSRMLS_CC)));
+    }
+
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
+    if (src->doc_comment) {
+        CHECK((dst->doc_comment = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC)));
+    }
+#endif
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_property_info_for_execution */
+static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_property_info*) apc_pool_alloc(ctxt->pool, sizeof(*src)));
+    }
+
+    /* We need only a shallow copy */
+    memcpy(dst, src, sizeof(*src));
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_arg_info_array */
+static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, const zend_arg_info* src, uint num_args, apc_context_t* ctxt TSRMLS_DC)
+{
+    uint i = 0;
+
+
+    if (!dst) {
+        CHECK(dst = (zend_arg_info*) apc_pool_alloc(ctxt->pool, (sizeof(*src) * num_args)));
+    }
+
+    /* Start with a bitwise copy */
+    memcpy(dst, src, sizeof(*src)*num_args);
+
+    for(i=0; i < num_args; i++) {
+        CHECK((my_copy_arg_info( &dst[i], &src[i], ctxt TSRMLS_CC)));
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_arg_info */
+static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, const zend_arg_info* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_arg_info*) apc_pool_alloc(pool, sizeof(*src)));
+    }
+
+    /* Start with a bitwise copy */
+    memcpy(dst, src, sizeof(*src));
+
+    dst->name = NULL;
+    dst->class_name = NULL;
+
+    if (src->name) {
+        CHECK((dst->name = apc_string_pmemcpy((char *) src->name, src->name_len+1, pool TSRMLS_CC)));
+    }
+
+    if (src->class_name) {
+        CHECK((dst->class_name = apc_string_pmemcpy((char *) src->class_name, src->class_name_len+1, pool TSRMLS_CC)));
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_copy_class_entry */
+zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    return my_copy_class_entry(dst, src, ctxt TSRMLS_CC);
+}
+
+/* {{{ my_copy_class_entry */
+static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    int i = 0;
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_class_entry*) apc_pool_alloc(pool, sizeof(*src)));
+    }
+
+    /* Start with a bitwise copy */
+    memcpy(dst, src, sizeof(*src));
+
+    dst->name = NULL;
+    memset(&dst->function_table, 0, sizeof(dst->function_table));
+    ZEND_CE_DOC_COMMENT(dst) = NULL;
+    ZEND_CE_FILENAME(dst) = NULL;
+    memset(&dst->properties_info, 0, sizeof(dst->properties_info));
+    memset(&dst->constants_table, 0, sizeof(dst->constants_table));
+
+    if (src->name) {
+        CHECK((dst->name = apc_pstrdup(src->name, pool TSRMLS_CC)));
+    }
+
+    if(!(my_copy_hashtable_ex(&dst->function_table,
+                            &src->function_table TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_function,
+                            0,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_function,
+                            src))) {
+        return NULL;
+    }
+
+    /* the interfaces are populated at runtime using ADD_INTERFACE */
+    dst->interfaces = NULL; 
+
+    /* the current count includes inherited interfaces as well,
+       the real dynamic ones are the first <n> which are zero'd
+       out in zend_do_end_class_declaration */
+    for(i = 0 ; (uint)i < src->num_interfaces ; i++) {
+        if(src->interfaces[i])
+        {
+            dst->num_interfaces = i;
+            break;
+        }
+    }
+
+    /* these will either be set inside my_fixup_hashtable or 
+     * they will be copied out from parent inside zend_do_inheritance 
+     */
+    dst->parent = NULL;
+    dst->constructor =  NULL;
+    dst->destructor = NULL;
+    dst->clone = NULL;
+    dst->__get = NULL;
+    dst->__set = NULL;
+    dst->__unset = NULL;
+    dst->__isset = NULL;
+    dst->__call = NULL;
+#ifdef ZEND_ENGINE_2_2
+    dst->__tostring = NULL;
+#endif
+#ifdef ZEND_ENGINE_2_3
+	dst->__callstatic = NULL;
+#endif
+
+    /* unset function proxies */
+    dst->serialize_func = NULL;
+    dst->unserialize_func = NULL;
+
+    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
+
+#ifdef ZEND_ENGINE_2_4
+	dst->default_properties_count = src->default_properties_count;
+    if (src->default_properties_count) {
+        CHECK(dst->default_properties_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_properties_count)));
+        for (i = 0; i < src->default_properties_count; i++) {
+            if (src->default_properties_table[i]) {
+                my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC);
+            } else {
+                dst->default_properties_table[i] = NULL;
+            }
+        }
+    } else {
+        dst->default_properties_table = NULL;
+    }
+#else
+    memset(&dst->default_properties, 0, sizeof(dst->default_properties));
+    CHECK((my_copy_hashtable_ex(&dst->default_properties,
+                            &src->default_properties TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_zval_ptr,
+                            1,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_default_property,
+                            src)));
+#endif
+
+    CHECK((my_copy_hashtable_ex(&dst->properties_info,
+                            &src->properties_info TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_property_info,
+                            0,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_property_info,
+                            src)));
+
+#ifdef ZEND_ENGINE_2_2
+    /* php5.2 introduced a scope attribute for property info */
+    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
+#endif
+
+#ifdef ZEND_ENGINE_2_4
+    dst->default_static_members_count = src->default_static_members_count;
+
+    if (src->default_static_members_count) {
+        CHECK(dst->default_static_members_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_static_members_count)));
+        for (i = 0; i < src->default_static_members_count; i++) {
+            if (src->default_static_members_table[i]) {
+                my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC);
+            } else {
+                dst->default_static_members_table[i] = NULL;
+            }
+        }
+    } else {
+        dst->default_static_members_table = NULL;
+    }
+    dst->static_members_table = dst->default_static_members_table;
+#else
+    memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
+    dst->static_members = NULL;
+    CHECK(my_copy_hashtable_ex(&dst->default_static_members,
+                            &src->default_static_members TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_zval_ptr,
+                            1,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_static_member,
+                            src,
+                            &src->default_static_members));
+
+    if(src->static_members != &src->default_static_members)
+    {
+        CHECK((dst->static_members = my_copy_hashtable_ex(NULL,
+                            src->static_members TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_zval_ptr,
+                            1,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_static_member,
+                            src,
+                            src->static_members)));
+    }
+    else
+    {
+        dst->static_members = &dst->default_static_members;
+    }
+#endif
+
+    CHECK((my_copy_hashtable_ex(&dst->constants_table,
+                            &src->constants_table TSRMLS_CC,
+                            (ht_copy_fun_t) my_copy_zval_ptr,
+                            1,
+                            ctxt,
+                            (ht_check_copy_fun_t) my_check_copy_constant,
+                            src)));
+
+    if (src->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(src)) {
+        CHECK(ZEND_CE_DOC_COMMENT(dst) =
+                    apc_pmemcpy(ZEND_CE_DOC_COMMENT(src), (ZEND_CE_DOC_COMMENT_LEN(src) + 1), pool TSRMLS_CC));
+    }
+
+    if (src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)) {
+        int i, n;
+
+        for (n = 0; src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)[n].fname != NULL; n++) {}
+
+        CHECK((ZEND_CE_BUILTIN_FUNCTIONS(dst) =
+                (zend_function_entry*) apc_pool_alloc(pool, ((n + 1) * sizeof(zend_function_entry)))));
+
+        for (i = 0; i < n; i++) {
+            CHECK(my_copy_function_entry((zend_function_entry*)(&ZEND_CE_BUILTIN_FUNCTIONS(dst)[i]),
+                                   &ZEND_CE_BUILTIN_FUNCTIONS(src)[i],
+                                   ctxt TSRMLS_CC));
+        }
+        *(char**)&(ZEND_CE_BUILTIN_FUNCTIONS(dst)[n].fname) = NULL;
+    }
+
+    if (src->type == ZEND_USER_CLASS && ZEND_CE_FILENAME(src)) {
+        CHECK((ZEND_CE_FILENAME(dst) = apc_pstrdup(ZEND_CE_FILENAME(src), pool TSRMLS_CC)));
+    }
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_hashtable_ex */
+static HashTable* my_copy_hashtable_ex(HashTable* dst,
+                                    HashTable* src TSRMLS_DC,
+                                    ht_copy_fun_t copy_fn,
+                                    int holds_ptrs,
+                                    apc_context_t* ctxt,
+                                    ht_check_copy_fun_t check_fn,
+                                    ...)
+{
+    Bucket* curr = NULL;
+    Bucket* prev = NULL;
+    Bucket* newp = NULL;
+    int first = 1;
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (HashTable*) apc_pool_alloc(pool, sizeof(src[0])));
+    }
+
+    memcpy(dst, src, sizeof(src[0]));
+
+    /* allocate buckets for the new hashtable */
+    CHECK((dst->arBuckets = apc_pool_alloc(pool, (dst->nTableSize * sizeof(Bucket*)))));
+
+    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
+    dst->pInternalPointer = NULL;
+    dst->pListHead = NULL;
+
+    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
+        int n = curr->h % dst->nTableSize;
+
+        if(check_fn) {
+            va_list args;
+            va_start(args, check_fn);
+
+            /* Call the check_fn to see if the current bucket
+             * needs to be copied out
+             */
+            if(!check_fn(curr, args)) {
+                dst->nNumOfElements--;
+                va_end(args);
+                continue;
+            }
+
+            va_end(args);
+        }
+
+        /* create a copy of the bucket 'curr' */
+#ifdef ZEND_ENGINE_2_4
+        if (!curr->nKeyLength) {
+            CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
+        } else if (IS_INTERNED(curr->arKey)) {
+            CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
+        } else if (pool->type != APC_UNPOOL) {
+            char *arKey;
+
+            arKey = apc_new_interned_string(curr->arKey, curr->nKeyLength TSRMLS_CC);
+            if (!arKey) {
+                CHECK((newp = (Bucket*) apc_pmemcpy(curr, (sizeof(Bucket) + curr->nKeyLength), pool TSRMLS_CC)));
+                newp->arKey = ((char*)newp) + sizeof(Bucket);
+            } else {
+                CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
+                newp->arKey = arKey;
+            }
+        } else {
+            CHECK((newp = (Bucket*) apc_pmemcpy(curr, (sizeof(Bucket) + curr->nKeyLength), pool TSRMLS_CC)));
+            newp->arKey = ((char*)newp) + sizeof(Bucket);
+        }        
+#else
+        CHECK((newp = (Bucket*) apc_pmemcpy(curr,
+                                  (sizeof(Bucket) + curr->nKeyLength - 1),
+                                  pool TSRMLS_CC)));
+#endif
+
+        /* insert 'newp' into the linked list at its hashed index */
+        if (dst->arBuckets[n]) {
+            newp->pNext = dst->arBuckets[n];
+            newp->pLast = NULL;
+            newp->pNext->pLast = newp;
+        }
+        else {
+            newp->pNext = newp->pLast = NULL;
+        }
+
+        dst->arBuckets[n] = newp;
+
+        /* copy the bucket data using our 'copy_fn' callback function */
+        CHECK((newp->pData = copy_fn(NULL, curr->pData, ctxt TSRMLS_CC)));
+
+        if (holds_ptrs) {
+            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
+        }
+        else {
+            newp->pDataPtr = NULL;
+        }
+
+        /* insert 'newp' into the table-thread linked list */
+        newp->pListLast = prev;
+        newp->pListNext = NULL;
+
+        if (prev) {
+            prev->pListNext = newp;
+        }
+
+        if (first) {
+            dst->pListHead = newp;
+            first = 0;
+        }
+
+        prev = newp;
+    }
+
+    dst->pListTail = newp;
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ my_copy_static_variables */
+static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    if (src->static_variables == NULL) {
+        return NULL;
+    }
+
+    return my_copy_hashtable(NULL,
+                             src->static_variables,
+                             (ht_copy_fun_t) my_copy_zval_ptr,
+                             1,
+                             ctxt);
+}
+/* }}} */
+
+/* {{{ apc_copy_zval */
+zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    apc_pool* pool = ctxt->pool;
+    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
+
+    assert(src != NULL);
+
+    if (!dst) {
+        if(usegc) {
+            ALLOC_ZVAL(dst);
+            CHECK(dst);
+        } else {
+            CHECK(dst = (zval*) apc_pool_alloc(pool, sizeof(zval)));
+        }
+    }
+
+    CHECK(dst = my_copy_zval(dst, src, ctxt TSRMLS_CC));
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_fixup_op_array_jumps */
+static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
+{
+    uint i;
+
+    for (i=0; i < dst->last; ++i) {
+        zend_op *zo = &(dst->opcodes[i]);
+        /*convert opline number to jump address*/
+        switch (zo->opcode) {
+#ifdef ZEND_ENGINE_2_3
+            case ZEND_GOTO:
+#endif
+            case ZEND_JMP:
+                /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
+#ifdef ZEND_ENGINE_2_4
+                zo->op1.jmp_addr = dst->opcodes + (zo->op1.jmp_addr - src->opcodes);
+#else
+                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
+#endif
+                break;
+            case ZEND_JMPZ:
+            case ZEND_JMPNZ:
+            case ZEND_JMPZ_EX:
+            case ZEND_JMPNZ_EX:
+#ifdef ZEND_ENGINE_2_3
+            case ZEND_JMP_SET:
+#endif
+#ifdef ZEND_ENGINE_2_4
+                zo->op2.jmp_addr = dst->opcodes + (zo->op2.jmp_addr - src->opcodes);
+#else
+                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
+#endif
+                break;
+            default:
+                break;
+        }
+    }
+}
+/* }}} */
+
+/* {{{ apc_copy_op_array */
+zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    int i;
+    apc_fileinfo_t *fileinfo = NULL;
+    char canon_path[MAXPATHLEN];
+    char *fullpath = NULL;
+    apc_opflags_t * flags = NULL;
+    apc_pool* pool = ctxt->pool;
+
+    assert(src != NULL);
+
+    if (!dst) {
+        CHECK(dst = (zend_op_array*) apc_pool_alloc(pool, sizeof(src[0])));
+    }
+
+    if(APCG(apc_optimize_function)) {
+        APCG(apc_optimize_function)(src TSRMLS_CC);
+    }
+
+    /* start with a bitwise copy of the array */
+    memcpy(dst, src, sizeof(src[0]));
+
+    dst->function_name = NULL;
+    dst->filename = NULL;
+    dst->refcount = NULL;
+    dst->opcodes = NULL;
+    dst->brk_cont_array = NULL;
+    dst->static_variables = NULL;
+    dst->try_catch_array = NULL;
+    dst->arg_info = NULL;
+    dst->doc_comment = NULL;
+#ifdef ZEND_ENGINE_2_1
+    dst->vars = NULL;
+#endif
+
+    /* copy the arg types array (if set) */
+    if (src->arg_info) {
+        CHECK(dst->arg_info = my_copy_arg_info_array(NULL,
+                                                src->arg_info,
+                                                src->num_args,
+                                                ctxt TSRMLS_CC));
+    }
+
+    if (src->function_name) {
+        CHECK(dst->function_name = apc_pstrdup(src->function_name, pool TSRMLS_CC));
+    }
+    if (src->filename) {
+        CHECK(dst->filename = apc_pstrdup(src->filename, pool TSRMLS_CC));
+    }
+
+    CHECK(dst->refcount = apc_pmemcpy(src->refcount,
+                                      sizeof(src->refcount[0]),
+                                      pool TSRMLS_CC));
+
+#ifdef ZEND_ENGINE_2_4
+    if (src->literals) {
+        zend_literal *p, *q, *end;
+
+        q = src->literals;
+        p = dst->literals = (zend_literal*) apc_pool_alloc(pool, (sizeof(zend_literal) * src->last_literal));
+        end = p + src->last_literal;
+        while (p < end) {
+            *p = *q;
+            my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
+            p++;
+            q++;
+        }
+    }
+#endif
+
+    /* deep-copy the opcodes */
+    CHECK(dst->opcodes = (zend_op*) apc_pool_alloc(pool, (sizeof(zend_op) * src->last)));
+
+    if(apc_reserved_offset != -1) {
+        /* Insanity alert: the void* pointer is cast into an apc_opflags_t 
+         * struct. apc_zend_init() checks to ensure that it fits in a void* */
+        flags = (apc_opflags_t*) & (dst->reserved[apc_reserved_offset]);
+        memset(flags, 0, sizeof(apc_opflags_t));
+        /* assert(sizeof(apc_opflags_t) <= sizeof(dst->reserved)); */
+    }
+
+    for (i = 0; (uint) i < src->last; i++) {
+        zend_op *zo = &(src->opcodes[i]);
+        /* a lot of files are merely constant arrays with no jumps */
+        switch (zo->opcode) {
+#ifdef ZEND_ENGINE_2_3
+            case ZEND_GOTO:
+#endif
+            case ZEND_JMP:
+            case ZEND_JMPZ:
+            case ZEND_JMPNZ:
+            case ZEND_JMPZ_EX:
+            case ZEND_JMPNZ_EX:
+#ifdef ZEND_ENGINE_2_3
+            case ZEND_JMP_SET:
+#endif
+                if(flags != NULL) {
+                    flags->has_jumps = 1;
+                }
+                break;
+            /* auto_globals_jit was not in php-4.3.* */
+            case ZEND_FETCH_R:
+            case ZEND_FETCH_W:
+            case ZEND_FETCH_IS:
+            case ZEND_FETCH_FUNC_ARG:
+            case ZEND_FETCH_RW:
+            case ZEND_FETCH_UNSET:
+                if(PG(auto_globals_jit) && flags != NULL)
+                {
+                     /* The fetch is only required if auto_globals_jit=1  */
+#ifdef ZEND_ENGINE_2_4
+                    if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL &&
+                            zo->op1_type == IS_CONST && 
+                            Z_TYPE_P(zo->op1.zv) == IS_STRING) {
+                        if (Z_STRVAL_P(zo->op1.zv)[0] == '_') {
+# define SET_IF_AUTOGLOBAL(member) \
+    if(!strcmp(Z_STRVAL_P(zo->op1.zv), #member)) \
+        flags->member = 1 /* no ';' here */
+#else
+                    if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
+                            zo->op1.op_type == IS_CONST && 
+                            zo->op1.u.constant.type == IS_STRING) {
+                        znode * varname = &zo->op1;
+                        if (varname->u.constant.value.str.val[0] == '_') {
+# define SET_IF_AUTOGLOBAL(member) \
+    if(!strcmp(varname->u.constant.value.str.val, #member)) \
+        flags->member = 1 /* no ';' here */
+#endif
+                            SET_IF_AUTOGLOBAL(_GET);
+                            else SET_IF_AUTOGLOBAL(_POST);
+                            else SET_IF_AUTOGLOBAL(_COOKIE);
+                            else SET_IF_AUTOGLOBAL(_SERVER);
+                            else SET_IF_AUTOGLOBAL(_ENV);
+                            else SET_IF_AUTOGLOBAL(_FILES);
+                            else SET_IF_AUTOGLOBAL(_REQUEST);
+                            else SET_IF_AUTOGLOBAL(_SESSION);
+#ifdef ZEND_ENGINE_2_4
+                            else if(zend_is_auto_global(
+                                            Z_STRVAL_P(zo->op1.zv),
+                                            Z_STRLEN_P(zo->op1.zv)
+                                            TSRMLS_CC))
+#else
+                            else if(zend_is_auto_global(
+                                            varname->u.constant.value.str.val,
+                                            varname->u.constant.value.str.len
+                                            TSRMLS_CC))
+#endif
+                            {
+                                flags->unknown_global = 1;
+                            }
+#ifdef ZEND_ENGINE_2_4
+                        } else SET_IF_AUTOGLOBAL(GLOBALS);
+#else
+                        }
+#endif
+                    }
+                }
+                break;
+            case ZEND_RECV_INIT:
+#ifdef ZEND_ENGINE_2_4
+                if(zo->op2_type == IS_CONST &&
+                    Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY) {
+#else
+                if(zo->op2.op_type == IS_CONST &&
+                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
+#endif
+                    if(flags != NULL) {
+                        flags->deep_copy = 1;
+                    }
+                }
+                break;
+            default:
+#ifdef ZEND_ENGINE_2_4
+                if((zo->op1_type == IS_CONST &&
+                    Z_TYPE_P(zo->op1.zv) == IS_CONSTANT_ARRAY) ||
+                    (zo->op2_type == IS_CONST &&
+                        Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY)) {
+#else
+                if((zo->op1.op_type == IS_CONST &&
+                    zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
+                    (zo->op2.op_type == IS_CONST &&
+                        zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
+#endif
+                    if(flags != NULL) {
+                        flags->deep_copy = 1;
+                    }
+                }
+                break;
+        }
+
+        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, ctxt TSRMLS_CC))) {
+            return NULL;
+        }
+
+#ifdef ZEND_ENGINE_2_4
+        if (zo->op1_type == IS_CONST) {
+            dst->opcodes[i].op1.literal = src->opcodes[i].op1.literal - src->literals + dst->literals;
+        }
+        if (zo->op2_type == IS_CONST) {
+            dst->opcodes[i].op2.literal = src->opcodes[i].op2.literal - src->literals + dst->literals;
+        }
+        if (zo->result_type == IS_CONST) {
+            dst->opcodes[i].result.literal = src->opcodes[i].result.literal - src->literals + dst->literals;
+        }
+#endif
+
+        /* This code breaks apc's rule#1 - cache what you compile */
+        if((APCG(fpstat)==0) && APCG(canonicalize)) {
+            /* not pool allocated, because the pool allocations eat up shm space */
+            fileinfo = (apc_fileinfo_t*) apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
+#ifdef ZEND_ENGINE_2_4
+            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
+                (zo->op1_type == IS_CONST && Z_TYPE_P(zo->op1.zv) == IS_STRING)) {
+                /* constant includes */
+                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(zo->op1.zv),Z_STRLEN_P(zo->op1.zv))) { 
+                    if (apc_search_paths(Z_STRVAL_P(zo->op1.zv), PG(include_path), fileinfo TSRMLS_CC) == 0) {
+#else
+            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
+                (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
+                /* constant includes */
+                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) { 
+                    if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), fileinfo TSRMLS_CC) == 0) {
+#endif
+                        if((fullpath = realpath(fileinfo->fullpath, canon_path))) {
+                            /* everything has to go through a realpath() */
+                            zend_op *dzo = &(dst->opcodes[i]);
+#ifdef ZEND_ENGINE_2_4
+                            dzo->op1.literal = (zend_literal*) apc_pool_alloc(pool, sizeof(zend_literal));
+                            Z_STRLEN_P(dzo->op1.zv) = strlen(fullpath);
+                            Z_STRVAL_P(dzo->op1.zv) = apc_pstrdup(fullpath, pool TSRMLS_CC);
+                            Z_SET_REFCOUNT_P(dzo->op1.zv, 2);
+                            Z_SET_ISREF_P(dzo->op1.zv);
+                            dzo->op1.literal->hash_value = zend_hash_func(Z_STRVAL_P(dzo->op1.zv), Z_STRLEN_P(dzo->op1.zv)+1);
+#else
+                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
+                            dzo->op1.u.constant.value.str.val = apc_pstrdup(fullpath, pool TSRMLS_CC);
+#endif
+                        }
+                    }
+                }
+            }
+            apc_php_free(fileinfo TSRMLS_CC);
+        }
+    }
+
+    if(flags == NULL || flags->has_jumps) {
+        apc_fixup_op_array_jumps(dst,src);
+    }
+
+    /* copy the break-continue array */
+    if (src->brk_cont_array) {
+        CHECK(dst->brk_cont_array = apc_pmemcpy(src->brk_cont_array,
+                                    sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
+                                    pool TSRMLS_CC));
+    }
+
+    /* copy the table of static variables */
+    if (src->static_variables) {
+        CHECK(dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC));
+    }
+
+    if (src->try_catch_array) {
+        CHECK(dst->try_catch_array = apc_pmemcpy(src->try_catch_array,
+                                        sizeof(src->try_catch_array[0]) * src->last_try_catch,
+                                        pool TSRMLS_CC));
+    }
+
+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
+    if (src->vars) {
+        CHECK(dst->vars = apc_pmemcpy(src->vars,
+                            sizeof(src->vars[0]) * src->last_var,
+                            pool TSRMLS_CC));
+
+        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
+
+        for(i = 0; i <  src->last_var; i++) {
+            CHECK(dst->vars[i].name = apc_string_pmemcpy(src->vars[i].name,
+                                src->vars[i].name_len + 1,
+                                pool TSRMLS_CC));
+        }
+    }
+#endif
+
+    if (src->doc_comment) {
+        CHECK(dst->doc_comment
+                = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC));
+    }
+
+    return dst;
+}
+/* }}} */
+
+
+/* {{{ apc_copy_new_functions */
+apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC)
+{
+    apc_function_t* array;
+    int new_count;              /* number of new functions in table */
+    int i;
+    apc_pool* pool = ctxt->pool;
+
+    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
+    assert(new_count >= 0);
+
+    CHECK(array =
+        (apc_function_t*)
+            apc_pool_alloc(pool, (sizeof(apc_function_t) * (new_count + 1))));
+
+    if (new_count == 0) {
+        array[0].function = NULL;
+        return array;
+    }
+
+    /* Skip the first `old_count` functions in the table */
+    zend_hash_internal_pointer_reset(CG(function_table));
+    for (i = 0; i < old_count; i++) {
+        zend_hash_move_forward(CG(function_table));
+    }
+
+    /* Add the next `new_count` functions to our array */
+    for (i = 0; i < new_count; i++) {
+        char* key;
+        uint key_size;
+        zend_function* fun;
+
+        zend_hash_get_current_key_ex(CG(function_table),
+                                     &key,
+                                     &key_size,
+                                     NULL,
+                                     0,
+                                     NULL);
+
+        zend_hash_get_current_data(CG(function_table), (void**) &fun);
+
+        CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC));
+        array[i].name_len = (int) key_size-1;
+        CHECK(array[i].function = my_copy_function(NULL, fun, ctxt TSRMLS_CC));
+        zend_hash_move_forward(CG(function_table));
+    }
+
+    array[i].function = NULL;
+    return array;
+}
+/* }}} */
+
+/* {{{ apc_copy_new_classes */
+apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t *ctxt TSRMLS_DC)
+{
+    apc_class_t* array;
+    int new_count;              /* number of new classes in table */
+    int i;
+    apc_pool* pool = ctxt->pool;
+
+    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
+    assert(new_count >= 0);
+
+    CHECK(array =
+        (apc_class_t*)
+            apc_pool_alloc(pool, (sizeof(apc_class_t) * (new_count + 1))));
+
+    if (new_count == 0) {
+        array[0].class_entry = NULL;
+        return array;
+    }
+
+    /* Skip the first `old_count` classes in the table */
+    zend_hash_internal_pointer_reset(CG(class_table));
+    for (i = 0; i < old_count; i++) {
+        zend_hash_move_forward(CG(class_table));
+    }
+
+    /* Add the next `new_count` classes to our array */
+    for (i = 0; i < new_count; i++) {
+        char* key;
+        uint key_size;
+        zend_class_entry* elem = NULL;
+
+        array[i].class_entry = NULL;
+
+        zend_hash_get_current_key_ex(CG(class_table),
+                                     &key,
+                                     &key_size,
+                                     NULL,
+                                     0,
+                                     NULL);
+
+        zend_hash_get_current_data(CG(class_table), (void**) &elem);
+
+
+        elem = *((zend_class_entry**)elem);
+
+        CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC));
+        array[i].name_len = (int) key_size-1;
+        CHECK(array[i].class_entry = my_copy_class_entry(NULL, elem, ctxt TSRMLS_CC));
+
+        /*
+         * If the class has a pointer to its parent class, save the parent
+         * name so that we can enable compile-time inheritance when we reload
+         * the child class; otherwise, set the parent name to null and scan
+         * the op_array to determine if this class inherits from some base
+         * class at execution-time.
+         */
+
+        if (elem->parent) {
+            CHECK(array[i].parent_name = apc_pstrdup(elem->parent->name, pool TSRMLS_CC));
+        }
+        else {
+            array[i].parent_name = NULL;
+        }
+
+        zend_hash_move_forward(CG(class_table));
+    }
+
+    array[i].class_entry = NULL;
+    return array;
+}
+/* }}} */
+
+/* Used only by my_prepare_op_array_for_execution */
+#ifdef ZEND_ENGINE_2_4
+# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                               \
+                         /* The fetch is only required if auto_globals_jit=1  */                \
+                        if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL &&    \
+                            zo->op1_type == IS_CONST &&                                         \
+                            Z_TYPE_P(zo->op1.zv) == IS_STRING &&                                \
+                            Z_STRVAL_P(zo->op1.zv)[0] == '_') {                                 \
+                            (void)zend_is_auto_global(Z_STRVAL_P(zo->op1.zv),                   \
+                                                      Z_STRLEN_P(zo->op1.zv)                    \
+                                                      TSRMLS_CC);                               \
+                        }
+#else
+# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                               \
+                         /* The fetch is only required if auto_globals_jit=1  */                \
+                        if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&                            \
+                            zo->op1.op_type == IS_CONST &&                                      \
+                            zo->op1.u.constant.type == IS_STRING &&                             \
+                            zo->op1.u.constant.value.str.val[0] == '_') {                       \
+                                                                                                \
+                            znode* varname = &zo->op1;                                          \
+                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
+                                                          varname->u.constant.value.str.len     \
+                                                          TSRMLS_CC);                           \
+                        }
+#endif
+
+/* {{{ my_prepare_op_array_for_execution */
+static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) 
+{
+    /* combine my_fetch_global_vars and my_copy_data_exceptions.
+     *   - Pre-fetch superglobals which would've been pre-fetched in parse phase.
+     *   - If the opcode stream contain mutable data, ensure a copy.
+     *   - Fixup array jumps in the same loop.
+     */
+    int i=src->last;
+    zend_op *zo;
+    zend_op *dzo;
+    apc_opflags_t * flags = apc_reserved_offset  != -1 ? 
+                                (apc_opflags_t*) & (src->reserved[apc_reserved_offset]) : NULL;
+    int needcopy = flags ? flags->deep_copy : 1;
+    /* auto_globals_jit was not in php4 */
+    int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
+
+#define FETCH_AUTOGLOBAL(member) do { \
+    if(flags && flags->member == 1) { \
+        zend_is_auto_global(#member,\
+                            (sizeof(#member) - 1)\
+                            TSRMLS_CC);\
+    } \
+} while(0);
+
+    FETCH_AUTOGLOBAL(_GET);
+    FETCH_AUTOGLOBAL(_POST);
+    FETCH_AUTOGLOBAL(_COOKIE);
+    FETCH_AUTOGLOBAL(_SERVER);
+    FETCH_AUTOGLOBAL(_ENV);
+    FETCH_AUTOGLOBAL(_FILES);
+    FETCH_AUTOGLOBAL(_REQUEST);
+    FETCH_AUTOGLOBAL(_SESSION);
+#ifdef ZEND_ENGINE_2_4
+    FETCH_AUTOGLOBAL(GLOBALS);
+#endif
+
+    if(needcopy) {
+
+#ifdef ZEND_ENGINE_2_4
+        if (src->literals) {
+            zend_literal *p, *q, *end;
+
+            q = src->literals;
+            p = dst->literals = (zend_literal*) apc_xmemcpy(src->literals,
+                                        sizeof(zend_literal) * src->last_literal,
+                                        apc_php_malloc TSRMLS_CC);
+            end = p + src->last_literal;
+            while (p < end) {
+                if (Z_TYPE(q->constant) == IS_CONSTANT_ARRAY) {
+                    my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
+                }
+                p++;
+                q++;
+            }
+        }
+#endif
+
+        dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
+                                    sizeof(zend_op) * src->last,
+                                    apc_php_malloc TSRMLS_CC);
+        zo = src->opcodes;
+        dzo = dst->opcodes;
+        while(i > 0) {
+
+#ifdef ZEND_ENGINE_2_4
+            if(zo->op1_type == IS_CONST) {
+               dzo->op1.literal = zo->op1.literal - src->literals + dst->literals;
+            }
+            if(zo->op2_type == IS_CONST) {
+               dzo->op2.literal = zo->op2.literal - src->literals + dst->literals;
+            }
+            if(zo->result_type == IS_CONST) {
+               dzo->result.literal = zo->result.literal - src->literals + dst->literals;
+            }
+#else
+            if( ((zo->op1.op_type == IS_CONST &&
+                  zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
+                ((zo->op2.op_type == IS_CONST &&
+                  zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
+
+                if(!(my_copy_zend_op(dzo, zo, ctxt TSRMLS_CC))) {
+                    assert(0); /* emalloc failed or a bad constant array */
+                }
+            }
+#endif
+
+            switch(zo->opcode) {
+#ifdef ZEND_ENGINE_2_3
+                case ZEND_GOTO:
+#endif
+                case ZEND_JMP:
+#ifdef ZEND_ENGINE_2_4
+                    dzo->op1.jmp_addr = dst->opcodes +
+                                            (zo->op1.jmp_addr - src->opcodes);
+#else
+                    dzo->op1.u.jmp_addr = dst->opcodes +
+                                            (zo->op1.u.jmp_addr - src->opcodes);
+#endif
+                    break;
+                case ZEND_JMPZ:
+                case ZEND_JMPNZ:
+                case ZEND_JMPZ_EX:
+                case ZEND_JMPNZ_EX:
+#ifdef ZEND_ENGINE_2_3
+                case ZEND_JMP_SET:
+#endif
+#ifdef ZEND_ENGINE_2_4
+                    dzo->op2.jmp_addr = dst->opcodes +
+                                            (zo->op2.jmp_addr - src->opcodes);
+#else
+                    dzo->op2.u.jmp_addr = dst->opcodes +
+                                            (zo->op2.u.jmp_addr - src->opcodes);
+#endif
+                    break;
+                case ZEND_FETCH_R:
+                case ZEND_FETCH_W:
+                case ZEND_FETCH_IS:
+                case ZEND_FETCH_FUNC_ARG:
+                    if(do_prepare_fetch_global)
+                    {
+                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
+                    }
+                    break;
+                default:
+                    break;
+            }
+            i--;
+            zo++;
+            dzo++;
+        }
+    } else {  /* !needcopy */
+        /* The fetch is only required if auto_globals_jit=1  */
+        if(do_prepare_fetch_global)
+        {
+            zo = src->opcodes;
+            while(i > 0) {
+
+                if(zo->opcode == ZEND_FETCH_R ||
+                   zo->opcode == ZEND_FETCH_W ||
+                   zo->opcode == ZEND_FETCH_IS ||
+                   zo->opcode == ZEND_FETCH_FUNC_ARG
+                  ) {
+                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
+                }
+
+                i--;
+                zo++;
+            }
+        }
+    }
+    return 1;
+}
+/* }}} */
+
+/* {{{ apc_copy_op_array_for_execution */
+zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    if(dst == NULL) {
+        dst = (zend_op_array*) emalloc(sizeof(src[0]));
+    }
+    memcpy(dst, src, sizeof(src[0]));
+    dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC);
+
+    /* memory leak */
+    dst->refcount = apc_pmemcpy(src->refcount,
+                                      sizeof(src->refcount[0]),
+                                      ctxt->pool TSRMLS_CC);
+
+    my_prepare_op_array_for_execution(dst,src, ctxt TSRMLS_CC);
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_copy_function_for_execution */
+zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    zend_function* dst;
+
+    dst = (zend_function*) emalloc(sizeof(src[0]));
+    memcpy(dst, src, sizeof(src[0]));
+    apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array), ctxt TSRMLS_CC);
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_copy_function_for_execution_ex */
+zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
+{
+    if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
+    return apc_copy_function_for_execution(src, ctxt TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_copy_class_entry_for_execution */
+zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
+{
+#ifdef ZEND_ENGINE_2_4
+    int i;
+#endif
+    zend_class_entry* dst = (zend_class_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0]));
+    memcpy(dst, src, sizeof(src[0]));
+
+    if(src->num_interfaces)
+    {
+        /* These are slots to be populated later by ADD_INTERFACE insns */
+        dst->interfaces = apc_php_malloc(
+                            (sizeof(zend_class_entry*) * src->num_interfaces) TSRMLS_CC);
+        memset(dst->interfaces, 0, 
+                            sizeof(zend_class_entry*) * src->num_interfaces);
+    }
+    else
+    {
+        /* assert(dst->interfaces == NULL); */
+    }
+
+    /* Deep-copy the class properties, because they will be modified */
+
+#ifdef ZEND_ENGINE_2_4
+	dst->default_properties_count = src->default_properties_count;
+    if (src->default_properties_count) {
+        dst->default_properties_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_properties_count) TSRMLS_CC);
+        for (i = 0; i < src->default_properties_count; i++) {
+            if (src->default_properties_table[i]) {
+                my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC);
+            } else {
+                dst->default_properties_table[i] = NULL;
+            }
+        }
+    } else {
+        dst->default_properties_table = NULL;
+    }
+#else
+    my_copy_hashtable(&dst->default_properties,
+                      &src->default_properties,
+                      (ht_copy_fun_t) my_copy_zval_ptr,
+                      1,
+                      ctxt);
+#endif
+
+    /* For derived classes, we must also copy the function hashtable (although
+     * we can merely bitwise copy the functions it contains) */
+
+    my_copy_hashtable(&dst->function_table,
+                      &src->function_table,
+                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
+                      0,
+                      ctxt);
+
+    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
+
+    /* zend_do_inheritance merges properties_info.
+     * Need only shallow copying as it doesn't hold the pointers.
+     */
+    my_copy_hashtable(&dst->properties_info,
+                      &src->properties_info,
+                      (ht_copy_fun_t) my_copy_property_info_for_execution,
+                      0,
+                      ctxt);
+
+#ifdef ZEND_ENGINE_2_2
+    /* php5.2 introduced a scope attribute for property info */
+    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
+#endif
+
+    /* if inheritance results in a hash_del, it might result in
+     * a pefree() of the pointers here. Deep copying required. 
+     */
+
+    my_copy_hashtable(&dst->constants_table,
+                      &src->constants_table,
+                      (ht_copy_fun_t) my_copy_zval_ptr,
+                      1,
+                      ctxt);
+
+#ifdef ZEND_ENGINE_2_4
+	dst->default_static_members_count = src->default_static_members_count;
+    if (src->default_static_members_count) {
+        dst->default_static_members_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_static_members_count) TSRMLS_CC);
+        for (i = 0; i < src->default_static_members_count; i++) {
+            if (src->default_static_members_table[i]) {
+                my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC);
+            } else {
+                dst->default_static_members_table[i] = NULL;
+            }
+        }
+    } else {
+        dst->default_static_members_table = NULL;
+    }
+    dst->static_members_table = dst->default_static_members_table;
+#else
+    my_copy_hashtable(&dst->default_static_members,
+                      &src->default_static_members,
+                      (ht_copy_fun_t) my_copy_zval_ptr,
+                      1,
+                      ctxt);
+
+    if(src->static_members != &(src->default_static_members))
+    {
+        dst->static_members = my_copy_hashtable(NULL,
+                          src->static_members,
+                          (ht_copy_fun_t) my_copy_zval_ptr,
+                          1,
+                          ctxt);
+    }
+    else 
+    {
+        dst->static_members = &(dst->default_static_members);
+    }
+#endif
+
+    return dst;
+}
+/* }}} */
+
+/* {{{ apc_free_class_entry_after_execution */
+void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC)
+{
+    if(src->num_interfaces > 0 && src->interfaces) {
+        apc_php_free(src->interfaces TSRMLS_CC);
+        src->interfaces = NULL;
+        src->num_interfaces = 0;
+    }
+    /* my_destroy_hashtable() does not play nice with refcounts */
+
+#ifdef ZEND_ENGINE_2_4
+    if (src->default_static_members_table) {
+       int i;
+
+       for (i = 0; i < src->default_static_members_count; i++) {
+          zval_ptr_dtor(&src->default_static_members_table[i]);
+       }
+       efree(src->default_static_members_table);
+       src->default_static_members_table = NULL;
+    }
+    src->static_members_table = NULL;
+    if (src->default_properties_table) {
+       int i;
+
+       for (i = 0; i < src->default_properties_count; i++) {
+           if (src->default_properties_table[i]) {
+               zval_ptr_dtor(&src->default_properties_table[i]);
+           }
+       }
+       efree(src->default_properties_table);
+       src->default_properties_table = NULL;
+    }
+#else
+    zend_hash_clean(&src->default_static_members);
+    if(src->static_members != &(src->default_static_members))
+    {
+        zend_hash_destroy(src->static_members);
+        apc_php_free(src->static_members TSRMLS_CC);
+        src->static_members = NULL;
+    }
+    else
+    {
+        src->static_members = NULL;
+    }
+
+    zend_hash_clean(&src->default_properties);
+#endif
+    zend_hash_clean(&src->constants_table);
+
+    /* TODO: more cleanup */
+}
+/* }}} */
+
+/* {{{ apc_file_halt_offset */
+long apc_file_halt_offset(const char *filename TSRMLS_DC)
+{
+    zend_constant *c;
+    char *name;
+    int len;
+    char haltoff[] = "__COMPILER_HALT_OFFSET__";
+    long value = -1;
+
+    zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, filename, strlen(filename), 0);
+    
+    if (zend_hash_find(EG(zend_constants), name, len+1, (void **) &c) == SUCCESS) {
+        value = Z_LVAL(c->value);
+    }
+    
+    pefree(name, 0);
+
+    return value;
+}
+/* }}} */
+
+/* {{{ apc_do_halt_compiler_register */
+void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC)
+{
+    char *name;
+    char haltoff[] = "__COMPILER_HALT_OFFSET__";
+    int len;
+   
+    if(halt_offset > 0) {
+        
+        zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, 
+                                    filename, strlen(filename), 0);
+        
+        zend_register_long_constant(name, len+1, halt_offset, CONST_CS, 0 TSRMLS_CC);
+
+        pefree(name, 0);
+    }
+}
+/* }}} */
+
+
+
+/* {{{ my_fixup_function */
+static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
+{
+    zend_function* zf = p->pData;
+
+    #define SET_IF_SAME_NAME(member) \
+    do { \
+        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
+            dst->member = zf; \
+        } \
+    } \
+    while(0)
+
+    if(zf->common.scope == src)
+    {
+
+        /* Fixing up the default functions for objects here since
+         * we need to compare with the newly allocated functions
+         *
+         * caveat: a sub-class method can have the same name as the
+         * parent's constructor and create problems.
+         */
+
+        if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
+        else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
+        else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
+        else
+        {
+            SET_IF_SAME_NAME(__get);
+            SET_IF_SAME_NAME(__set);
+            SET_IF_SAME_NAME(__unset);
+            SET_IF_SAME_NAME(__isset);
+            SET_IF_SAME_NAME(__call);
+#ifdef ZEND_ENGINE_2_2
+            SET_IF_SAME_NAME(__tostring);
+#endif
+#ifdef ZEND_ENGINE_2_3
+            SET_IF_SAME_NAME(__callstatic);
+#endif
+        }
+        zf->common.scope = dst;
+    }
+    else
+    {
+        /* no other function should reach here */
+        assert(0);
+    }
+
+    #undef SET_IF_SAME_NAME
+}
+/* }}} */
+
+#ifdef ZEND_ENGINE_2_2
+/* {{{ my_fixup_property_info */
+static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
+{
+    zend_property_info* property_info = (zend_property_info*)p->pData;
+
+    if(property_info->ce == src)
+    {
+        property_info->ce = dst;
+    }
+    else
+    {
+        assert(0); /* should never happen */
+    }
+}
+/* }}} */
+#endif
+
+/* {{{ my_fixup_hashtable */
+static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
+{
+    Bucket *p;
+    uint i;
+
+    for (i = 0; i < ht->nTableSize; i++) {
+        if(!ht->arBuckets) break;
+        p = ht->arBuckets[i];
+        while (p != NULL) {
+            fixup(p, src, dst);
+            p = p->pNext;
+        }
+    }
+}
+/* }}} */
+
+
+/* {{{ my_check_copy_function */
+static int my_check_copy_function(Bucket* p, va_list args)
+{
+    zend_class_entry* src = va_arg(args, zend_class_entry*);
+    zend_function* zf = (zend_function*)p->pData;
+
+    return (zf->common.scope == src);
+}
+/* }}} */
+
+#ifndef ZEND_ENGINE_2_4
+/* {{{ my_check_copy_default_property */
+static int my_check_copy_default_property(Bucket* p, va_list args)
+{
+    zend_class_entry* src = va_arg(args, zend_class_entry*);
+    zend_class_entry* parent = src->parent;
+    zval ** child_prop = (zval**)p->pData;
+    zval ** parent_prop = NULL;
+
+    if (parent &&
+        zend_hash_quick_find(&parent->default_properties, p->arKey, 
+            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
+
+        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
+        {
+            return 0;
+        }
+    }
+
+    /* possibly not in the parent */
+    return 1;
+}
+/* }}} */
+#endif
+
+/* {{{ my_check_copy_property_info */
+static int my_check_copy_property_info(Bucket* p, va_list args)
+{
+    zend_class_entry* src = va_arg(args, zend_class_entry*);
+    zend_class_entry* parent = src->parent;
+    zend_property_info* child_info = (zend_property_info*)p->pData;
+    zend_property_info* parent_info = NULL;
+
+#ifdef ZEND_ENGINE_2_2
+    /* so much easier */
+    return (child_info->ce == src);
+#endif
+
+    if (parent &&
+        zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
+            p->h, (void **) &parent_info)==SUCCESS) {
+        if(parent_info->flags & ZEND_ACC_PRIVATE)
+        {
+            return 1;
+        }
+        if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
+            (child_info->flags & ZEND_ACC_PPP_MASK))
+        {
+            /* TODO: figure out whether ACC_CHANGED is more appropriate
+             * here */
+            return 1;
+        }
+        return 0;
+    }
+
+    /* property doesn't exist in parent, copy into cached child */
+    return 1;
+}
+/* }}} */
+
+#ifndef ZEND_ENGINE_2_4
+/* {{{ my_check_copy_static_member */
+static int my_check_copy_static_member(Bucket* p, va_list args)
+{
+    zend_class_entry* src = va_arg(args, zend_class_entry*);
+    HashTable * ht = va_arg(args, HashTable*);
+    zend_class_entry* parent = src->parent;
+    HashTable * parent_ht = NULL;
+    char * member_name;
+    char * class_name = NULL;
+
+    zend_property_info *parent_info = NULL;
+    zend_property_info *child_info = NULL;
+    zval ** parent_prop = NULL;
+    zval ** child_prop = (zval**)(p->pData);
+
+    if(!parent) {
+        return 1;
+    }
+
+    /* these do not need free'ing */
+#ifdef ZEND_ENGINE_2_2
+    zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
+#else
+    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
+#endif
+
+    /* please refer do_inherit_property_access_check in zend_compile.c
+     * to understand why we lookup in properties_info.
+     */
+    if((zend_hash_find(&parent->properties_info, member_name,
+                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
+        &&
+        (zend_hash_find(&src->properties_info, member_name,
+                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
+    {
+        if(ht == &(src->default_static_members))
+        {
+            parent_ht = &parent->default_static_members;
+        }
+        else
+        {
+            parent_ht = parent->static_members;
+        }
+
+        if(zend_hash_quick_find(parent_ht, p->arKey,
+                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
+        {
+            /* they point to the same zval */
+            if(*parent_prop == *child_prop)
+            {
+                return 0;
+            }
+        }
+    }
+
+    return 1;
+}
+/* }}} */
+#endif
+
+/* {{{ my_check_copy_constant */
+static int my_check_copy_constant(Bucket* p, va_list args)
+{
+    zend_class_entry* src = va_arg(args, zend_class_entry*);
+    zend_class_entry* parent = src->parent;
+    zval ** child_const = (zval**)p->pData;
+    zval ** parent_const = NULL;
+
+    if (parent &&
+        zend_hash_quick_find(&parent->constants_table, p->arKey, 
+            p->nKeyLength, p->h, (void **) &parent_const)==SUCCESS) {
+
+        if((parent_const && child_const) && (*parent_const) == (*child_const))
+        {
+            return 0;
+        }
+    }
+
+    /* possibly not in the parent */
+    return 1;
+}
+/* }}} */
+
+/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
+ *      register a optimizer callback function, returns the previous callback
+ */
+apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
+    apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
+    APCG(apc_optimize_function) = optimizer;
+    return old_optimizer;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_compile.h
@@ -0,0 +1,146 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          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_compile.h 303388 2010-09-15 09:50:28Z dmitry $ */
+
+#ifndef APC_COMPILE_H
+#define APC_COMPILE_H
+
+/*
+ * This module encapsulates most of the complexity involved in deep-copying
+ * the Zend compiler data structures. The routines are allocator-agnostic, so
+ * the same function can be used for copying to and from shared memory.
+ */
+
+#include "apc.h"
+#include "apc_php.h"
+#include "apc_main.h"
+
+/* {{{ struct definition: apc_function_t */
+typedef struct apc_function_t apc_function_t;
+struct apc_function_t {
+    char* name;                 /* the function name */
+    int name_len;               /* length of name */
+    zend_function* function;    /* the zend function data structure */
+};
+/* }}} */
+
+/* {{{ struct definition: apc_class_t */
+typedef struct apc_class_t apc_class_t;
+struct apc_class_t {
+    char* name;                     /* the class name */
+    int name_len;                   /* length of name */
+    char* parent_name;              /* the parent class name */
+    zend_class_entry* class_entry;  /* the zend class data structure */
+};
+/* }}} */
+
+/* {{{ struct definition: apc_opflags_t */
+typedef struct apc_opflags_t apc_opflags_t;
+struct apc_opflags_t {
+    unsigned int has_jumps      : 1; /* has jump offsets */
+    unsigned int deep_copy      : 1; /* needs deep copy */
+
+    /* autoglobal bits */
+    unsigned int _POST          : 1;
+    unsigned int _GET           : 1;
+    unsigned int _COOKIE        : 1;
+    unsigned int _SERVER        : 1;
+    unsigned int _ENV           : 1;
+    unsigned int _FILES         : 1;
+    unsigned int _REQUEST       : 1;
+    unsigned int _SESSION       : 1;
+#ifdef ZEND_ENGINE_2_4
+    unsigned int GLOBALS        : 1;
+#endif
+    unsigned int unknown_global : 1;
+};
+/* }}} */
+
+/*
+ * These are the top-level copy functions.
+ */
+
+extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
+extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC);
+extern apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC);
+extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t* ctxt TSRMLS_DC);
+extern zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC);
+
+#if 0
+/*
+ * Deallocation functions corresponding to the copy functions above.
+ */
+
+extern void apc_free_op_array(zend_op_array* src, apc_context_t* ctxt);
+extern void apc_free_functions(apc_function_t* src, apc_context_t* ctxt);
+extern void apc_free_classes(apc_class_t* src, apc_context_t* ctxt);
+extern void apc_free_zval(zval* src, apc_context_t* ctxt);
+#endif
+
+/*
+ * These "copy-for-execution" functions must be called after retrieving an
+ * object from the shared cache. They do the minimal amount of work necessary
+ * to allow multiple processes to concurrently execute the same VM data
+ * structures.
+ */
+
+extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
+extern zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC);
+extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC);
+
+/*
+ * The "free-after-execution" function performs a cursory clean up of the class data
+ * This is required to minimize memory leak warnings and to ensure correct destructor
+ * ordering of some variables.
+ */
+extern void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC);
+
+/*
+ * Optimization callback definition and registration function. 
+ */
+typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
+extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
+
+/*
+ * To handle __COMPILER_HALT_OFFSET__
+ */
+long apc_file_halt_offset(const char* filename TSRMLS_DC);
+void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_debug.c
@@ -0,0 +1,70 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          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_debug.c 304107 2010-10-05 15:14:06Z kalle $ */
+#include "apc.h"
+#include <stdio.h>
+#include "zend.h"
+#include "zend_compile.h"
+
+#if defined(__DEBUG_APC__)
+
+/* keep track of vld_dump_oparray() signature */
+typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
+
+#endif
+
+void dump(zend_op_array *op_array TSRMLS_DC)
+{
+#if defined(__DEBUG_APC__)
+  vld_dump_f dump_op_array;
+  DL_HANDLE handle = NULL;
+
+#ifdef PHP_WIN32
+  handle = GetModuleHandle(NULL);
+  
+  if (!handle) {
+	apc_warning("unable to fetch current module handle." TSRMLS_CC);
+  }
+#endif
+  
+  dump_op_array = (vld_dump_f) DL_FETCH_SYMBOL(handle, "vld_dump_oparray");
+  
+#ifdef PHP_WIN32
+  DL_UNLOAD(handle);
+#endif
+
+  if(dump_op_array) {
+    dump_op_array(op_array TSRMLS_CC);
+  
+    return;
+  }
+  
+  apc_warning("vld is not installed or something even worse." TSRMLS_CC);
+#endif
+}
--- /dev/null
+++ b/ext/apc/apc_debug.h
@@ -0,0 +1,29 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          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.
+*/
+
+void dump(zend_op_array * TSRMLS_DC);
--- /dev/null
+++ b/ext/apc/apc_fcntl.c
@@ -0,0 +1,123 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: George Schlossnagle <george@omniti.com>                     |
+  |          Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_fcntl.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc.h"
+
+#ifdef APC_FCNTL_LOCKS
+
+#include "apc_fcntl.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+int apc_fcntl_create(const char* pathname TSRMLS_DC)
+{
+    int fd;
+    if(pathname == NULL) {
+        char lock_path[] = "/tmp/.apc.XXXXXX";
+        mktemp(lock_path);
+        fd = open(lock_path, O_RDWR|O_CREAT, 0666);
+        if(fd > 0 ) {
+            unlink(lock_path);
+            return fd;
+        } else {
+            apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, lock_path);
+            return -1;
+        }
+    }
+    fd = open(pathname, O_RDWR|O_CREAT, 0666);
+    if(fd > 0 ) {
+        unlink(pathname);
+        return fd;
+    }
+    apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, pathname);
+    return -1;
+}
+
+void apc_fcntl_destroy(int fd)
+{
+    close(fd);
+}
+
+static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
+{
+  int ret;
+  struct flock lock;
+
+  lock.l_type = type;
+  lock.l_start = offset;
+  lock.l_whence = whence;
+  lock.l_len = len;
+  lock.l_pid = 0;
+
+  do { ret = fcntl(fd, cmd, &lock) ; }
+  while(ret < 0 && errno == EINTR);
+  return(ret);
+}
+
+void apc_fcntl_lock(int fd TSRMLS_DC)
+{
+    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
+        apc_error("apc_fcntl_lock failed:" TSRMLS_CC);
+    }
+}
+
+void apc_fcntl_rdlock(int fd TSRMLS_DC)
+{
+    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
+        apc_error("apc_fcntl_rdlock failed:" TSRMLS_CC);
+    }
+}
+
+zend_bool apc_fcntl_nonblocking_lock(int fd TSRMLS_DC)
+{
+    if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
+        if(errno==EACCES||errno==EAGAIN) return 0;
+        else apc_error("apc_fcntl_lock failed:" TSRMLS_CC);
+    }
+    return 1;
+}
+
+void apc_fcntl_unlock(int fd TSRMLS_DC)
+{
+    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
+        apc_error("apc_fcntl_unlock failed:" TSRMLS_CC);
+    }
+}
+
+#endif /* APC_FCNTL_LOCKS */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_fcntl.h
@@ -0,0 +1,50 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: George Schlossnagle <george@omniti.com>                     |
+  |          Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_fcntl.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_FCNTL_H
+#define APC_FCNTL_H
+
+
+extern int apc_fcntl_create(const char* pathname TSRMLS_DC);
+extern void apc_fcntl_destroy(int fd);
+extern void apc_fcntl_lock(int fd TSRMLS_DC);
+extern void apc_fcntl_rdlock(int fd TSRMLS_DC);
+extern void apc_fcntl_unlock(int fd TSRMLS_DC);
+extern unsigned char apc_fcntl_nonblocking_lock(int fd TSRMLS_DC);
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_fcntl_win32.c
@@ -0,0 +1,117 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: George Schlossnagle <george@omniti.com>                     |
+  |          Edin Kadribasic <edink@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_fcntl_win32.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc.h"
+#include "apc_fcntl.h"
+#include <php.h>
+#include <win32/flock.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int apc_fcntl_create(const char* pathname TSRMLS_DC)
+{
+    char *lock_file = emalloc(MAXPATHLEN);
+    HANDLE fd;
+    DWORD tmplen;
+    static int i=0;
+
+    tmplen = GetTempPath(MAXPATHLEN, lock_file);
+    if (!tmplen) {
+        efree(lock_file);
+        return -1;
+    }
+
+    snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
+
+    fd = CreateFile(lock_file,
+        GENERIC_READ | GENERIC_WRITE,
+        FILE_SHARE_READ | FILE_SHARE_WRITE,
+        NULL,
+        OPEN_ALWAYS,
+        FILE_ATTRIBUTE_NORMAL,
+        NULL);
+
+
+    if (fd == INVALID_HANDLE_VALUE) {
+        apc_error("apc_fcntl_create: could not open %s" TSRMLS_CC, lock_file);
+        efree(lock_file);
+        return -1;
+    }
+
+    efree(lock_file);
+    return (int)fd;
+}
+
+void apc_fcntl_destroy(int fd)
+{
+    CloseHandle((HANDLE)fd);
+}
+
+void apc_fcntl_lock(int fd TSRMLS_DC)
+{
+    OVERLAPPED offset = {0, 0, 0, 0, NULL};
+
+    if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
+        apc_error("apc_fcntl_lock failed errno:%d" TSRMLS_CC, GetLastError());
+    }
+}
+
+void apc_fcntl_rdlock(int fd TSRMLS_DC)
+{
+    OVERLAPPED offset = {0, 0, 0, 0, NULL};
+
+    if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
+        apc_error("apc_fcntl_rdlock failed errno:%d" TSRMLS_CC, GetLastError());
+    }
+}
+
+void apc_fcntl_unlock(int fd TSRMLS_DC)
+{
+    OVERLAPPED offset = {0, 0, 0, 0, NULL};
+
+    if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
+        DWORD error_code = GetLastError();
+        /* Ignore already unlocked error */
+        if (error_code != ERROR_NOT_LOCKED) {
+            apc_error("apc_fcntl_unlock failed errno:%d" TSRMLS_CC, error_code);
+        }
+    }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_globals.h
@@ -0,0 +1,148 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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_globals.h 301232 2010-07-13 12:23:35Z gopalv $ */
+
+#ifndef APC_GLOBALS_H
+#define APC_GLOBALS_H
+
+#include "apc_cache.h"
+#include "apc_stack.h"
+#include "apc_php.h"
+
+/* {{{ struct apc_rfc1867_data */
+
+typedef struct _apc_rfc1867_data apc_rfc1867_data;
+
+struct _apc_rfc1867_data {
+    char tracking_key[64];
+    int  key_length;
+    size_t content_length;
+    char filename[128];
+    char name[64];
+    char *temp_filename;
+    int cancel_upload;
+    double start_time;
+    size_t bytes_processed;
+    size_t prev_bytes_processed;
+    int update_freq;
+    double rate;
+    int started;
+};
+/* }}} */
+
+ZEND_BEGIN_MODULE_GLOBALS(apc)
+    /* configuration parameters */
+    zend_bool enabled;      /* if true, apc is enabled (defaults to true) */
+    long shm_segments;      /* number of shared memory segments to use */
+    long shm_size;          /* size of each shared memory segment (in MB) */
+    long num_files_hint;    /* parameter to apc_cache_create */
+    long user_entries_hint;
+    long gc_ttl;            /* parameter to apc_cache_create */
+    long ttl;               /* parameter to apc_cache_create */
+    long user_ttl;
+#if APC_MMAP
+    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
+#endif
+    char** filters;         /* array of regex filters that prevent caching */
+    void* compiled_filters; /* compiled regex filters */
+
+    /* module variables */
+    zend_bool initialized;       /* true if module was initialized */
+    apc_stack_t* cache_stack;    /* the stack of cached executable code */
+    zend_bool cache_by_default;  /* true if files should be cached unless filtered out */
+                                 /* false if files should only be cached if filtered in */
+    long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
+    zend_bool enable_cli;        /* Flag to override turning APC off for CLI */
+    long max_file_size;          /* Maximum size of file, in bytes that APC will be allowed to cache */
+    zend_bool fpstat;            /* true if fullpath includes should be stat'ed */
+    zend_bool canonicalize;      /* true if relative paths should be canonicalized in no-stat mode */
+    zend_bool stat_ctime;        /* true if ctime in addition to mtime should be checked */
+    zend_bool write_lock;        /* true for a global write lock */
+    zend_bool slam_defense;      /* true for user cache slam defense */ 
+    zend_bool report_autofilter; /* true for auto-filter warnings */
+    zend_bool include_once;      /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
+    apc_optimize_function_t apc_optimize_function;   /* optimizer function callback */
+#ifdef MULTIPART_EVENT_FORMDATA
+    zend_bool rfc1867;            /* Flag to enable rfc1867 handler */
+    char* rfc1867_prefix;         /* Key prefix */
+    char* rfc1867_name;           /* Name of hidden field to activate upload progress/key suffix */
+    double rfc1867_freq;          /* Update frequency as percentage or bytes */
+    long rfc1867_ttl;             /* TTL for rfc1867 entries */
+    apc_rfc1867_data rfc1867_data;/* Per-request data */
+#endif
+    HashTable copied_zvals;      /* my_copy recursion detection list */
+    zend_bool force_file_update; /* force files to be updated during apc_compile_file */
+    char canon_path[MAXPATHLEN]; /* canonical path for key data */
+#ifdef APC_FILEHITS
+    zval *filehits;              /* Files that came from the cache for this request */
+#endif
+    zend_bool coredump_unmap;    /* Trap signals that coredump and unmap shared memory */
+    apc_cache_t *current_cache;  /* current cache being modified/read */
+    char *preload_path;
+    zend_bool file_md5;           /* record md5 hash of files */
+    void *apc_bd_alloc_ptr;      /* bindump alloc() ptr */
+    void *apc_bd_alloc_ubptr;    /* bindump alloc() upper bound ptr */
+    HashTable apc_bd_alloc_list; /* bindump alloc() ptr list */
+    zend_bool use_request_time;  /* use the SAPI request start time for TTL */
+    zend_bool lazy_functions;        /* enable/disable lazy function loading */
+    HashTable *lazy_function_table;  /* lazy function entry table */
+    zend_bool lazy_classes;          /* enable/disable lazy class loading */
+    HashTable *lazy_class_table;     /* lazy class entry table */
+#ifdef ZEND_ENGINE_2_4
+    long shm_strings_buffer;
+#endif
+ZEND_END_MODULE_GLOBALS(apc)
+
+/* (the following declaration is defined in php_apc.c) */
+ZEND_EXTERN_MODULE_GLOBALS(apc)
+
+#ifdef ZTS
+# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
+#else
+# define APCG(v) (apc_globals.v)
+#endif
+
+/* True globals */
+extern apc_cache_t* apc_cache;       /* the global compiler cache */
+extern apc_cache_t* apc_user_cache;  /* the global user content cache */
+extern void* apc_compiled_filters;   /* compiled filters */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc.h
@@ -0,0 +1,124 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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.h 304310 2010-10-11 12:19:24Z gopalv $ */
+
+#ifndef APC_H
+#define APC_H
+
+/*
+ * This module defines utilities and helper functions used elsewhere in APC.
+ */
+
+/* Commonly needed C library headers. */
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* UNIX headers (needed for struct stat) */
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef PHP_WIN32
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "php.h"
+#include "main/php_streams.h"
+
+/* typedefs for extensible memory allocators */
+typedef void* (*apc_malloc_t)(size_t TSRMLS_DC);
+typedef void  (*apc_free_t)  (void * TSRMLS_DC);
+
+/* wrappers for memory allocation routines */
+extern void* apc_emalloc(size_t n TSRMLS_DC);
+extern void* apc_erealloc(void* p, size_t n TSRMLS_DC);
+extern void apc_efree(void* p TSRMLS_DC);
+extern char* apc_estrdup(const char* s TSRMLS_DC);
+extern void* apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC);
+extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC);
+
+/* console display functions */
+extern void apc_error(const char *format TSRMLS_DC, ...);
+extern void apc_warning(const char *format TSRMLS_DC, ...);
+extern void apc_notice(const char *format TSRMLS_DC, ...);
+extern void apc_debug(const char *format TSRMLS_DC, ...);
+
+/* string and text manipulation */
+extern char* apc_append(const char* s, const char* t TSRMLS_DC);
+extern char* apc_substr(const char* s, int start, int length TSRMLS_DC);
+extern char** apc_tokenize(const char* s, char delim TSRMLS_DC);
+
+/* filesystem functions */
+
+typedef struct apc_fileinfo_t 
+{
+    char *fullpath;
+    char path_buf[MAXPATHLEN];
+    php_stream_statbuf st_buf;
+} apc_fileinfo_t;
+
+extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC);
+
+/* regular expression wrapper functions */
+extern void* apc_regex_compile_array(char* patterns[] TSRMLS_DC);
+extern void apc_regex_destroy_array(void* p TSRMLS_DC);
+extern int apc_regex_match_array(void* p, const char* input);
+
+/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
+extern unsigned int apc_crc32(const char* buf, int len);
+
+/* apc_flip_hash flips keys and values for faster searching */
+extern HashTable* apc_flip_hash(HashTable *hash); 
+
+#define APC_NEGATIVE_MATCH 1
+#define APC_POSITIVE_MATCH 2
+
+#define apc_time() \
+    (APCG(use_request_time) ? sapi_get_request_time(TSRMLS_C) : time(0));
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_iterator.c
@@ -0,0 +1,710 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_iterator.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "php_apc.h"
+#include "apc_iterator.h"
+#include "apc_cache.h"
+#include "apc_zend.h"
+
+#include "ext/standard/md5.h"
+
+#include "zend_interfaces.h"
+
+zend_class_entry *apc_iterator_ce;
+zend_object_handlers apc_iterator_object_handlers;
+
+
+/* {{{ apc_iterator_item */
+static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp TSRMLS_DC) {
+    zval *zvalue;
+    char md5str[33];
+    slot_t *slot = *slot_pp;
+    apc_context_t ctxt = {0, };
+    apc_iterator_item_t *item = ecalloc(1, sizeof(apc_iterator_item_t));
+
+    if (slot->key.type == APC_CACHE_KEY_FILE) {
+        /* keys should be unique and with stat=1 we could have multiple files with the same name, so use '<device> <inode>' instead */
+#ifdef PHP_WIN32
+        item->key_len = spprintf(&item->key, 0, "%I64d %I64d", slot->key.data.file.device, slot->key.data.file.inode);
+#else
+        item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode);
+#endif
+        item->filename_key = estrdup(slot->value->data.file.filename);
+    } else if (slot->key.type == APC_CACHE_KEY_USER) {
+        item->key = estrndup((char*)slot->key.data.user.identifier, slot->key.data.user.identifier_len);
+        item->key_len = slot->key.data.user.identifier_len;
+        item->filename_key = item->key; 
+    } else if (slot->key.type == APC_CACHE_KEY_FPFILE) {
+        item->key = estrndup((char*)slot->key.data.fpfile.fullpath, slot->key.data.fpfile.fullpath_len);
+        item->key_len = slot->key.data.fpfile.fullpath_len;
+        item->filename_key = item->key;
+    } else {
+        apc_error("Internal error, invalid entry type." TSRMLS_CC);
+    }
+
+    ALLOC_INIT_ZVAL(item->value);
+    array_init(item->value);
+
+    if (APC_ITER_TYPE & iterator->format) {
+        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
+            add_assoc_string(item->value, "type", "file", 1);
+        } else if(slot->value->type == APC_CACHE_ENTRY_USER) {
+            add_assoc_string(item->value, "type", "user", 1);
+        }
+    }
+    if (APC_ITER_FILENAME & iterator->format) {
+        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
+            if (slot->key.type == APC_CACHE_KEY_FILE) {
+              add_assoc_string(item->value, "filename", slot->value->data.file.filename, 1);
+            } else {  /* APC_CACHE_FPFILE */
+              add_assoc_string(item->value, "filename", (char*)slot->key.data.fpfile.fullpath, 1);
+            }
+        }
+    }
+    if (APC_ITER_DEVICE & iterator->format) {
+        if(slot->key.type == APC_CACHE_KEY_FILE) {
+#ifdef PHP_WIN32
+			char buf[20];
+			sprintf(buf, "%I64d", slot->key.data.file.device);
+			add_assoc_string(item->value, "device", buf, 1);
+#else
+            add_assoc_long(item->value, "device", slot->key.data.file.device);
+#endif
+        }
+    }
+    if (APC_ITER_INODE & iterator->format) {
+        if(slot->key.type == APC_CACHE_KEY_FILE) {
+#ifdef PHP_WIN32
+			char buf[20];
+			sprintf(buf, "%I64d", slot->key.data.file.device);
+			add_assoc_string(item->value, "device", buf, 1);
+#else
+            add_assoc_long(item->value, "inode", slot->key.data.file.inode);
+#endif
+        }
+    }
+    if (APC_ITER_KEY & iterator->format) {
+        add_assoc_stringl(item->value, "key", item->key, (item->key_len - 1), 1);
+    }
+    if (APC_ITER_VALUE & iterator->format) {
+        if(slot->value->type == APC_CACHE_ENTRY_USER) {
+
+            ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC);
+            ctxt.copy = APC_COPY_OUT_USER;
+
+            MAKE_STD_ZVAL(zvalue);
+            apc_cache_fetch_zval(zvalue, slot->value->data.user.val, &ctxt TSRMLS_CC);
+            apc_pool_destroy(ctxt.pool TSRMLS_CC);
+            add_assoc_zval(item->value, "value", zvalue);
+        }
+    }
+    if (APC_ITER_MD5 & iterator->format) {
+        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
+            if(slot->key.md5) {
+                make_digest(md5str, slot->key.md5);
+                add_assoc_string(item->value, "md5", md5str, 1);
+            }
+        }
+    }
+    if (APC_ITER_NUM_HITS & iterator->format) {
+        add_assoc_long(item->value, "num_hits", slot->num_hits);
+    }
+    if (APC_ITER_MTIME & iterator->format) {
+        add_assoc_long(item->value, "mtime", slot->key.mtime);
+    }
+    if (APC_ITER_CTIME & iterator->format) {
+        add_assoc_long(item->value, "creation_time", slot->creation_time);
+    }
+    if (APC_ITER_DTIME & iterator->format) {
+        add_assoc_long(item->value, "deletion_time", slot->deletion_time);
+    }
+    if (APC_ITER_ATIME & iterator->format) {
+        add_assoc_long(item->value, "access_time", slot->access_time);
+    }
+    if (APC_ITER_REFCOUNT & iterator->format) {
+        add_assoc_long(item->value, "ref_count", slot->value->ref_count);
+    }
+    if (APC_ITER_MEM_SIZE & iterator->format) {
+        add_assoc_long(item->value, "mem_size", slot->value->mem_size);
+    }
+    if (APC_ITER_TTL & iterator->format) {
+        if(slot->value->type == APC_CACHE_ENTRY_USER) {
+            add_assoc_long(item->value, "ttl", slot->value->data.user.ttl);
+        }
+    }
+
+    return item;
+}
+/* }}} */
+
+/* {{{ apc_iterator_clone */
+static zend_object_value apc_iterator_clone(zval *zobject TSRMLS_DC) {
+    zend_object_value value = {0};
+    apc_error("APCIterator object cannot be cloned." TSRMLS_CC);
+    return value;
+}
+/* }}} */
+
+/* {{{ apc_iterator_item_dtor */
+static void apc_iterator_item_dtor(apc_iterator_item_t *item) {
+    if (item->filename_key && item->filename_key != item->key) {
+        efree(item->filename_key);
+    }
+    if (item->key) {
+        efree(item->key);
+    }
+    if (item->value) {
+        zval_ptr_dtor(&item->value);
+    }
+    efree(item);
+}
+/* }}} */
+
+/* {{{ apc_iterator_destroy */
+static void apc_iterator_destroy(void *object, zend_object_handle handle TSRMLS_DC) {
+    apc_iterator_t *iterator = (apc_iterator_t*)object;
+
+    if (iterator->initialized == 0) {
+        return;
+    }
+
+    while (apc_stack_size(iterator->stack) > 0) {
+        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
+    }
+    if (iterator->regex) {
+        efree(iterator->regex);
+    }
+    if (iterator->search_hash) {
+        zend_hash_destroy(iterator->search_hash);
+        efree(iterator->search_hash);
+    }
+    iterator->initialized = 0;
+
+}
+/* }}} */
+
+/* {{{ acp_iterator_free */
+static void apc_iterator_free(void *object TSRMLS_DC) {
+    zend_object_std_dtor(object TSRMLS_CC);
+    efree(object);
+}
+/* }}} */
+
+/* {{{ apc_iterator_create */
+static zend_object_value apc_iterator_create(zend_class_entry *ce TSRMLS_DC) {
+    zend_object_value retval;
+    apc_iterator_t *iterator;
+
+    iterator = emalloc(sizeof(apc_iterator_t));
+    iterator->obj.ce = ce;
+    ALLOC_HASHTABLE(iterator->obj.properties);
+    zend_hash_init(iterator->obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+    iterator->obj.guards = NULL;
+    iterator->initialized = 0;
+    retval.handle = zend_objects_store_put(iterator, apc_iterator_destroy, apc_iterator_free, NULL TSRMLS_CC);
+    retval.handlers = &apc_iterator_object_handlers;
+
+    return retval;
+}
+/* }}} */
+
+/* {{{ apc_iterator_search_match
+ *       Verify if the key matches oru search parameters
+ */
+static int apc_iterator_search_match(apc_iterator_t *iterator, slot_t **slot) {
+    char *key;
+    int key_len;
+    char *fname_key = NULL;
+    int fname_key_len;
+    int rval = 1;
+
+    if ((*slot)->key.type == APC_CACHE_KEY_FILE) {
+        key = estrdup((*slot)->value->data.file.filename);
+        key_len = strlen(key);
+        fname_key_len = spprintf(&fname_key, 0, "%ld %ld", (*slot)->key.data.file.device, (*slot)->key.data.file.inode);
+    } else if ((*slot)->key.type == APC_CACHE_KEY_USER) {
+        key = (char*)(*slot)->key.data.user.identifier;
+        key_len = (*slot)->key.data.user.identifier_len;
+    } else if ((*slot)->key.type == APC_CACHE_KEY_FPFILE) {
+        key = (char*)(*slot)->key.data.fpfile.fullpath;
+        key_len = (*slot)->key.data.fpfile.fullpath_len;
+    }
+
+#ifdef ITERATOR_PCRE
+    if (iterator->regex) {
+        rval = (pcre_exec(iterator->re, NULL, key, strlen(key), 0, 0, NULL, 0) >= 0);
+    }
+#endif
+            
+    if (iterator->search_hash) {
+        rval = zend_hash_exists(iterator->search_hash, key, key_len);
+        if (!rval && fname_key) {
+            rval = zend_hash_exists(iterator->search_hash, fname_key, fname_key_len+1);
+        }
+    }
+
+    return rval;
+}
+/* }}} */
+
+/* {{{ apc_iterator_fetch_active */
+static int apc_iterator_fetch_active(apc_iterator_t *iterator TSRMLS_DC) {
+    int count=0;
+    slot_t **slot;
+    apc_iterator_item_t *item;
+
+    while (apc_stack_size(iterator->stack) > 0) {
+        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
+    }
+
+    CACHE_LOCK(iterator->cache);
+    while(count <= iterator->chunk_size && iterator->slot_idx < iterator->cache->num_slots) {
+        slot = &iterator->cache->slots[iterator->slot_idx];
+        while(*slot) {
+            if (apc_iterator_search_match(iterator, slot)) {
+                count++;
+                item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
+                if (item) {
+                    apc_stack_push(iterator->stack, item TSRMLS_CC);
+                }
+            }
+            slot = &(*slot)->next;
+        }
+        iterator->slot_idx++;
+    }
+    CACHE_UNLOCK(iterator->cache);
+    iterator->stack_idx = 0;
+    return count;
+}
+/* }}} */
+
+/* {{{ apc_iterator_fetch_deleted */
+static int apc_iterator_fetch_deleted(apc_iterator_t *iterator TSRMLS_DC) {
+    int count=0;
+    slot_t **slot;
+    apc_iterator_item_t *item;
+
+    CACHE_LOCK(iterator->cache);
+    slot = &iterator->cache->header->deleted_list;
+    while ((*slot) && count <= iterator->slot_idx) {
+        count++;
+        slot = &(*slot)->next;
+    }
+    count = 0;
+    while ((*slot) && count < iterator->chunk_size) {
+        if (apc_iterator_search_match(iterator, slot)) {
+            count++;
+            item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
+            if (item) {
+                apc_stack_push(iterator->stack, item TSRMLS_CC);
+            }
+        }
+        slot = &(*slot)->next;
+    }
+    CACHE_UNLOCK(iterator->cache);
+    iterator->slot_idx += count;
+    iterator->stack_idx = 0;
+    return count;
+}
+/* }}} */
+
+/* {{{ apc_iterator_totals */
+static void apc_iterator_totals(apc_iterator_t *iterator TSRMLS_DC) {
+    slot_t **slot;
+    int i;
+
+    CACHE_LOCK(iterator->cache);
+    for (i=0; i < iterator->cache->num_slots; i++) {
+        slot = &iterator->cache->slots[i];
+        while((*slot)) {
+            if (apc_iterator_search_match(iterator, slot)) {
+                iterator->size += (*slot)->value->mem_size;
+                iterator->hits += (*slot)->num_hits;
+                iterator->count++;
+            }
+            slot = &(*slot)->next;
+        }
+    }
+    CACHE_UNLOCK(iterator->cache);
+    iterator->totals_flag = 1;
+}
+/* }}} */
+
+/* {{{ proto object APCIterator::__costruct(string cache [, mixed search [, long format [, long chunk_size [, long list ]]]]) */
+PHP_METHOD(apc_iterator, __construct) {
+    zval *object = getThis();
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
+    char *cachetype;
+    int cachetype_len;
+    long format = APC_ITER_ALL;
+    long chunk_size=0;
+    zval *search = NULL;
+    long list = APC_LIST_ACTIVE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zlll", &cachetype, &cachetype_len, &search, &format, &chunk_size, &list) == FAILURE) {
+        return;
+    }
+
+    if (!APCG(enabled)) {
+        apc_error("APC must be enabled to use APCIterator." TSRMLS_CC);
+    }
+
+    if (chunk_size < 0) {
+        apc_error("APCIterator chunk size must be 0 or greater." TSRMLS_CC);
+        return;
+    }
+
+    if (format > APC_ITER_ALL) {
+        apc_error("APCIterator format is invalid." TSRMLS_CC);
+        return;
+    }
+
+    if (list == APC_LIST_ACTIVE) {
+        iterator->fetch = apc_iterator_fetch_active;
+    } else if (list == APC_LIST_DELETED) {
+        iterator->fetch = apc_iterator_fetch_deleted;
+    } else {
+        apc_warning("APCIterator invalid list type." TSRMLS_CC);
+        return;
+    }
+
+    if(!strcasecmp(cachetype,"user")) {
+        iterator->cache = apc_user_cache;
+    } else {
+        iterator->cache = apc_cache;
+    }
+
+    iterator->slot_idx = 0;
+    iterator->stack_idx = 0;
+    iterator->key_idx = 0;
+    iterator->chunk_size = chunk_size == 0 ? APC_DEFAULT_CHUNK_SIZE : chunk_size;
+    iterator->stack = apc_stack_create(chunk_size TSRMLS_CC);
+    iterator->format = format;
+    iterator->totals_flag = 0;
+    iterator->count = 0;
+    iterator->size = 0;
+    iterator->hits = 0;
+    iterator->regex = NULL;
+    iterator->regex_len = 0;
+    iterator->search_hash = NULL;
+    if (search && Z_TYPE_P(search) == IS_STRING && Z_STRLEN_P(search)) {
+#ifdef ITERATOR_PCRE
+        iterator->regex = estrndup(Z_STRVAL_P(search), Z_STRLEN_P(search));
+        iterator->regex_len = Z_STRLEN_P(search);
+        iterator->re = pcre_get_compiled_regex(Z_STRVAL_P(search), NULL, NULL TSRMLS_CC);
+
+        if(!iterator->re) {
+            apc_error("Could not compile regular expression: %s" TSRMLS_CC, Z_STRVAL_P(search));
+        }
+#else
+        apc_error("Regular expressions support is not enabled, please enable PCRE for APCIterator regex support" TSRMLS_CC);
+#endif
+    } else if (search && Z_TYPE_P(search) == IS_ARRAY) {
+        Z_ADDREF_P(search);
+        iterator->search_hash = apc_flip_hash(Z_ARRVAL_P(search));
+    }
+    iterator->initialized = 1;
+}
+/* }}} */
+
+/* {{{ proto APCIterator::rewind() */
+PHP_METHOD(apc_iterator, rewind) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    iterator->slot_idx = 0;
+    iterator->stack_idx = 0;
+    iterator->key_idx = 0;
+    iterator->fetch(iterator TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ proto boolean APCIterator::valid() */
+PHP_METHOD(apc_iterator, valid) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
+        iterator->fetch(iterator TSRMLS_CC);
+    }
+
+    RETURN_BOOL(apc_stack_size(iterator->stack) == 0 ? 0 : 1);
+}
+/* }}} */
+
+/* {{{ proto mixed APCIterator::current() */
+PHP_METHOD(apc_iterator, current) {
+    apc_iterator_item_t *item;
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
+        if (iterator->fetch(iterator TSRMLS_CC) == 0) {
+            RETURN_FALSE;
+        }
+    }
+
+    item = apc_stack_get(iterator->stack, iterator->stack_idx);
+    RETURN_ZVAL(item->value, 1, 0);
+}
+/* }}} */
+
+/* {{{ proto string APCIterator::key() */
+PHP_METHOD(apc_iterator, key) {
+    apc_iterator_item_t *item;
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
+        RETURN_FALSE;
+    }
+
+    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
+        if (iterator->fetch(iterator TSRMLS_CC) == 0) {
+            RETURN_FALSE;
+        }
+    }
+
+    item = apc_stack_get(iterator->stack, iterator->stack_idx);
+
+    if (item->key) {
+        RETURN_STRINGL(item->key, (item->key_len-1), 1);
+    } else {
+        RETURN_LONG(iterator->key_idx);
+    }
+}
+/* }}} */
+
+/* {{{ proto APCIterator::next() */
+PHP_METHOD(apc_iterator, next) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
+        RETURN_FALSE;
+    }
+
+    iterator->stack_idx++;
+    iterator->key_idx++;
+
+    RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto long APCIterator::getTotalHits() */
+PHP_METHOD(apc_iterator, getTotalHits) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    if (iterator->totals_flag == 0) {
+        apc_iterator_totals(iterator TSRMLS_CC);
+    }
+
+    RETURN_LONG(iterator->hits);
+}
+/* }}} */
+
+/* {{{ proto long APCIterator::getTotalSize() */
+PHP_METHOD(apc_iterator, getTotalSize) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    if (iterator->totals_flag == 0) {
+        apc_iterator_totals(iterator TSRMLS_CC);
+    }
+
+    RETURN_LONG(iterator->size);
+}
+/* }}} */
+
+/* {{{ proto long APCIterator::getTotalCount() */
+PHP_METHOD(apc_iterator, getTotalCount) {
+    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+    if (zend_parse_parameters_none() == FAILURE) {
+        return;
+    }
+
+    if (iterator->initialized == 0) {
+        RETURN_FALSE;
+    }
+
+    if (iterator->totals_flag == 0) {
+        apc_iterator_totals(iterator TSRMLS_CC);
+    }
+
+    RETURN_LONG(iterator->count);
+}
+/* }}} */
+
+/* {{{ arginfo */
+#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
+# define PHP_APC_ARGINFO
+#else
+# define PHP_APC_ARGINFO static
+#endif
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator___construct, 0, 0, 1)
+	ZEND_ARG_INFO(0, cache)
+	ZEND_ARG_INFO(0, search)
+	ZEND_ARG_INFO(0, format)
+	ZEND_ARG_INFO(0, chunk_size)
+	ZEND_ARG_INFO(0, list)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator_void, 0, 0, 0)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ apc_iterator_functions */
+static zend_function_entry apc_iterator_functions[] = {
+    PHP_ME(apc_iterator, __construct, arginfo_apc_iterator___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+    PHP_ME(apc_iterator, rewind, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, current, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, key, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, next, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, valid, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, getTotalHits, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, getTotalSize, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    PHP_ME(apc_iterator, getTotalCount, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
+    {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ apc_iterator_init */
+int apc_iterator_init(int module_number TSRMLS_DC) {
+    zend_class_entry ce;
+
+    INIT_CLASS_ENTRY(ce, APC_ITERATOR_NAME, apc_iterator_functions);
+    apc_iterator_ce = zend_register_internal_class(&ce TSRMLS_CC);
+    apc_iterator_ce->create_object = apc_iterator_create;
+    zend_class_implements(apc_iterator_ce TSRMLS_CC, 1, zend_ce_iterator);
+
+    zend_register_long_constant("APC_LIST_ACTIVE", sizeof("APC_LIST_ACTIVE"), APC_LIST_ACTIVE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_LIST_DELETED", sizeof("APC_LIST_DELETED"), APC_LIST_DELETED, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+
+    zend_register_long_constant("APC_ITER_TYPE", sizeof("APC_ITER_TYPE"), APC_ITER_TYPE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_KEY", sizeof("APC_ITER_KEY"), APC_ITER_KEY, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_FILENAME", sizeof("APC_ITER_FILENAME"), APC_ITER_FILENAME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_DEVICE", sizeof("APC_ITER_DEVICE"), APC_ITER_DEVICE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_INODE", sizeof("APC_ITER_INODE"), APC_ITER_INODE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_VALUE", sizeof("APC_ITER_VALUE"), APC_ITER_VALUE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_MD5", sizeof("APC_ITER_MD5"), APC_ITER_MD5, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_NUM_HITS", sizeof("APC_ITER_NUM_HITS"), APC_ITER_NUM_HITS, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_MTIME", sizeof("APC_ITER_MTIME"), APC_ITER_MTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_CTIME", sizeof("APC_ITER_CTIME"), APC_ITER_CTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_DTIME", sizeof("APC_ITER_DTIME"), APC_ITER_DTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_ATIME", sizeof("APC_ITER_ATIME"), APC_ITER_ATIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_REFCOUNT", sizeof("APC_ITER_REFCOUNT"), APC_ITER_REFCOUNT, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_MEM_SIZE", sizeof("APC_ITER_MEM_SIZE"), APC_ITER_MEM_SIZE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_TTL", sizeof("APC_ITER_TTL"), APC_ITER_TTL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_NONE", sizeof("APC_ITER_NONE"), APC_ITER_NONE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+    zend_register_long_constant("APC_ITER_ALL", sizeof("APC_ITER_ALL"), APC_ITER_ALL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
+
+    memcpy(&apc_iterator_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+    apc_iterator_object_handlers.clone_obj = apc_iterator_clone;
+
+    return SUCCESS;
+}
+/* }}} */
+
+
+int apc_iterator_delete(zval *zobj TSRMLS_DC) {
+    apc_iterator_t *iterator;
+    zend_class_entry *ce = Z_OBJCE_P(zobj);
+    apc_iterator_item_t *item;
+
+    if (!ce || !instanceof_function(ce, apc_iterator_ce TSRMLS_CC)) {
+        apc_error("apc_delete object argument must be instance of APCIterator" TSRMLS_CC);
+        return 0;
+    }
+    iterator = (apc_iterator_t*)zend_object_store_get_object(zobj TSRMLS_CC);
+
+    if (iterator->initialized == 0) {
+        return 0;
+    }
+
+    while (iterator->fetch(iterator TSRMLS_CC)) {
+        while (iterator->stack_idx < apc_stack_size(iterator->stack)) {
+            item = apc_stack_get(iterator->stack, iterator->stack_idx++);
+            if (iterator->cache == apc_cache) {
+                apc_cache_delete(apc_cache, item->filename_key, strlen(item->filename_key) + 1 TSRMLS_CC);
+            } else {
+                apc_cache_user_delete(apc_user_cache, item->key, item->key_len TSRMLS_CC);
+            }
+        }
+    }
+
+    return 1;
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_iterator.h
@@ -0,0 +1,117 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@.php.net>                                |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_iterator.h 300979 2010-07-04 10:15:05Z kalle $ */
+
+#ifndef APC_ITERATOR_H
+#define APC_ITERATOR_H
+
+#include "apc.h"
+#include "apc_stack.h"
+
+#if HAVE_PCRE || HAVE_BUNDLED_PCRE
+/*  Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
+#   if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
+#       include "apc_php_pcre.h"
+#   else
+#       include "ext/pcre/php_pcre.h"
+#   endif
+#   include "ext/standard/php_smart_str.h"
+#   define ITERATOR_PCRE 1
+#endif
+
+
+#define APC_ITERATOR_NAME "APCIterator"
+
+#define APC_DEFAULT_CHUNK_SIZE 100
+
+#define APC_LIST_ACTIVE   0x1
+#define APC_LIST_DELETED  0x2
+
+#define APC_ITER_TYPE       (1L << 0) 
+#define APC_ITER_KEY        (1L << 1) 
+#define APC_ITER_FILENAME   (1L << 2) 
+#define APC_ITER_DEVICE     (1L << 3) 
+#define APC_ITER_INODE      (1L << 4) 
+#define APC_ITER_VALUE      (1L << 5) 
+#define APC_ITER_MD5        (1L << 6) 
+#define APC_ITER_NUM_HITS   (1L << 7) 
+#define APC_ITER_MTIME      (1L << 8) 
+#define APC_ITER_CTIME      (1L << 9) 
+#define APC_ITER_DTIME      (1L << 10) 
+#define APC_ITER_ATIME      (1L << 11) 
+#define APC_ITER_REFCOUNT   (1L << 12) 
+#define APC_ITER_MEM_SIZE   (1L << 13) 
+#define APC_ITER_TTL        (1L << 14)
+
+#define APC_ITER_NONE       (0x00000000L)
+#define APC_ITER_ALL        (0xffffffffL)
+
+typedef void* (*apc_iterator_item_cb_t)(slot_t **slot);
+
+
+/* {{{ apc_iterator_t */
+typedef struct _apc_iterator_t {
+    zend_object obj;         /* must always be first */
+    short int initialized;   /* sanity check in case __construct failed */
+    long format;             /* format bitmask of the return values ie: key, value, info */
+    int (*fetch)(struct _apc_iterator_t *iterator TSRMLS_DC);
+                             /* fetch callback to fetch items from cache slots or lists */
+    apc_cache_t *cache;      /* cache which we are iterating on */
+    long slot_idx;           /* index to the slot array or linked list */
+    long chunk_size;         /* number of entries to pull down per fetch */
+    apc_stack_t *stack;      /* stack of entries pulled from cache */
+    int stack_idx;           /* index into the current stack */
+#ifdef ITERATOR_PCRE
+    pcre *re;                /* regex filter on entry identifiers */
+#endif
+    char *regex;             /* original regex expression or NULL */
+    int regex_len;           /* regex length */
+    HashTable *search_hash;  /* hash of keys to iterate over */
+    long key_idx;            /* incrementing index for numerical keys */
+    short int totals_flag;   /* flag if totals have been calculated */
+    long hits;               /* hit total */
+    size_t size;             /* size total */
+    long count;              /* count total */
+} apc_iterator_t;
+/* }}} */
+
+/* {{{ apc_iterator_item */
+typedef struct _apc_iterator_item_t {
+    char *key;              /* string key */
+    long key_len;           /* strlen of key */
+    char *filename_key;     /* filename key used for deletion */
+    zval *value;
+} apc_iterator_item_t;
+/* }}} */
+
+
+extern int apc_iterator_init(int module_number TSRMLS_DC);
+extern int apc_iterator_delete(zval *zobj TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_lock.h
@@ -0,0 +1,101 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: George Schlossnagle <george@omniti.com>                     |
+  |          Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_lock.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_LOCK
+#define APC_LOCK
+
+#include "apc.h"
+#include "apc_sem.h"
+#include "apc_fcntl.h"
+#include "apc_pthreadmutex.h"
+#include "apc_spin.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* {{{ generic locking macros */
+#define CREATE_LOCK(lock)     apc_lck_create(NULL, 0, 1, lock)
+#define DESTROY_LOCK(lock)    apc_lck_destroy(lock)
+#define LOCK(lock)          { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(lock); }
+#define RDLOCK(lock)        { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(lock); }
+#define UNLOCK(lock)        { apc_lck_unlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
+/* }}} */
+
+#if defined(APC_SEM_LOCKS)
+#define APC_LOCK_TYPE "IPC Semaphore"
+#define RDLOCK_AVAILABLE 0
+#define NONBLOCKING_LOCK_AVAILABLE 1 
+#define apc_lck_t int
+#define apc_lck_create(a,b,c,d) d=apc_sem_create((b),(c) TSRMLS_CC)
+#define apc_lck_destroy(a)    apc_sem_destroy(a)
+#define apc_lck_lock(a)       apc_sem_lock(a TSRMLS_CC)
+#define apc_lck_nb_lock(a)    apc_sem_nonblocking_lock(a TSRMLS_CC)
+#define apc_lck_rdlock(a)     apc_sem_lock(a TSRMLS_CC)
+#define apc_lck_unlock(a)     apc_sem_unlock(a TSRMLS_CC)
+#elif defined(APC_PTHREADMUTEX_LOCKS)
+#define APC_LOCK_TYPE "pthread mutex Locks"
+#define RDLOCK_AVAILABLE 0
+#define NONBLOCKING_LOCK_AVAILABLE 1
+#define apc_lck_t pthread_mutex_t 
+#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d TSRMLS_CC)
+#define apc_lck_destroy(a)    apc_pthreadmutex_destroy(&a)
+#define apc_lck_lock(a)       apc_pthreadmutex_lock(&a TSRMLS_CC)
+#define apc_lck_nb_lock(a)    apc_pthreadmutex_nonblocking_lock(&a TSRMLS_CC)
+#define apc_lck_rdlock(a)     apc_pthreadmutex_lock(&a TSRMLS_CC)
+#define apc_lck_unlock(a)     apc_pthreadmutex_unlock(&a TSRMLS_CC)
+#elif defined(APC_SPIN_LOCKS)
+#define APC_LOCK_TYPE "spin Locks"
+#define RDLOCK_AVAILABLE 0
+#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
+#define apc_lck_t slock_t 
+#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
+#define apc_lck_destroy(a)    apc_slock_destroy(&a)
+#define apc_lck_lock(a)       apc_slock_lock(&a TSRMLS_CC)
+#define apc_lck_nb_lock(a)    apc_slock_nonblocking_lock(&a)
+#define apc_lck_rdlock(a)     apc_slock_lock(&a TSRMLS_CC)
+#define apc_lck_unlock(a)     apc_slock_unlock(&a)
+#else
+#define APC_LOCK_TYPE "File Locks"
+#define RDLOCK_AVAILABLE 1
+#ifdef PHP_WIN32
+#define NONBLOCKING_LOCK_AVAILABLE 0
+#else
+#define NONBLOCKING_LOCK_AVAILABLE 1
+#endif
+#define apc_lck_t int
+#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a) TSRMLS_CC)
+#define apc_lck_destroy(a)    apc_fcntl_destroy(a)
+#define apc_lck_lock(a)       apc_fcntl_lock(a TSRMLS_CC)
+#define apc_lck_nb_lock(a)    apc_fcntl_nonblocking_lock(a TSRMLS_CC)
+#define apc_lck_rdlock(a)     apc_fcntl_rdlock(a TSRMLS_CC)
+#define apc_lck_unlock(a)     apc_fcntl_unlock(a TSRMLS_CC)
+#endif
+
+#endif
--- /dev/null
+++ b/ext/apc/apc_main.c
@@ -0,0 +1,969 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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 304994 2010-10-30 20:33:46Z gopalv $ */
+
+#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 "apc_pool.h"
+#include "apc_string.h"
+#include "SAPI.h"
+#include "php_scandir.h"
+#include "ext/standard/php_var.h"
+#include "ext/standard/md5.h"
+
+/* {{{ 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, apc_context_t* ctxt, int lazy TSRMLS_DC)
+{
+    int status;
+
+#if APC_HAVE_LOOKUP_HOOKS
+    if(lazy && fn.name[0] != '\0' && strncmp(fn.name, "__autoload", fn.name_len) != 0) {
+        status = zend_hash_add(APCG(lazy_function_table),
+                              fn.name,
+                              fn.name_len+1,
+                              &fn,
+                              sizeof(apc_function_t),
+                              NULL);
+#else
+    if(0) {
+#endif
+    } else {
+        zend_function *func = apc_copy_function_for_execution(fn.function, ctxt TSRMLS_CC);
+        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_error("Cannot redeclare %s()" TSRMLS_CC, fn.name); */
+    }
+
+    return status;
+}
+/* }}} */
+
+/* {{{ apc_lookup_function_hook */
+int apc_lookup_function_hook(char *name, int len, ulong hash, zend_function **fe) {
+    apc_function_t *fn;
+    int status = FAILURE;
+    apc_context_t ctxt = {0,};
+    TSRMLS_FETCH();
+
+    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+    ctxt.copy = APC_COPY_OUT_OPCODE;
+
+    if(zend_hash_quick_find(APCG(lazy_function_table), name, len, hash, (void**)&fn) == SUCCESS) {
+        *fe = apc_copy_function_for_execution(fn->function, &ctxt TSRMLS_CC);
+        status = zend_hash_add(EG(function_table),
+                                  fn->name,
+                                  fn->name_len+1,
+                                  *fe,
+                                  sizeof(zend_function),
+                                  NULL);
+    }
+
+    return status;
+}
+/* }}} */
+
+/* {{{ install_class */
+static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC)
+{
+    zend_class_entry* class_entry = cl.class_entry;
+    zend_class_entry* parent = NULL;
+    int status;
+    zend_class_entry** allocated_ce = NULL;
+
+    /* 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;
+        }
+    }
+
+    if(lazy && cl.name_len != 0 && cl.name[0] != '\0') {
+        status = zend_hash_add(APCG(lazy_class_table),
+                               cl.name,
+                               cl.name_len+1,
+                               &cl,
+                               sizeof(apc_class_t),
+                               NULL);
+        if(status == FAILURE) {
+            zend_error(E_ERROR, "Cannot redeclare class %s", cl.name);
+        }
+        return status;
+    }
+
+    /*
+     * XXX: We need to free this somewhere...
+     */
+    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*) TSRMLS_CC);
+
+    if(!allocated_ce) {
+        return FAILURE;
+    }
+
+    *allocated_ce =
+    class_entry =
+        apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC);
+
+
+    /* restore parent class pointer for compile-time inheritance */
+    if (cl.parent_name != NULL) {
+        zend_class_entry** parent_ptr = NULL;
+        /*
+         * __autoload brings in the old issues with mixed inheritance.
+         * When a statically inherited class triggers autoload, it runs
+         * afoul of a potential require_once "parent.php" in the previous 
+         * line, which when executed provides the parent class, but right
+         * now goes and hits __autoload which could fail. 
+         * 
+         * missing parent == re-compile. 
+         *
+         * whether __autoload is enabled or not, because __autoload errors
+         * cause php to die.
+         *
+         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
+         * zend_lookup_class_ex does it internally anyway!
+         */
+        status = zend_lookup_class_ex(cl.parent_name,
+                                    strlen(cl.parent_name), 
+#ifdef ZEND_ENGINE_2_4
+                                    NULL,
+#endif
+                                    0,
+                                    &parent_ptr TSRMLS_CC);
+        if (status == FAILURE) {
+            if(APCG(report_autofilter)) {
+                apc_warning("Dynamic inheritance detected for class %s" TSRMLS_CC, cl.name);
+            }
+            class_entry->parent = NULL;
+            return status;
+        }
+        else {
+            parent = *parent_ptr;
+            class_entry->parent = parent;
+            zend_do_inheritance(class_entry, parent TSRMLS_CC);
+        }
+
+
+    }
+
+    status = zend_hash_add(EG(class_table),
+                           cl.name,
+                           cl.name_len+1,
+                           allocated_ce,
+                           sizeof(zend_class_entry*),
+                           NULL);
+
+    if (status == FAILURE) {
+        apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name);
+    }
+    return status;
+}
+/* }}} */
+
+/* {{{ apc_lookup_class_hook */
+int apc_lookup_class_hook(char *name, int len, ulong hash, zend_class_entry ***ce) {
+
+    apc_class_t *cl;
+    apc_context_t ctxt = {0,};
+    TSRMLS_FETCH();
+
+    if(zend_is_compiling(TSRMLS_C)) { return FAILURE; }
+
+    if(zend_hash_quick_find(APCG(lazy_class_table), name, len, hash, (void**)&cl) == FAILURE) {
+        return FAILURE;
+    }
+
+    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+    ctxt.copy = APC_COPY_OUT_OPCODE;
+
+    if(install_class(*cl, &ctxt, 0 TSRMLS_CC) == FAILURE) {
+        apc_warning("apc_lookup_class_hook: could not install %s" TSRMLS_CC, name);
+        return FAILURE;
+    }
+
+    if(zend_hash_quick_find(EG(class_table), name, len, hash, (void**)ce) == FAILURE) {
+        apc_warning("apc_lookup_class_hook: known error trying to fetch class %s" TSRMLS_CC, name);
+        return FAILURE;
+    }
+
+    return SUCCESS;
+
+}
+/* }}} */
+
+/* {{{ uninstall_class */
+static int uninstall_class(apc_class_t cl TSRMLS_DC)
+{
+    int status;
+
+    status = zend_hash_del(EG(class_table),
+                           cl.name,
+                           cl.name_len+1);
+    if (status == FAILURE) {
+        apc_error("Cannot delete class %s" TSRMLS_CC, cl.name);
+    }
+    return status;
+}
+/* }}} */
+
+/* {{{ copy_function_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
+static int copy_function_name(apc_function_t *pf TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+{
+    zval *internal_ar = va_arg(args, zval *),
+         *user_ar     = va_arg(args, zval *);
+    zend_function *func = pf->function;
+
+    if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
+        return 0;
+    }
+
+    if (func->type == ZEND_INTERNAL_FUNCTION) {
+        add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
+    } else if (func->type == ZEND_USER_FUNCTION) {
+        add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
+    }
+
+    return 0;
+}
+
+/* {{{ copy_class_or_interface_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
+static int copy_class_or_interface_name(apc_class_t *cl TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+{
+    zval *array = va_arg(args, zval *);
+    zend_uint mask = va_arg(args, zend_uint);
+    zend_uint comply = va_arg(args, zend_uint);
+    zend_uint comply_mask = (comply)? mask:0;
+    zend_class_entry *ce  = cl->class_entry;
+
+    if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
+        && (comply_mask == (ce->ce_flags & mask))) {
+        add_next_index_stringl(array, ce->name, ce->name_length, 1);
+    }
+    return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* }}} */
+
+/* {{{ apc_defined_function_hook */
+int apc_defined_function_hook(zval *internal, zval *user) {
+    TSRMLS_FETCH();
+    zend_hash_apply_with_arguments(APCG(lazy_function_table) 
+#ifdef ZEND_ENGINE_2_3
+    TSRMLS_CC
+#endif
+    ,(apply_func_args_t) copy_function_name, 2, internal, user);
+  return 1;
+}
+/* }}} */
+
+/* {{{ apc_declared_class_hook */
+int apc_declared_class_hook(zval *classes, zend_uint mask, zend_uint comply) {
+    TSRMLS_FETCH();
+    zend_hash_apply_with_arguments(APCG(lazy_class_table) 
+#ifdef ZEND_ENGINE_2_3
+    TSRMLS_CC
+#endif
+    , (apply_func_args_t) copy_class_or_interface_name, 3, classes, mask, comply);
+  return 1;
+}
+/* }}} */
+
+/* {{{ cached_compile */
+static zend_op_array* cached_compile(zend_file_handle* h,
+                                        int type,
+                                        apc_context_t* ctxt 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) {
+        int lazy_classes = APCG(lazy_classes);
+        for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
+            if(install_class(cache_entry->data.file.classes[i], ctxt, lazy_classes TSRMLS_CC) == FAILURE) {
+                goto default_compile;
+            }
+        }
+    }
+
+    if (cache_entry->data.file.functions) {
+        int lazy_functions = APCG(lazy_functions);
+        for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
+            install_function(cache_entry->data.file.functions[i], ctxt, lazy_functions TSRMLS_CC);
+        }
+    }
+
+    apc_do_halt_compiler_register(cache_entry->data.file.filename, cache_entry->data.file.halt_offset TSRMLS_CC);
+
+
+    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array, ctxt TSRMLS_CC);
+
+default_compile:
+
+    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 TSRMLS_CC);
+
+    /* cannot free up cache data yet, it maybe in use */
+
+    return NULL;
+}
+/* }}} */
+
+/* {{{ apc_compile_cache_entry  */
+zend_bool apc_compile_cache_entry(apc_cache_key_t key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array, apc_cache_entry_t** cache_entry TSRMLS_DC) {
+    int num_functions, num_classes;
+    apc_function_t* alloc_functions;
+    zend_op_array* alloc_op_array;
+    apc_class_t* alloc_classes;
+    char *path;
+    apc_context_t ctxt;
+
+    /* 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,  *
+     * we set *op_array here so we return opcodes during     *
+     * a failure.  We should not return prior to this line.  */
+    *op_array = old_compile_file(h, type TSRMLS_CC);
+    if (*op_array == NULL) {
+        return FAILURE;
+    }
+
+    ctxt.pool = apc_pool_create(APC_MEDIUM_POOL, apc_sma_malloc, apc_sma_free, 
+                                                 apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+    if (!ctxt.pool) {
+        apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+        return FAILURE;
+    }
+    ctxt.copy = APC_COPY_IN_OPCODE;
+
+    if(APCG(file_md5)) {
+        int n;
+        unsigned char buf[1024];
+        PHP_MD5_CTX context;
+        php_stream *stream;
+        char *filename;
+
+        if(h->opened_path) {
+            filename = h->opened_path;
+        } else {
+            filename = h->filename;
+        }
+        stream = php_stream_open_wrapper(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+        if(stream) {
+            PHP_MD5Init(&context);
+            while((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
+                PHP_MD5Update(&context, buf, n);
+            }
+            PHP_MD5Final(key.md5, &context);
+            php_stream_close(stream);
+            if(n<0) {
+                apc_warning("Error while reading '%s' for md5 generation." TSRMLS_CC, filename);
+            }
+        } else {
+            apc_warning("Unable to open '%s' for md5 generation." TSRMLS_CC, filename);
+        }
+    }
+
+    if(!(alloc_op_array = apc_copy_op_array(NULL, *op_array, &ctxt TSRMLS_CC))) {
+        goto freepool;
+    }
+
+    if(!(alloc_functions = apc_copy_new_functions(num_functions, &ctxt TSRMLS_CC))) {
+        goto freepool;
+    }
+    if(!(alloc_classes = apc_copy_new_classes(*op_array, num_classes, &ctxt TSRMLS_CC))) {
+        goto freepool;
+    }
+
+    path = h->opened_path;
+    if(!path) path=h->filename;
+
+    apc_debug("2. h->opened_path=[%s]  h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
+
+    if(!(*cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
+        goto freepool;
+    }
+
+    return SUCCESS;
+
+freepool:
+    apc_pool_destroy(ctxt.pool TSRMLS_CC);
+    ctxt.pool = NULL;
+
+    return FAILURE;
+
+}
+/* }}} */
+
+/* {{{ 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 = NULL;
+    time_t t;
+    apc_context_t ctxt = {0,};
+    int bailout=0;
+	const char* filename = NULL;
+
+    if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
+        return old_compile_file(h, type TSRMLS_CC);
+    }
+
+    if(h->opened_path) {
+        filename = h->opened_path;
+    } else {
+        filename = h->filename;
+    }
+
+    /* check our regular expression filters */
+    if (APCG(filters) && APCG(compiled_filters) && filename) {
+        int ret = apc_regex_match_array(APCG(compiled_filters), 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);
+    }
+    APCG(current_cache) = apc_cache;
+
+
+    t = apc_time();
+
+    apc_debug("1. h->opened_path=[%s]  h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
+
+    /* 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 TSRMLS_CC);
+        ctxt.force_update = 0;
+    } else {
+        cache_entry = NULL;
+        ctxt.force_update = 1;
+    }
+
+    if (cache_entry != NULL) {
+        int dummy = 1;
+        
+        ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free,
+                                                apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+        if (!ctxt.pool) {
+            apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+            return old_compile_file(h, type TSRMLS_CC);
+        }
+        ctxt.copy = APC_COPY_OUT_OPCODE;
+        
+        zend_hash_add(&EG(included_files), cache_entry->data.file.filename, 
+                            strlen(cache_entry->data.file.filename)+1,
+                            (void *)&dummy, sizeof(int), NULL);
+
+        apc_stack_push(APCG(cache_stack), cache_entry TSRMLS_CC);
+        op_array = cached_compile(h, type, &ctxt 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
+            /* this is an unpool, which has no cleanup - this only free's the pool header */
+            apc_pool_destroy(ctxt.pool TSRMLS_CC);
+            
+            /* We might leak fds without this hack */
+            if (h->type != ZEND_HANDLE_FILENAME) {
+                zend_llist_add_element(&CG(open_files), h); 
+            }
+            return op_array;
+        }
+        if(APCG(report_autofilter)) {
+            apc_warning("Autofiltering %s" TSRMLS_CC, 
+                            (h->opened_path ? h->opened_path : h->filename));
+            apc_warning("Recompiling %s" TSRMLS_CC, cache_entry->data.file.filename);
+        }
+        /* TODO: check what happens with EG(included_files) */
+    }
+
+    /* Make sure the mtime reflects the files last known mtime, and we respect max_file_size 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 TSRMLS_CC) != 0) {
+                apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC,h->filename,SG(request_info).path_translated);
+                return old_compile_file(h, type TSRMLS_CC);
+            }
+        }
+        if (APCG(max_file_size) < fileinfo.st_buf.sb.st_size) { 
+            apc_debug("File is too big %s (%ld) - bailing\n" TSRMLS_CC, h->filename, fileinfo.st_buf.sb.st_size);
+            return old_compile_file(h, type TSRMLS_CC);
+        }
+        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 TSRMLS_CC)) {
+            HANDLE_UNBLOCK_INTERRUPTIONS();
+            return old_compile_file(h, type TSRMLS_CC);
+        }
+    }
+#endif
+
+    zend_try {
+        if (apc_compile_cache_entry(key, h, type, t, &op_array, &cache_entry TSRMLS_CC) == SUCCESS) {
+            ctxt.pool = cache_entry->pool;
+            ctxt.copy = APC_COPY_IN_OPCODE;
+            if (apc_cache_insert(apc_cache, key, cache_entry, &ctxt, t TSRMLS_CC) != 1) {
+                apc_pool_destroy(ctxt.pool TSRMLS_CC);
+                ctxt.pool = NULL;
+            }
+        }
+    } zend_catch {
+        bailout=1; /* in the event of a bailout, ensure we don't create a dead-lock */
+    } zend_end_try();
+
+    APCG(current_cache) = NULL;
+
+#if NONBLOCKING_LOCK_AVAILABLE
+    if(APCG(write_lock)) {
+        apc_cache_write_unlock(apc_cache TSRMLS_CC);
+    }
+#endif
+    HANDLE_UNBLOCK_INTERRUPTIONS();
+
+    if (bailout) zend_bailout();
+
+    return op_array;
+}
+/* }}} */
+
+/* {{{ data preload */
+
+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
+
+static zval* data_unserialize(const char *filename TSRMLS_DC)
+{
+    zval* retval;
+    long len = 0;
+    struct stat sb;
+    char *contents, *tmp;
+    FILE *fp;
+    php_unserialize_data_t var_hash;
+
+    if(VCWD_STAT(filename, &sb) == -1) {
+        return NULL;
+    }
+
+    fp = fopen(filename, "rb");
+
+    len = sizeof(char)*sb.st_size;
+
+    tmp = contents = malloc(len);
+
+    if(!contents) {
+       return NULL;
+    }
+
+    if(fread(contents, 1, len, fp) < 1) {	
+      free(contents);
+      return NULL;
+    }
+
+    MAKE_STD_ZVAL(retval);
+
+    PHP_VAR_UNSERIALIZE_INIT(var_hash);
+    
+    /* I wish I could use json */
+    if(!php_var_unserialize(&retval, (const unsigned char**)&tmp, (const unsigned char*)(contents+len), &var_hash TSRMLS_CC)) {
+        zval_ptr_dtor(&retval);
+        return NULL;
+    }
+
+    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+    free(contents);
+    fclose(fp);
+
+    return retval;
+}
+
+static int apc_load_data(const char *data_file TSRMLS_DC)
+{
+    char *p;
+    char key[MAXPATHLEN] = {0,};
+    unsigned int key_len;
+    zval *data;
+
+    p = strrchr(data_file, DEFAULT_SLASH);
+
+    if(p && p[1]) {
+        strlcpy(key, p+1, sizeof(key));
+        p = strrchr(key, '.');
+
+        if(p) {
+            p[0] = '\0';
+            key_len = strlen(key);
+
+            data = data_unserialize(data_file TSRMLS_CC);
+            if(data) {
+                _apc_store(key, key_len, data, 0, 1 TSRMLS_CC);
+            }
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static int apc_walk_dir(const char *path TSRMLS_DC)
+{
+    char file[MAXPATHLEN]={0,};
+    int ndir, i;
+    char *p = NULL;
+    struct dirent **namelist = NULL;
+
+    if ((ndir = php_scandir(path, &namelist, 0, php_alphasort)) > 0)
+    {
+        for (i = 0; i < ndir; i++)
+        {
+            /* check for extension */
+            if (!(p = strrchr(namelist[i]->d_name, '.'))
+                    || (p && strcmp(p, ".data")))
+            {
+                free(namelist[i]);
+                continue;
+            }
+            snprintf(file, MAXPATHLEN, "%s%c%s",
+                    path, DEFAULT_SLASH, namelist[i]->d_name);
+            if(!apc_load_data(file TSRMLS_CC))
+            {
+                /* print error */
+            }
+            free(namelist[i]);
+        }
+        free(namelist);
+    }
+
+    return 1;
+}
+
+void apc_data_preload(TSRMLS_D)
+{
+    if(!APCG(preload_path)) return;
+
+    apc_walk_dir(APCG(preload_path) TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ 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), APCG(mmap_file_mask) TSRMLS_CC);
+#else
+    apc_sma_init(APCG(shm_segments), APCG(shm_size), NULL TSRMLS_CC);
+#endif
+    apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl) TSRMLS_CC);
+    apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl) TSRMLS_CC);
+
+    /* 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);
+    REGISTER_LONG_CONSTANT("\000apc_compile_file", (long)&my_compile_file, CONST_PERSISTENT | CONST_CS);
+
+    apc_pool_init();
+
+    apc_data_preload(TSRMLS_C);
+
+#if APC_HAVE_LOOKUP_HOOKS
+    if(APCG(lazy_functions)) {
+        zend_set_lookup_function_hook(apc_lookup_function_hook TSRMLS_CC);
+        zend_set_defined_function_hook(apc_defined_function_hook TSRMLS_CC);
+    }
+    if(APCG(lazy_classes)) {
+        zend_set_lookup_class_hook(apc_lookup_class_hook TSRMLS_CC);
+        zend_set_declared_class_hook(apc_declared_class_hook TSRMLS_CC);
+    }
+#else
+    if(APCG(lazy_functions) || APCG(lazy_classes)) {
+        apc_warning("Lazy function/class loading not available with this version of PHP, please disable APC lazy loading." TSRMLS_CC);
+        APCG(lazy_functions) = APCG(lazy_classes) = 0;
+    }
+#endif
+
+#ifdef ZEND_ENGINE_2_4
+    apc_interned_strings_init(TSRMLS_C);
+#endif
+
+    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 TSRMLS_CC);
+    }
+
+    apc_cache_destroy(apc_cache TSRMLS_CC);
+    apc_cache_destroy(apc_user_cache TSRMLS_CC);
+    apc_sma_cleanup(TSRMLS_C);
+
+#ifdef ZEND_ENGINE_2_4
+    apc_interned_strings_shutdown(TSRMLS_C);
+#endif
+
+    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);
+        zend_class_entry** pzce = NULL;
+
+        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++) {
+                centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
+                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;
+                }
+
+                zce = *pzce;
+
+                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 TSRMLS_CC);
+            }
+        }
+        apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
+    }
+}
+/* }}} */
+
+/* {{{ request init and shutdown */
+
+int apc_request_init(TSRMLS_D)
+{
+    apc_stack_clear(APCG(cache_stack));
+    if (!APCG(compiled_filters) && APCG(filters)) {
+        /* compile regex filters here to avoid race condition between MINIT of PCRE and APC.
+         * This should be moved to apc_cache_create() if this race condition between modules is resolved */
+        APCG(compiled_filters) = apc_regex_compile_array(APCG(filters) TSRMLS_CC);
+    }
+
+#if APC_HAVE_LOOKUP_HOOKS
+    if(APCG(lazy_functions)) {
+        APCG(lazy_function_table) = emalloc(sizeof(HashTable));
+        zend_hash_init(APCG(lazy_function_table), 0, NULL, NULL, 0);
+    }
+    if(APCG(lazy_classes)) {
+        APCG(lazy_class_table) = emalloc(sizeof(HashTable));
+        zend_hash_init(APCG(lazy_class_table), 0, NULL, NULL, 0);
+    }
+#endif
+
+#ifdef APC_FILEHITS
+    ALLOC_INIT_ZVAL(APCG(filehits));
+    array_init(APCG(filehits));
+#endif
+
+    return 0;
+}
+
+int apc_request_shutdown(TSRMLS_D)
+{
+
+#if APC_HAVE_LOOKUP_HOOKS
+    if(APCG(lazy_class_table)) {
+        zend_hash_destroy(APCG(lazy_class_table));
+        efree(APCG(lazy_class_table));
+    }
+    if(APCG(lazy_function_table)) {
+        zend_hash_destroy(APCG(lazy_function_table));
+        efree(APCG(lazy_function_table));
+    }
+#endif
+
+    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:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_main.h
@@ -0,0 +1,74 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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.h 300979 2010-07-04 10:15:05Z kalle $ */
+
+#ifndef APC_MAIN_H
+#define APC_MAIN_H
+
+#include "apc_pool.h"
+
+/*
+ * This module provides the primary interface between PHP and APC.
+ */
+
+extern int apc_module_init(int module_number TSRMLS_DC);
+extern int apc_module_shutdown(TSRMLS_D);
+extern int apc_process_init(int module_number TSRMLS_DC);
+extern int apc_process_shutdown(TSRMLS_D);
+extern int apc_request_init(TSRMLS_D);
+extern int apc_request_shutdown(TSRMLS_D);
+
+typedef enum _apc_copy_type {
+    APC_NO_COPY = 0,
+    APC_COPY_IN_OPCODE,
+    APC_COPY_OUT_OPCODE,
+    APC_COPY_IN_USER,
+    APC_COPY_OUT_USER
+} apc_copy_type;
+
+typedef struct _apc_context_t
+{
+    apc_pool *pool;
+    apc_copy_type copy;
+    unsigned int force_update:1;
+} apc_context_t;
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_mmap.c
@@ -0,0 +1,175 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_mmap.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc.h"
+#include "apc_mmap.h"
+#include "apc_lock.h"
+
+#if APC_MMAP
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+/*
+ * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
+ * tells whatever update daemons might be running to not flush dirty
+ * vm pages to disk unless absolutely necessary.  My guess is that
+ * most systems that don't have this probably default to only synching
+ * to disk when absolutely necessary.
+ */
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC 0
+#endif
+
+/* support for systems where MAP_ANONYMOUS is defined but not MAP_ANON, ie: HP-UX bug #14615 */
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+
+apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC)
+{
+    apc_segment_t segment; 
+
+    int fd = -1;
+    int flags = MAP_SHARED | MAP_NOSYNC;
+    int remap = 1;
+
+    /* If no filename was provided, do an anonymous mmap */
+    if(!file_mask || (file_mask && !strlen(file_mask))) {
+#if !defined(MAP_ANON)
+        apc_error("Anonymous mmap does not apear to be available on this system (MAP_ANON/MAP_ANONYMOUS).  Please see the apc.mmap_file_mask INI option." TSRMLS_CC);
+#else
+        fd = -1;
+        flags = MAP_SHARED | MAP_ANON;
+        remap = 0;
+#endif
+    } else if(!strcmp(file_mask,"/dev/zero")) { 
+        fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
+        if(fd == -1) {
+            apc_error("apc_mmap: open on /dev/zero failed:" TSRMLS_CC);
+            goto error;
+        }
+        remap = 0; /* cannot remap */
+    } else if(strstr(file_mask,".shm")) {
+        /*
+         * If the filemask contains .shm we try to do a POSIX-compliant shared memory
+         * backed mmap which should avoid synchs on some platforms.  At least on
+         * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
+         * a file in a mounted shmfs.  For this to work on Linux you need to make sure
+         * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
+         * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
+         * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
+         * path you want here.
+         */
+        if(!mktemp(file_mask)) {
+            apc_error("apc_mmap: mktemp on %s failed:" TSRMLS_CC, file_mask);
+            goto error;
+        }
+        fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
+        if(fd == -1) {
+            apc_error("apc_mmap: shm_open on %s failed:" TSRMLS_CC, file_mask);
+            goto error;
+        }
+        if (ftruncate(fd, size) < 0) {
+            close(fd);
+            shm_unlink(file_mask);
+            apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
+            goto error;
+        }
+        shm_unlink(file_mask);
+    } else {
+        /*
+         * Otherwise we do a normal filesystem mmap
+         */
+        fd = mkstemp(file_mask);
+        if(fd == -1) {
+            apc_error("apc_mmap: mkstemp on %s failed:" TSRMLS_CC, file_mask);
+            goto error;
+        }
+        if (ftruncate(fd, size) < 0) {
+            close(fd);
+            unlink(file_mask);
+            apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
+            goto error;
+        }
+        unlink(file_mask);
+    }
+
+    segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
+
+#ifdef APC_MEMPROTECT
+    if(remap) {
+        segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0);
+    } else {
+        segment.roaddr = NULL;
+    }
+#endif
+
+    if((long)segment.shmaddr == -1) {
+        apc_error("apc_mmap: mmap failed:" TSRMLS_CC);
+    }
+
+    if(fd != -1) close(fd);
+    
+    return segment;
+
+error:
+
+    segment.shmaddr = (void*)-1;
+#ifdef APC_MEMPROTECT
+    segment.roaddr = NULL;
+#endif
+    return segment;
+}
+
+void apc_unmap(apc_segment_t *segment TSRMLS_DC)
+{
+    if (munmap(segment->shmaddr, segment->size) < 0) {
+        apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
+    }
+
+#ifdef APC_MEMPROTECT
+    if (segment->roaddr && munmap(segment->roaddr, segment->size) < 0) {
+        apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
+    }
+#endif
+
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_mmap.h
@@ -0,0 +1,54 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Gopal V <gopalv@php.net>                                    |
+  +----------------------------------------------------------------------+
+
+   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_mmap.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_MMAP_H
+#define APC_MMAP_H
+
+#include <limits.h>
+
+#include "apc.h"
+#include "apc_sma.h"
+
+/* Wrapper functions for shared memory mapped files */
+
+#if APC_MMAP
+apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC);
+void apc_unmap(apc_segment_t* segment TSRMLS_DC);
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc.php
@@ -0,0 +1,1362 @@
+<?php
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Ralf Becker <beckerr@php.net>                               |
+  |          Rasmus Lerdorf <rasmus@php.net>                             |
+  |          Ilia Alshanetsky <ilia@prohost.org>                         |
+  +----------------------------------------------------------------------+
+
+   All other licensing and usage conditions are those of the PHP Group.
+
+ */
+
+$VERSION='$Id: apc.php 304410 2010-10-15 11:21:07Z gopalv $';
+
+////////// READ OPTIONAL CONFIGURATION FILE ////////////
+if (file_exists("apc.conf.php")) include("apc.conf.php");
+////////////////////////////////////////////////////////
+
+////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
+
+defaults('USE_AUTHENTICATION',1);			// Use (internal) authentication - best choice if 
+											// no other authentication is available
+											// If set to 0:
+											//  There will be no further authentication. You 
+											//  will have to handle this by yourself!
+											// If set to 1:
+											//  You need to change ADMIN_PASSWORD to make
+											//  this work!
+defaults('ADMIN_USERNAME','apc'); 			// Admin Username
+defaults('ADMIN_PASSWORD','password');  	// Admin Password - CHANGE THIS TO ENABLE!!!
+
+// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
+//           users generate a md5 or crypt password in a easy way to fill it in above
+
+//defaults('DATE_FORMAT', "d.m.Y H:i:s");	// German
+defaults('DATE_FORMAT', 'Y/m/d H:i:s'); 	// US
+
+defaults('GRAPH_SIZE',200);					// Image size
+
+//defaults('PROXY', 'tcp://127.0.0.1:8080');
+
+////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
+
+
+// "define if not defined"
+function defaults($d,$v) {
+	if (!defined($d)) define($d,$v); // or just @define(...)
+}
+
+// rewrite $PHP_SELF to block XSS attacks
+//
+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';
+$time = time();
+$host = php_uname('n');
+if($host) { $host = '('.$host.')'; }
+if (isset($_SERVER['SERVER_ADDR'])) {
+  $host .= ' ('.$_SERVER['SERVER_ADDR'].')';
+}
+
+// operation constants
+define('OB_HOST_STATS',1);
+define('OB_SYS_CACHE',2);
+define('OB_USER_CACHE',3);
+define('OB_SYS_CACHE_DIR',4);
+define('OB_VERSION_CHECK',9);
+
+// check validity of input variables
+$vardom=array(
+	'OB'	=> '/^\d+$/',			// operational mode switch
+	'CC'	=> '/^[01]$/',			// clear cache requested
+	'DU'	=> '/^.*$/',			// Delete User Key
+	'SH'	=> '/^[a-z0-9]+$/',		// shared object description
+
+	'IMG'	=> '/^[123]$/',			// image to generate
+	'LO'	=> '/^1$/',				// login requested
+
+	'COUNT'	=> '/^\d+$/',			// number of line displayed in list
+	'SCOPE'	=> '/^[AD]$/',			// list view scope
+	'SORT1'	=> '/^[AHSMCDTZ]$/',	// first sort key
+	'SORT2'	=> '/^[DA]$/',			// second sort key
+	'AGGR'	=> '/^\d+$/',			// aggregation by dir level
+	'SEARCH'	=> '~^[a-zA-Z0-1/_.-]*$~'			// aggregation by dir level
+);
+
+// default cache mode
+$cache_mode='opcode';
+
+// cache scope
+$scope_list=array(
+	'A' => 'cache_list',
+	'D' => 'deleted_list'
+);
+
+// handle POST and GET requests
+if (empty($_REQUEST)) {
+	if (!empty($_GET) && !empty($_POST)) {
+		$_REQUEST = array_merge($_GET, $_POST);
+	} else if (!empty($_GET)) {
+		$_REQUEST = $_GET;
+	} else if (!empty($_POST)) {
+		$_REQUEST = $_POST;
+	} else {
+		$_REQUEST = array();
+	}
+}
+
+// check parameter syntax
+foreach($vardom as $var => $dom) {
+	if (!isset($_REQUEST[$var])) {
+		$MYREQUEST[$var]=NULL;
+	} else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
+		$MYREQUEST[$var]=$_REQUEST[$var];
+	} else {
+		$MYREQUEST[$var]=$_REQUEST[$var]=NULL;
+	}
+}
+
+// check parameter sematics
+if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
+if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
+if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
+if (empty($MYREQUEST['OB']))	$MYREQUEST['OB']=OB_HOST_STATS;
+if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
+if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
+
+$MY_SELF=
+	"$PHP_SELF".
+	"?SCOPE=".$MYREQUEST['SCOPE'].
+	"&SORT1=".$MYREQUEST['SORT1'].
+	"&SORT2=".$MYREQUEST['SORT2'].
+	"&COUNT=".$MYREQUEST['COUNT'];
+$MY_SELF_WO_SORT=
+	"$PHP_SELF".
+	"?SCOPE=".$MYREQUEST['SCOPE'].
+	"&COUNT=".$MYREQUEST['COUNT'];
+
+// authentication needed?
+//
+if (!USE_AUTHENTICATION) {
+	$AUTHENTICATED=1;
+} else {
+	$AUTHENTICATED=0;
+	if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
+
+		if (!isset($_SERVER['PHP_AUTH_USER']) ||
+			!isset($_SERVER['PHP_AUTH_PW']) ||
+			$_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
+			$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
+			Header("WWW-Authenticate: Basic realm=\"APC Login\"");
+			Header("HTTP/1.0 401 Unauthorized");
+
+			echo <<<EOB
+				<html><body>
+				<h1>Rejected!</h1>
+				<big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
+				<big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
+				</body></html>
+EOB;
+			exit;
+			
+		} else {
+			$AUTHENTICATED=1;
+		}
+	}
+}
+	
+// select cache mode
+if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
+	$cache_mode='user';
+}
+// clear cache
+if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
+	apc_clear_cache($cache_mode);
+}
+
+if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
+	apc_delete($MYREQUEST['DU']);
+}
+
+if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
+	echo "No cache info available.  APC does not appear to be running.";
+  exit;
+}
+
+$cache_user = apc_cache_info('user', 1);  
+$mem=apc_sma_info();
+if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
+
+// don't cache this page
+//
+header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");                                    // HTTP/1.0
+
+function duration($ts) {
+    global $time;
+    $years = (int)((($time - $ts)/(7*86400))/52.177457);
+    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
+    $weeks = (int)(($rem)/(7*86400));
+    $days = (int)(($rem)/86400) - $weeks*7;
+    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
+    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
+    $str = '';
+    if($years==1) $str .= "$years year, ";
+    if($years>1) $str .= "$years years, ";
+    if($weeks==1) $str .= "$weeks week, ";
+    if($weeks>1) $str .= "$weeks weeks, ";
+    if($days==1) $str .= "$days day,";
+    if($days>1) $str .= "$days days,";
+    if($hours == 1) $str .= " $hours hour and";
+    if($hours>1) $str .= " $hours hours and";
+    if($mins == 1) $str .= " 1 minute";
+    else $str .= " $mins minutes";
+    return $str;
+}
+
+// create graphics
+//
+function graphics_avail() {
+	return extension_loaded('gd');
+}
+if (isset($MYREQUEST['IMG']))
+{
+	if (!graphics_avail()) {
+		exit(0);
+	}
+
+	function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
+		$r=$diameter/2;
+		$w=deg2rad((360+$start+($end-$start)/2)%360);
+
+		
+		if (function_exists("imagefilledarc")) {
+			// exists only if GD 2.0.1 is avaliable
+			imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
+			imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
+			imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
+		} else {
+			imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
+			imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
+		}
+		if ($text) {
+			if ($placeindex>0) {
+				imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
+				imagestring($im,4,$diameter, $placeindex*12,$text,$color1);	
+				
+			} else {
+				imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
+			}
+		}
+	} 
+
+	function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
+		$r=$diameter/2;
+		$w=deg2rad((360+$start+($end-$start)/2)%360);
+
+		if ($placeindex>0) {
+			imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
+			imagestring($im,4,$diameter, $placeindex*12,$text,$color1);	
+				
+		} else {
+			imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
+		}
+	} 
+	
+	function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
+		global $col_black;
+		$x1=$x+$w-1;
+		$y1=$y+$h-1;
+
+		imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
+		if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
+		else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
+		imagerectangle($im, $x, $y1, $x1, $y, $color1);
+		if ($text) {
+			if ($placeindex>0) {
+			
+				if ($placeindex<16)
+				{
+					$px=5;
+					$py=$placeindex*12+6;
+					imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
+					imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
+					imagestring($im,2,$px,$py-6,$text,$color1);	
+					
+				} else {
+					if ($placeindex<31) {
+						$px=$x+40*2;
+						$py=($placeindex-15)*12+6;
+					} else {
+						$px=$x+40*2+100*intval(($placeindex-15)/15);
+						$py=($placeindex%15)*12+6;
+					}
+					imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
+					imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
+					imagestring($im,2,$px+2,$py-6,$text,$color1);	
+				}
+			} else {
+				imagestring($im,4,$x+5,$y1-16,$text,$color1);
+			}
+		}
+	}
+
+
+	$size = GRAPH_SIZE; // image size
+	if ($MYREQUEST['IMG']==3)
+		$image = imagecreate(2*$size+150, $size+10);
+	else
+		$image = imagecreate($size+50, $size+10);
+
+	$col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
+	$col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
+	$col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
+	$col_black = imagecolorallocate($image,   0,   0,   0);
+	imagecolortransparent($image,$col_white);
+
+	switch ($MYREQUEST['IMG']) {
+	
+	case 1:
+		$s=$mem['num_seg']*$mem['seg_size'];
+		$a=$mem['avail_mem'];
+		$x=$y=$size/2;
+		$fuzz = 0.000001;
+
+		// This block of code creates the pie chart.  It is a lot more complex than you
+		// would expect because we try to visualize any memory fragmentation as well.
+		$angle_from = 0;
+		$string_placement=array();
+		for($i=0; $i<$mem['num_seg']; $i++) {	
+			$ptr = 0;
+			$free = $mem['block_lists'][$i];
+			uasort($free, 'block_sort');
+			foreach($free as $block) {
+				if($block['offset']!=$ptr) {       // Used block
+					$angle_to = $angle_from+($block['offset']-$ptr)/$s;
+					if(($angle_to+$fuzz)>1) $angle_to = 1;
+					if( ($angle_to*360) - ($angle_from*360) >= 1) {
+						fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
+						if (($angle_to-$angle_from)>0.05) {
+							array_push($string_placement, array($angle_from,$angle_to));
+						}
+					}
+					$angle_from = $angle_to;
+				}
+				$angle_to = $angle_from+($block['size'])/$s;
+				if(($angle_to+$fuzz)>1) $angle_to = 1;
+				if( ($angle_to*360) - ($angle_from*360) >= 1) {
+					fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
+					if (($angle_to-$angle_from)>0.05) {
+						array_push($string_placement, array($angle_from,$angle_to));
+					}
+				}
+				$angle_from = $angle_to;
+				$ptr = $block['offset']+$block['size'];
+			}
+			if ($ptr < $mem['seg_size']) { // memory at the end 
+				$angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
+				if(($angle_to+$fuzz)>1) $angle_to = 1;
+				fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
+				if (($angle_to-$angle_from)>0.05) {
+					array_push($string_placement, array($angle_from,$angle_to));
+				}
+			}
+		}
+		foreach ($string_placement as $angle) {
+			text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
+		}
+		break;
+		
+	case 2: 
+		$s=$cache['num_hits']+$cache['num_misses'];
+		$a=$cache['num_hits'];
+		
+		fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
+		fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
+		break;
+		
+	case 3:
+		$s=$mem['num_seg']*$mem['seg_size'];
+		$a=$mem['avail_mem'];
+		$x=130;
+		$y=1;
+		$j=1;
+
+		// This block of code creates the bar chart.  It is a lot more complex than you
+		// would expect because we try to visualize any memory fragmentation as well.
+		for($i=0; $i<$mem['num_seg']; $i++) {	
+			$ptr = 0;
+			$free = $mem['block_lists'][$i];
+			uasort($free, 'block_sort');
+			foreach($free as $block) {
+				if($block['offset']!=$ptr) {       // Used block
+					$h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
+					if ($h>0) {
+                                                $j++;
+						if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
+                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
+                                        }
+					$y+=$h;
+				}
+				$h=(GRAPH_SIZE-5)*($block['size'])/$s;
+				if ($h>0) {
+                                        $j++;
+					if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
+					else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
+                                }
+				$y+=$h;
+				$ptr = $block['offset']+$block['size'];
+			}
+			if ($ptr < $mem['seg_size']) { // memory at the end 
+				$h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
+				if ($h > 0) {
+					fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
+				}
+			}
+		}
+		break;
+	case 4: 
+		$s=$cache['num_hits']+$cache['num_misses'];
+		$a=$cache['num_hits'];
+	        	
+		fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
+		fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
+		break;
+	
+	}
+	header("Content-type: image/png");
+	imagepng($image);
+	exit;
+}
+
+// pretty printer for byte values
+//
+function bsize($s) {
+	foreach (array('','K','M','G') as $i => $k) {
+		if ($s < 1024) break;
+		$s/=1024;
+	}
+	return sprintf("%5.1f %sBytes",$s,$k);
+}
+
+// sortable table header in "scripts for this host" view
+function sortheader($key,$name,$extra='') {
+	global $MYREQUEST, $MY_SELF_WO_SORT;
+	
+	if ($MYREQUEST['SORT1']==$key) {
+		$MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
+	}
+	return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
+
+}
+
+// create menu entry 
+function menu_entry($ob,$title) {
+	global $MYREQUEST,$MY_SELF;
+	if ($MYREQUEST['OB']!=$ob) {
+		return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
+	} else if (empty($MYREQUEST['SH'])) {
+		return "<li><span class=active>$title</span></li>";
+	} else {
+		return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";	
+	}
+}
+
+function put_login_link($s="Login")
+{
+	global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
+	// needs ADMIN_PASSWORD to be changed!
+	//
+	if (!USE_AUTHENTICATION) {
+		return;
+	} else if (ADMIN_PASSWORD=='password')
+	{
+		print <<<EOB
+			<a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
+EOB;
+	} else if ($AUTHENTICATED) {
+		print <<<EOB
+			'{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
+EOB;
+	} else{
+		print <<<EOB
+			<a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
+EOB;
+	}
+}
+
+function block_sort($array1, $array2)
+{
+	if ($array1['offset'] > $array2['offset']) {
+		return 1;
+	} else {
+		return -1;
+	}
+}
+
+
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head><title>APC INFO <?php echo $host ?></title>
+<style><!--
+body { background:white; font-size:100.01%; margin:0; padding:0; }
+body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
+* html body   {font-size:0.8em}
+* html p      {font-size:0.8em}
+* html td     {font-size:0.8em}
+* html th     {font-size:0.8em}
+* html input  {font-size:0.8em}
+* html submit {font-size:0.8em}
+td { vertical-align:top }
+a { color:black; font-weight:none; text-decoration:none; }
+a:hover { text-decoration:underline; }
+div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
+
+
+div.head div.login {
+	position:absolute;
+	right: 1em;
+	top: 1.2em;
+	color:white;
+	width:6em;
+	}
+div.head div.login a {
+	position:absolute;
+	right: 0em;
+	background:rgb(119,123,180);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	}
+div.head div.login a:hover {
+	background:rgb(193,193,244);
+	}
+
+h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
+* html h1.apc { margin-bottom:-7px; }
+h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
+h1.apc div.logo span.logo {
+	background:rgb(119,123,180);
+	color:black;
+	border-right: solid black 1px;
+	border-bottom: solid black 1px;
+	font-style:italic;
+	font-size:1em;
+	padding-left:1.2em;
+	padding-right:1.2em;
+	text-align:right;
+	}
+h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
+h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
+h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
+hr.apc {
+	background:white;
+	border-bottom:solid rgb(102,102,153) 1px;
+	border-style:none;
+	border-top:solid rgb(102,102,153) 10px;
+	height:12px;
+	margin:0;
+	margin-top:1px;
+	padding:0;
+}
+
+ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
+ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
+ol.menu a {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	margin-left: 5px;
+	}
+ol.menu a.child_active {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	border-left: solid black 5px;
+	margin-left: 0px;
+	}
+ol.menu span.active {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:black;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	border-left: solid black 5px;
+	}
+ol.menu span.inactive {
+	background:rgb(193,193,244);
+	border:solid rgb(182,182,233) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	margin-left: 5px;
+	}
+ol.menu a:hover {
+	background:rgb(193,193,244);
+	text-decoration:none;
+	}
+	
+	
+div.info {
+	background:rgb(204,204,204);
+	border:solid rgb(204,204,204) 1px;
+	margin-bottom:1em;
+	}
+div.info h2 {
+	background:rgb(204,204,204);
+	color:black;
+	font-size:1em;
+	margin:0;
+	padding:0.1em 1em 0.1em 1em;
+	}
+div.info table {
+	border:solid rgb(204,204,204) 1px;
+	border-spacing:0;
+	width:100%;
+	}
+div.info table th {
+	background:rgb(204,204,204);
+	color:white;
+	margin:0;
+	padding:0.1em 1em 0.1em 1em;
+	}
+div.info table th a.sortable { color:black; }
+div.info table tr.tr-0 { background:rgb(238,238,238); }
+div.info table tr.tr-1 { background:rgb(221,221,221); }
+div.info table td { padding:0.3em 1em 0.3em 1em; }
+div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
+div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
+div.info table td h3 {
+	color:black;
+	font-size:1.1em;
+	margin-left:-0.3em;
+	}
+
+div.graph { margin-bottom:1em }
+div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
+div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
+div.graph table td.td-0 { background:rgb(238,238,238); }
+div.graph table td.td-1 { background:rgb(221,221,221); }
+div.graph table td { padding:0.2em 1em 0.4em 1em; }
+
+div.div1,div.div2 { margin-bottom:1em; width:35em; }
+div.div3 { position:absolute; left:40em; top:1em; width:580px; }
+//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
+
+div.sorting { margin:1.5em 0em 1.5em 2em }
+.center { text-align:center }
+.aright { position:absolute;right:1em }
+.right { text-align:right }
+.ok { color:rgb(0,200,0); font-weight:bold}
+.failed { color:rgb(200,0,0); font-weight:bold}
+
+span.box {
+	border: black solid 1px;
+	border-right:solid black 2px;
+	border-bottom:solid black 2px;
+	padding:0 0.5em 0 0.5em;
+	margin-right:1em;
+}
+span.green { background:#60F060; padding:0 0.5em 0 0.5em}
+span.red { background:#D06030; padding:0 0.5em 0 0.5em }
+
+div.authneeded {
+	background:rgb(238,238,238);
+	border:solid rgb(204,204,204) 1px;
+	color:rgb(200,0,0);
+	font-size:1.2em;
+	font-weight:bold;
+	padding:2em;
+	text-align:center;
+	}
+	
+input {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:1em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	}
+//-->
+</style>
+</head>
+<body>
+<div class="head">
+	<h1 class="apc">
+		<div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
+		<div class="nameinfo">Opcode Cache</div>
+	</h1>
+	<div class="login">
+	<?php put_login_link(); ?>
+	</div>
+	<hr class="apc">
+</div>
+<?php
+
+
+// Display main Menu
+echo <<<EOB
+	<ol class=menu>
+	<li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
+EOB;
+echo
+	menu_entry(1,'View Host Stats'),
+	menu_entry(2,'System Cache Entries');
+if ($AUTHENTICATED) {
+	echo menu_entry(4,'Per-Directory Entries');
+}
+echo
+	menu_entry(3,'User Cache Entries'),
+	menu_entry(9,'Version Check');
+	
+if ($AUTHENTICATED) {
+	echo <<<EOB
+		<li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascript:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
+EOB;
+}
+echo <<<EOB
+	</ol>
+EOB;
+
+
+// CONTENT
+echo <<<EOB
+	<div class=content>
+EOB;
+
+// MAIN SWITCH STATEMENT 
+
+switch ($MYREQUEST['OB']) {
+
+
+
+
+
+// -----------------------------------------------
+// Host Stats
+// -----------------------------------------------
+case OB_HOST_STATS:
+	$mem_size = $mem['num_seg']*$mem['seg_size'];
+	$mem_avail= $mem['avail_mem'];
+	$mem_used = $mem_size-$mem_avail;
+	$seg_size = bsize($mem['seg_size']);
+	$req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
+	$hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
+	$miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
+	$insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
+	$req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
+	$hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
+	$miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
+	$insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
+	$apcversion = phpversion('apc');
+	$phpversion = phpversion();
+	$number_files = $cache['num_entries']; 
+    $size_files = bsize($cache['mem_size']);
+	$number_vars = $cache_user['num_entries'];
+    $size_vars = bsize($cache_user['mem_size']);
+	$i=0;
+	echo <<< EOB
+		<div class="info div1"><h2>General Cache Information</h2>
+		<table cellspacing=0><tbody>
+		<tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
+		<tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
+EOB;
+
+	if(!empty($_SERVER['SERVER_NAME']))
+		echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
+	if(!empty($_SERVER['SERVER_SOFTWARE']))
+		echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
+
+	echo <<<EOB
+		<tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
+    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
+    </td></tr>
+EOB;
+	echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
+	echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
+	echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
+	echo <<<EOB
+		</tbody></table>
+		</div>
+
+		<div class="info div1"><h2>File Cache Information</h2>
+		<table cellspacing=0><tbody>
+		<tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
+		<tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
+		<tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
+		<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
+		</tbody></table>
+		</div>
+
+		<div class="info div1"><h2>User Cache Information</h2>
+		<table cellspacing=0><tbody>
+    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
+		<tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
+		<tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
+		<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
+
+		</tbody></table>
+		</div>
+
+		<div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
+EOB;
+
+	$j = 0;
+	foreach (ini_get_all('apc') as $k => $v) {
+		echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
+		$j = 1 - $j;
+	}
+
+	if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
+		$mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
+	else
+		$mem_note = "Memory Usage";
+
+	echo <<< EOB
+		</tbody></table>
+		</div>
+
+		<div class="graph div3"><h2>Host Status Diagrams</h2>
+		<table cellspacing=0><tbody>
+EOB;
+	$size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
+	echo <<<EOB
+		<tr>
+		<td class=td-0>$mem_note</td>
+		<td class=td-1>Hits &amp; Misses</td>
+		</tr>
+EOB;
+
+	echo
+		graphics_avail() ? 
+			  '<tr>'.
+			  "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
+			  "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
+			: "",
+		'<tr>',
+		'<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
+		'<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
+		'</tr>',
+		'<tr>',
+		'<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
+		'<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
+	echo <<< EOB
+		</tr>
+		</tbody></table>
+
+		<br/>
+		<h2>Detailed Memory Usage and Fragmentation</h2>
+		<table cellspacing=0><tbody>
+		<tr>
+		<td class=td-0 colspan=2><br/>
+EOB;
+
+	// Fragementation: (freeseg - 1) / total_seg
+	$nseg = $freeseg = $fragsize = $freetotal = 0;
+	for($i=0; $i<$mem['num_seg']; $i++) {
+		$ptr = 0;
+		foreach($mem['block_lists'][$i] as $block) {
+			if ($block['offset'] != $ptr) {
+				++$nseg;
+			}
+			$ptr = $block['offset'] + $block['size'];
+                        /* Only consider blocks <5M for the fragmentation % */
+                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
+                        $freetotal+=$block['size'];
+		}
+		$freeseg += count($mem['block_lists'][$i]);
+	}
+	
+	if ($freeseg > 1) {
+		$frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
+	} else {
+		$frag = "0%";
+	}
+
+	if (graphics_avail()) {
+		$size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
+		echo <<<EOB
+			<img alt="" $size src="$PHP_SELF?IMG=3&$time">
+EOB;
+	}
+	echo <<<EOB
+		</br>Fragmentation: $frag
+		</td>
+		</tr>
+EOB;
+        if(isset($mem['adist'])) {
+          foreach($mem['adist'] as $i=>$v) {
+            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
+            if($i==0) $range = "1";
+            else $range = "$cur - $nxt";
+            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
+          }
+        }
+        echo <<<EOB
+		</tbody></table>
+		</div>
+EOB;
+		
+	break;
+
+
+// -----------------------------------------------
+// User Cache Entries
+// -----------------------------------------------
+case OB_USER_CACHE:
+	if (!$AUTHENTICATED) {
+    echo '<div class="error">You need to login to see the user values here!<br/>&nbsp;<br/>';
+		put_login_link("Login now!");
+		echo '</div>';
+		break;
+	}
+	$fieldname='info';
+	$fieldheading='User Entry Label';
+	$fieldkey='info';
+
+// -----------------------------------------------
+// System Cache Entries		
+// -----------------------------------------------
+case OB_SYS_CACHE:	
+	if (!isset($fieldname))
+	{
+		$fieldname='filename';
+		$fieldheading='Script Filename';
+		if(ini_get("apc.stat")) $fieldkey='inode';
+		else $fieldkey='filename'; 
+	}
+	if (!empty($MYREQUEST['SH']))
+	{
+		echo <<< EOB
+			<div class="info"><table cellspacing=0><tbody>
+			<tr><th>Attribute</th><th>Value</th></tr>
+EOB;
+
+		$m=0;
+		foreach($scope_list as $j => $list) {
+			foreach($cache[$list] as $i => $entry) {
+				if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
+				foreach($entry as $k => $value) {
+					if (!$AUTHENTICATED) {
+						// hide all path entries if not logged in
+						$value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
+					}
+
+					if ($k == "num_hits") {
+						$value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
+					}
+					if ($k == 'deletion_time') {
+						if(!$entry['deletion_time']) $value = "None";
+					}
+					echo
+						"<tr class=tr-$m>",
+						"<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
+						"<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),"</td>",
+						"</tr>";
+					$m=1-$m;
+				}
+				if($fieldkey=='info') {
+					echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
+					$output = var_export(apc_fetch($entry[$fieldkey]),true);
+					echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
+					echo "</pre></td></tr>\n";
+				}
+				break;
+			}
+		}
+
+		echo <<<EOB
+			</tbody></table>
+			</div>
+EOB;
+		break;
+	}
+
+	$cols=6;
+	echo <<<EOB
+		<div class=sorting><form>Scope:
+		<input type=hidden name=OB value={$MYREQUEST['OB']}>
+		<select name=SCOPE>
+EOB;
+	echo 
+		"<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
+		"<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
+		"</select>",
+		", Sorting:<select name=SORT1>",
+		"<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
+		"<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
+		"<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
+		"<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
+		"<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
+		"<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
+		"<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
+	if($fieldname=='info') echo
+		"<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
+	echo 
+		'</select>',
+		'<select name=SORT2>',
+		'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
+		'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
+		'</select>',
+		'<select name=COUNT onChange="form.submit()">',
+		'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
+		'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
+		'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
+		'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
+		'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
+		'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
+		'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
+		'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
+		'</select>',
+    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
+		'&nbsp;<input type=submit value="GO!">',
+		'</form></div>';
+
+  if (isset($MYREQUEST['SEARCH'])) {
+   // Don't use preg_quote because we want the user to be able to specify a
+   // regular expression subpattern.
+   $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i';
+   if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
+     echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
+     break;
+   }
+  }
+
+  echo
+		'<div class="info"><table cellspacing=0><tbody>',
+		'<tr>',
+		'<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
+
+	if($fieldname=='info') {
+		$cols+=2;
+		 echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
+	}
+	echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
+
+	// builds list with alpha numeric sortable keys
+	//
+	$list = array();
+	foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
+		switch($MYREQUEST['SORT1']) {
+			case 'A': $k=sprintf('%015d-',$entry['access_time']); 	break;
+			case 'H': $k=sprintf('%015d-',$entry['num_hits']); 		break;
+			case 'Z': $k=sprintf('%015d-',$entry['mem_size']); 		break;
+			case 'M': $k=sprintf('%015d-',$entry['mtime']);			break;
+			case 'C': $k=sprintf('%015d-',$entry['creation_time']);	break;
+			case 'T': $k=sprintf('%015d-',$entry['ttl']);			break;
+			case 'D': $k=sprintf('%015d-',$entry['deletion_time']);	break;
+			case 'S': $k='';										break;
+		}
+		if (!$AUTHENTICATED) {
+			// hide all path entries if not logged in
+			$list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry);
+		} else {
+			$list[$k.$entry[$fieldname]]=$entry;
+		}
+	}
+
+	if ($list) {
+		
+		// sort list
+		//
+		switch ($MYREQUEST['SORT2']) {
+			case "A":	krsort($list);	break;
+			case "D":	ksort($list);	break;
+		}
+		
+		// output list
+		$i=0;
+		foreach($list as $k => $entry) {
+      if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {  
+        $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8');
+        echo
+          '<tr class=tr-',$i%2,'>',
+          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$field_value,'</a></td>',
+          '<td class="td-n center">',$entry['num_hits'],'</td>',
+          '<td class="td-n right">',$entry['mem_size'],'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
+
+        if($fieldname=='info') {
+          if($entry['ttl'])
+            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
+          else
+            echo '<td class="td-n center">None</td>';
+        }
+        if ($entry['deletion_time']) {
+
+          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
+        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
+
+          echo '<td class="td-last center">';
+          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
+          echo '</td>';
+        } else {
+          echo '<td class="td-last center"> &nbsp; </td>';
+        }
+        echo '</tr>';
+        $i++;
+        if ($i == $MYREQUEST['COUNT'])
+          break;
+      }
+		}
+		
+	} else {
+		echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+EOB;
+
+	if ($list && $i < count($list)) {
+		echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
+	}
+
+	echo <<< EOB
+		</div>
+EOB;
+	break;
+
+
+// -----------------------------------------------
+// Per-Directory System Cache Entries
+// -----------------------------------------------
+case OB_SYS_CACHE_DIR:	
+	if (!$AUTHENTICATED) {
+		break;
+	}
+
+	echo <<<EOB
+		<div class=sorting><form>Scope:
+		<input type=hidden name=OB value={$MYREQUEST['OB']}>
+		<select name=SCOPE>
+EOB;
+	echo 
+		"<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
+		"<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
+		"</select>",
+		", Sorting:<select name=SORT1>",
+		"<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
+		"<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
+		"<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
+		"<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
+		"<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
+		"<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
+		'</select>',
+		'<select name=SORT2>',
+		'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
+		'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
+		'</select>',
+		'<select name=COUNT onChange="form.submit()">',
+		'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
+		'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
+		'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
+		'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
+		'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
+		'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
+		'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
+		'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
+		'</select>',
+		", Group By Dir Level:<select name=AGGR>",
+		"<option value='' selected>None</option>";
+		for ($i = 1; $i < 10; $i++)
+			echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
+		echo '</select>',
+		'&nbsp;<input type=submit value="GO!">',
+		'</form></div>',
+
+		'<div class="info"><table cellspacing=0><tbody>',
+		'<tr>',
+		'<th>',sortheader('S','Directory Name',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('H','Total Hits',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('Z','Total Size',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('C','Avg. Hits',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('A','Avg. Size',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'</tr>';
+
+	// builds list with alpha numeric sortable keys
+	//
+	$tmp = $list = array();
+	foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
+		$n = dirname($entry['filename']);
+		if ($MYREQUEST['AGGR'] > 0) {
+			$n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
+		}
+		if (!isset($tmp[$n])) {
+			$tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
+		}
+		$tmp[$n]['hits'] += $entry['num_hits'];
+		$tmp[$n]['size'] += $entry['mem_size'];
+		++$tmp[$n]['ents'];
+	}
+
+	foreach ($tmp as $k => $v) {
+		switch($MYREQUEST['SORT1']) {
+			case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
+			case 'T': $kn=sprintf('%015d-',$v['ents']);		break;
+			case 'H': $kn=sprintf('%015d-',$v['hits']);		break;
+			case 'Z': $kn=sprintf('%015d-',$v['size']);		break;
+			case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
+			case 'S': $kn = $k;					break;
+		}
+		$list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
+	}
+
+	if ($list) {
+		
+		// sort list
+		//
+		switch ($MYREQUEST['SORT2']) {
+			case "A":	krsort($list);	break;
+			case "D":	ksort($list);	break;
+		}
+		
+		// output list
+		$i = 0;
+		foreach($list as $entry) {
+			echo
+				'<tr class=tr-',$i%2,'>',
+				"<td class=td-0>",$entry[0],'</a></td>',
+				'<td class="td-n center">',$entry[1],'</td>',
+				'<td class="td-n center">',$entry[2],'</td>',
+				'<td class="td-n center">',$entry[3],'</td>',
+				'<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
+				'<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
+				'</tr>';
+
+			if (++$i == $MYREQUEST['COUNT']) break;
+		}
+		
+	} else {
+		echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+EOB;
+
+	if ($list && $i < count($list)) {
+		echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
+	}
+
+	echo <<< EOB
+		</div>
+EOB;
+	break;
+
+// -----------------------------------------------
+// Version check
+// -----------------------------------------------
+case OB_VERSION_CHECK:
+	echo <<<EOB
+		<div class="info"><h2>APC Version Information</h2>
+		<table cellspacing=0><tbody>
+		<tr>
+		<th></th>
+		</tr>
+EOB;
+  if (defined('PROXY')) {
+    $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) );
+    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt);
+  } else {
+    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
+  }
+	if (!$rss) {
+		echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
+	} else {
+		$apcversion = phpversion('apc');
+
+		preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
+		echo '<tr class="tr-0 center"><td>';
+		if (version_compare($apcversion, $match[1], '>=')) {
+			echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
+			$i = 3;
+		} else {
+			echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
+				newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
+				http://pecl.php.net/package/APC/'.$match[1].'</a>
+				</div>';
+			$i = -1;
+		}
+		echo '</td></tr>';
+		echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
+
+		preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
+		next($match[2]); next($match[2]);
+
+		while (list(,$v) = each($match[2])) {
+			list(,$ver) = explode(' ', $v, 2);
+			if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
+				break;
+			} else if (!$i--) {
+				break;
+			}
+			echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."</a></b><br><blockquote>";
+			echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."</blockquote>";
+			next($match[2]);
+		}
+		echo '</td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+		</div>
+EOB;
+	break;
+
+}
+
+echo <<< EOB
+	</div>
+EOB;
+
+?>
+
+<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
+</body>
+</html>
--- /dev/null
+++ b/ext/apc/apc_php.h
@@ -0,0 +1,77 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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_php.h 300979 2010-07-04 10:15:05Z kalle $ */
+
+#ifndef APC_PHP_H
+#define APC_PHP_H
+
+/*
+ * The purpose of this header file is to include all PHP and Zend headers that
+ * are typically needed elsewhere in APC. This makes it easy to insure that
+ * all required headers are available.
+ */
+
+#include "php.h"
+#include "zend.h"
+#include "zend_API.h"
+#include "zend_compile.h"
+#include "zend_hash.h"
+#include "zend_extensions.h"
+
+#if ZEND_MODULE_API_NO >= 20100409
+#define ZEND_ENGINE_2_4
+#endif
+#if ZEND_MODULE_API_NO > 20060613
+#define ZEND_ENGINE_2_3
+#endif
+#if ZEND_MODULE_API_NO > 20050922
+#define ZEND_ENGINE_2_2
+#endif
+#if ZEND_MODULE_API_NO > 20050921
+#define ZEND_ENGINE_2_1
+#endif
+#ifdef ZEND_ENGINE_2_1
+#include "zend_vm.h"
+#endif
+
+#include "rfc1867.h"
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_php_pcre.h
@@ -0,0 +1,98 @@
+/*
+   +----------------------------------------------------------------------+
+   | APC/PHP Version 5                                                    |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2010 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.               |
+   +----------------------------------------------------------------------+
+   | Author: Andrei Zmievski <andrei@php.net>                             |
+   +----------------------------------------------------------------------+
+ */
+ 
+/* $Id: apc_php_pcre.h 300979 2010-07-04 10:15:05Z kalle $ */
+
+#ifndef PHP_PCRE_H
+#define PHP_PCRE_H
+
+#if HAVE_PCRE || HAVE_BUNDLED_PCRE
+
+#if HAVE_BUNDLED_PCRE
+#include "ext/pcre/pcrelib/pcre.h"
+#else
+#include "pcre.h"
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+PHP_FUNCTION(preg_match);
+PHP_FUNCTION(preg_match_all);
+PHP_FUNCTION(preg_replace);
+PHP_FUNCTION(preg_replace_callback);
+PHP_FUNCTION(preg_split);
+PHP_FUNCTION(preg_quote);
+PHP_FUNCTION(preg_grep);
+
+PHPAPI char *php_pcre_replace(char *regex, int regex_len, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
+PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC);
+PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC);
+
+extern zend_module_entry pcre_module_entry;
+#define pcre_module_ptr &pcre_module_entry
+
+typedef struct {
+	pcre *re;
+	pcre_extra *extra;
+	int preg_options;
+#if HAVE_SETLOCALE
+	char *locale;
+	unsigned const char *tables;
+#endif
+	int compile_options;
+	int refcount;
+} pcre_cache_entry;
+
+PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC);
+
+PHPAPI void  php_pcre_match_impl(  pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
+	zval *subpats, int global, int use_flags, long flags, long start_offset TSRMLS_DC);
+
+PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, 
+	int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
+
+PHPAPI void  php_pcre_split_impl(  pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
+	long limit_val, long flags TSRMLS_DC);
+
+PHPAPI void  php_pcre_grep_impl(   pcre_cache_entry *pce, zval *input, zval *return_value,
+	long flags TSRMLS_DC);
+
+ZEND_BEGIN_MODULE_GLOBALS(pcre)
+	HashTable pcre_cache;
+	long backtrack_limit;
+	long recursion_limit;
+	int  error_code;
+ZEND_END_MODULE_GLOBALS(pcre)
+
+#ifdef ZTS
+# define PCRE_G(v) TSRMG(pcre_globals_id, zend_pcre_globals *, v)
+#else
+# define PCRE_G(v)	(pcre_globals.v)
+#endif
+
+#else
+
+#define pcre_module_ptr NULL
+
+#endif /* HAVE_PCRE || HAVE_BUNDLED_PCRE */
+
+#define phpext_pcre_ptr pcre_module_ptr
+
+#endif /* PHP_PCRE_H */
--- /dev/null
+++ b/ext/apc/apc_pool.c
@@ -0,0 +1,488 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
+  +----------------------------------------------------------------------+
+
+   This software was contributed to PHP by Yahoo! Inc. in 2008.
+
+   Future revisions and derivatives of this source code must acknowledge
+   Yahoo! 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_pool.c 301964 2010-08-07 03:34:18Z rasmus $ */
+
+
+#include "apc_pool.h"
+#include <assert.h>
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
+
+/* {{{ forward references */
+static apc_pool* apc_unpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC);
+static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC);
+/* }}} */
+
+/* {{{ apc_pool_create */
+apc_pool* apc_pool_create(apc_pool_type pool_type, 
+                            apc_malloc_t allocate, 
+                            apc_free_t deallocate,
+                            apc_protect_t protect,
+                            apc_unprotect_t unprotect
+			    TSRMLS_DC)
+{
+    if(pool_type == APC_UNPOOL) {
+        return apc_unpool_create(pool_type, allocate, deallocate,
+                                            protect, unprotect TSRMLS_CC);
+    }
+
+    return apc_realpool_create(pool_type, allocate, deallocate, 
+                                          protect,  unprotect TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_pool_destroy */
+void apc_pool_destroy(apc_pool *pool TSRMLS_DC)
+{
+    apc_free_t deallocate = pool->deallocate;
+    apc_pcleanup_t cleanup = pool->cleanup;
+
+    cleanup(pool TSRMLS_CC);
+    deallocate(pool TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_unpool implementation */
+
+typedef struct _apc_unpool apc_unpool;
+
+struct _apc_unpool {
+    apc_pool parent;
+    /* apc_unpool is a lie! */
+};
+
+static void* apc_unpool_alloc(apc_pool* pool, size_t size TSRMLS_DC) 
+{
+    apc_unpool *upool = (apc_unpool*)pool;
+
+    apc_malloc_t allocate = upool->parent.allocate;
+
+    upool->parent.size += size;
+    upool->parent.used += size;
+
+    return allocate(size TSRMLS_CC);
+}
+
+static void apc_unpool_free(apc_pool* pool, void *ptr TSRMLS_DC)
+{
+    apc_unpool *upool = (apc_unpool*) pool;
+
+    apc_free_t deallocate = upool->parent.deallocate;
+
+    deallocate(ptr TSRMLS_CC);
+}
+
+static void apc_unpool_cleanup(apc_pool* pool TSRMLS_DC)
+{
+}
+
+static apc_pool* apc_unpool_create(apc_pool_type type, 
+                    apc_malloc_t allocate, apc_free_t deallocate,
+                    apc_protect_t protect, apc_unprotect_t unprotect
+		    TSRMLS_DC)
+{
+    apc_unpool* upool = allocate(sizeof(apc_unpool) TSRMLS_CC);
+
+    if (!upool) {
+        return NULL;
+    }
+
+    upool->parent.type = type;
+    upool->parent.allocate = allocate;
+    upool->parent.deallocate = deallocate;
+
+    upool->parent.protect = protect;
+    upool->parent.unprotect = unprotect;
+
+    upool->parent.palloc = apc_unpool_alloc;
+    upool->parent.pfree  = apc_unpool_free;
+
+    upool->parent.cleanup = apc_unpool_cleanup;
+
+    upool->parent.used = 0;
+    upool->parent.size = 0;
+
+    return &(upool->parent);
+}
+/* }}} */
+
+
+/*{{{ apc_realpool implementation */
+
+/* {{{ typedefs */
+typedef struct _pool_block
+{
+    size_t              avail;
+    size_t              capacity;
+    unsigned char       *mark;
+    struct _pool_block  *next;
+    unsigned             :0; /* this should align to word */
+    /* data comes here */
+}pool_block;
+
+/*
+   parts in ? are optional and turned on for fun, memory loss,
+   and for something else that I forgot about ... ah, debugging
+
+                 |--------> data[]         |<-- non word boundary (too)
+   +-------------+--------------+-----------+-------------+-------------->>>
+   | pool_block  | ?sizeinfo<1> | block<1>  | ?redzone<1> | ?sizeinfo<2>
+   |             |  (size_t)    |           | padded left |
+   +-------------+--------------+-----------+-------------+-------------->>>
+ */
+
+typedef struct _apc_realpool apc_realpool;
+
+struct _apc_realpool
+{
+    struct _apc_pool parent;
+
+    size_t     dsize;
+    void       *owner;
+
+    pool_block *head;
+    pool_block first; 
+};
+
+/* }}} */
+
+/* {{{ redzone code */
+static const unsigned char decaff[] =  {
+    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
+    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
+    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
+    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad
+};
+
+/* a redzone is at least 4 (0xde,0xca,0xc0,0xff) bytes */
+#define REDZONE_SIZE(size) \
+    ((ALIGNWORD((size)) > ((size) + 4)) ? \
+        (ALIGNWORD((size)) - (size)) : /* does not change realsize */\
+        ALIGNWORD((size)) - (size) + ALIGNWORD((sizeof(char)))) /* adds 1 word to realsize */
+
+#define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t))
+
+#define MARK_REDZONE(block, redsize) do {\
+       memcpy(block, decaff, redsize );\
+    } while(0)
+
+#define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0)
+
+/* }}} */
+
+#define INIT_POOL_BLOCK(rpool, entry, size) do {\
+    (entry)->avail = (entry)->capacity = (size);\
+    (entry)->mark =  ((unsigned char*)(entry)) + ALIGNWORD(sizeof(pool_block));\
+    (entry)->next = (rpool)->head;\
+    (rpool)->head = (entry);\
+} while(0)
+
+/* {{{ create_pool_block */
+static pool_block* create_pool_block(apc_realpool *rpool, size_t size TSRMLS_DC)
+{
+    apc_malloc_t allocate = rpool->parent.allocate;
+
+    size_t realsize = sizeof(pool_block) + ALIGNWORD(size);
+
+    pool_block* entry = allocate(realsize TSRMLS_CC);
+
+    if (!entry) {
+        return NULL;
+    }
+
+    INIT_POOL_BLOCK(rpool, entry, size);
+    
+    rpool->parent.size += realsize;
+
+    return entry;
+}
+/* }}} */
+
+/* {{{ apc_realpool_alloc */
+static void* apc_realpool_alloc(apc_pool *pool, size_t size TSRMLS_DC)
+{
+    apc_realpool *rpool = (apc_realpool*)pool;
+    unsigned char *p = NULL;
+    size_t realsize = ALIGNWORD(size);
+    size_t poolsize;
+    unsigned char *redzone  = NULL;
+    size_t redsize  = 0;
+    size_t *sizeinfo= NULL;
+    pool_block *entry = NULL;
+    
+    if(APC_POOL_HAS_REDZONES(pool)) {
+        redsize = REDZONE_SIZE(size); /* redsize might be re-using word size padding */
+        realsize = size + redsize;    /* recalculating realsize */
+    } else {
+        redsize = realsize - size; /* use padding space */
+    }
+
+    if(APC_POOL_HAS_SIZEINFO(pool)) {
+        realsize += ALIGNWORD(sizeof(size_t));
+    }
+
+
+    for(entry = rpool->head; entry != NULL; entry = entry->next) {
+        if(entry->avail >= realsize) {
+            goto found;
+        }
+    }
+
+    poolsize = ALIGNSIZE(realsize, rpool->dsize);
+
+    entry = create_pool_block(rpool, poolsize TSRMLS_CC);
+
+    if(!entry) {
+        return NULL;
+    }
+
+found:
+    p = entry->mark;
+
+    if(APC_POOL_HAS_SIZEINFO(pool)) {
+        sizeinfo = (size_t*)p;
+        p += SIZEINFO_SIZE;
+        *sizeinfo = size;
+    }
+
+    redzone = p + size;
+
+    if(APC_POOL_HAS_REDZONES(pool)) {
+        MARK_REDZONE(redzone, redsize);
+    }
+
+#ifdef VALGRIND_MAKE_MEM_NOACCESS
+    if(redsize != 0) {
+        VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
+    }
+#endif
+
+    entry->avail -= realsize;
+    entry->mark  += realsize;
+    pool->used   += realsize;
+
+#ifdef VALGRIND_MAKE_MEM_UNDEFINED
+    /* need to write before reading data off this */
+    VALGRIND_MAKE_MEM_UNDEFINED(p, size);
+#endif
+
+    return (void*)p;
+}
+/* }}} */
+
+/* {{{ apc_realpool_check_integrity */
+/*
+ * Checking integrity at runtime, does an
+ * overwrite check only when the sizeinfo
+ * is set.
+ */
+static int apc_realpool_check_integrity(apc_realpool *rpool) 
+{
+    apc_pool *pool = &(rpool->parent); 
+    pool_block *entry;
+    size_t *sizeinfo = NULL;
+    unsigned char *start;
+    size_t realsize;
+    unsigned char   *redzone;
+    size_t redsize;
+
+    for(entry = rpool->head; entry != NULL; entry = entry->next) {
+        start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
+        if((entry->mark - start) != (entry->capacity - entry->avail)) {
+            return 0;
+        }
+    }
+
+    if(!APC_POOL_HAS_REDZONES(pool) ||
+        !APC_POOL_HAS_SIZEINFO(pool)) {
+        return 1;
+    }
+
+    for(entry = rpool->head; entry != NULL; entry = entry->next) {
+        start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
+
+        while(start < entry->mark) {
+            sizeinfo = (size_t*)start;
+            /* redzone starts where real data ends, in a non-word boundary
+             * redsize is at least 4 bytes + whatever's needed to make it
+             * to another word boundary.
+             */
+            redzone = start + SIZEINFO_SIZE + (*sizeinfo);
+            redsize = REDZONE_SIZE(*sizeinfo);
+#ifdef VALGRIND_MAKE_MEM_DEFINED
+            VALGRIND_MAKE_MEM_DEFINED(redzone, redsize);
+#endif
+            if(!CHECK_REDZONE(redzone, redsize))
+            {
+                /*
+                fprintf(stderr, "Redzone check failed for %p\n", 
+                                start + ALIGNWORD(sizeof(size_t)));*/
+                return 0;
+            }
+#ifdef VALGRIND_MAKE_MEM_NOACCESS
+            VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
+#endif
+            realsize = SIZEINFO_SIZE + *sizeinfo + redsize;
+            start += realsize;
+        }
+    }
+
+    return 1;
+}
+/* }}} */
+
+/* {{{ apc_realpool_free */
+/*
+ * free does not do anything other than
+ * check for redzone values when free'ing
+ * data areas.
+ */
+static void apc_realpool_free(apc_pool *pool, void *p TSRMLS_DC)
+{
+}
+/* }}} */
+
+static void apc_realpool_cleanup(apc_pool *pool TSRMLS_DC) 
+{
+    pool_block *entry;
+    pool_block *tmp;
+    apc_realpool *rpool = (apc_realpool*)pool;
+    apc_free_t deallocate = pool->deallocate;
+
+    assert(apc_realpool_check_integrity(rpool)!=0);
+
+    entry = rpool->head;
+
+    while(entry->next != NULL) {
+        tmp = entry->next;
+        deallocate(entry TSRMLS_CC);
+        entry = tmp;
+    }
+}
+
+/* {{{ apc_realpool_create */
+static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t allocate, apc_free_t deallocate, 
+                                                         apc_protect_t protect, apc_unprotect_t unprotect
+                                                         TSRMLS_DC)
+{
+
+    size_t dsize = 0;
+    apc_realpool *rpool;
+
+    switch(type & APC_POOL_SIZE_MASK) {
+        case APC_SMALL_POOL:
+            dsize = 512;
+            break;
+
+        case APC_LARGE_POOL:
+            dsize = 8192;
+            break;
+
+        case APC_MEDIUM_POOL:
+            dsize = 4096;
+            break;
+
+        default:
+            return NULL;
+    }
+
+    rpool = (apc_realpool*)allocate((sizeof(apc_realpool) + ALIGNWORD(dsize)) TSRMLS_CC);
+
+    if(!rpool) {
+        return NULL;
+    }
+
+    rpool->parent.type = type;
+
+    rpool->parent.allocate = allocate;
+    rpool->parent.deallocate = deallocate;
+
+    rpool->parent.size = sizeof(apc_realpool) + ALIGNWORD(dsize);
+
+    rpool->parent.palloc = apc_realpool_alloc;
+    rpool->parent.pfree  = apc_realpool_free;
+
+    rpool->parent.protect = protect;
+    rpool->parent.unprotect = unprotect;
+
+    rpool->parent.cleanup = apc_realpool_cleanup;
+
+    rpool->dsize = dsize;
+    rpool->head = NULL;
+
+    INIT_POOL_BLOCK(rpool, &(rpool->first), dsize);
+
+    return &(rpool->parent);
+}
+
+
+/* }}} */
+
+/* {{{ apc_pool_init */
+void apc_pool_init()
+{
+    /* put all ye sanity checks here */
+    assert(sizeof(decaff) > REDZONE_SIZE(ALIGNWORD(sizeof(char))));
+    assert(sizeof(pool_block) == ALIGNWORD(sizeof(pool_block)));
+#if APC_POOL_DEBUG
+    assert((APC_POOL_SIZE_MASK & (APC_POOL_SIZEINFO | APC_POOL_REDZONES)) == 0);
+#endif
+}
+/* }}} */
+
+/* {{{ apc_pstrdup */
+void* apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC)
+{
+    return s != NULL ? apc_pmemcpy(s, (strlen(s) + 1), pool TSRMLS_CC) : NULL;
+}
+/* }}} */
+
+/* {{{ apc_pmemcpy */
+void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC)
+{
+    void* q;
+
+    if (p != NULL && (q = apc_pool_alloc(pool, n)) != NULL) {
+        memcpy(q, p, n);
+        return q;
+    }
+    return NULL;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_pool.h
@@ -0,0 +1,114 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
+  +----------------------------------------------------------------------+
+
+   This software was contributed to PHP by Yahoo! Inc. in 2008.
+
+   Future revisions and derivatives of this source code must acknowledge
+   Yahoo! 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_pool.h 301682 2010-07-29 11:09:00Z gopalv $ */
+
+#ifndef APC_POOL_H
+#define APC_POOL_H
+
+#include "apc.h"
+#include "apc_sma.h"
+
+/* #define APC_POOL_DEBUG 1 */
+
+typedef enum {
+    APC_UNPOOL         = 0x0,
+    APC_SMALL_POOL     = 0x1,
+    APC_MEDIUM_POOL    = 0x2,
+    APC_LARGE_POOL     = 0x3,
+    APC_POOL_SIZE_MASK = 0x7,   /* waste a bit */
+#if APC_POOL_DEBUG
+    APC_POOL_REDZONES  = 0x08,
+    APC_POOL_SIZEINFO  = 0x10,
+    APC_POOL_OPT_MASK  = 0x18
+#endif
+} apc_pool_type;
+
+#if APC_POOL_DEBUG
+#define APC_POOL_HAS_SIZEINFO(pool) ((pool->type & APC_POOL_SIZEINFO)!=0)
+#define APC_POOL_HAS_REDZONES(pool) ((pool->type & APC_POOL_REDZONES)!=0)
+#else
+/* let gcc optimize away the optional features */
+#define APC_POOL_HAS_SIZEINFO(pool) (0)
+#define APC_POOL_HAS_REDZONES(pool) (0)
+#endif
+
+
+typedef struct _apc_pool apc_pool;
+
+typedef void  (*apc_pcleanup_t)(apc_pool *pool TSRMLS_DC);
+
+typedef void* (*apc_palloc_t)(apc_pool *pool, size_t size TSRMLS_DC);
+typedef void  (*apc_pfree_t) (apc_pool *pool, void* p TSRMLS_DC);
+
+typedef void* (*apc_protect_t)  (void *p);
+typedef void* (*apc_unprotect_t)(void *p);
+
+struct _apc_pool {
+    apc_pool_type   type;
+
+    apc_malloc_t    allocate;
+    apc_free_t      deallocate;
+
+    apc_palloc_t    palloc;
+    apc_pfree_t     pfree;
+
+	apc_protect_t   protect;
+	apc_unprotect_t unprotect;
+
+    apc_pcleanup_t  cleanup;
+
+    size_t          size;
+    size_t          used;
+
+    /* apc_realpool and apc_unpool add more here */
+};
+
+#define apc_pool_alloc(pool, size)  ((void *) pool->palloc(pool, size TSRMLS_CC))
+#define apc_pool_free(pool, ptr) 	((void)   pool->pfree (pool, ptr TSRMLS_CC))
+
+#define apc_pool_protect(pool, ptr)  (pool->protect ? \
+										(pool)->protect((ptr)) : (ptr))
+
+#define apc_pool_unprotect(pool, ptr)  (pool->unprotect ? \
+											(pool)->unprotect((ptr)) : (ptr))
+
+extern void apc_pool_init();
+
+extern apc_pool* apc_pool_create(apc_pool_type pool_type,
+                            apc_malloc_t allocate,
+                            apc_free_t deallocate,
+							apc_protect_t protect,
+							apc_unprotect_t unprotect
+							TSRMLS_DC);
+
+extern void apc_pool_destroy(apc_pool* pool TSRMLS_DC);
+
+extern void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC);
+extern void* apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC);
+
+#endif
--- /dev/null
+++ b/ext/apc/apc_pthreadmutex.c
@@ -0,0 +1,111 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_pthreadmutex.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc_pthreadmutex.h"
+
+#ifdef APC_PTHREADMUTEX_LOCKS
+
+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC) 
+{
+    int result;
+    pthread_mutexattr_t* attr;
+    attr = malloc(sizeof(pthread_mutexattr_t));
+
+    result = pthread_mutexattr_init(attr);
+    if(result == ENOMEM) {
+        apc_error("pthread mutex error: Insufficient memory exists to create the mutex attribute object." TSRMLS_CC);
+    } else if(result == EINVAL) {
+        apc_error("pthread mutex error: attr does not point to writeable memory." TSRMLS_CC);
+    } else if(result == EFAULT) {
+        apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC);
+    }
+
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+       result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
+       if (result == EINVAL) {
+               apc_error("pthread_mutexattr_settype: unable to set adaptive mutexes" TSRMLS_CC);
+       }
+#endif
+
+    /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
+    result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
+    if(result == EINVAL) {
+        apc_error("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC);
+    } else if(result == EFAULT) {
+        apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC);
+    } else if(result == ENOTSUP) {
+        apc_error("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC);
+    }
+
+    if(pthread_mutex_init(lock, attr)) { 
+        apc_error("unable to initialize pthread lock" TSRMLS_CC);
+    }
+    return lock;
+}
+
+void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
+{
+    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
+}
+
+void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC)
+{
+    int result;
+    result = pthread_mutex_lock(lock);
+    if(result == EINVAL) {
+        apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC);
+    } else if(result == EDEADLK) {
+        apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC);
+    }
+}
+
+void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC)
+{
+    if(pthread_mutex_unlock(lock)) {
+        apc_error("unable to unlock pthread lock" TSRMLS_CC);
+    }
+}
+
+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC)
+{
+    int rval;
+    rval = pthread_mutex_trylock(lock);
+    if(rval == EBUSY) {     /* Lock is already held */
+        return 0;
+    } else if(rval == 0) {  /* Obtained lock */
+        return 1;
+    } else {                /* Other error */
+        apc_error("unable to obtain pthread trylock" TSRMLS_CC);
+        return 0;
+    }
+}
+
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_pthreadmutex.h
@@ -0,0 +1,48 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_pthreadmutex.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_PTHREADMUTEX_H
+#define APC_PTHREADMUTEX_H
+
+#include "apc.h"
+
+#ifdef APC_PTHREADMUTEX_LOCKS
+
+#include <pthread.h>
+
+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC);
+void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
+void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC);
+void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC);
+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC);
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_rfc1867.c
@@ -0,0 +1,232 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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_rfc1867.c 305798 2010-11-28 13:43:20Z gopalv $*/
+
+#include "apc.h"
+#include "apc_globals.h"
+#include "rfc1867.h"
+
+#ifdef PHP_WIN32
+#include "win32/time.h"
+#endif
+
+#ifdef MULTIPART_EVENT_FORMDATA
+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC);
+extern int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC);
+
+static int update_bytes_processed(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
+    int *bytes_ptr = (int*)data;
+    zval* val = entry->data.user.val;
+
+    if(Z_TYPE_P(val) == IS_ARRAY) {
+        HashTable *ht = val->value.ht;
+        Bucket* curr = NULL;
+        for (curr = ht->pListHead; curr != NULL; curr = curr->pListNext) {
+            if(curr->nKeyLength == 8 && 
+                (!memcmp(curr->arKey, "current", curr->nKeyLength))) {
+                zval* current =  ((zval**)curr->pData)[0];
+                current->value.lval = *bytes_ptr;
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static double my_time() {
+    struct timeval a;
+    double t;
+    gettimeofday(&a, NULL);
+    t = a.tv_sec + (a.tv_usec/1000000.00);
+    return t;
+}
+
+
+#define RFC1867_DATA(name) \
+                ((request_data)->name)
+
+int apc_rfc1867_progress(uint event, void *event_data, void **extra TSRMLS_DC) {
+    apc_rfc1867_data *request_data = &APCG(rfc1867_data);
+    zval *track = NULL;
+
+    switch (event) {
+        case MULTIPART_EVENT_START:
+            {
+                multipart_event_start *data = (multipart_event_start *) event_data;
+                
+                RFC1867_DATA(content_length)    = data->content_length;
+                RFC1867_DATA(tracking_key)[0]   = '\0';
+                RFC1867_DATA(name)[0]           = '\0';
+                RFC1867_DATA(cancel_upload)     = 0;
+                RFC1867_DATA(temp_filename)     = NULL;
+                RFC1867_DATA(filename)[0]       = '\0';
+                RFC1867_DATA(key_length)        = 0;
+                RFC1867_DATA(start_time)        = my_time();
+                RFC1867_DATA(bytes_processed)   = 0;
+                RFC1867_DATA(prev_bytes_processed) = 0;
+                RFC1867_DATA(rate)              = 0;
+                RFC1867_DATA(update_freq)       = (int) APCG(rfc1867_freq);
+                RFC1867_DATA(started)           = 0;
+                
+                if(RFC1867_DATA(update_freq) < 0) {  // frequency is a percentage, not bytes
+                    RFC1867_DATA(update_freq) = (int) (RFC1867_DATA(content_length) * APCG(rfc1867_freq) / 100); 
+                }
+            }
+            break;
+
+        case MULTIPART_EVENT_FORMDATA:
+            {
+                int prefix_len = strlen(APCG(rfc1867_prefix));
+                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
+                if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) 
+                    && data->value && data->length) { 
+                    
+                    if(data->length >= sizeof(RFC1867_DATA(tracking_key)) - prefix_len) {
+                        apc_warning("Key too long for '%s'. Maximum size is '%d' characters." TSRMLS_CC, 
+                                    APCG(rfc1867_name), 
+                                    sizeof(RFC1867_DATA(tracking_key)) - prefix_len);
+                        break;
+                    }
+
+                    if(RFC1867_DATA(started)) {
+                        apc_warning("Upload progress key '%s' should be before the file upload entry in the form." TSRMLS_CC, 
+                                    APCG(rfc1867_name)); 
+                        break;
+                    }
+
+                    strlcat(RFC1867_DATA(tracking_key), APCG(rfc1867_prefix), 63);
+                    strlcat(RFC1867_DATA(tracking_key), *data->value, 63);
+                    RFC1867_DATA(key_length) = data->length + prefix_len;
+                    RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
+                }
+            }
+            break;
+
+        case MULTIPART_EVENT_FILE_START:
+            {
+                RFC1867_DATA(started) = 1;
+                if(*RFC1867_DATA(tracking_key)) {
+                    multipart_event_file_start *data = (multipart_event_file_start *) event_data;
+
+                    RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
+                    strlcpy(RFC1867_DATA(filename),*data->filename,128);
+                    RFC1867_DATA(temp_filename) = NULL;
+                    strlcpy(RFC1867_DATA(name),data->name,64);
+                    ALLOC_INIT_ZVAL(track);
+                    array_init(track);
+                    add_assoc_long(track, "total", RFC1867_DATA(content_length));
+                    add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
+                    add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
+                    add_assoc_string(track, "name", RFC1867_DATA(name), 1);
+                    add_assoc_long(track, "done", 0);
+                    add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
+                    _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
+                    zval_ptr_dtor(&track);
+                }
+            }
+            break;
+
+        case MULTIPART_EVENT_FILE_DATA:
+            if(*RFC1867_DATA(tracking_key)) {
+                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
+                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
+                if(RFC1867_DATA(bytes_processed) - RFC1867_DATA(prev_bytes_processed) > (uint) RFC1867_DATA(update_freq)) {
+                    if(!_apc_update(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), update_bytes_processed, &RFC1867_DATA(bytes_processed) TSRMLS_CC)) {
+                        ALLOC_INIT_ZVAL(track);
+                        array_init(track);
+                        add_assoc_long(track, "total", RFC1867_DATA(content_length));
+                        add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
+                        add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
+                        add_assoc_string(track, "name", RFC1867_DATA(name), 1);
+                        add_assoc_long(track, "done", 0);
+                        add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
+                        _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
+                        zval_ptr_dtor(&track);
+                    }
+                    RFC1867_DATA(prev_bytes_processed) = RFC1867_DATA(bytes_processed);
+                }
+            }
+            break;
+
+        case MULTIPART_EVENT_FILE_END:
+            if(*RFC1867_DATA(tracking_key)) {
+                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
+                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
+                RFC1867_DATA(cancel_upload) = data->cancel_upload;
+                RFC1867_DATA(temp_filename) = data->temp_filename;
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", RFC1867_DATA(content_length));
+                add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
+                add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
+                add_assoc_string(track, "name", RFC1867_DATA(name), 1);
+                add_assoc_string(track, "temp_filename", RFC1867_DATA(temp_filename), 1);
+                add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
+                add_assoc_long(track, "done", 0);
+                add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
+                _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
+                zval_ptr_dtor(&track);
+            }
+            break;
+
+        case MULTIPART_EVENT_END:
+            if(*RFC1867_DATA(tracking_key)) {
+                double now = my_time(); 
+                multipart_event_end *data = (multipart_event_end *) event_data;
+                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
+                if(now>RFC1867_DATA(start_time)) RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed)/(now-RFC1867_DATA(start_time));
+                else RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed);  /* Too quick */
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", RFC1867_DATA(content_length));
+                add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
+                add_assoc_double(track, "rate", RFC1867_DATA(rate));
+                add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
+                add_assoc_string(track, "name", RFC1867_DATA(name), 1);
+                add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
+                add_assoc_long(track, "done", 1);
+                add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
+                _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
+                zval_ptr_dtor(&track);
+            }
+            break;
+    }
+
+    return SUCCESS;
+}
+
+#endif
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_sem.c
@@ -0,0 +1,192 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_sem.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc.h"
+
+#ifdef APC_SEM_LOCKS
+
+#include "apc_sem.h"
+#include "php.h"
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if HAVE_SEMUN
+/* we have semun, no need to define */
+#else
+#undef HAVE_SEMUN
+union semun {
+    int val;                  /* value for SETVAL */
+    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
+    unsigned short *array;    /* array for GETALL, SETALL */
+                              /* Linux specific part: */
+    struct seminfo *__buf;    /* buffer for IPC_INFO */
+};
+#define HAVE_SEMUN 1
+#endif
+
+#ifndef SEM_R
+# define SEM_R 0444
+#endif
+#ifndef SEM_A
+# define SEM_A 0222
+#endif
+
+/* always use SEM_UNDO, otherwise we risk deadlock */
+#define USE_SEM_UNDO
+
+#ifdef USE_SEM_UNDO
+# define UNDO SEM_UNDO
+#else
+# define UNDO 0
+#endif
+
+int apc_sem_create(int proj, int initval TSRMLS_DC)
+{
+    int semid;
+    int perms = 0777;
+    union semun arg;
+    key_t key = IPC_PRIVATE;
+
+    if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
+        /* sempahore created for the first time, initialize now */
+        arg.val = initval;
+        if (semctl(semid, 0, SETVAL, arg) < 0) {
+            apc_error("apc_sem_create: semctl(%d,...) failed:" TSRMLS_CC, semid);
+        }
+    }
+    else if (errno == EEXIST) {
+        /* sempahore already exists, don't initialize */
+        if ((semid = semget(key, 1, perms)) < 0) {
+            apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key);
+        }
+        /* insert <sleazy way to avoid race condition> here */
+    }
+    else {
+        apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key);
+    }
+
+    return semid;
+}
+
+void apc_sem_destroy(int semid)
+{
+    /* we expect this call to fail often, so we do not check */
+    union semun arg;
+    semctl(semid, 0, IPC_RMID, arg);
+}
+
+void apc_sem_lock(int semid TSRMLS_DC)
+{
+    struct sembuf op;
+
+    op.sem_num = 0;
+    op.sem_op  = -1;
+    op.sem_flg = UNDO;
+
+    if (semop(semid, &op, 1) < 0) {
+        if (errno != EINTR) {
+            apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid);
+        }
+    }
+}
+
+int apc_sem_nonblocking_lock(int semid TSRMLS_DC) 
+{
+    struct sembuf op;
+
+    op.sem_num = 0;
+    op.sem_op  = -1;
+    op.sem_flg = UNDO | IPC_NOWAIT;
+
+    if (semop(semid, &op, 1) < 0) {
+      if (errno == EAGAIN) {
+        return 0;  /* Lock is already held */
+      } else if (errno != EINTR) {
+        apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid);
+      }
+    }
+
+    return 1;  /* Lock obtained */
+}
+
+void apc_sem_unlock(int semid TSRMLS_DC)
+{
+    struct sembuf op;
+
+    op.sem_num = 0;
+    op.sem_op  = 1;
+    op.sem_flg = UNDO;
+
+    if (semop(semid, &op, 1) < 0) {
+        if (errno != EINTR) {
+            apc_error("apc_sem_unlock: semop(%d) failed:" TSRMLS_CC, semid);
+        }
+    }
+}
+
+void apc_sem_wait_for_zero(int semid TSRMLS_DC)
+{
+    struct sembuf op;
+
+    op.sem_num = 0;
+    op.sem_op  = 0;
+    op.sem_flg = UNDO;
+
+    if (semop(semid, &op, 1) < 0) {
+        if (errno != EINTR) {
+            apc_error("apc_sem_waitforzero: semop(%d) failed:" TSRMLS_CC, semid);
+        }
+    }
+}
+
+int apc_sem_get_value(int semid TSRMLS_DC)
+{
+    union semun arg;
+    unsigned short val[1];
+
+    arg.array = val;
+    if (semctl(semid, 0, GETALL, arg) < 0) {
+        apc_error("apc_sem_getvalue: semctl(%d,...) failed:" TSRMLS_CC, semid);
+    }
+    return val[0];
+}
+
+#endif /* APC_SEM_LOCKS */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_sem.h
@@ -0,0 +1,52 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_sem.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_SEM_H
+#define APC_SEM_H
+
+/* Wrapper functions for SysV sempahores */
+
+extern int apc_sem_create(int proj, int initval TSRMLS_DC);
+extern void apc_sem_destroy(int semid);
+extern void apc_sem_lock(int semid TSRMLS_DC);
+extern int apc_sem_nonblocking_lock(int semid TSRMLS_DC); 
+extern void apc_sem_unlock(int semid TSRMLS_DC);
+extern void apc_sem_wait_for_zero(int semid TSRMLS_DC);
+extern int apc_sem_get_value(int semid TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_shm.c
@@ -0,0 +1,114 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>                             |
+  +----------------------------------------------------------------------+
+
+   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_shm.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc_shm.h"
+#include "apc.h"
+#ifdef PHP_WIN32
+/* shm functions are available in TSRM */
+#include <tsrm/tsrm_win32.h>
+#define key_t long
+#else
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#endif
+
+#ifndef SHM_R
+# define SHM_R 0444 /* read permission */
+#endif
+#ifndef SHM_A
+# define SHM_A 0222 /* write permission */
+#endif
+
+int apc_shm_create(int proj, size_t size TSRMLS_DC)
+{
+    int shmid;			/* shared memory id */
+    int oflag;			/* permissions on shm */
+    key_t key = IPC_PRIVATE;	/* shm key */
+
+    oflag = IPC_CREAT | SHM_R | SHM_A;
+    if ((shmid = shmget(key, size, oflag)) < 0) {
+        apc_error("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment." TSRMLS_CC, key, size, oflag, strerror(errno));
+    }
+
+    return shmid;
+}
+
+void apc_shm_destroy(int shmid)
+{
+    /* we expect this call to fail often, so we do not check */
+    shmctl(shmid, IPC_RMID, 0);
+}
+
+apc_segment_t apc_shm_attach(int shmid TSRMLS_DC)
+{
+    apc_segment_t segment; /* shm segment */
+
+    if ((long)(segment.shmaddr = shmat(shmid, 0, 0)) == -1) {
+        apc_error("apc_shm_attach: shmat failed:" TSRMLS_CC);
+    }
+
+#ifdef APC_MEMPROTECT
+    
+    if ((long)(segment.roaddr = shmat(shmid, 0, SHM_RDONLY)) == -1) {
+        segment.roaddr = NULL;
+    }
+
+#endif
+
+    /*
+     * We set the shmid for removal immediately after attaching to it. The
+     * segment won't disappear until all processes have detached from it.
+     */
+    apc_shm_destroy(shmid);
+    return segment;
+}
+
+void apc_shm_detach(apc_segment_t* segment TSRMLS_DC)
+{
+    if (shmdt(segment->shmaddr) < 0) {
+        apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
+    }
+
+#ifdef APC_MEMPROTECT
+    if (segment->roaddr && shmdt(segment->roaddr) < 0) {
+        apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
+    }
+#endif
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_shm.h
@@ -0,0 +1,56 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_shm.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_SHM_H
+#define APC_SHM_H
+
+#include <sys/types.h>
+#ifdef PHP_WIN32
+#include <time.h>
+#endif
+
+#include "apc_sma.h"
+
+/* Wrapper functions for unix shared memory */
+
+extern int apc_shm_create(int proj, size_t size TSRMLS_DC);
+extern void apc_shm_destroy(int shmid);
+extern apc_segment_t apc_shm_attach(int shmid TSRMLS_DC);
+extern void apc_shm_detach(apc_segment_t* segment TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_signal.c
@@ -0,0 +1,197 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Lucas Nealan <lucas@php.net>                                |
+  +----------------------------------------------------------------------+
+
+   This software was contributed to PHP by Facebook Inc. in 2007.
+
+   Future revisions and derivatives of this source code must acknowledge
+   Facebook 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_signal.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+ /* Allows apc to install signal handlers and maintain signalling
+    to already registered handlers. Registers all signals that
+    coredump by default and unmaps the shared memory segment
+    before the coredump. Note: PHP module init is called before 
+    signals are set by Apache and thus apc_set_signals should
+    be called in request init (RINIT)
+  */
+
+#include "apc.h"
+
+#if HAVE_SIGACTION
+#include <signal.h>
+#include "apc_globals.h"
+#include "apc_sma.h"
+#include "apc_signal.h"
+
+static apc_signal_info_t apc_signal_info = {0};
+
+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC);
+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
+
+/* {{{ apc_core_unmap 
+ *  Coredump signal handler, unmaps shm and calls previously installed handlers 
+ */
+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) 
+{
+    TSRMLS_FETCH();
+	
+    apc_sma_cleanup(TSRMLS_C);
+    apc_rehandle_signal(signo, siginfo, context);
+
+#if !defined(WIN32) && !defined(NETWARE)
+    kill(getpid(), signo);
+#else
+    raise(signo);
+#endif
+} /* }}} */
+
+/* {{{ apc_rehandle_signal
+ *  Call the previously registered handler for a signal
+ */
+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
+{
+    int i;
+    apc_signal_entry_t p_sig = {0};
+
+    for (i=0;  (i < apc_signal_info.installed && p_sig.signo != signo);  i++) {
+        p_sig = *apc_signal_info.prev[i];
+        if (p_sig.signo == signo) {
+            if (p_sig.siginfo) {
+                (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
+            } else {
+                (*(void (*)(int))p_sig.handler)(signo);
+            }
+        }
+    }
+
+} /* }}} */
+
+/* {{{ apc_register_signal
+ *  Set a handler for a previously installed signal and save so we can 
+ *  callback when handled 
+ */
+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC)
+{
+    struct sigaction sa = {{0}};
+    apc_signal_entry_t p_sig = {0};
+
+    if (sigaction(signo, NULL, &sa) == 0) {
+        if ((void*)sa.sa_handler == (void*)handler) {
+            return SUCCESS;
+        }
+
+        if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
+            p_sig.signo = signo;
+            p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
+            p_sig.handler = (void *)sa.sa_handler;
+
+            apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *) TSRMLS_CC);
+            apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t) TSRMLS_CC);
+            *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
+        } else {
+            /* inherit flags and mask if already set */
+            sigemptyset(&sa.sa_mask);
+            sa.sa_flags = 0;
+            sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
+#if defined(SA_ONESHOT)
+            sa.sa_flags = SA_ONESHOT;
+#elif defined(SA_RESETHAND)
+            sa.sa_flags = SA_RESETHAND;
+#endif
+        }
+        sa.sa_handler = (void*)handler;
+
+        if (sigaction(signo, &sa, NULL) < 0) {
+            apc_warning("Error installing apc signal handler for %d" TSRMLS_CC, signo);
+        }
+
+        return SUCCESS;
+    }
+    return FAILURE;
+} /* }}} */
+
+/* {{{ apc_set_signals
+ *  Install our signal handlers */
+void apc_set_signals(TSRMLS_D) 
+{
+    if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
+        /* ISO C standard signals that coredump */
+        apc_register_signal(SIGSEGV, apc_core_unmap TSRMLS_CC);
+        apc_register_signal(SIGABRT, apc_core_unmap TSRMLS_CC);
+        apc_register_signal(SIGFPE, apc_core_unmap TSRMLS_CC);
+        apc_register_signal(SIGILL, apc_core_unmap TSRMLS_CC);
+        /* extended signals that coredump */
+#ifdef SIGBUS
+        apc_register_signal(SIGBUS, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGABORT
+        apc_register_signal(SIGABORT, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGEMT
+        apc_register_signal(SIGEMT, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGIOT
+        apc_register_signal(SIGIOT, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGQUIT
+        apc_register_signal(SIGQUIT, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGSYS
+        apc_register_signal(SIGSYS, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGTRAP
+        apc_register_signal(SIGTRAP, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGXCPU
+        apc_register_signal(SIGXCPU, apc_core_unmap TSRMLS_CC);
+#endif
+#ifdef SIGXFSZ
+        apc_register_signal(SIGXFSZ, apc_core_unmap TSRMLS_CC);
+#endif
+    }
+} /* }}} */
+
+/* {{{ apc_set_signals
+ *  cleanup signals for shutdown */
+void apc_shutdown_signals(TSRMLS_D) 
+{
+    int i=0;
+    if (apc_signal_info.installed > 0) {
+        for (i=0;  (i < apc_signal_info.installed);  i++) {
+            apc_efree(apc_signal_info.prev[i] TSRMLS_CC);
+        }
+        apc_efree(apc_signal_info.prev TSRMLS_CC);
+        apc_signal_info.installed = 0; /* just in case */
+    }
+}
+
+#endif  /* HAVE_SIGACTION */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_signal.h
@@ -0,0 +1,51 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Lucas Nealan <lucas@php.net>                                |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_signal.h 300986 2010-07-04 14:41:33Z felipe $ */
+
+#ifndef APC_SIGNAL_H
+#define APC_SIGNAL_H
+
+#include "apc.h"
+#include "apc_php.h"
+
+typedef struct apc_signal_entry_t {
+    int signo;          /* signal number */
+    int siginfo;        /* siginfo style handler calling */
+    void* handler;      /* signal handler */
+} apc_signal_entry_t;
+
+typedef struct apc_signal_info_t {
+    int installed;                  /* How many signals we've installed handles for */
+    apc_signal_entry_t **prev;      /* Previous signal handlers */
+} apc_signal_info_t;
+
+void apc_set_signals(TSRMLS_D);
+void apc_shutdown_signals(TSRMLS_D);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_sma.c
@@ -0,0 +1,765 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>                             |
+  +----------------------------------------------------------------------+
+
+   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_sma.c 305260 2010-11-10 19:23:02Z gopalv $ */
+
+#include "apc_sma.h"
+#include "apc.h"
+#include "apc_globals.h"
+#include "apc_lock.h"
+#include "apc_shm.h"
+#include "apc_cache.h"
+
+#include <limits.h>
+#include "apc_mmap.h"
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
+enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
+
+static int sma_initialized = 0;     /* true if the sma has been initialized */
+static uint sma_numseg;     /* number of shm segments to allow */
+static size_t sma_segsize;          /* size of each shm segment */
+static apc_segment_t* sma_segments; /* array of shm segments */
+static int sma_lastseg = 0;         /* index of MRU segment */
+
+typedef struct sma_header_t sma_header_t;
+struct sma_header_t {
+    apc_lck_t sma_lock;     /* segment lock, MUST BE ALIGNED for futex locks */
+    size_t segsize;         /* size of entire segment */
+    size_t avail;           /* bytes available (not necessarily contiguous) */
+#if ALLOC_DISTRIBUTION
+    size_t adist[30];
+#endif
+};
+
+#define SMA_HDR(i)  ((sma_header_t*)((sma_segments[i]).shmaddr))
+#define SMA_ADDR(i) ((char*)(SMA_HDR(i)))
+#define SMA_RO(i)   ((char*)(sma_segments[i]).roaddr)
+#define SMA_LCK(i)  ((SMA_HDR(i))->sma_lock)
+
+
+/* do not enable for threaded http servers */
+/* #define __APC_SMA_DEBUG__ 1 */
+
+#ifdef __APC_SMA_DEBUG__
+/* global counter for identifying blocks
+ * Technically it is possible to do the same
+ * using offsets, but double allocations of the
+ * same offset can happen. */
+static volatile size_t block_id = 0;
+#endif
+
+#define APC_SMA_CANARIES 1
+
+typedef struct block_t block_t;
+struct block_t {
+    size_t size;       /* size of this block */
+    size_t prev_size;  /* size of sequentially previous block, 0 if prev is allocated */
+    size_t fnext;      /* offset in segment of next free block */
+    size_t fprev;      /* offset in segment of prev free block */
+#ifdef APC_SMA_CANARIES
+    size_t canary;     /* canary to check for memory overwrites */
+#endif
+#ifdef __APC_SMA_DEBUG__
+    size_t id;         /* identifier for the memory block */
+#endif
+};
+
+/* The macros BLOCKAT and OFFSET are used for convenience throughout this
+ * module. Both assume the presence of a variable shmaddr that points to the
+ * beginning of the shared memory segment in question. */
+
+#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
+#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
+
+/* macros for getting the next or previous sequential block */
+#define NEXT_SBLOCK(block) ((block_t*)((char*)block + block->size))
+#define PREV_SBLOCK(block) (block->prev_size ? ((block_t*)((char*)block - block->prev_size)) : NULL)
+
+/* Canary macros for setting, checking and resetting memory canaries */
+#ifdef APC_SMA_CANARIES
+    #define SET_CANARY(v) (v)->canary = 0x42424242
+    #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
+    #define RESET_CANARY(v) (v)->canary = -42
+#else
+    #define SET_CANARY(v) 
+    #define CHECK_CANARY(v)
+    #define RESET_CANARY(v)
+#endif
+
+
+/* {{{ MINBLOCKSIZE */
+#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
+/* }}} */
+
+#if 0
+/* {{{ sma_debug_state(apc_sma_segment_t *segment, int canary_check, int verbose)
+ *        useful for debuging state of memory blocks and free list, and sanity checking
+ */
+static void sma_debug_state(void* shmaddr, int canary_check, int verbose TSRMLS_DC) {
+    sma_header_t *header = (sma_header_t*)shmaddr;
+    block_t *cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+    block_t *prv = NULL;
+    size_t avail;
+
+    /* Verify free list */
+    if (verbose) apc_warning("Free List: " TSRMLS_CC);
+    while(1) {
+        if (verbose) apc_warning(" 0x%x[%d] (s%d)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
+        if (canary_check) CHECK_CANARY(cur);
+        if (!cur->fnext) break;
+        cur = BLOCKAT(cur->fnext);
+        avail += cur->size;
+        if (prv == cur) {
+            apc_warning("Circular list detected!" TSRMLS_CC);
+            assert(0);
+        }
+        if (prv && cur->fprev != OFFSET(prv)) {
+            apc_warning("Previous pointer does not point to previous!" TSRMLS_CC);
+            assert(0);
+        }
+        prv = cur;
+    }
+    assert(avail == header->avail);
+
+    /* Verify each block */
+    if (verbose) apc_warning("Block List: " TSRMLS_CC);
+    cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+    while(1) {
+        if(!cur->fnext) {
+            if (verbose) apc_warning(" 0x%x[%d] (s%d) (u)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
+        } else {
+            if (verbose) apc_warning(" 0x%x[%d] (s%d) (f)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
+        }
+        if (canary_check) CHECK_CANARY(cur);
+        if (!cur->size && !cur->fnext) break;
+        if (!cur->size) {
+            cur = BLOCKAT(OFFSET(cur) + ALIGNWORD(sizeof(block_t)));
+        } else {
+            cur = NEXT_SBLOCK(cur);
+        }
+        if (prv == cur) {
+            apc_warning("Circular list detected!" TSRMLS_CC);
+            assert(0);
+        }
+        prv = cur;
+    }
+}
+/* }}} */
+#endif
+
+/* {{{ sma_allocate: tries to allocate at least size bytes in a segment */
+static size_t sma_allocate(sma_header_t* header, size_t size, size_t fragment, size_t *allocated)
+{
+    void* shmaddr;          /* header of shared memory segment */
+    block_t* prv;           /* block prior to working block */
+    block_t* cur;           /* working block in list */
+    block_t* prvnextfit;    /* block before next fit */
+    size_t realsize;        /* actual size of block needed, including header */
+    const size_t block_size = ALIGNWORD(sizeof(struct block_t));
+
+    realsize = ALIGNWORD(size + block_size);
+
+    /*
+     * First, insure that the segment contains at least realsize free bytes,
+     * even if they are not contiguous.
+     */
+    shmaddr = header;
+
+    if (header->avail < realsize) {
+        return -1;
+    }
+
+    prvnextfit = 0;     /* initially null (no fit) */
+    prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+    CHECK_CANARY(prv);
+
+    while (prv->fnext != 0) {
+        cur = BLOCKAT(prv->fnext);
+#ifdef __APC_SMA_DEBUG__
+        CHECK_CANARY(cur);
+#endif
+        /* If it can fit realsize bytes in cur block, stop searching */
+        if (cur->size >= realsize) {
+            prvnextfit = prv;
+            break;
+        }
+        prv = cur;
+    }
+
+    if (prvnextfit == 0) {
+        return -1;
+    }
+
+    prv = prvnextfit;
+    cur = BLOCKAT(prv->fnext);
+
+    CHECK_CANARY(prv);
+    CHECK_CANARY(cur);
+
+    if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE + fragment)))) {
+        /* cur is big enough for realsize, but too small to split - unlink it */
+        *(allocated) = cur->size - block_size;
+        prv->fnext = cur->fnext;
+        BLOCKAT(cur->fnext)->fprev = OFFSET(prv);
+        NEXT_SBLOCK(cur)->prev_size = 0;  /* block is alloc'd */
+    } else {
+        /* nextfit is too big; split it into two smaller blocks */
+        block_t* nxt;      /* the new block (chopped part of cur) */
+        size_t oldsize;    /* size of cur before split */
+
+        oldsize = cur->size;
+        cur->size = realsize;
+        *(allocated) = cur->size - block_size;
+        nxt = NEXT_SBLOCK(cur);
+        nxt->prev_size = 0;                       /* block is alloc'd */
+        nxt->size = oldsize - realsize;           /* and fix the size */
+        NEXT_SBLOCK(nxt)->prev_size = nxt->size;  /* adjust size */
+        SET_CANARY(nxt);
+
+        /* replace cur with next in free list */
+        nxt->fnext = cur->fnext;
+        nxt->fprev = cur->fprev;
+        BLOCKAT(nxt->fnext)->fprev = OFFSET(nxt);
+        BLOCKAT(nxt->fprev)->fnext = OFFSET(nxt);
+#ifdef __APC_SMA_DEBUG__
+        nxt->id = -1;
+#endif
+    }
+
+    cur->fnext = 0;
+
+    /* update the block header */
+    header->avail -= cur->size;
+#if ALLOC_DISTRIBUTION
+    header->adist[(int)(log(size)/log(2))]++;
+#endif
+
+    SET_CANARY(cur);
+#ifdef __APC_SMA_DEBUG__
+    cur->id = ++block_id;
+    fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
+#endif
+
+    return OFFSET(cur) + block_size;
+}
+/* }}} */
+
+/* {{{ sma_deallocate: deallocates the block at the given offset */
+static size_t sma_deallocate(void* shmaddr, size_t offset)
+{
+    sma_header_t* header;   /* header of shared memory segment */
+    block_t* cur;       /* the new block to insert */
+    block_t* prv;       /* the block before cur */
+    block_t* nxt;       /* the block after cur */
+    size_t size;        /* size of deallocated block */
+
+    offset -= ALIGNWORD(sizeof(struct block_t));
+    assert(offset >= 0);
+
+    /* find position of new block in free list */
+    cur = BLOCKAT(offset);
+
+    /* update the block header */
+    header = (sma_header_t*) shmaddr;
+    header->avail += cur->size;
+    size = cur->size;
+
+    if (cur->prev_size != 0) {
+        /* remove prv from list */
+        prv = PREV_SBLOCK(cur);
+        BLOCKAT(prv->fnext)->fprev = prv->fprev;
+        BLOCKAT(prv->fprev)->fnext = prv->fnext;
+        /* cur and prv share an edge, combine them */
+        prv->size +=cur->size;
+        RESET_CANARY(cur);
+        cur = prv;
+    }
+
+    nxt = NEXT_SBLOCK(cur);
+    if (nxt->fnext != 0) {
+        assert(NEXT_SBLOCK(NEXT_SBLOCK(cur))->prev_size == nxt->size);
+        /* cur and nxt shared an edge, combine them */
+        BLOCKAT(nxt->fnext)->fprev = nxt->fprev;
+        BLOCKAT(nxt->fprev)->fnext = nxt->fnext;
+        cur->size += nxt->size;
+#ifdef __APC_SMA_DEBUG__
+        CHECK_CANARY(nxt);
+        nxt->id = -1; /* assert this or set it ? */
+#endif
+        RESET_CANARY(nxt);
+    }
+
+    NEXT_SBLOCK(cur)->prev_size = cur->size;
+
+    /* insert new block after prv */
+    prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+    cur->fnext = prv->fnext;
+    prv->fnext = OFFSET(cur);
+    cur->fprev = OFFSET(prv);
+    BLOCKAT(cur->fnext)->fprev = OFFSET(cur);
+
+    return size;
+}
+/* }}} */
+
+/* {{{ apc_sma_init */
+
+void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC)
+{
+    uint i;
+
+    if (sma_initialized) {
+        return;
+    }
+    sma_initialized = 1;
+
+#if APC_MMAP
+    /*
+     * I don't think multiple anonymous mmaps makes any sense
+     * so force sma_numseg to 1 in this case
+     */
+    if(!mmap_file_mask || 
+       (mmap_file_mask && !strlen(mmap_file_mask)) ||
+       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
+        sma_numseg = 1;
+    } else {
+        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
+    }
+#else
+    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
+#endif
+
+    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
+
+    sma_segments = (apc_segment_t*) apc_emalloc((sma_numseg * sizeof(apc_segment_t)) TSRMLS_CC);
+
+    for (i = 0; i < sma_numseg; i++) {
+        sma_header_t*   header;
+        block_t     *first, *empty, *last;
+        void*       shmaddr;
+
+#if APC_MMAP
+        sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize TSRMLS_CC);
+        if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
+#else
+        sma_segments[i] = apc_shm_attach(apc_shm_create(i, sma_segsize TSRMLS_CC) TSRMLS_CC);
+#endif
+        
+        sma_segments[i].size = sma_segsize;
+
+        shmaddr = sma_segments[i].shmaddr;
+
+        header = (sma_header_t*) shmaddr;
+        apc_lck_create(NULL, 0, 1, header->sma_lock);
+        header->segsize = sma_segsize;
+        header->avail = sma_segsize - ALIGNWORD(sizeof(sma_header_t)) - ALIGNWORD(sizeof(block_t)) - ALIGNWORD(sizeof(block_t));
+#if ALLOC_DISTRIBUTION
+        {
+           int j;
+           for(j=0; j<30; j++) header->adist[j] = 0;
+        }
+#endif
+        first = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+        first->size = 0;
+        first->fnext = ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t));
+        first->fprev = 0;
+        first->prev_size = 0;
+        SET_CANARY(first);
+#ifdef __APC_SMA_DEBUG__
+        block->id = -1;
+#endif
+        empty = BLOCKAT(first->fnext);
+        empty->size = header->avail - ALIGNWORD(sizeof(block_t));
+        empty->fnext = OFFSET(empty) + empty->size;
+        empty->fprev = ALIGNWORD(sizeof(sma_header_t));
+        empty->prev_size = 0;
+        SET_CANARY(empty);
+#ifdef __APC_SMA_DEBUG__
+        empty->id = -1;
+#endif
+        last = BLOCKAT(empty->fnext);
+        last->size = 0;
+        last->fnext = 0;
+        last->fprev =  OFFSET(empty);
+        last->prev_size = empty->size;
+        SET_CANARY(last);
+#ifdef __APC_SMA_DEBUG__
+        last->id = -1;
+#endif
+    }
+}
+/* }}} */
+
+/* {{{ apc_sma_cleanup */
+void apc_sma_cleanup(TSRMLS_D)
+{
+    uint i;
+
+    assert(sma_initialized);
+
+    for (i = 0; i < sma_numseg; i++) {
+        apc_lck_destroy(SMA_LCK(i));
+#if APC_MMAP
+        apc_unmap(&sma_segments[i] TSRMLS_CC);
+#else
+        apc_shm_detach(&sma_segments[i] TSRMLS_CC);
+#endif
+    }
+    sma_initialized = 0;
+    apc_efree(sma_segments TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_sma_malloc_ex */
+void* apc_sma_malloc_ex(size_t n, size_t fragment, size_t* allocated TSRMLS_DC)
+{
+    size_t off;
+    uint i;
+    int nuked = 0;
+
+restart:
+    assert(sma_initialized);
+    LOCK(SMA_LCK(sma_lastseg));
+
+    off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
+
+    if(off == -1 && APCG(current_cache)) { 
+        /* retry failed allocation after we expunge */
+        UNLOCK(SMA_LCK(sma_lastseg));
+        APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC);
+        LOCK(SMA_LCK(sma_lastseg));
+        off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
+    }
+
+    if (off != -1) {
+        void* p = (void *)(SMA_ADDR(sma_lastseg) + off);
+        UNLOCK(SMA_LCK(sma_lastseg));
+#ifdef VALGRIND_MALLOCLIKE_BLOCK
+        VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
+#endif
+        return p;
+    }
+    
+    UNLOCK(SMA_LCK(sma_lastseg));
+
+    for (i = 0; i < sma_numseg; i++) {
+        if (i == sma_lastseg) {
+            continue;
+        }
+        LOCK(SMA_LCK(i));
+        off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
+        if(off == -1 && APCG(current_cache)) { 
+            /* retry failed allocation after we expunge */
+            UNLOCK(SMA_LCK(i));
+            APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC);
+            LOCK(SMA_LCK(i));
+            off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
+        }
+        if (off != -1) {
+            void* p = (void *)(SMA_ADDR(i) + off);
+            UNLOCK(SMA_LCK(i));
+            sma_lastseg = i;
+#ifdef VALGRIND_MALLOCLIKE_BLOCK
+            VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
+#endif
+            return p;
+        }
+        UNLOCK(SMA_LCK(i));
+    }
+
+    /* I've tried being nice, but now you're just asking for it */
+    if(!nuked) {
+        apc_cache->expunge_cb(apc_cache, (n+fragment) TSRMLS_CC);
+        apc_user_cache->expunge_cb(apc_cache, (n+fragment) TSRMLS_CC);
+        nuked = 1;
+        goto restart;
+    }
+
+    /* now, I've truly and well given up */
+
+    return NULL;
+}
+/* }}} */
+
+/* {{{ apc_sma_malloc */
+void* apc_sma_malloc(size_t n TSRMLS_DC)
+{
+    size_t allocated;
+    void *p = apc_sma_malloc_ex(n, MINBLOCKSIZE, &allocated TSRMLS_CC);
+
+    return p;
+}
+/* }}} */
+
+/* {{{ apc_sma_realloc */
+void* apc_sma_realloc(void *p, size_t n TSRMLS_DC)
+{
+    apc_sma_free(p TSRMLS_CC);
+    return apc_sma_malloc(n TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_sma_strdup */
+char* apc_sma_strdup(const char* s TSRMLS_DC)
+{
+    void* q;
+    int len;
+
+    if(!s) return NULL;
+
+    len = strlen(s)+1;
+    q = apc_sma_malloc(len TSRMLS_CC);
+    if(!q) return NULL;
+    memcpy(q, s, len);
+    return q;
+}
+/* }}} */
+
+/* {{{ apc_sma_free */
+void apc_sma_free(void* p TSRMLS_DC)
+{
+    uint i;
+    size_t offset;
+    size_t d_size;
+
+    if (p == NULL) {
+        return;
+    }
+
+    assert(sma_initialized);
+
+    
+    for (i = 0; i < sma_numseg; i++) {
+        offset = (size_t)((char *)p - SMA_ADDR(i));
+        if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
+            LOCK(SMA_LCK(i));
+            d_size = sma_deallocate(SMA_HDR(i), offset);
+            UNLOCK(SMA_LCK(i));
+#ifdef VALGRIND_FREELIKE_BLOCK
+            VALGRIND_FREELIKE_BLOCK(p, 0);
+#endif
+            return;
+        }
+    }
+
+    apc_error("apc_sma_free: could not locate address %p" TSRMLS_CC, p);
+}
+/* }}} */
+
+#ifdef APC_MEMPROTECT
+/* {{{ */
+void* apc_sma_protect(void *p)
+{
+    unsigned int i = 0;
+    size_t offset;
+
+    if (p == NULL) {
+        return NULL;
+    }
+
+    if(SMA_RO(sma_lastseg) == NULL) return p;
+
+    offset = (size_t)((char *)p - SMA_ADDR(sma_lastseg));
+
+    if(p >= (void*)SMA_ADDR(sma_lastseg) && offset < sma_segsize) {
+        return SMA_RO(sma_lastseg) + offset;
+    }
+
+    for (i = 0; i < sma_numseg; i++) {
+        offset = (size_t)((char *)p - SMA_ADDR(i));
+        if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
+            return SMA_RO(i) + offset;
+        }
+    }
+
+    return NULL;
+}
+/* }}} */
+
+/* {{{ */
+void* apc_sma_unprotect(void *p)
+{
+    unsigned int i = 0;
+    size_t offset;
+
+    if (p == NULL) {
+        return NULL;
+    }
+
+    if(SMA_RO(sma_lastseg) == NULL) return p;
+
+    offset = (size_t)((char *)p - SMA_RO(sma_lastseg));
+
+    if(p >= (void*)SMA_RO(sma_lastseg) && offset < sma_segsize) {
+        return SMA_ADDR(sma_lastseg) + offset;
+    }
+
+    for (i = 0; i < sma_numseg; i++) {
+        offset = (size_t)((char *)p - SMA_RO(i));
+        if (p >= (void*)SMA_RO(i) && offset < sma_segsize) {
+            return SMA_ADDR(i) + offset;
+        }
+    }
+
+    return NULL;
+}
+/* }}} */
+#else
+/* {{{ */
+void* apc_sma_protect(void *p) { return p; }
+void* apc_sma_unprotect(void *p) { return p; }
+/* }}} */
+#endif
+
+/* {{{ apc_sma_info */
+apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC)
+{
+    apc_sma_info_t* info;
+    apc_sma_link_t** link;
+    uint i;
+    char* shmaddr;
+    block_t* prv;
+
+    if (!sma_initialized) {
+        return NULL;
+    }
+
+    info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t) TSRMLS_CC);
+    info->num_seg = sma_numseg;
+    info->seg_size = sma_segsize - (ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t)) + ALIGNWORD(sizeof(block_t)));
+
+    info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*) TSRMLS_CC);
+    for (i = 0; i < sma_numseg; i++) {
+        info->list[i] = NULL;
+    }
+
+    if(limited) return info;
+
+    /* For each segment */
+    for (i = 0; i < sma_numseg; i++) {
+        RDLOCK(SMA_LCK(i));
+        shmaddr = SMA_ADDR(i);
+        prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
+
+        link = &info->list[i];
+
+        /* For each block in this segment */
+        while (BLOCKAT(prv->fnext)->fnext != 0) {
+            block_t* cur = BLOCKAT(prv->fnext);
+#ifdef __APC_SMA_DEBUG__
+            CHECK_CANARY(cur);
+#endif
+
+            *link = apc_emalloc(sizeof(apc_sma_link_t) TSRMLS_CC);
+            (*link)->size = cur->size;
+            (*link)->offset = prv->fnext;
+            (*link)->next = NULL;
+            link = &(*link)->next;
+
+            prv = cur;
+
+#if ALLOC_DISTRIBUTION
+            sma_header_t* header = (sma_header_t*) segment->shmaddr;
+            memcpy(info->seginfo[i].adist, header->adist, sizeof(size_t) * 30);
+#endif
+
+        }
+        UNLOCK(SMA_LCK(i));
+    }
+
+    return info;
+}
+/* }}} */
+
+/* {{{ apc_sma_free_info */
+void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC)
+{
+    int i;
+
+    for (i = 0; i < info->num_seg; i++) {
+        apc_sma_link_t* p = info->list[i];
+        while (p) {
+            apc_sma_link_t* q = p;
+            p = p->next;
+            apc_efree(q TSRMLS_CC);
+        }
+    }
+    apc_efree(info->list TSRMLS_CC);
+    apc_efree(info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ apc_sma_get_avail_mem */
+size_t apc_sma_get_avail_mem()
+{
+    size_t avail_mem = 0;
+    uint i;
+
+    for (i = 0; i < sma_numseg; i++) {
+        sma_header_t* header = SMA_HDR(i);
+        avail_mem += header->avail;
+    }
+    return avail_mem;
+}
+/* }}} */
+
+/* {{{ apc_sma_get_avail_size */
+zend_bool apc_sma_get_avail_size(size_t size)
+{
+    uint i;
+
+    for (i = 0; i < sma_numseg; i++) {
+    	sma_header_t* header = SMA_HDR(i);
+		if (header->avail > size) {
+			return 1;
+		}
+    }
+    return 0;
+}
+/* }}} */
+
+
+#if ALLOC_DISTRIBUTION
+size_t *apc_sma_get_alloc_distribution(void) {
+    sma_header_t* header = (sma_header_t*) segment->sma_shmaddr;
+    return header->adist;
+}
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_sma.h
@@ -0,0 +1,103 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_sma.h 303274 2010-09-11 14:31:32Z iliaa $ */
+
+#ifndef APC_SMA_H
+#define APC_SMA_H
+
+#define ALLOC_DISTRIBUTION 0
+
+#include "apc.h"
+
+/* Simple shared memory allocator */
+
+typedef struct _apc_segment_t apc_segment_t;
+
+struct _apc_segment_t {
+    size_t size;
+    void* shmaddr;
+#ifdef APC_MEMPROTECT
+    void* roaddr;
+#endif
+};
+
+extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC);
+extern void apc_sma_cleanup(TSRMLS_D);
+extern void* apc_sma_malloc(size_t size TSRMLS_DC);
+extern void* apc_sma_malloc_ex(size_t size, size_t fragment, size_t* allocated TSRMLS_DC);
+extern void* apc_sma_realloc(void* p, size_t size TSRMLS_DC);
+extern char* apc_sma_strdup(const char *s TSRMLS_DC);
+extern void apc_sma_free(void* p TSRMLS_DC);
+#if ALLOC_DISTRIBUTION 
+extern size_t *apc_sma_get_alloc_distribution();
+#endif
+
+extern void* apc_sma_protect(void *p);
+extern void* apc_sma_unprotect(void *p);
+
+/* {{{ struct definition: apc_sma_link_t */
+typedef struct apc_sma_link_t apc_sma_link_t;
+struct apc_sma_link_t {
+    long size;               /* size of this free block */
+    long offset;             /* offset in segment of this block */
+    apc_sma_link_t* next;   /* link to next free block */
+};
+/* }}} */
+
+/* {{{ struct definition: apc_sma_info_t */
+typedef struct apc_sma_info_t apc_sma_info_t;
+struct apc_sma_info_t {
+    int num_seg;            /* number of shared memory segments */
+    size_t seg_size;           /* size of each shared memory segment */
+    apc_sma_link_t** list;  /* there is one list per segment */
+};
+/* }}} */
+
+extern apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC);
+extern void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC);
+
+extern size_t apc_sma_get_avail_mem();
+extern zend_bool apc_sma_get_avail_size(size_t size);
+extern void apc_sma_check_integrity();
+
+/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
+typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
+#define ALIGNSIZE(x, size) ((size) * (1 + (((x)-1)/(size))))
+#define ALIGNWORD(x) ALIGNSIZE(x, sizeof(apc_word_t))
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_spin.c
@@ -0,0 +1,66 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_spin.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc_spin.h"
+
+#ifdef APC_SPIN_LOCKS
+
+slock_t *apc_slock_create(slock_t *lock)
+{
+   S_INIT_LOCK(lock);
+   return lock;
+}
+
+void apc_slock_destroy(slock_t *lock)
+{
+    return;
+}
+
+void apc_slock_lock(slock_t *lock TSRMLS_DC)
+{
+    S_LOCK(lock);
+}
+
+void apc_slock_unlock(slock_t *lock)
+{
+    S_UNLOCK(lock);
+}
+
+zend_bool apc_slock_nonblocking_lock(slock_t *lock)
+{
+    /* Technically we aren't supposed to call this directly, but the original
+     *  code provides no method for absolute non-blocking locks, so we'll call into
+     *  the TAS (test and set) functionality directly 
+     */
+    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
+}
+
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_spin.h
@@ -0,0 +1,48 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Brian Shire <shire@php.net>                                 |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: apc_spin.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_SPIN_H
+#define APC_SPIN_H
+
+#include "apc.h"
+
+#ifdef APC_SPIN_LOCKS
+
+#include "pgsql_s_lock.h"
+
+slock_t *apc_slock_create(slock_t *lock);
+void apc_slock_destroy(slock_t *lock);
+void apc_slock_lock(slock_t *lock TSRMLS_DC);
+zend_bool apc_slock_nonblocking_lock(slock_t *lock);
+void apc_slock_unlock(slock_t *lock);
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_stack.c
@@ -0,0 +1,106 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_stack.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+#include "apc.h"
+#include "apc_stack.h"
+
+struct apc_stack_t {
+    void** data;
+    int capacity;
+    int size;
+};
+
+apc_stack_t* apc_stack_create(int size_hint TSRMLS_DC)
+{
+    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t) TSRMLS_CC);
+
+    stack->capacity = (size_hint > 0) ? size_hint : 10;
+    stack->size = 0;
+    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity TSRMLS_CC);
+
+    return stack;
+}
+
+void apc_stack_destroy(apc_stack_t* stack TSRMLS_DC)
+{
+    if (stack != NULL) {
+        apc_efree(stack->data TSRMLS_CC);
+        apc_efree(stack TSRMLS_CC);
+    }
+}
+
+void apc_stack_clear(apc_stack_t* stack)
+{
+    assert(stack != NULL);
+    stack->size = 0;
+}
+
+void apc_stack_push(apc_stack_t* stack, void* item TSRMLS_DC)
+{
+    assert(stack != NULL);
+    if (stack->size == stack->capacity) {
+        stack->capacity *= 2;
+        stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity TSRMLS_CC);
+    }
+    stack->data[stack->size++] = item;
+}
+
+void* apc_stack_pop(apc_stack_t* stack)
+{
+    assert(stack != NULL && stack->size > 0);
+    return stack->data[--stack->size];
+}
+
+void* apc_stack_top(apc_stack_t* stack)
+{
+    assert(stack != NULL && stack->size > 0);
+    return stack->data[stack->size-1];
+}
+
+void* apc_stack_get(apc_stack_t* stack, int n)
+{
+    assert(stack != NULL && stack->size > n);
+    return stack->data[n];
+}
+
+int apc_stack_size(apc_stack_t* stack)
+{
+    assert(stack != NULL);
+    return stack->size;
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_stack.h
@@ -0,0 +1,58 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.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_stack.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+#ifndef APC_STACK_H
+#define APC_STACK_H
+
+/* Basic stack datatype */
+
+#define T apc_stack_t*
+typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
+
+extern T apc_stack_create(int size_hint TSRMLS_DC);
+extern void apc_stack_destroy(T stack TSRMLS_DC);
+extern void apc_stack_clear(T stack);
+extern void apc_stack_push(T stack, void* item TSRMLS_DC);
+extern void* apc_stack_pop(T stack);
+extern void* apc_stack_top(T stack);
+extern void* apc_stack_get(T stack, int n);
+extern int apc_stack_size(T stack);
+
+#undef T
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_string.c
@@ -0,0 +1,247 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Dmitry Stogov <dmitry@zend.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: $ */
+
+#include "apc.h"
+#include "apc_globals.h"
+#include "apc_php.h"
+#include "apc_lock.h"
+
+#ifdef ZEND_ENGINE_2_4
+
+typedef struct _apc_interned_strings_data_t {
+    char *interned_strings_start;
+    char *interned_strings_end;
+    char *interned_strings_top;
+    apc_lck_t lock;
+    HashTable interned_strings;
+} apc_interned_strings_data_t;
+
+apc_interned_strings_data_t *apc_interned_strings_data = NULL;
+
+#define APCSG(v) (apc_interned_strings_data->v)
+
+static char *old_interned_strings_start;
+static char *old_interned_strings_end;
+static char *(*old_new_interned_string)(char *str, int len, int free_src TSRMLS_DC);
+static void (*old_interned_strings_snapshot)(TSRMLS_D);
+static void (*old_interned_strings_restore)(TSRMLS_D);
+
+static char *apc_dummy_new_interned_string_for_php(char *str, int len, int free_src TSRMLS_DC)
+{
+    return str;
+}
+
+static void apc_dummy_interned_strings_snapshot_for_php(TSRMLS_D)
+{
+}
+
+static void apc_dummy_interned_strings_restore_for_php(TSRMLS_D)
+{
+}
+
+char *apc_new_interned_string(char *arKey, int nKeyLength TSRMLS_DC)
+{
+    ulong h;
+    uint nIndex;
+    Bucket *p;
+
+    if (arKey >= APCSG(interned_strings_start) && arKey < APCSG(interned_strings_end)) {
+        return arKey;
+    }
+
+    h = zend_inline_hash_func(arKey, nKeyLength);
+    nIndex = h & APCSG(interned_strings).nTableMask;
+
+    p = APCSG(interned_strings).arBuckets[nIndex];
+    while (p != NULL) {
+        if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
+            if (!memcmp(p->arKey, arKey, nKeyLength)) {
+                return p->arKey;
+            }
+        }
+        p = p->pNext;
+    }
+   
+    if (APCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
+        APCSG(interned_strings_end)) {
+        /* no memory */
+        return NULL;
+    }
+
+    p = (Bucket *) APCSG(interned_strings_top);
+    APCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
+
+    p->arKey = (char*)(p+1);
+    memcpy(p->arKey, arKey, nKeyLength);
+    p->nKeyLength = nKeyLength;
+    p->h = h;
+    p->pData = &p->pDataPtr;
+    p->pDataPtr = p;
+
+    p->pNext = APCSG(interned_strings).arBuckets[nIndex];
+    p->pLast = NULL;
+    if (p->pNext) {
+        p->pNext->pLast = p;
+    }
+    APCSG(interned_strings).arBuckets[nIndex] = p;
+
+    p->pListLast = APCSG(interned_strings).pListTail;
+    APCSG(interned_strings).pListTail = p;
+    p->pListNext = NULL;
+    if (p->pListLast != NULL) {
+        p->pListLast->pListNext = p;
+    }
+    if (!APCSG(interned_strings).pListHead) {
+        APCSG(interned_strings).pListHead = p;
+    }
+
+    APCSG(interned_strings).nNumOfElements++;
+
+    return p->arKey;
+}
+
+static void apc_copy_internal_strings(TSRMLS_D)
+{
+    Bucket *p, *q;
+
+    p = CG(function_table)->pListHead;
+    while (p) {
+        if (p->nKeyLength) {
+            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
+        }
+        p = p->pListNext;
+    }
+
+    p = CG(class_table)->pListHead;
+    while (p) {
+        zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr);
+
+        if (p->nKeyLength) {
+            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
+        }
+
+        q = ce->properties_info.pListHead;
+        while (q) {
+            zend_property_info *info = (zend_property_info*)(q->pData);
+
+            if (q->nKeyLength) {
+                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
+            }
+
+            if (info->name) {
+                info->name = apc_new_interned_string(info->name, info->name_length+1 TSRMLS_CC);
+            }
+
+            q = q->pListNext;
+        }
+
+        q = ce->function_table.pListHead;
+        while (q) {
+            if (q->nKeyLength) {
+                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
+            }
+            q = q->pListNext;
+        }
+
+        q = ce->constants_table.pListHead;
+        while (q) {
+            if (q->nKeyLength) {
+                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
+            }
+            q = q->pListNext;
+        }
+
+        p = p->pListNext;
+    }
+
+    p = EG(zend_constants)->pListHead;
+    while (p) {
+        if (p->nKeyLength) {
+            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
+       }
+        p = p->pListNext;
+    }
+}
+
+void apc_interned_strings_init(TSRMLS_D)
+{
+    int count = APCG(shm_strings_buffer) / (sizeof(Bucket) + sizeof(Bucket*) * 2);
+
+    apc_interned_strings_data = (apc_interned_strings_data_t*) apc_sma_malloc(APCG(shm_strings_buffer) TSRMLS_CC);
+
+    CREATE_LOCK(APCSG(lock));
+
+    zend_hash_init(&APCSG(interned_strings), count, NULL, NULL, 1);
+    APCSG(interned_strings).nTableMask = APCSG(interned_strings).nTableSize - 1;
+    APCSG(interned_strings).arBuckets = (Bucket**)((char*)apc_interned_strings_data + sizeof(apc_interned_strings_data_t));
+   
+    APCSG(interned_strings_start) = (char*)APCSG(interned_strings).arBuckets + APCSG(interned_strings).nTableSize * sizeof(Bucket *);
+    APCSG(interned_strings_end)   = (char*)apc_interned_strings_data + APCG(shm_strings_buffer);
+    APCSG(interned_strings_top)   = APCSG(interned_strings_start);
+
+    old_interned_strings_start = CG(interned_strings_start);
+    old_interned_strings_end = CG(interned_strings_end);
+    old_new_interned_string = zend_new_interned_string;
+    old_interned_strings_snapshot = zend_interned_strings_snapshot;
+    old_interned_strings_restore = zend_interned_strings_restore;
+
+    CG(interned_strings_start) = APCSG(interned_strings_start);
+    CG(interned_strings_end) = APCSG(interned_strings_end);
+    zend_new_interned_string = apc_dummy_new_interned_string_for_php;
+    zend_interned_strings_snapshot = apc_dummy_interned_strings_snapshot_for_php;
+    zend_interned_strings_restore = apc_dummy_interned_strings_restore_for_php;
+
+    apc_copy_internal_strings(TSRMLS_C);
+}
+
+void apc_interned_strings_shutdown(TSRMLS_D)
+{	
+    zend_hash_clean(CG(function_table));
+    zend_hash_clean(CG(class_table));
+    zend_hash_clean(EG(zend_constants));
+
+    CG(interned_strings_start) = old_interned_strings_start;
+    CG(interned_strings_end) = old_interned_strings_end;
+    zend_new_interned_string = old_new_interned_string;
+    zend_interned_strings_snapshot = old_interned_strings_snapshot;
+    zend_interned_strings_restore = old_interned_strings_restore;
+
+    DESTROY_LOCK(APCSG(lock));
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_string.h
@@ -0,0 +1,49 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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: Dmitry Stogov <dmitry@zend.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: $ */
+
+#ifndef APC_STRING
+#define APC_STRING
+
+#include "apc.h"
+
+void apc_interned_strings_init(TSRMLS_D);
+void apc_interned_strings_shutdown(TSRMLS_D);
+
+char *apc_new_interned_string(char *arKey, int nKeyLength TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_zend.c
@@ -0,0 +1,271 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_zend.c 303426 2010-09-16 16:39:08Z iliaa $ */
+
+#include "apc_zend.h"
+#include "apc_globals.h"
+
+/* true global */
+int apc_reserved_offset;
+
+void* apc_php_malloc(size_t n TSRMLS_DC)
+{
+    return emalloc(n);
+}
+
+void apc_php_free(void* p TSRMLS_DC)
+{
+    efree(p);
+}
+
+#ifdef APC_OPCODE_OVERRIDE
+
+static opcode_handler_t *apc_original_opcode_handlers;
+static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
+
+#define APC_EX_T(offset)                    (*(temp_variable *)((char*)execute_data->Ts + offset))
+
+#ifdef ZEND_ENGINE_2_4
+static zval *apc_get_zval_ptr(zend_uchar op_type, znode_op *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
+{
+    *freeval = NULL;
+
+    switch (op_type) {
+        case IS_CONST:
+            return node->zv;
+        case IS_VAR:
+            return APC_EX_T(node->var).var.ptr;
+        case IS_TMP_VAR:
+            return (*freeval = &APC_EX_T(node->var).tmp_var);
+        case IS_CV:
+        {
+            zval ***ret = &execute_data->CVs[node->var];
+
+            if (!*ret) {
+                zend_compiled_variable *cv = &EG(active_op_array)->vars[node->var];
+
+                if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
+                    apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name);
+                    return &EG(uninitialized_zval);
+                }
+            }
+            return **ret;
+        }
+        case IS_UNUSED:
+        default:
+            return NULL;
+    }
+}
+#else
+static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
+{
+    *freeval = NULL;
+
+    switch (node->op_type) {
+        case IS_CONST:
+            return &(node->u.constant);
+        case IS_VAR:
+            return APC_EX_T(node->u.var).var.ptr;
+        case IS_TMP_VAR:
+            return (*freeval = &APC_EX_T(node->u.var).tmp_var);
+#ifdef ZEND_ENGINE_2_1
+        case IS_CV:
+        {
+            zval ***ret = &execute_data->CVs[node->u.var];
+
+            if (!*ret) {
+                zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
+
+                if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
+                    apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name);
+                    return &EG(uninitialized_zval);
+                }
+            }
+            return **ret;
+        }
+#endif
+        case IS_UNUSED:
+        default:
+            return NULL;
+    }
+}
+#endif
+
+static int ZEND_FASTCALL apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
+{
+    APC_ZEND_OPLINE
+    zval *freeop1 = NULL;
+    zval *inc_filename = NULL, tmp_inc_filename;
+    char realpath[MAXPATHLEN];
+    php_stream_wrapper *wrapper;
+    char *path_for_open;
+    char *full_path = NULL;
+    int ret = 0;
+    apc_opflags_t* flags = NULL;
+
+#ifdef ZEND_ENGINE_2_4
+    if (opline->extended_value != ZEND_INCLUDE_ONCE &&
+        opline->extended_value != ZEND_REQUIRE_ONCE) {
+        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+    }
+
+    inc_filename = apc_get_zval_ptr(opline->op1_type, &opline->op1, &freeop1, execute_data TSRMLS_CC);
+#else
+    if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
+        Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
+        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+    }
+
+    inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
+#endif
+
+    if (Z_TYPE_P(inc_filename) != IS_STRING) {
+        tmp_inc_filename = *inc_filename;
+        zval_copy_ctor(&tmp_inc_filename);
+        convert_to_string(&tmp_inc_filename);
+        inc_filename = &tmp_inc_filename;
+    }
+
+    wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
+
+    if (wrapper != &php_plain_files_wrapper || !(IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) || (full_path = expand_filepath(path_for_open, realpath TSRMLS_CC)))) {
+        /* Fallback to original handler */
+        if (inc_filename == &tmp_inc_filename) {
+            zval_dtor(&tmp_inc_filename);
+        }
+        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+    }
+
+    if (!full_path) {
+    	full_path = path_for_open;
+    }
+    if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
+#ifdef ZEND_ENGINE_2_4
+        if (!(opline->result_type & EXT_TYPE_UNUSED)) {
+            ALLOC_INIT_ZVAL(APC_EX_T(opline->result.var).var.ptr);
+            ZVAL_TRUE(APC_EX_T(opline->result.var).var.ptr);
+        }
+#else
+        if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
+            ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
+            ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
+        }
+#endif
+        if (inc_filename == &tmp_inc_filename) {
+            zval_dtor(&tmp_inc_filename);
+        }
+        if (freeop1) {
+            zval_dtor(freeop1);
+        }
+        execute_data->opline++;
+        return 0;
+    }
+
+    if (inc_filename == &tmp_inc_filename) {
+        zval_dtor(&tmp_inc_filename);
+    }
+
+    if(apc_reserved_offset != -1) {
+        /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
+        flags = (apc_opflags_t*) & (execute_data->op_array->reserved[apc_reserved_offset]);
+    }
+
+    if(flags && flags->deep_copy == 1) {
+        /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily 
+         * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
+         */
+#ifdef ZEND_ENGINE_2_4
+        opline->extended_value = (opline->extended_value == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
+        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+        opline->extended_value = (opline->extended_value == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
+#else
+        Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
+        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+        Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
+#endif
+    } else {
+        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+    }
+
+    return ret;
+}
+
+void apc_zend_init(TSRMLS_D)
+{
+    zend_extension dummy_ext;
+    apc_reserved_offset = zend_get_resource_handle(&dummy_ext); 
+    assert(apc_reserved_offset == dummy_ext.resource_number);
+    assert(apc_reserved_offset != -1);
+    assert(sizeof(apc_opflags_t) <= sizeof(void*));
+    if (!APCG(include_once)) {
+        /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
+        return;
+    }
+
+    memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
+
+    /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
+#ifdef ZEND_ENGINE_2_1
+    apc_original_opcode_handlers = zend_opcode_handlers;
+    zend_opcode_handlers = apc_opcode_handlers;
+#else
+    apc_original_opcode_handlers = apc_opcode_handlers;
+#endif
+
+    APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
+}
+
+void apc_zend_shutdown(TSRMLS_D)
+{
+    if (!APCG(include_once)) {
+        /* Nothing changed, nothing to restore */
+        return;
+    }
+
+#ifdef ZEND_ENGINE_2_1
+    zend_opcode_handlers = apc_original_opcode_handlers;
+#else
+    memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
+#endif
+}
+
+#else /* Opcode Overrides unavailable */
+
+void apc_zend_init(TSRMLS_D) { }
+void apc_zend_shutdown(TSRMLS_D) { }
+
+#endif /* APC_OPCODE_OVERRIDE */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/apc_zend.h
@@ -0,0 +1,191 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  +----------------------------------------------------------------------+
+
+   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_zend.h 303464 2010-09-17 12:19:29Z gopalv $ */
+
+#ifndef APC_ZEND_H
+#define APC_ZEND_H
+
+/* Utilities for interfacing with the zend engine */
+
+#include "apc.h"
+#include "apc_php.h"
+
+#ifndef Z_REFCOUNT_P
+#define Z_REFCOUNT_P(pz)              (pz)->refcount
+#define Z_REFCOUNT_PP(ppz)            Z_REFCOUNT_P(*(ppz))
+#endif
+
+#ifndef Z_SET_REFCOUNT_P
+#define Z_SET_REFCOUNT_P(pz, rc)      (pz)->refcount = rc
+#define Z_SET_REFCOUNT_PP(ppz, rc)    Z_SET_REFCOUNT_P(*(ppz), rc)
+#endif
+
+#ifndef Z_ADDREF_P
+#define Z_ADDREF_P(pz)                (pz)->refcount++
+#define Z_ADDREF_PP(ppz)              Z_ADDREF_P(*(ppz))
+#endif
+
+#ifndef Z_DELREF_P
+#define Z_DELREF_P(pz)                (pz)->refcount--
+#define Z_DELREF_PP(ppz)              Z_DELREF_P(*(ppz))
+#endif
+
+#ifndef Z_ISREF_P
+#define Z_ISREF_P(pz)                 (pz)->is_ref
+#define Z_ISREF_PP(ppz)               Z_ISREF_P(*(ppz))
+#endif
+
+#ifndef Z_SET_ISREF_P
+#define Z_SET_ISREF_P(pz)             (pz)->is_ref = 1
+#define Z_SET_ISREF_PP(ppz)           Z_SET_ISREF_P(*(ppz))
+#endif
+
+#ifndef Z_UNSET_ISREF_P
+#define Z_UNSET_ISREF_P(pz)           (pz)->is_ref = 0
+#define Z_UNSET_ISREF_PP(ppz)         Z_UNSET_ISREF_P(*(ppz))
+#endif
+
+#ifndef Z_SET_ISREF_TO_P
+#define Z_SET_ISREF_TO_P(pz, isref)   (pz)->is_ref = isref
+#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
+#endif
+
+
+extern void* apc_php_malloc(size_t n TSRMLS_DC);
+extern void apc_php_free(void* p TSRMLS_DC);
+
+extern void apc_zend_init(TSRMLS_D);
+extern void apc_zend_shutdown(TSRMLS_D);
+
+
+/* offset for apc info in op_array->reserved */
+extern int apc_reserved_offset;
+
+#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
+# define ZEND_VM_KIND_CALL  1
+#endif
+
+#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
+# define ZEND_VM_KIND   ZEND_VM_KIND_CALL
+#endif
+
+#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
+# define APC_OPCODE_OVERRIDE
+#endif
+
+#ifdef APC_OPCODE_OVERRIDE
+
+#ifdef ZEND_ENGINE_2_1
+/* Taken from Zend/zend_vm_execute.h */
+#define _CONST_CODE  0
+#define _TMP_CODE    1
+#define _VAR_CODE    2
+#define _UNUSED_CODE 3
+#define _CV_CODE     4
+static inline int _apc_opcode_handler_decode(zend_op *opline)
+{
+    static const int apc_vm_decode[] = {
+        _UNUSED_CODE, /* 0              */
+        _CONST_CODE,  /* 1 = IS_CONST   */
+        _TMP_CODE,    /* 2 = IS_TMP_VAR */
+        _UNUSED_CODE, /* 3              */
+        _VAR_CODE,    /* 4 = IS_VAR     */
+        _UNUSED_CODE, /* 5              */
+        _UNUSED_CODE, /* 6              */
+        _UNUSED_CODE, /* 7              */
+        _UNUSED_CODE, /* 8 = IS_UNUSED  */
+        _UNUSED_CODE, /* 9              */
+        _UNUSED_CODE, /* 10             */
+        _UNUSED_CODE, /* 11             */
+        _UNUSED_CODE, /* 12             */
+        _UNUSED_CODE, /* 13             */
+        _UNUSED_CODE, /* 14             */
+        _UNUSED_CODE, /* 15             */
+        _CV_CODE      /* 16 = IS_CV     */
+    };
+#ifdef ZEND_ENGINE_2_4
+    return (opline->opcode * 25) + (apc_vm_decode[opline->op1_type] * 5) + apc_vm_decode[opline->op2_type];
+#else
+    return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
+#endif
+}
+
+# define APC_ZEND_OPLINE                    zend_op *opline = execute_data->opline;
+# define APC_OPCODE_HANDLER_DECODE(opline)  _apc_opcode_handler_decode(opline)
+# if PHP_MAJOR_VERSION >= 6
+#  define APC_OPCODE_HANDLER_COUNT          ((25 * 152) + 1)
+# elif defined(ZEND_ENGINE_2_4)
+#  define APC_OPCODE_HANDLER_COUNT          ((25 * 157) + 1) /* 3 new opcodes in 5.4? - separate, bind_trais, add_trait */
+# elif PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3
+#  define APC_OPCODE_HANDLER_COUNT          ((25 * 154) + 1) /* 3 new opcodes in 5.3 - unused, lambda, jmp_set */
+# else
+#  define APC_OPCODE_HANDLER_COUNT          ((25 * 151) + 1)
+# endif
+# define APC_REPLACE_OPCODE(opname)         { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; }
+
+#else /* ZE2.0 */
+# define APC_ZEND_ONLINE
+# define APC_OPCODE_HANDLER_DECODE(opline)  (opline->opcode)
+# define APC_OPCODE_HANDLER_COUNT           512
+# define APC_REPLACE_OPCODE(opname)         zend_opcode_handlers[opname] = apc_op_##opname;
+#endif
+
+#ifndef ZEND_FASTCALL  /* Added in ZE2.3.0 */
+#define ZEND_FASTCALL
+#endif
+
+/* Added in ZE2.3.0 */
+#ifndef zend_parse_parameters_none
+# define zend_parse_parameters_none() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
+#endif
+
+
+#endif  /* APC_OPCODE_OVERRIDE */
+
+#ifdef ZEND_ENGINE_2_4
+# define ZEND_CE_FILENAME(ce)			(ce)->info.user.filename
+# define ZEND_CE_DOC_COMMENT(ce)        (ce)->info.user.doc_comment
+# define ZEND_CE_DOC_COMMENT_LEN(ce)	(ce)->info.user.doc_comment_len
+# define ZEND_CE_BUILTIN_FUNCTIONS(ce)  (ce)->info.internal.builtin_functions
+#else
+# define ZEND_CE_FILENAME(ce)			(ce)->filename
+# define ZEND_CE_DOC_COMMENT(ce)        (ce)->doc_comment
+# define ZEND_CE_DOC_COMMENT_LEN(ce)	(ce)->doc_comment_len
+# define ZEND_CE_BUILTIN_FUNCTIONS(ce)  (ce)->builtin_functions
+#endif
+
+#endif  /* APC_ZEND_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/CHANGELOG
@@ -0,0 +1,249 @@
+
+3.1.2 : 2008-12-12
+
+- pecl package.xml/build fixes (bjori)
+
+3.1.1 : 2008-12-12
+
+- PHP4 compatibilty break
+- apc_pool allocator (Gopal) 
+- doubly-linked sma allocator (Shire)
+- php 5.3 gc compatibility (Gopal)
+- APCIterator for easy access (Shire)
+- apc_delete_file (Shire)
+- apc_inc/apc_dec/apc_cas functions (Shire)
+- apc.canonicalize (Gopal)
+- apc.preload_path (Gopal)
+- apc.rfc1867_ttl  (Shire)
+- apc.file_md5     (Shire)
+- consolidate locking macros (Shire)
+- remove futex/TSRM locks  (Shire)
+- non-blocking semaphore locks  (Shire)
+- zval* object rework (Gopal)
+
+3.0.19: 2008-05-14
+- Safe-mode and fast-cgi fixes
+- Fix double-free of builtin_functions
+- php 5.3 fixes
+
+3.0.18: 2008-03-29
+- Revert apc_expunge_cb bug-fix
+- Misc memleaks
+
+3.0.17: 2008-03-26
+- Crash fixes
+- Fix apc_add() cache expunge bug (Rasmus)
+- Added parameter to apc_fetch to determine success/failure when fetching booleans (shire)
+- Fix misc. memleaks (shire)
+  
+3.0.16: 2007-12-26
+- Fix for longstanding cache-full crash (Christian Seiler)
+  http://news.php.net/php.pecl.dev/4951 for the details
+- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
+- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
+- Minor cleanups (Lucas Nealan)
+- Added configure option to enable apc_cache_info('filehits') (Shire)
+
+3.0.15: 2007-10-18
+- Eliminate a per-request time() syscall (Rasmus)
+- Added rfc1867 prefix, name, and freq ini options (Shire)
+- Allow deletion of individual user cache entries via apc.php (Sara)
+- Fix overzealous cleanup during RSHUTDOWN (Gopal)
+- Fix memory alignment and locking issues (Gopal) 
+- Make apc_compile insert/replace entries (Shire)
+- Make mixed inheritance recompile & cache afresh  (Gopal)
+- Make nostat mode search include_path for canonicalization (Gopal)
+- ZTS & other compile fixes (Gopal, Edin, Shire)
+  
+3.0.14: 2007-03-21
+- Build fix (Shire)
+- Don't hook the upload hook if APC is disabled (Rasmus)
+- Local shadow cache support (Gopal)
+- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
+- Fix apc_add() to overwrite timed out user entries (Rasmus)
+- Fix double inclusion of files with conditional classes in php4 (Gopal)
+- Allocator fixes to reduce fragmentation (Gopal)
+
+3.0.13: 2007-02-24
+- File upload progress (Rasmus)
+- Pthread mutex and spin locks (Shire)
+- Recursive zval support for apc_fetch/_store (Shire, Gopal)
+- apc.stat_ctime flag for ctime checks (Rasmus)
+- Multiple key fetches with apc_fetch (Shire)
+- Canary checks for shm memory deallocation (Gopal)
+- Add hooks for external optimizer (Shire)
+- Obsolete and remove apc optimizer (Gopal)
+- APC info changes - cache insert rate, hit and miss rates (Shire)
+- Fix apc_load_constants (Gopal)
+- Rewrite dump opcode code to use vld (Gopal)
+- Use apc_[ewn]print functions for error reporting (Shire) 
+- Auto global fixes and refactoring (Gopal, Shire)
+- Fix memory leaks in object serialization (Ilia)
+- Memory cleanup code for destructor order (Gopal)
+- Win32 build fixes (Ilia, Wez)
+- ZTS and Php 4 build fixes (Bjori)
+- Add apc_add() function (Rasmus)
+- Add optional limited flag to apc_sma_info() (Rasmus)
+
+3.0.12p2: 2006-09-05
+- Package version up
+
+3.0,12p1: 2006-09-05
+- PHP4 build fixes
+
+3.0.12: 2006-09-05
+- PHP 5.2 compatibility (Gopal)
+- TSRM fixes (Gopal)
+- Add extra flags to op_array->reserved to improve op array 
+  processing code (Gopal)
+- Fix crashes in optimizer and cli mode (Ilia)
+- Optimizer fixes for PHP5 (Ilia, Gopal)
+- Allow multiple inclusions of a file with a dynamic class (Gopal)
+- Php 4 function table and properties fixes (Gopal)
+- Fix memory leaks in apc_cache_info (Gopal)
+
+3.0.11: 2006-08-16
+- Made --enable-apc-mmap the default compile option (for real this time)
+- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
+  only fetch header information to make it useful when you have tens of
+  thousands of entries.  (Brian Shire)
+- 64-bit fixes (George)
+- Don't mix Full Path and Inode keys (George)
+- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
+  require_once() and include_once() statements. (Sara)
+- Add a non-blocking write_lock for cache inserts.  This is a better approach
+  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
+- A bit of work on the optimizer.  (Sara)
+- Various memory issues resolved. (Gopal)
+
+3.0.10: 2006-03-11
+- Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
+  includes will not be stat'ed for any changes.  You will have to restart the server if you
+  change anything.  This mode increases performance quite a bit, especially if you have a
+  lot of includes.
+
+- Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
+  than it solves.  I'll need to revisit locking and signal handling at some point soon.
+
+3.0.9: 2006-03-04
+- Eliminate rand() call when slam_defense is not set (Rasmus)
+- Fix for __isset problem (Gopal)
+- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
+- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
+- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
+- Add cache busy flag which is set when an expunge is underway (Rasmus)
+- Add automatic serialization of objects in apc_store() (Marcus)
+- 64-bit .ini flag fix (Rasmus)
+- Static members fix (Gopal)
+- sma_cleanup() mem leak fix (Rasmus)
+- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
+- Fix autoglobals JIT bug (Gopal)
+- Fix instance bug (Gopal)
+- Add a lock cleanup safety net to request shutdown (Rasmus)
+- Fix apc.slam_defense edge-case bug (Rasmus)
+- User entry memory usage tracking support (Ilia)
+- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
+
+3.0.8: 2005-08-24
+Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
+Cache corruption fix in cache-full cleanup code (Gopal)
+
+3.0.7: 2005-08-16
+- Fix to apc.php to show final segment in frag chart. (Ilia)
+- A couple of win32 fixes. (Frank)
+- Add apc.enable_cli ini directive. (Rasmus)
+- Add test cases. (Marcus)
+- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
+- Simplify user cache handling by removing the user_cache_stack (Rasmus)
+- Fix apc_fetch() memory corruption (Andrei,Rasmus)
+- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
+
+3.0.6: 2005-07-30
+- Added apc.php to package.xml file.
+- Track per-entry memory usage. (Val)
+- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
+- fcntl locking robustness fixes. (Rasmus)
+- Shared read-locks where possible. (Rasmus)
+- Added file_update_protection configuration parameter. (Rasmus)
+- Windows ZTS fixes (Frank)
+
+3.0.5: 2005-07-27
+- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
+- Support extensions such as bcompiler that need to hook into compile_file. (Val)
+- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
+- Segfault in cache cleanup code (Ilia, Rasmus)
+
+3.0.4: 2005-07-18
+- Add win32 support (Edin )
+- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
+- A couple of other minor fixes
+
+3.0.3: 2005-07-05
+- Fix compile problem against PHP 5.0.x
+
+3.0.2: 2005-07-05
+- Better shm error message
+
+3.0.1: 2005-07-05
+- PHP4 build fix
+
+3.0: 2005-06-23
+- PHP 5.1 support (Arun, Gopal, Rasmus)
+- Major Inheritance bug fix (Arun, Gopal)
+
+2.0: 2003-02-10
+- ground-up rewrite sharing none of the original source code (djc)
+
+1.0.10:
+- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
+- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
+  this parameter to your php.ini file to activate apc shm or mmap caching
+- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
+  2001-05-15]
+- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
+- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
+- experminental 'fast' cache-retrieval [djc 2001-05-20]
+- fixed regex support [gws 2001-05-16]
+- enhanced reader-writer lock support [rg 2001-05-07]
+
+1.0.9:
+- fixed (?) memory alignment bug on 64 bit archiecures 
+- added many cache visibiliy functions 
+- added opional fcntl locks under shm version 
+- numerous bug fixes 
+
+1.0.8:
+- added ability to detect and decompile compiled files placed as 'source'
+  [gws,dw 2001-01-30]
+- fixed apc_rstat bug [gws 2001-01-29]
+- added hack to support included urls [gws 2001-01-30]
+- fixed apc_cache_index [mb 2001-01-31]
+- added multiple regex support [gs 2001-02-03]
+- added apc_cache_info [mb,gs 2001-02-03]
+
+1.0.7:
+- partially fixed for Solaris [gws 2001-01-29]
+- fixed mtime support for relative includes [gws 2001-01-29]
+- code cleanup [yg,ta,gws 2001-01-29]
+
+1.0.6:
+- support for mtime in mmap [yg,gws 2001-01-27]
+- fixed indexed-array initialization bug [djc,gws 2001-01-27]
+
+1.0.5:
+- support for relative include paths [djc,gws 2001-01-19]
+- class member array support fixed [djc 2001-01-18]
+- added apc_cache_index [gws 2001-01-18]
+
+1.0.4:
+- support for class hierarchies greater than two levels deep [djc 2001-01-17]
+
+1.0.3:
+- fixed support for class inheritance [djc 2001-01-16]
+
+1.0.2:
+- support for inherited classes [gws 2001-01-15]
+- support for intialization of class variables and objects [gws 2001-01-13]
+
+1.0.1:
+- added optional file modification time check [djc 2001-01-12]
--- /dev/null
+++ b/ext/apc/config.m4
@@ -0,0 +1,246 @@
+dnl
+dnl $Id: config.m4 304101 2010-10-05 14:37:36Z kalle $
+dnl
+
+PHP_ARG_ENABLE(apc, whether to enable APC support,
+[  --enable-apc           Enable APC support])
+
+AC_ARG_ENABLE(apc-debug,
+[  --enable-apc-debug     Enable APC debugging], 
+[
+  PHP_APC_DEBUG=yes
+], 
+[
+  PHP_APC_DEBUG=no
+])
+
+AC_MSG_CHECKING(whether we should enable cache request file info)
+AC_ARG_ENABLE(apc-filehits,
+[  --enable-apc-filehits   Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
+[
+  PHP_APC_FILEHITS=$enableval
+	AC_MSG_RESULT($enableval)
+], 
+[
+  PHP_APC_FILEHITS=no
+	AC_MSG_RESULT(no)
+])
+
+AC_MSG_CHECKING(whether we should use mmap)
+AC_ARG_ENABLE(apc-mmap,
+[  --disable-apc-mmap
+                          Disable mmap support and use IPC shm instead],
+[
+  PHP_APC_MMAP=$enableval
+  AC_MSG_RESULT($enableval)
+], [
+  PHP_APC_MMAP=yes
+  AC_MSG_RESULT(yes)
+])
+
+AC_MSG_CHECKING(whether we should use semaphore locking instead of fcntl)
+AC_ARG_ENABLE(apc-sem,
+[  --enable-apc-sem
+                          Enable semaphore locks instead of fcntl],
+[
+  PHP_APC_SEM=$enableval
+  AC_MSG_RESULT($enableval)
+], [
+  PHP_APC_SEM=no
+  AC_MSG_RESULT(no)
+])
+
+AC_MSG_CHECKING(whether we should use pthread mutex locking)
+AC_ARG_ENABLE(apc-pthreadmutex,
+[  --disable-apc-pthreadmutex
+                          Disable pthread mutex locking ],
+[
+  PHP_APC_PTHREADMUTEX=$enableval
+  AC_MSG_RESULT($enableval)
+],
+[
+  PHP_APC_PTHREADMUTEX=yes
+  AC_MSG_RESULT(yes)
+])
+
+if test "$PHP_APC_PTHREADMUTEX" != "no"; then
+	orig_LIBS="$LIBS"
+	LIBS="$LIBS -lpthread"
+	AC_TRY_RUN(
+			[
+				#include <sys/types.h>
+				#include <pthread.h>
+                                main() {
+				pthread_mutex_t mutex;
+				pthread_mutexattr_t attr;	
+
+				if(pthread_mutexattr_init(&attr)) { 
+					puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
+					return -1; 
+				}
+				if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { 
+					puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
+					return -1; 
+				}	
+				if(pthread_mutex_init(&mutex, &attr)) { 
+					puts("Unable to initialize the mutex (pthread_mutex_init).");
+					return -1; 
+				}
+				if(pthread_mutexattr_destroy(&attr)) { 
+					puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
+					return -1; 
+				}
+				if(pthread_mutex_destroy(&mutex)) { 
+					puts("Unable to destroy mutex (pthread_mutex_destroy).");
+					return -1; 
+				}
+
+				puts("pthread mutex's are supported!");
+				return 0;
+                                }
+			],
+			[ dnl -Success-
+				PHP_ADD_LIBRARY(pthread)
+			],
+			[ dnl -Failure-
+				AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
+  			PHP_APC_PTHREADMUTEX=no
+			],
+			[
+				PHP_ADD_LIBRARY(pthread)
+			]
+	)
+	LIBS="$orig_LIBS"
+fi
+
+AC_MSG_CHECKING(whether we should use spin locks)
+AC_ARG_ENABLE(apc-spinlocks,
+[  --enable-apc-spinlocks
+                          Enable spin locks  EXPERIMENTAL ],
+[
+  PHP_APC_SPINLOCKS=$enableval
+  AC_MSG_RESULT($enableval)
+],
+[
+  PHP_APC_SPINLOCKS=no
+  AC_MSG_RESULT(no)
+])
+
+AC_MSG_CHECKING(whether we should enable memory protection)
+AC_ARG_ENABLE(apc-memprotect,
+[  --enable-apc-memprotect
+                          Enable mmap/shm memory protection],
+[
+  PHP_APC_MEMPROTECT=$enableval
+  AC_MSG_RESULT($enableval)
+], [
+  PHP_APC_MEMPROTECT=no
+  AC_MSG_RESULT(no)
+])
+
+if test "$PHP_APC" != "no"; then
+  test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
+  test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
+
+	if test "$PHP_APC_DEBUG" != "no"; then
+		AC_DEFINE(__DEBUG_APC__, 1, [ ])
+	fi
+
+	if test "$PHP_APC_SEM" != "no"; then
+		AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
+	elif test "$PHP_APC_SPINLOCKS" != "no"; then
+		AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) 
+	elif test "$PHP_APC_PTHREADMUTEX" != "no"; then 
+		AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
+	else 
+		AC_DEFINE(APC_FCNTL_LOCKS, 1, [ ])
+	fi
+  
+	if test "$PHP_APC_MEMPROTECT" != "no"; then
+		AC_DEFINE(APC_MEMPROTECT, 1, [ shm/mmap memory protection ])
+	fi
+
+  AC_CACHE_CHECK(for zend_set_lookup_function_hook, php_cv_zend_set_lookup_function_hook,
+  [
+    orig_cflags=$CFLAGS
+    CFLAGS="$INCLUDES $EXTRA_INCLUDES"
+    AC_TRY_COMPILE([
+#include "main/php.h"
+#include "Zend/zend_API.h"
+    ], [#ifndef zend_set_lookup_function_hook
+	(void) zend_set_lookup_function_hook;
+#endif], [
+      php_cv_zend_set_lookup_function_hook=yes
+    ],[
+      php_cv_zend_set_lookup_function_hook=no
+    ])
+    CFLAGS=$orig_cflags
+  ])
+  if test "$php_cv_zend_set_lookup_function_hook" = "yes"; then
+    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 1, [ ])
+  else
+    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 0, [ ])
+  fi
+
+  AC_CHECK_FUNCS(sigaction)
+  AC_CACHE_CHECK(for union semun, php_cv_semun,
+  [
+    AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+    ], [union semun x; x.val=1], [
+      php_cv_semun=yes
+    ],[
+      php_cv_semun=no
+    ])
+  ])
+  if test "$php_cv_semun" = "yes"; then
+    AC_DEFINE(HAVE_SEMUN, 1, [ ])
+  else
+    AC_DEFINE(HAVE_SEMUN, 0, [ ])
+  fi
+
+  AC_MSG_CHECKING(whether we should enable valgrind support)
+  AC_ARG_ENABLE(valgrind-checks,
+  [  --disable-valgrind-checks
+                          Disable valgrind based memory checks],
+  [
+    PHP_APC_VALGRIND=$enableval
+    AC_MSG_RESULT($enableval)
+  ], [
+    PHP_APC_VALGRIND=yes
+    AC_MSG_RESULT(yes)
+    AC_CHECK_HEADER(valgrind/memcheck.h, 
+  		[AC_DEFINE([HAVE_VALGRIND_MEMCHECK_H],1, [enable valgrind memchecks])])
+  ])
+
+  apc_sources="apc.c php_apc.c \
+               apc_cache.c \
+               apc_compile.c \
+               apc_debug.c \
+               apc_fcntl.c \
+               apc_main.c \
+               apc_mmap.c \
+               apc_sem.c \
+               apc_shm.c \
+               apc_pthreadmutex.c \
+               apc_spin.c \
+               pgsql_s_lock.c \
+               apc_sma.c \
+               apc_stack.c \
+               apc_zend.c \
+               apc_rfc1867.c \
+               apc_signal.c \
+               apc_pool.c \
+               apc_iterator.c \
+               apc_bin.c \
+               apc_string.c "
+
+  PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
+  PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
+  PHP_SUBST(APC_SHARED_LIBADD)
+  PHP_SUBST(APC_CFLAGS)
+  AC_DEFINE(HAVE_APC, 1, [ ])
+fi
+
--- /dev/null
+++ b/ext/apc/config.w32
@@ -0,0 +1,48 @@
+// $Id: config.w32 305410 2010-11-16 16:47:18Z pajoye $
+// vim:ft=javascript
+
+
+ARG_ENABLE('apc', 'Whether to enable APC support', 'no');
+ARG_ENABLE('apc-debug', 'Whether to enable APC debugging', 'no');
+ARG_ENABLE('apc-filehits', 'Whether to enable cache request file info', 'no');
+ARG_ENABLE('apc-spinlocks', 'Whether to use spin locks (experimental)', 'no');
+ARG_ENABLE('apc-memprotect', 'Whether to enable memory protection (experimental)', 'no');
+
+if(PHP_APC != 'no')
+{
+	var apc_sources = 	'apc.c php_apc.c apc_cache.c apc_compile.c apc_debug.c ' + 
+				'apc_fcntl_win32.c apc_iterator.c apc_main.c apc_shm.c ' + 
+				'apc_sma.c apc_stack.c apc_rfc1867.c apc_zend.c apc_pool.c ' +
+				'apc_bin.c apc_string.c';
+
+	if(PHP_APC_DEBUG != 'no')
+	{
+		ADD_FLAG('CFLAGS_APC', '/D __DEBUG_APC__=1');
+	}
+
+	if(PHP_APC_FILEHITS != 'no')
+	{
+		AC_DEFINE('APC_FILEHITS', 1);
+	}
+
+	if(PHP_APC_MEMPROTECT != 'no')
+	{
+		AC_DEFINE('APC_MEMPROTECT', 1);
+	}
+
+	if(PHP_APC_SPINLOCKS != 'no')
+	{
+		AC_DEFINE('APC_SPIN_LOCKS', 1);
+		ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1');
+
+		apc_sources += ' apc_spin.c pgsql_s_lock.c';
+	}
+	else
+	{
+		AC_DEFINE('APC_FCNTL_LOCKS', 1);
+	}
+
+	AC_DEFINE('HAVE_APC', 1);
+
+	EXTENSION('apc', apc_sources);
+}
\ No newline at end of file
--- /dev/null
+++ b/ext/apc/INSTALL
@@ -0,0 +1,400 @@
+Installation Instructions for APC
+---------------------------------
+
+This version of APC should work on PHP 4.3.0 - 4.4.x and
+5.1.0 - 5.2.x.  Yes, that means PHP 5.0.x is no longer 
+supported.  Upgrade to PHP 5.1.x or 5.2.x and you will 
+notice all sorts of performance increases.
+
+CVS Instructions
+----------------
+Building from CVS can be done like this:
+
+  svn co http://svn.php.net/repository/pecl/apc/trunk apc
+  cd apc
+  phpize
+  ./configure --with-php-config=/usr/local/php/bin/php-config
+  make
+  export TEST_PHP_ARGS='-n'
+  make test
+  make install
+
+Suggested Configuration (in your php.ini file)
+----------------------------------------------
+  extension=apc.so
+  apc.enabled=1
+  apc.shm_size=128
+  apc.ttl=7200
+  apc.user_ttl=7200
+  apc.enable_cli=1
+
+These are fully described at the bottom of this file.
+
++---------------------+
+| QUICK INSTALL (DSO) |
++---------------------+
+
+These instructions assume your PHP installation is located in /usr/local/php and you
+want Apache optimizations (--with-apxs).
+
+$ gunzip -c apc_x.y.tar.gz | tar xf -
+$ cd apc_x.y
+$ /usr/local/php/bin/phpize
+$ ./configure --with-php-config=/usr/local/php/bin/php-config
+$ make
+$ make install
+
+You will probably need to run the final command (make install) as root.
+
+The above sequence of commands will install a .so file in your PHP
+installation extension directory. The output of make install should display
+that path to the screen.
+
+Next you must edit your php.ini file, which is normally located in
+/usr/local/php/lib/php.ini, and add the following line:
+
+    extension="apc.so"
+
+Replace "/path/to/php/extensions" with whatever path was displayed when you
+ran make install above.
+
+Then restart your web server and consult the output of phpinfo(). If there is
+an informational section for APC, the installation was successful.
+
++------------------------+
+| QUICK INSTALL (Static) |
++------------------------+
+
+APC will not successfully compile on all systems as a DSO. If you run into
+problems using the DSO quick install, you can try to compile it statically
+into PHP. (The DSO install is recommended, though.)
+
+These instructions assume the current directory is the root of the PHP source
+tree, and that you have already configured PHP by running its bundled
+configure script.
+
+$ cd ext
+$ gunzip -c apc_x.y.tar.gz | tar xf -
+$ cd ..
+$ ./buildconf
+$ ./config.nice
+$ make
+$ make install
+
+Once this is complete, simply restart your web server. You do not need to
+modify your php.ini file to enable APC.
+
++-----------------+
+| VERBOSE INSTALL |
++-----------------+
+
+These instructions assume your PHP installation is located in /usr/local/php.
+
+1.  Unpack your distribution file.
+
+    You will have downloaded a file named something like apc_x.y.tar.gz.
+    Unzip this file with a command like
+    
+        gunzip apc_x.y.tar.gz
+    
+    Next you have to untar it with
+    
+        tar xvf apc_x.y.tar
+
+    This will create an apc_x.y directory. cd into this new directory:
+
+        cd apc_x.y
+
+2.  Run phpize.
+
+    phpize is a script that should have been installed with PHP, and is
+    normally located in /usr/local/php/bin assuming you installed PHP in
+    /usr/local/php. (If you do not have the phpize script, you must reinstall
+    PHP and be sure not to disable PEAR.)
+
+    Run the phpize command:
+    
+        /usr/local/php/bin/phpize
+
+    Its output should resemble this:
+
+        autoheader: `config.h.in' is created
+        You should update your `aclocal.m4' by running aclocal.
+        Configuring for:
+          PHP Api Version:   20020918
+          Zend Module Api No:   20020429
+          Zend Extension Api No:   20021010
+ 
+    phpize should create a configure script in the current directory. If you
+    get errors instead, you might be missing some required development tools,
+    such as autoconf or libtool. You can try downloading the latest versions
+    of those tools and running phpize again.
+ 
+3.  Run the configure script.
+ 
+    phpize creates a configure script. The only option you need to specify is
+    the location of your php-config script:
+
+        ./configure --enable-apc
+
+    php-config should be located in the same directory as phpize.
+
+    If you prefer to use mmap instead of the default IPC shared memory support,
+    add --enable-apc-mmap to your configure line. 
+
+	If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
+	--enable-sem to your configure line.  If you don't have a problem
+	with your server segaulting, or any other unnatural accumulation of
+	semaphores on your system, the semaphore based locking is slightly faster.
+
+4.  Compile and install the files. Simply type: make install
+
+    (You may need to be root in order to install)
+
+    If you encounter errors from libtool or gcc during this step, please
+    contact the project maintainer (dcowgill@php.net).
+
+5.  Edit your php.ini
+
+    make install should have printed a line resembling the following:
+
+        Installing shared extensions: /path/to/extension/
+
+    Copy the path /path/to/extension/ and add the following line to your
+    php.ini file (normally located in /usr/local/php/lib/php.ini):
+
+        extension="apc.so"
+
+    If you don't have a php.ini file in that location, you can create it now.
+
+6.  Restart the web server and test the installation.
+
+    Restart your web server now (for apache, it's apachectl restart) and
+    create a small test PHP file in your document root. The file should
+    contain just the following line:
+
+        <?php phpinfo() ?>
+
+    Request that file in a web browser. If there is an entry for APC in the
+    list of installed modules, the installation was successful.
+
+    If APC is not listed, consult your web server error log. If it contains an
+    error message saying that it can't load the APC extension, your system
+    might not be able to load shared libraries created with PHP's build
+    system. One alternative would be to compile APC statically into PHP. See
+    the Quick Install (Static) instructions above.
+
+    You should consult your error log anyway to see if APC generated any
+    errors. On BSD-based platforms, it is typical for APC to be unable to
+    allocate the default-sized shared memory segment. See below for hints on
+    raising your system's shared memory limitations.
+
++-----------------+
+| CONFIGURING APC |
++-----------------+
+
+Although the default APC settings are fine for many installations, serious
+users should consider tuning the following parameters:
+
+    OPTION                  DESCRIPTION
+    ------------------      --------------------------------------------------
+    apc.enabled             This can be set to 0 to disable APC. This is
+                            primarily useful when APC is statically compiled
+                            into PHP, since there is no other way to disable
+                            it (when compiled as a DSO, the zend_extension
+                            line can just be commented-out).
+                            (Default: 1)
+                            
+    apc.shm_segments        The number of shared memory segments to allocate
+                            for the compiler cache. If APC is running out of
+                            shared memory but you have already set
+                            apc.shm_size as high as your system allows, you
+                            can try raising this value.  Setting this to a
+                            value other than 1 has no effect in mmap mode
+                            since mmap'ed shm segments don't have size limits.
+                            (Default: 1)
+                            
+    apc.shm_size            The size of each shared memory segment in MB.
+                            By default, some systems (including most BSD
+                            variants) have very low limits on the size of a
+                            shared memory segment.
+                            (Default: 30)
+                            
+    apc.optimization        This option has been deprecated.
+                            (Default: 0)
+    
+    apc.num_files_hint      A "hint" about the number of distinct source files
+                            that will be included or requested on your web
+                            server. Set to zero or omit if you're not sure;
+                            this setting is mainly useful for sites that have
+                            many thousands of source files.
+                            (Default: 1000)
+
+    apc.user_entries_hint   Just like num_files_hint, a "hint" about the number
+                            of distinct user cache variables to store. 
+                            Set to zero or omit if you're not sure;
+                            (Default: 4096)
+
+    apc.ttl                 The number of seconds a cache entry is allowed to
+                            idle in a slot in case this cache entry slot is 
+                            needed by another entry.  Leaving this at zero
+                            means that your cache could potentially fill up
+                            with stale entries while newer entries won't be
+                            cached.  
+                            (Default: 0)
+
+    apc.user_ttl            The number of seconds a user cache entry is allowed 
+                            to idle in a slot in case this cache entry slot is 
+                            needed by another entry.  Leaving this at zero
+                            means that your cache could potentially fill up
+                            with stale entries while newer entries won't be
+                            cached.  
+                            (Default: 0)
+
+
+    apc.gc_ttl              The number of seconds that a cache entry may
+                            remain on the garbage-collection list. This value
+                            provides a failsafe in the event that a server
+                            process dies while executing a cached source file;
+                            if that source file is modified, the memory
+                            allocated for the old version will not be
+                            reclaimed until this TTL reached. Set to zero to
+                            disable this feature.
+                            (Default: 3600)
+
+    apc.cache_by_default    On by default, but can be set to off and used in
+                            conjunction with positive apc.filters so that files
+                            are only cached if matched by a positive filter.
+                            (Default: On)
+
+    apc.filters             A comma-separated list of POSIX extended regular
+                            expressions. If any pattern matches the source
+                            filename, the file will not be cached. Note that
+                            the filename used for matching is the one passed
+                            to include/require, not the absolute path.  If the
+                            first character of the expression is a + then the
+                            expression will be additive in the sense that any
+                            files matched by the expression will be cached, and
+                            if the first character is a - then anything matched
+                            will not be cached.  The - case is the default, so
+                            it can be left off.
+                            (Default: "")
+
+    apc.mmap_file_mask      If compiled with MMAP support by using --enable-mmap
+                            this is the mktemp-style file_mask to pass to the
+                            mmap module for determing whether your mmap'ed memory
+                            region is going to be file-backed or shared memory
+                            backed.  For straight file-backed mmap, set it to
+                            something like /tmp/apc.XXXXXX (exactly 6 X's).
+                            To use POSIX-style shm_open/mmap put a ".shm"
+                            somewhere in your mask.  eg.  "/apc.shm.XXXXXX"
+                            You can also set it to "/dev/zero" to use your 
+                            kernel's /dev/zero interface to anonymous mmap'ed 
+                            memory.  Leaving it undefined will force an 
+                            anonymous mmap.
+                            (Default: "")
+
+    apc.slam_defense        ** DEPRECATED - Use apc.write_lock instead **
+                            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)
+
+    apc.file_update_protection
+                            When you modify a file on a live web server you really
+                            should do so in an atomic manner.  That is, write to a
+                            temporary file and rename (mv) the file into its permanent
+                            position when it is ready.  Many text editors, cp, tar and
+                            other such programs don't do this.  This means that there
+                            is a chance that a file is accessed (and cached) while it
+                            is still being written to.  This file_update_protection
+                            setting puts a delay on caching brand new files.  The
+                            default is 2 seconds which means that if the modification
+                            timestamp (mtime) on a file shows that it is less than 2
+                            seconds old when it is accessed, it will not be cached.  
+                            The unfortunate person who accessed this half-written file
+                            will still see weirdness, but at least it won't persist.
+                            If you are certain you always atomically update your files
+                            by using something like rsync which does this correctly, you
+                            can turn this protection off by setting it to 0.  If you
+                            have a system that is flooded with io causing some update
+                            procedure to take longer than 2 seconds, you may want to
+                            increase this a bit.
+                            (Default: 2)
+
+    apc.enable_cli          Mostly for testing and debugging.  Setting this enables APC
+                            for the CLI version of PHP.  Normally you wouldn't want to
+                            create, populate and tear down the APC cache on every CLI
+                            request, but for various test scenarios it is handy to be
+                            able to enable APC for the CLI version of APC easily.
+                            (Default: 0)
+
+    apc.max_file_size       Prevents large files from being cached.  
+                            (Default: 1M)
+
+    apc.stat                Whether to stat the main script file and the fullpath
+                            includes.  If you turn this off you will need to restart
+                            your server in order to update scripts.
+                            (Default: 1)
+
+    apc.canonicalize        Whether to canonicalize paths in stat=0 mode or
+                            fall back to stat behaviour if set to 0
+                            (Default: 0)
+
+    apc.write_lock          On busy servers when you first start up the server, or when
+                            many files are modified, you can end up with all your processes
+                            trying to compile and cache the same files.  With write_lock 
+                            enabled, only one process at a time will try to compile an
+                            uncached script while the other processes will run uncached
+                            instead of sitting around waiting on a lock.
+                            (Default: 1)
+
+    apc.report_autofilter   Logs any scripts that were automatically excluded from being
+                            cached due to early/late binding issues.
+                            (Default: 0)
+
+    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
+                            if you compiled APC against PHP 5.2.0 or later.  When enabled
+                            any file uploads which includes a field called 
+                            APC_UPLOAD_PROGRESS before the file field in an upload form
+                            will cause APC to automatically create an upload_<key>
+                            user cache entry where <key> is the value of the 
+                            APC_UPLOAD_PROGRESS form entry.
+
+                            Note that the file upload tracking is not threadsafe at this
+                            point, so new uploads that happen while a previous one is 
+                            still going will disable the tracking for the previous.
+                            (Default: 0)
+
+    apc.rfc1867_prefix      Key prefix to use for the user cache entry generated by
+                            rfc1867 upload progress functionality.  
+                            (Default: "upload_")
+
+    apc.rfc1867_name        Specify the hidden form entry name that activates APC upload
+                            progress and specifies the user cache key suffix.
+                            (Default: "APC_UPLOAD_PROGRESS")
+
+    apc.rfc1867_freq        The frequency that updates should be made to the user cache
+                            entry for upload progress.  This can take the form of a 
+                            percentage of the total file size or a size in bytes 
+                            optionally suffixed with 'k', 'm', or 'g' for kilobytes, 
+                            megabytes, or gigabytes respectively (case insensitive).  
+                            A setting of 0 updates as often as possible, which may cause 
+                            slower uploads.
+                            (Default: 0)
+
+    apc.localcache         ** REMOVED 
+    apc.localcache.size    ** REMOVED
+    
+    apc.include_once_override 
+                            Optimize include_once and require_once calls and avoid the 
+                            expensive system calls used.
+                            (Default: 0)
--- /dev/null
+++ b/ext/apc/LICENSE
@@ -0,0 +1,68 @@
+-------------------------------------------------------------------- 
+                  The PHP License, version 3.01
+Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
+-------------------------------------------------------------------- 
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+ 
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+ 
+  3. The name "PHP" must not be used to endorse or promote products
+     derived from this software without prior written permission. For
+     written permission, please contact group@php.net.
+  
+  4. Products derived from this software may not be called "PHP", nor
+     may "PHP" appear in their name, without prior written permission
+     from group@php.net.  You may indicate that your software works in
+     conjunction with PHP by saying "Foo for PHP" instead of calling
+     it "PHP Foo" or "phpfoo"
+ 
+  5. The PHP Group may publish revised and/or new versions of the
+     license from time to time. Each version will be given a
+     distinguishing version number.
+     Once covered code has been published under a particular version
+     of the license, you may always continue to use it under the terms
+     of that version. You may also choose to use such covered code
+     under the terms of any subsequent version of the license
+     published by the PHP Group. No one other than the PHP Group has
+     the right to modify the terms applicable to covered code created
+     under this License.
+
+  6. Redistributions of any form whatsoever must retain the following
+     acknowledgment:
+     "This product includes PHP software, freely available from
+     <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------- 
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project, 
+please see <http://www.php.net>.
+
+PHP includes the Zend Engine, freely available at
+<http://www.zend.com>.
--- /dev/null
+++ b/ext/apc/NOTICE
@@ -0,0 +1,43 @@
+This is the NOTICE file that holds acknowledgements and stuff.
+
+The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
+This extension is being released under the PHP License for complete compliance
+with PHP and to encourage wide-spread use.  It is our intention that this
+project be kept open source and that all commercial spin-offs contribute their
+modifications back into the public source-tree.
+
+Creators:
+    Daniel Cowgill
+    George Schlossnagle
+
+PHP5 support and major features by:
+    Arun C. Murthy 
+    Gopal Vijayaraghavan
+    Rasmus Lerdorf
+
+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.
+
+We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting 
+this project and providing a challenging and stimulating environment in 
+which exciting projects can happen.
+
+Contributors:
+    Mike Bretz          bug fixes, GUI, and lots of work
+    Ricardo Galli       changed read-write locks to prefer readers
+    Yann Grossel        bug fixes
+    Thies Arntzen       bug fixes
+    Sara Golemon        optimizer work
+
+Special Thanks:
+    Florian Baumert     help debugging phplib problems
+    Thomas Duffey       help debugging inheritance issues
+    Vibol Hou           help debugging phplib problems
+    Angel Li            diffs for ANSI comment compliance
+    Christian Rish�j    help debugging phplib problems
+    Sascha Schumann     memory error bug fix
--- /dev/null
+++ b/ext/apc/package.xml
@@ -0,0 +1,827 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.9.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+ <name>APC</name>
+ <channel>pecl.php.net</channel>
+ <summary>Alternative PHP Cache</summary>
+ <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
+ <lead>
+  <name>Daniel Cowgill</name>
+  <user>dcowgill</user>
+  <email>dan@mail.communityconnect.com</email>
+  <active>no</active>
+ </lead>
+ <lead>
+  <name>George Schlossnagle</name>
+  <user>gschlossnagle</user>
+  <email>george@omniti.com</email>
+  <active>no</active>
+ </lead>
+ <lead>
+  <name>Rasmus Lerdorf</name>
+  <user>rasmus</user>
+  <email>rasmus@php.net</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Gopal Vijayaraghavan</name>
+  <user>gopalv</user>
+  <email>gopalv@php.net</email>
+  <active>yes</active>
+ </lead>
+ <developer>
+  <name>Edin Kadribasic</name>
+  <user>edink</user>
+  <email>edink@emini.dk</email>
+  <active>no</active>
+ </developer>
+ <developer>
+  <name>Ilia Alshanetsky</name>
+  <user>iliaa</user>
+  <email>ilia@prohost.org</email>
+  <active>yes</active>
+ </developer>
+ <developer>
+  <name>Marcus Börger</name>
+  <user>helly</user>
+  <email>helly@php.net</email>
+  <active>no</active>
+ </developer>
+ <developer>
+  <name>Sara Golemon</name>
+  <user>pollita</user>
+  <email>pollita@php.net</email>
+  <active>no</active>
+ </developer>
+ <developer>
+  <name>Brian Shire</name>
+  <user>shire</user>
+  <email>shire@php.net</email>
+  <active>yes</active>
+ </developer>
+ <developer>
+  <name>Kalle Sommer Nielsen</name>
+  <user>kalle</user>
+  <email>kalle@php.net</email>
+  <active>yes</active>
+ </developer>
+ <developer>
+  <name>Pierre Joye</name>
+  <user>pajoye</user>
+  <email>pierre@php.net</email>
+  <active>yes</active>
+ </developer>
+ <date>2010-11-30</date>
+ <time>15:48:31</time>
+ <version>
+  <release>3.1.6</release>
+  <api>3.1.0</api>
+ </version>
+ <stability>
+  <release>stable</release>
+  <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- make slam_defense a little more optimistic, allow a thread/process to write to cache in a loop
+- ensure realpaths hit the realpath_cache, in no-stat mode
+- prevent memory starvation, nuke all caches when expunging just one doesn&apos;t work
+- fix uploadprogress keylength issues (NUL is part of keylen, pecl bug #20016)
+ </notes>
+ <contents>
+  <dir name="/">
+   <file md5sum="d8778d844e157a2bb49e11858057050f" name="tests/apc_001.phpt" role="test" />
+   <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
+   <file md5sum="04c800594e9934cf8e15157e9bd4c52f" name="tests/apc_003.phpt" role="test" />
+   <file md5sum="538f198f432614d9f2c0819fea5193a7" name="tests/apc_003b.phpt" role="test" />
+   <file md5sum="43c8e1c89fad5bb25ded528837e63b2b" name="tests/apc_004.phpt" role="test" />
+   <file md5sum="06432141cbc82df8ddde7fac52e9f65e" name="tests/apc_005.phpt" role="test" />
+   <file md5sum="74f802b99f111d1cdab6abaf20edae95" name="tests/apc_006.phpt" role="test" />
+   <file md5sum="b724592cd9629ab5e9dac9f1ef5d3e10" name="tests/apc_007.phpt" role="test" />
+   <file md5sum="0674cbe2e88fe5c331bee3fbb1395d4f" name="tests/apc_008.phpt" role="test" />
+   <file md5sum="4f15ba9d73035c6c0493f05e57ee70f0" name="tests/apc_009.phpt" role="test" />
+   <file md5sum="6640964ee33a683b1693b545d1ff2ed0" name="tests/apc_010.phpt" role="test" />
+   <file md5sum="611e5e725d57fcca216bf79778238290" name="tests/apc53_001.phpt" role="test" />
+   <file md5sum="1cd474d5a3567601d66d1078699fd587" name="tests/apc53_002.phpt" role="test" />
+   <file md5sum="3d863bb88c5f2624320b7b72e368d668" name="tests/apc53_003.phpt" role="test" />
+   <file md5sum="128e9590ff8d3d0791a1ef9ce9c078f5" name="tests/apc53_004.phpt" role="test" />
+   <file md5sum="c710a33310dfacef4d51cb721855857e" name="tests/apc53_005.phpt" role="test" />
+   <file md5sum="5001c1cd063b4c2032189fcb74d04644" name="tests/apc_bin_001.phpt" role="test" />
+   <file md5sum="c992d44557b849a10984b089419d2e01" name="tests/apc_bin_002-1.inc" role="test" />
+   <file md5sum="409cadd9efc9d863421b15d63d8c6515" name="tests/apc_bin_002-2.inc" role="test" />
+   <file md5sum="2667d74094dac9e366020c11b3a9bd47" name="tests/apc_bin_002.phpt" role="test" />
+   <file md5sum="1bb542e50a5e6eb06b54a89ceaa81976" name="tests/iterator_001.phpt" role="test" />
+   <file md5sum="7ee077f992cd81940f74b5f1b0e885c0" name="tests/iterator_002.phpt" role="test" />
+   <file md5sum="eccbaee4d483213ee8ba0583c705224b" name="tests/iterator_003.phpt" role="test" />
+   <file md5sum="4ec172b4fc8ed2f45f3d7426865a0db5" name="tests/iterator_004.phpt" role="test" />
+   <file md5sum="eec4bf6bdfa4936cb122845216cad7e0" name="tests/iterator_005.phpt" role="test" />
+   <file md5sum="3b0a6f2a4e03382a0d56d66b7f7324bc" name="tests/iterator_006.phpt" role="test" />
+   <file md5sum="82a40b37c545631cd87c3e1e421353b5" name="tests/iterator_007.phpt" role="test" />
+   <file md5sum="92e7b033fac8b625c6ad52e21d1222bf" name="tests/php_5_3_ns.inc" role="test" />
+   <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
+   <file md5sum="ed9a4192d7ab7f953856b92c5e689cf5" name="CHANGELOG" role="doc" />
+   <file md5sum="530c37a06cb3d2f7dc578399e08dc532" name="INSTALL" role="doc" />
+   <file md5sum="cb564efdf78cce8ea6e4b5a4f7c05d97" name="LICENSE" role="doc" />
+   <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
+   <file md5sum="4bcb366801c544b5d9df03a445f33b3f" name="TODO" role="doc" />
+   <file md5sum="1a12ed6c0aa4124837cc96cefa507fe1" name="TECHNOTES.txt" role="doc" />
+   <file md5sum="f1df0d7f7d913424082440bd1c456f57" name="apc.c" role="src" />
+   <file md5sum="db933bf95d955bdac3756ff64aa68e00" name="apc.h" role="src" />
+   <file md5sum="94a046b4eb5890778dc0f78173d0d4cc" name="apc_bin.c" role="src" />
+   <file md5sum="7f88578dc04a829b8b66a4992241b93c" name="apc_bin.h" role="src" />
+   <file md5sum="0960b84970794199b1d303097bbb6ace" name="apc_cache.c" role="src" />
+   <file md5sum="f4e3dc54d403741e3d62caa5a5ba0f22" name="apc_cache.h" role="src" />
+   <file md5sum="0a7155470ba3df4718883710122abb2b" name="apc_compile.c" role="src" />
+   <file md5sum="c8f3eb20167f2c4274e0d851c16bd9e0" name="apc_compile.h" role="src" />
+   <file md5sum="5b5a25592270765352ef45ffd5b514d9" name="apc_debug.c" role="src" />
+   <file md5sum="3d8d0bd66ed185f6fbb9b4612b20bd2a" name="apc_debug.h" role="src" />
+   <file md5sum="e874b4944016989e23801dae5ad7c5ad" name="apc_fcntl.c" role="src" />
+   <file md5sum="e6d336752e1a0c7768e8d013de60c861" name="apc_fcntl.h" role="src" />
+   <file md5sum="972d4372d466abca82b531f448501331" name="apc_globals.h" role="src" />
+   <file md5sum="fe05863f7a9e156a3494ff2e3012e2fb" name="apc_lock.h" role="src" />
+   <file md5sum="bda9b7cd75b85fda2dad3c9cb20ed293" name="apc_main.c" role="src" />
+   <file md5sum="248fc93a72f5b6beba82c3d29eba3f24" name="apc_main.h" role="src" />
+   <file md5sum="f49d49907ef24e6698b1c85aeb89bcd4" name="apc_mmap.c" role="src" />
+   <file md5sum="d86e21617ad249ab5b2be1a7d7fcfd21" name="apc_mmap.h" role="src" />
+   <file md5sum="9a82909be30c52b1ca267886d832b129" name="apc_php.h" role="src" />
+   <file md5sum="7d193d20531dbc39acf2e828a757f01b" name="apc_php_pcre.h" role="php" />
+   <file md5sum="e1e4fc3330b2e6497259caf08b27100c" name="apc_pthreadmutex.c" role="src" />
+   <file md5sum="52fa7e9b676a9e6264dbb4425320aa7f" name="apc_pthreadmutex.h" role="src" />
+   <file md5sum="88028345c8f453573975ec59241442ef" name="apc_sem.c" role="src" />
+   <file md5sum="15c5e77be5e97cf089a8b4b0719e2ec6" name="apc_sem.h" role="src" />
+   <file md5sum="05f78a27fbf80993c1f35933e16bbe6d" name="apc_shm.c" role="src" />
+   <file md5sum="0bb9ac1689d846570a819b708af1105a" name="apc_shm.h" role="src" />
+   <file md5sum="b16c47e998f8092c5e6c61368e1d4a24" name="apc_sma.c" role="src" />
+   <file md5sum="3e5265ba778a5b9de42148b27c199c7d" name="apc_sma.h" role="src" />
+   <file md5sum="a107ff01a0df3349a96d38ae5fc84f5f" name="apc_spin.c" role="src" />
+   <file md5sum="8a44c26956bf889155cb24088712dc50" name="apc_spin.h" role="src" />
+   <file md5sum="0939854bf2b61f1d88201da833243e37" name="apc_stack.c" role="src" />
+   <file md5sum="1c36a4153b213cb6f9b3ccad26606791" name="apc_stack.h" role="src" />
+   <file md5sum="aba4b2d34f04ba69d10bd9bcff696e84" name="apc_string.h" role="src" />
+   <file md5sum="0c8e5033f2bf7189badf50954a2c99a0" name="apc_string.c" role="src" />
+   <file md5sum="458f49fb5f03544e94ac5f530d0a9c68" name="apc_zend.c" role="src" />
+   <file md5sum="15b6b1e684e6b22390f0a3783d2bc134" name="apc_zend.h" role="src" />
+   <file md5sum="b94678c89b8f0b6f5bd1a8aba00e77a7" name="apc_signal.c" role="src" />
+   <file md5sum="596f0878de5ae6cf8ccd9d8242a203c4" name="apc_signal.h" role="src" />
+   <file md5sum="ac0ac4ad53248999d41ae83c9a460086" name="apc_iterator.c" role="src" />
+   <file md5sum="8bad478e9e94682a185cf22167be5e84" name="apc_iterator.h" role="src" />
+   <file md5sum="a4ad70727d8a4302a80aca9be6b267c2" name="apc_pool.c" role="src" />
+   <file md5sum="95d87754c41bb7cd919bd02c08fcbead" name="apc_pool.h" role="src" />
+   <file md5sum="0635ec3025ca2eac5b146ecd74240697" name="config.m4" role="src" />
+   <file md5sum="45ef21f58c191413ff5c06e708dec2f8" name="config.w32" role="src" />
+   <file md5sum="aee455af2782bed51730fa8e85deff5f" name="php_apc.c" role="src" />
+   <file md5sum="6b52620bc10e2d49ca33dbaa9c037002" name="php_apc.h" role="src" />
+   <file md5sum="3bdccc0fa74ea0b6c2539fcb0b5a6253" name="pgsql_s_lock.c" role="src" />
+   <file md5sum="c63703a3966a0486150ea5b780d6ebec" name="pgsql_s_lock.h" role="src" />
+   <file md5sum="3b737f451ebf7175e00ebe0246c97e16" name="apc_fcntl_win32.c" role="src" />
+   <file md5sum="48817fe8f775ad3861dc7c5307c88c59" name="apc_rfc1867.c" role="src" />
+   <file md5sum="f1d6a8535a55ed9129088066e18867b4" name="apc.php" role="php" />
+  </dir>
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.1.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.4.0</min>
+   </pearinstaller>
+  </required>
+ </dependencies>
+ <providesextension>apc</providesextension>
+ <extsrcrelease>
+  <configureoption default="no" name="enable-apc-filehits" prompt="Enable per request file info about files used from the APC cache" />
+  <configureoption default="no" name="enable-apc-spinlocks" prompt="Enable spin locks (EXPERIMENTAL)" />
+ </extsrcrelease>
+ <changelog>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>2.0.0</release>
+    <api>2.0.0</api>
+   </version>
+   <date>2003-07-01</date>
+   <notes>
+Complete rework.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>2.0.1</release>
+    <api>2.0.0</api>
+   </version>
+   <date>2003-07-01</date>
+   <notes>
+Win32 support added.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>2.0.2</release>
+    <api>2.0.0</api>
+   </version>
+   <date>2004-03-12</date>
+   <notes>
+Fixed non-existant class bug.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.0</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-05</date>
+   <notes>
+PHP-5.1 Support and numerous fixes
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.1</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-05</date>
+   <notes>
+PHP4 build fix
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.2</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-05</date>
+   <notes>
+Default to mmap and add a better error message for shmget failures
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.3</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-07</date>
+   <notes>
+Fix compile problem against PHP 5.0.x
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.4</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-18</date>
+   <notes>
+Add win32 support from Edin.
+Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches
+A couple of other minor fixes.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.5</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-27</date>
+   <notes>
+Make it easier for sapis that only populate file_handle-&gt;filename to use APC. (Rasmus)
+Support extensions such as bcompiler that need to hook into compile_file. (Val)
+Ralf Becker&apos;s apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
+Segfault in cache cleanup code (Ilia, Rasmus)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.6</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-07-30</date>
+   <notes>
+Added apc.php to package.xml file.
+Track per-entry memory usage. (Val)
+Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
+fcntl locking robustness fixes. (Rasmus)
+Shared read-locks where possible. (Rasmus)
+Added file_update_protection configuration parameter. (Rasmus)
+Windows ZTS fixes (Frank)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.7</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-08-16</date>
+   <notes>
+Fix to apc.php to show final segment in frag chart. (Ilia)
+A couple of win32 fixes. (Frank)
+Add apc.enable_cli ini directive. (Rasmus)
+Add test cases. (Marcus)
+Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
+Simplify user cache handling by removing the user_cache_stack (Rasmus)
+Fix apc_fetch() memory corruption (Andrei,Rasmus)
+Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.8</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2005-08-24</date>
+   <notes>
+Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
+Cache corruption fix in cache-full cleanup code (Gopal)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.9</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-03-04</date>
+   <notes>
+Eliminate rand() call when slam_defense is not set (Rasmus)
+Fix for __isset problem (Gopal)
+Rewrite allocator from a &quot;best fit&quot; to a &quot;next fit&quot; algorithm (Rasmus)
+Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
+Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
+Add cache busy flag which is set when an expunge is underway (Rasmus)
+Add automatic serialization of objects in apc_store() (Marcus)
+64-bit .ini flag fix (Rasmus)
+Static members fix (Gopal)
+sma_cleanup() mem leak fix (Rasmus)
+Fix for http://pecl.php.net/bugs/5311 (Rasmus)
+Fix autoglobals JIT bug (Gopal)
+Fix instance bug (Gopal)
+Add a lock cleanup safety net to request shutdown (Rasmus)
+Fix apc.slam_defense edge-case bug (Rasmus)
+User entry memory usage tracking support (Ilia)
+Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.10</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-03-11</date>
+   <notes>
+* Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
+  includes will not be stat&apos;ed for any changes.  You will have to restart the server if you
+  change anything.  This mode increases performance quite a bit, especially if you have a
+  lot of includes.
+
+* Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
+  than it solves.  I&apos;ll need to revisit locking and signal handling at some point soon.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.11</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-08-16</date>
+   <notes>
+* Made --enable-apc-mmap the default compile option (for real this time)
+
+* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
+  only fetch header information to make it useful when you have tens of
+  thousands of entries.  (Brian Shire)
+
+* 64-bit fixes (George)
+
+* Don&apos;t mix Full Path and Inode keys (George)
+
+* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
+  require_once() and include_once() statements. (Sara)
+
+* Add a non-blocking write_lock for cache inserts.  This is a better approach
+  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
+
+* A bit of work on the optimizer.  (Sara)
+
+* Various memory issues resolved. (Gopal)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.12</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-09-04</date>
+   <notes>
+* Fix stray debug message
+
+* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
+
+* Performance boost - Replace multiple loops over the opcode
+  array with a single loop for copying, jump fixups and auto
+  global pre-fetches. (Gopal)
+
+* Perform fetch_global checks only in php5 and only if 
+  auto_globals_jit is enabled. (Gopal)
+
+* Fix bug #8579 - scrub php4 classes&apos; function_table and default
+  properties before inserting into cache. (Gopal)
+
+* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a 
+  op1-&gt;type.  The opcodes applicable are ZEND_FETCH_R and 
+  ZEND_FETCH_W. (Gopal)
+
+* PHP 5.2 Compatibility (Gopal)
+
+* Make the include_once override optional - default off (Sara)
+
+* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
+
+* Ensure that the apc_globals-&gt;cache_stack is cleared before the 
+  shm cache is destroyed. Fixes segfault for corner-case i.e request
+  shutdown (apc_deactivate) is not called before module shutdown 
+  calls (php_apc_shutdown_globals)  (Gopal)
+
+* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
+
+* Fix memory leak of apc_cache_info_t-&gt;deleted_list (Gopal)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.12p1</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-09-05</date>
+   <notes>
+* The only change here is a trivial PHP 4 build fix.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.12p2</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2006-09-05</date>
+   <notes>
+* Let&apos;s get the version number right.  3.0.12p2 now.
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.13</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2007-02-24</date>
+   <notes>
+* PHP 5.2 file upload progress tracking support (Rasmus)
+* Pthread mutex and spin locks (Shire)
+* Recursive zval support for apc_fetch/_store (Shire, Gopal)
+* apc.stat_ctime flag for ctime checks (Rasmus)
+* Multiple key fetches with apc_fetch (Shire)
+* Canary checks for shm memory deallocation (Gopal)
+* Add hooks for external optimizer (Shire)
+* Obsolete and remove apc optimizer (Gopal)
+* APC info changes - cache insert rate, hit and miss rates (Shire)
+* Fix apc_load_constants (Gopal)
+* Rewrite dump opcode code to use vld (Gopal)
+* Use apc_[ewn]print functions for error reporting (Shire) 
+* Auto global fixes and refactoring (Gopal, Shire)
+* Fix memory leaks in object serialization (Ilia)
+* Memory cleanup code for destructor order (Gopal)
+* Win32 build fixes (Ilia, Wez)
+* ZTS and Php 4 build fixes (Bjori)
+* Add apc_add() function (Rasmus)
+* Add optional limited flag to apc_sma_info() (Rasmus)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.14</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2007-04-02</date>
+   <notes>
+* Build fix (Shire)
+* Don&apos;t hook the upload hook if APC is disabled (Rasmus)
+* Local shadow cache support (Gopal)
+* Avoid uneccessary loops over op_arrays for &quot;known&quot; auto-globals (Gopal)
+* Fix apc_add() to overwrite timed out user entries (Rasmus)
+* Fix double inclusion of files with conditional classes in php4 (Gopal)
+* Allocator fixes to reduce fragmentation (Gopal)
+   </notes>
+  </release>
+  <release>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <version>
+    <release>3.0.15</release>
+    <api>3.0.0</api>
+   </version>
+   <date>2007-10-18</date>
+   <notes>
+* Eliminate a per-request time() syscall (Rasmus)
+* Added rfc1867 prefix, name, and freq ini options (Shire)
+* Allow deletion of individual user cache entries via apc.php (Sara)
+* Fix overzealous cleanup during RSHUTDOWN (Gopal)
+* Fix memory alignment and locking issues (Gopal)
+* Make apc_compile insert/replace entries (Shire)
+* Make mixed inheritance recompile &amp; cache afresh  (Gopal)
+* Make nostat mode search include_path for canonicalization (Gopal)
+* ZTS &amp; other compile fixes (Gopal, Edin, Shire)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.0.16</release>
+    <api>3.0.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-03-26</date>
+   <notes>
+* Fix for longstanding cache-full crash (Christian Seiler)
+  http://news.php.net/php.pecl.dev/4951 for the details
+* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
+* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
+* Minor cleanups (Lucas Nealan)
+* Added configure option to enable apc_cache_info(&apos;filehits&apos;) (Shire)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.0.17</release>
+    <api>3.0.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-03-29</date>
+   <notes>
+* Crash fixes
+* Fix apc_add() cache expunge bug (Rasmus)
+* Added parameter to apc_fetch to determine success/failure when fetching booleans (shire)
+* Fix misc. memleaks (shire)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.0.18</release>
+    <api>3.0.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-03-29</date>
+   <notes>
+- Revert apc_expunge_cb bug-fix
+- Misc memleaks
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.0.19</release>
+    <api>3.0.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-05-15</date>
+   <notes>
+- Safe-mode and fast-cgi fixes
+- Fix double-free of builtin_functions
+- php 5.3 fixes
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.1</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-12-12</date>
+   <notes>
+- PHP4 compatibilty break
+- apc_pool allocator (Gopal) 
+- doubly-linked sma allocator (Shire)
+- php 5.3 gc compatibility (Gopal)
+- APCIterator for easy access (Shire)
+- apc_delete_file (Shire)
+- apc_inc/apc_dec/apc_cas functions (Shire)
+- apc.canonicalize (Gopal)
+- apc.preload_path (Gopal)
+- apc.rfc1867_ttl  (Shire)
+- apc.file_md5     (Shire)
+- consolidate locking macros (Shire)
+- remove futex/TSRM locks  (Shire)
+- non-blocking semaphore locks  (Shire)
+- zval* object rework (Gopal)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.2</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2008-12-12</date>
+   <notes>
+- pecl package.xml/build fixes (bjori)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.3</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2009-08-13</date>
+   <notes>
+- pecl package.xml/build fixes (bjori)
+- 5.3 support + test-cases (Gopal)
+- Lazy loading support (Shire)
+- Fix PCRE module init order issues (Shire)
+- APCIterator fixes (Shire)
+- Cache slam checks (Gopal)
+- ZEND_JMP_SET support (Shire)
+- apc.use_request_time option (shire)
+- apc.php hostname fixes (Shire)
+- memprotect framework (Gopal)
+- Win32 build-fixes (Kalle)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.3p1</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2009-08-14</date>
+   <notes>
+- fix pecl build / package.xml (Gopal)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.4</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2010-08-05</date>
+   <notes>
+- Windows builds may now have filehits and memory protection if enabled (Kalle)
+- Renamed the memory protection configure option to --enable-apc-memprotect (Kalle, Shire)
+- ZTS fixes and optimizations (Kalle, Felipe)
+- Win32 stat support (Pierre, Kalle) 
+- Added support for interned strings, run-time caches and Zend Engine 2.4 (Dmitry)
+- Added apc_exists() (Rasmus)
+- Fixed potential XSS in apc.php, CVE-2010-3294 (Pierre, Matt Chapman)
+- Fixed pecl bug #17597 (keys with embedded NUL) (Gopal)
+- Fixed pecl bug #17650 (Fix goto jump offsets) (Gopal)
+- Fixed pecl bug #17527 (Standardized error reporting) (Gopal, Paul Dragoonis)
+- Fixed pecl bug #17089 (Scrub the constant table of all inherited members before caching) (Gopal)
+- Fixed pecl bug #16860 (files can be included more than once even when include/require_once are used) (Pierre)
+- Fixed pecl bug #16717 (apc_fetch dies after 1 hour, regardless of ttl settings) (Kalle)
+- Fixed pecl bug #17597 (apc user cache keys with embedded NULs) (Gopal)
+- Fixed pecl bug #13583 (apc upload progress fixes) (Gopal)
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.1.5</release>
+    <api>3.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <date>2010-11-01</date>
+   <notes>
+- Reduce usage of CG(open_files) (mkoppanen at php dot net)
+- Add support for php-trunk, new op code, new internals string format, etc. (Dmitry)
+- apc_debug are not compiler-valid NOPs for non-debug builds
+
+- Fixed relative paths resolution when ./foo/a.php or ../foo/a.php (or similar path) 
+  are used. &apos;foo/a.php&apos; path behaviors remain unchanged
+- Fixed a possible memory corruption, when partial path cannot be resolved 
+  by expand_filepath()
+- Fixed notices in apc.php (Tomasz Krawczyk)
+
+- Fixed Bug #17978: standardize user keys to include NULs in identifier_len. Z_STRLEN_P() doesn&apos;t, so add to it.
+- Fixed bug #16966, apc produces tons of warnings &quot;Unable to allocate memory for pool&quot;.
+
+- Added --enable-apc-debug configuration argument to enable debugging (Kalle)
+- Added support for internal debugging on Windows (Kalle)
+- ZTS optimizations (Kalle)
+   </notes>
+  </release>
+ </changelog>
+</package>
--- /dev/null
+++ b/ext/apc/pgsql_s_lock.c
@@ -0,0 +1,391 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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.               |
+  +----------------------------------------------------------------------+
+  | The following code was ported from the PostgreSQL project, please    |
+  |  see appropriate copyright notices that follow.                      |
+  | Initial conversion by Brian Shire <shire@php.net>                    |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: pgsql_s_lock.c 302175 2010-08-13 06:20:28Z kalle $ */
+
+/*-------------------------------------------------------------------------
+ *
+ * s_lock.c
+ *	   Hardware-dependent implementation of spinlocks.
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/* #include "postgres.h"  -- Removed for APC */
+
+/* -- Added for APC -- */
+#include "apc.h"
+#ifdef APC_SPIN_LOCKS
+
+#ifdef S_LOCK_TEST
+#include <stdio.h>
+#endif
+#ifndef WIN32
+#include <sys/select.h>
+#endif
+/* ---- */
+
+#include <time.h>
+#ifdef WIN32
+#include "win32/unistd.h"
+#else
+#include <unistd.h>
+#endif
+
+/* #include "storage/s_lock.h" -- Removed for APC */
+#include "pgsql_s_lock.h"
+
+static int	spins_per_delay = DEFAULT_SPINS_PER_DELAY;
+
+
+/* -- APC specific additions ------------------------------*/
+/* The following dependencies have been copied from 
+ * other pgsql source files.  The original locations 
+ * have been noted.
+ */
+
+/* -- from include/c.h -- */
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* -- from include/pg_config_manual.h -- */
+#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
+
+/*
+ * Max
+ *    Return the maximum of two numbers.
+ */
+#define Max(x, y)   ((x) > (y) ? (x) : (y))
+
+/* -- from include/c.h -- */
+/*
+ * Min
+ *    Return the minimum of two numbers.
+ */
+#define Min(x, y)   ((x) < (y) ? (x) : (y))
+
+
+/* -- from backend/port/win32/signal.c -- */
+/*
+ * pg_usleep --- delay the specified number of microseconds.
+ *
+ * NOTE: although the delay is specified in microseconds, the effective
+ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen.  Expect
+ * the requested delay to be rounded up to the next resolution boundary.
+ *
+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
+ */
+void
+pg_usleep(long microsec)
+{
+	if (microsec > 0)
+	{
+#ifndef WIN32
+		struct timeval delay;
+
+		delay.tv_sec = microsec / 1000000L;
+		delay.tv_usec = microsec % 1000000L;
+		(void) select(0, NULL, NULL, NULL, &delay);
+#else
+		SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
+#endif
+	}
+}
+
+/* -- End APC specific additions ------------------------------*/
+
+
+/*
+ * s_lock_stuck() - complain about a stuck spinlock
+ */
+static void
+s_lock_stuck(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
+{
+#if defined(S_LOCK_TEST)
+	fprintf(stderr,
+			"\nStuck spinlock (%p) detected at %s:%d.\n",
+			lock, file, line);
+	exit(1);
+#else
+  /* -- Removed for APC
+	elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
+		 lock, file, line);
+  */
+  apc_error("Stuck spinlock (%p) detected" TSRMLS_CC, lock);
+#endif
+}
+
+
+/*
+ * s_lock(lock) - platform-independent portion of waiting for a spinlock.
+ */
+void
+s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
+{
+	/*
+	 * We loop tightly for awhile, then delay using pg_usleep() and try again.
+	 * Preferably, "awhile" should be a small multiple of the maximum time we
+	 * expect a spinlock to be held.  100 iterations seems about right as an
+	 * initial guess.  However, on a uniprocessor the loop is a waste of
+	 * cycles, while in a multi-CPU scenario it's usually better to spin a bit
+	 * longer than to call the kernel, so we try to adapt the spin loop count
+	 * depending on whether we seem to be in a uniprocessor or multiprocessor.
+	 *
+	 * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
+	 * be wrong; there are platforms where that can result in a "stuck
+	 * spinlock" failure.  This has been seen particularly on Alphas; it seems
+	 * that the first TAS after returning from kernel space will always fail
+	 * on that hardware.
+	 *
+	 * Once we do decide to block, we use randomly increasing pg_usleep()
+	 * delays. The first delay is 1 msec, then the delay randomly increases to
+	 * about one second, after which we reset to 1 msec and start again.  The
+	 * idea here is that in the presence of heavy contention we need to
+	 * increase the delay, else the spinlock holder may never get to run and
+	 * release the lock.  (Consider situation where spinlock holder has been
+	 * nice'd down in priority by the scheduler --- it will not get scheduled
+	 * until all would-be acquirers are sleeping, so if we always use a 1-msec
+	 * sleep, there is a real possibility of starvation.)  But we can't just
+	 * clamp the delay to an upper bound, else it would take a long time to
+	 * make a reasonable number of tries.
+	 *
+	 * We time out and declare error after NUM_DELAYS delays (thus, exactly
+	 * that many tries).  With the given settings, this will usually take 2 or
+	 * so minutes.	It seems better to fix the total number of tries (and thus
+	 * the probability of unintended failure) than to fix the total time
+	 * spent.
+	 *
+	 * The pg_usleep() delays are measured in milliseconds because 1 msec is a
+	 * common resolution limit at the OS level for newer platforms. On older
+	 * platforms the resolution limit is usually 10 msec, in which case the
+	 * total delay before timeout will be a bit more.
+	 */
+#define MIN_SPINS_PER_DELAY 10
+#define MAX_SPINS_PER_DELAY 1000
+#define NUM_DELAYS			1000
+#define MIN_DELAY_MSEC		1
+#define MAX_DELAY_MSEC		1000
+
+	int			spins = 0;
+	int			delays = 0;
+	int			cur_delay = 0;
+  
+	while (TAS(lock))
+	{
+		/* CPU-specific delay each time through the loop */
+		SPIN_DELAY();
+
+		/* Block the process every spins_per_delay tries */
+		if (++spins >= spins_per_delay)
+		{
+			if (++delays > NUM_DELAYS)
+				s_lock_stuck(lock, file, line TSRMLS_CC);
+
+			if (cur_delay == 0) /* first time to delay? */
+				cur_delay = MIN_DELAY_MSEC;
+
+			pg_usleep(cur_delay * 1000L);
+
+#if defined(S_LOCK_TEST)
+			fprintf(stdout, "*");
+			fflush(stdout);
+#endif
+
+			/* increase delay by a random fraction between 1X and 2X */
+			cur_delay += (int) (cur_delay *
+					  ((double) rand() / (double) MAX_RANDOM_VALUE) + 0.5);
+			/* wrap back to minimum delay when max is exceeded */
+			if (cur_delay > MAX_DELAY_MSEC)
+				cur_delay = MIN_DELAY_MSEC;
+
+			spins = 0;
+		}
+	}
+
+	/*
+	 * If we were able to acquire the lock without delaying, it's a good
+	 * indication we are in a multiprocessor.  If we had to delay, it's a sign
+	 * (but not a sure thing) that we are in a uniprocessor. Hence, we
+	 * decrement spins_per_delay slowly when we had to delay, and increase it
+	 * rapidly when we didn't.  It's expected that spins_per_delay will
+	 * converge to the minimum value on a uniprocessor and to the maximum
+	 * value on a multiprocessor.
+	 *
+	 * Note: spins_per_delay is local within our current process. We want to
+	 * average these observations across multiple backends, since it's
+	 * relatively rare for this function to even get entered, and so a single
+	 * backend might not live long enough to converge on a good value.	That
+	 * is handled by the two routines below.
+	 */
+	if (cur_delay == 0)
+	{
+		/* we never had to delay */
+		if (spins_per_delay < MAX_SPINS_PER_DELAY)
+			spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
+	}
+	else
+	{
+		if (spins_per_delay > MIN_SPINS_PER_DELAY)
+			spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
+	}
+}
+
+
+#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
+/*
+ * Set local copy of spins_per_delay during backend startup.
+ *
+ * NB: this has to be pretty fast as it is called while holding a spinlock
+ */
+void
+set_spins_per_delay(int shared_spins_per_delay)
+{
+	spins_per_delay = shared_spins_per_delay;
+}
+
+/*
+ * Update shared estimate of spins_per_delay during backend exit.
+ *
+ * NB: this has to be pretty fast as it is called while holding a spinlock
+ */
+int
+update_spins_per_delay(int shared_spins_per_delay)
+{
+	/*
+	 * We use an exponential moving average with a relatively slow adaption
+	 * rate, so that noise in any one backend's result won't affect the shared
+	 * value too much.	As long as both inputs are within the allowed range,
+	 * the result must be too, so we need not worry about clamping the result.
+	 *
+	 * We deliberately truncate rather than rounding; this is so that single
+	 * adjustments inside a backend can affect the shared estimate (see the
+	 * asymmetric adjustment rules above).
+	 */
+	return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
+}
+#endif
+
+/*
+ * Various TAS implementations that cannot live in s_lock.h as no inline
+ * definition exists (yet).
+ * In the future, get rid of tas.[cso] and fold it into this file.
+ *
+ * If you change something here, you will likely need to modify s_lock.h too,
+ * because the definitions for these are split between this file and s_lock.h.
+ */
+
+
+#ifdef HAVE_SPINLOCKS			/* skip spinlocks if requested */
+
+
+#if defined(__GNUC__)
+
+/*
+ * All the gcc flavors that are not inlined
+ */
+
+
+/*
+ * Note: all the if-tests here probably ought to be testing gcc version
+ * rather than platform, but I don't have adequate info to know what to
+ * write.  Ideally we'd flush all this in favor of the inline version.
+ */
+#if defined(__m68k__) && !defined(__linux__)
+/* really means: extern int tas(slock_t* **lock); */
+static void
+tas_dummy()
+{
+	__asm__		__volatile__(
+#if defined(__NetBSD__) && defined(__ELF__)
+/* no underscore for label and % for registers */
+										 "\
+.global		tas 				\n\
+tas:							\n\
+			movel	%sp@(0x4),%a0	\n\
+			tas 	%a0@		\n\
+			beq 	_success	\n\
+			moveq	#-128,%d0	\n\
+			rts 				\n\
+_success:						\n\
+			moveq	#0,%d0		\n\
+			rts 				\n"
+#else
+										 "\
+.global		_tas				\n\
+_tas:							\n\
+			movel	sp@(0x4),a0	\n\
+			tas 	a0@			\n\
+			beq 	_success	\n\
+			moveq 	#-128,d0	\n\
+			rts					\n\
+_success:						\n\
+			moveq 	#0,d0		\n\
+			rts					\n"
+#endif   /* __NetBSD__ && __ELF__ */
+	);
+}
+#endif   /* __m68k__ && !__linux__ */
+#else							/* not __GNUC__ */
+
+/*
+ * All non gcc
+ */
+
+
+#if defined(sun3)
+static void
+tas_dummy()						/* really means: extern int tas(slock_t
+								 * *lock); */
+{
+	asm("LLA0:");
+	asm("   .data");
+	asm("   .text");
+	asm("|#PROC# 04");
+	asm("   .globl  _tas");
+	asm("_tas:");
+	asm("|#PROLOGUE# 1");
+	asm("   movel   sp@(0x4),a0");
+	asm("   tas a0@");
+	asm("   beq LLA1");
+	asm("   moveq   #-128,d0");
+	asm("   rts");
+	asm("LLA1:");
+	asm("   moveq   #0,d0");
+	asm("   rts");
+	asm("   .data");
+}
+#endif   /* sun3 */
+#endif   /* not __GNUC__ */
+#endif   /* HAVE_SPINLOCKS */
+
+#endif /* APC_SPIN_LOCKS */
--- /dev/null
+++ b/ext/apc/pgsql_s_lock.h
@@ -0,0 +1,928 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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.               |
+  +----------------------------------------------------------------------+
+  | The following code was ported from the PostgreSQL project, please    |
+  |  see appropriate copyright notices that follow.                      |
+  | Initial conversion by Brian Shire <shire@php.net>                    |
+  +----------------------------------------------------------------------+
+
+ */
+
+/* $Id: pgsql_s_lock.h 302175 2010-08-13 06:20:28Z kalle $ */
+
+/*-------------------------------------------------------------------------
+ *
+ * s_lock.h
+ *	   Hardware-dependent implementation of spinlocks.
+ *
+ *	NOTE: none of the macros in this file are intended to be called directly.
+ *	Call them through the hardware-independent macros in spin.h.
+ *
+ *	The following hardware-dependent macros must be provided for each
+ *	supported platform:
+ *
+ *	void S_INIT_LOCK(slock_t *lock)
+ *		Initialize a spinlock (to the unlocked state).
+ *
+ *	void S_LOCK(slock_t *lock)
+ *		Acquire a spinlock, waiting if necessary.
+ *		Time out and abort() if unable to acquire the lock in a
+ *		"reasonable" amount of time --- typically ~ 1 minute.
+ *
+ *	void S_UNLOCK(slock_t *lock)
+ *		Unlock a previously acquired lock.
+ *
+ *	bool S_LOCK_FREE(slock_t *lock)
+ *		Tests if the lock is free. Returns TRUE if free, FALSE if locked.
+ *		This does *not* change the state of the lock.
+ *
+ *	void SPIN_DELAY(void)
+ *		Delay operation to occur inside spinlock wait loop.
+ *
+ *	Note to implementors: there are default implementations for all these
+ *	macros at the bottom of the file.  Check if your platform can use
+ *	these or needs to override them.
+ *
+ *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
+ *	TAS():
+ *
+ *	int TAS(slock_t *lock)
+ *		Atomic test-and-set instruction.  Attempt to acquire the lock,
+ *		but do *not* wait.	Returns 0 if successful, nonzero if unable
+ *		to acquire the lock.
+ *
+ *	TAS() is NOT part of the API, and should never be called directly.
+ *
+ *	CAUTION: on some platforms TAS() may sometimes report failure to acquire
+ *	a lock even when the lock is not locked.  For example, on Alpha TAS()
+ *	will "fail" if interrupted.  Therefore TAS() should always be invoked
+ *	in a retry loop, even if you are certain the lock is free.
+ *
+ *	ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
+ *	points, ie, loads and stores of other values must not be moved across
+ *	a lock or unlock.  In most cases it suffices to make the operation be
+ *	done through a "volatile" pointer.
+ *
+ *	On most supported platforms, TAS() uses a tas() function written
+ *	in assembly language to execute a hardware atomic-test-and-set
+ *	instruction.  Equivalent OS-supplied mutex routines could be used too.
+ *
+ *	If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
+ *	defined), then we fall back on an emulation that uses SysV semaphores
+ *	(see spin.c).  This emulation will be MUCH MUCH slower than a proper TAS()
+ *	implementation, because of the cost of a kernel call per lock or unlock.
+ *	An old report is that Postgres spends around 40% of its time in semop(2)
+ *	when using the SysV semaphore code.
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *	  $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef S_LOCK_H
+#define S_LOCK_H
+
+/** APC namespace protection ************************************************/
+/* hack to protect against any possible runtime namespace collisions...*/
+#define pg_usleep               apc_spin_pg_usleep
+#define s_lock                  apc_spin_s_lock
+#define spins_per_delay         apc_spin_spins_per_delay
+/****************************************************************************/
+
+
+/* #include "storage/pg_sema.h"   -- Removed for APC */
+
+#define HAVE_SPINLOCKS 1 /* -- Added for APC */
+
+#ifdef HAVE_SPINLOCKS	/* skip spinlocks if requested */
+
+
+#if defined(__GNUC__) || defined(__ICC)
+/*************************************************************************
+ * All the gcc inlines
+ * Gcc consistently defines the CPU as __cpu__.
+ * Other compilers use __cpu or __cpu__ so we test for both in those cases.
+ */
+
+/*----------
+ * Standard gcc asm format (assuming "volatile slock_t *lock"):
+
+	__asm__ __volatile__(
+		"	instruction	\n"
+		"	instruction	\n"
+		"	instruction	\n"
+:		"=r"(_res), "+m"(*lock)		// return register, in/out lock value
+:		"r"(lock)					// lock pointer, in input register
+:		"memory", "cc");			// show clobbered registers here
+
+ * The output-operands list (after first colon) should always include
+ * "+m"(*lock), whether or not the asm code actually refers to this
+ * operand directly.  This ensures that gcc believes the value in the
+ * lock variable is used and set by the asm code.  Also, the clobbers
+ * list (after third colon) should always include "memory"; this prevents
+ * gcc from thinking it can cache the values of shared-memory fields
+ * across the asm code.  Add "cc" if your asm code changes the condition
+ * code register, and also list any temp registers the code uses.
+ *----------
+ */
+
+
+#ifdef __i386__		/* 32-bit i386 */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register slock_t _res = 1;
+
+	/*
+	 * Use a non-locking test before asserting the bus lock.  Note that the
+	 * extra test appears to be a small loss on some x86 platforms and a small
+	 * win on others; it's by no means clear that we should keep it.
+	 */
+	__asm__ __volatile__(
+		"	cmpb	$0,%1	\n"
+		"	jne		1f		\n"
+		"	lock			\n"
+		"	xchgb	%0,%1	\n"
+		"1: \n"
+:		"+q"(_res), "+m"(*lock)
+:
+:		"memory", "cc");
+	return (int) _res;
+}
+
+#define SPIN_DELAY() spin_delay()
+
+static __inline__ void
+spin_delay(void)
+{
+	/*
+	 * This sequence is equivalent to the PAUSE instruction ("rep" is
+	 * ignored by old IA32 processors if the following instruction is
+	 * not a string operation); the IA-32 Architecture Software
+	 * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
+	 * PAUSE in the inner loop of a spin lock is necessary for good
+	 * performance:
+	 *
+	 *     The PAUSE instruction improves the performance of IA-32
+	 *     processors supporting Hyper-Threading Technology when
+	 *     executing spin-wait loops and other routines where one
+	 *     thread is accessing a shared lock or semaphore in a tight
+	 *     polling loop. When executing a spin-wait loop, the
+	 *     processor can suffer a severe performance penalty when
+	 *     exiting the loop because it detects a possible memory order
+	 *     violation and flushes the core processor's pipeline. The
+	 *     PAUSE instruction provides a hint to the processor that the
+	 *     code sequence is a spin-wait loop. The processor uses this
+	 *     hint to avoid the memory order violation and prevent the
+	 *     pipeline flush. In addition, the PAUSE instruction
+	 *     de-pipelines the spin-wait loop to prevent it from
+	 *     consuming execution resources excessively.
+	 */
+	__asm__ __volatile__(
+		" rep; nop			\n");
+}
+
+#endif	 /* __i386__ */
+
+
+#ifdef __x86_64__		/* AMD Opteron, Intel EM64T */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register slock_t _res = 1;
+
+	/*
+	 * On Opteron, using a non-locking test before the locking instruction
+	 * is a huge loss.  On EM64T, it appears to be a wash or small loss,
+	 * so we needn't bother to try to distinguish the sub-architectures.
+	 */
+	__asm__ __volatile__(
+		"	lock			\n"
+		"	xchgb	%0,%1	\n"
+:		"+q"(_res), "+m"(*lock)
+:
+:		"memory", "cc");
+	return (int) _res;
+}
+
+#define SPIN_DELAY() spin_delay()
+
+static __inline__ void
+spin_delay(void)
+{
+	/*
+	 * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
+	 * Opteron, but it may be of some use on EM64T, so we keep it.
+	 */
+	__asm__ __volatile__(
+		" rep; nop			\n");
+}
+
+#endif	 /* __x86_64__ */
+
+
+#if defined(__ia64__) || defined(__ia64)	/* Intel Itanium */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+#ifndef __INTEL_COMPILER
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	long int	ret;
+
+	__asm__ __volatile__(
+		"	xchg4 	%0=%1,%2	\n"
+:		"=r"(ret), "+m"(*lock)
+:		"r"(1)
+:		"memory");
+	return (int) ret;
+}
+
+#else /* __INTEL_COMPILER */
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	int		ret;
+
+	ret = _InterlockedExchange(lock,1);	/* this is a xchg asm macro */
+
+	return ret;
+}
+
+#endif /* __INTEL_COMPILER */
+#endif	 /* __ia64__ || __ia64 */
+
+
+#if defined(__arm__) || defined(__arm)
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register slock_t _res = 1;
+
+	__asm__ __volatile__(
+		"	swpb 	%0, %0, [%2]	\n"
+:		"+r"(_res), "+m"(*lock)
+:		"r"(lock)
+:		"memory");
+	return (int) _res;
+}
+
+#endif	 /* __arm__ */
+
+
+/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
+#if defined(__s390__) || defined(__s390x__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock)	   tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	int			_res = 0;
+
+	__asm__	__volatile__(
+		"	cs 	%0,%3,0(%2)		\n"
+:		"+d"(_res), "+m"(*lock)
+:		"a"(lock), "d"(1)
+:		"memory", "cc");
+	return _res;
+}
+
+#endif	 /* __s390__ || __s390x__ */
+
+
+#if defined(__sparc__)		/* Sparc */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register slock_t _res;
+
+	/*
+	 *	See comment in /pg/backend/port/tas/solaris_sparc.s for why this
+	 *	uses "ldstub", and that file uses "cas".  gcc currently generates
+	 *	sparcv7-targeted binaries, so "cas" use isn't possible.
+	 */
+	__asm__ __volatile__(
+		"	ldstub	[%2], %0	\n"
+:		"=r"(_res), "+m"(*lock)
+:		"r"(lock)
+:		"memory");
+	return (int) _res;
+}
+
+#endif	 /* __sparc__ */
+
+
+/* PowerPC */
+#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
+#define HAS_TEST_AND_SET
+
+#if defined(__ppc64__) || defined(__powerpc64__)
+typedef unsigned long slock_t;
+#else
+typedef unsigned int slock_t;
+#endif
+
+#define TAS(lock) tas(lock)
+/*
+ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
+ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
+ */
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	slock_t _t;
+	int _res;
+
+	__asm__ __volatile__(
+"	lwarx   %0,0,%3		\n"
+"	cmpwi   %0,0		\n"
+"	bne     1f			\n"
+"	addi    %0,%0,1		\n"
+"	stwcx.  %0,0,%3		\n"
+"	beq     2f         	\n"
+"1:	li      %1,1		\n"
+"	b		3f			\n"
+"2:						\n"
+"	isync				\n"
+"	li      %1,0		\n"
+"3:						\n"
+
+:	"=&r"(_t), "=r"(_res), "+m"(*lock)
+:	"r"(lock)
+:	"memory", "cc");
+	return _res;
+}
+
+/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
+#define S_UNLOCK(lock)	\
+do \
+{ \
+	__asm__ __volatile__ ("	sync \n"); \
+	*((volatile slock_t *) (lock)) = 0; \
+} while (0)
+
+#endif /* powerpc */
+
+
+/* Linux Motorola 68k */
+#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register int rv;
+
+	__asm__	__volatile__(
+		"	clrl	%0		\n"
+		"	tas		%1		\n"
+		"	sne		%0		\n"
+:		"=d"(rv), "+m"(*lock)
+:
+:		"memory", "cc");
+	return rv;
+}
+
+#endif	 /* (__mc68000__ || __m68k__) && __linux__ */
+
+
+/*
+ * VAXen -- even multiprocessor ones
+ * (thanks to Tom Ivar Helbekkmo)
+ */
+#if defined(__vax__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register int	_res;
+
+	__asm__ __volatile__(
+		"	movl 	$1, %0			\n"
+		"	bbssi	$0, (%2), 1f	\n"
+		"	clrl	%0				\n"
+		"1: \n"
+:		"=&r"(_res), "+m"(*lock)
+:		"r"(lock)
+:		"memory");
+	return _res;
+}
+
+#endif	 /* __vax__ */
+
+
+#if defined(__ns32k__)		/* National Semiconductor 32K */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register int	_res;
+
+	__asm__ __volatile__(
+		"	sbitb	0, %1	\n"
+		"	sfsd	%0		\n"
+:		"=r"(_res), "+m"(*lock)
+:
+:		"memory");
+	return _res;
+}
+
+#endif	 /* __ns32k__ */
+
+
+#if defined(__alpha) || defined(__alpha__)	/* Alpha */
+/*
+ * Correct multi-processor locking methods are explained in section 5.5.3
+ * of the Alpha AXP Architecture Handbook, which at this writing can be
+ * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
+ * For gcc we implement the handbook's code directly with inline assembler.
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned long slock_t;
+
+#define TAS(lock)  tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register slock_t _res;
+
+	__asm__	__volatile__(
+		"	ldq		$0, %1	\n"
+		"	bne		$0, 2f	\n"
+		"	ldq_l	%0, %1	\n"
+		"	bne		%0, 2f	\n"
+		"	mov		1,  $0	\n"
+		"	stq_c	$0, %1	\n"
+		"	beq		$0, 2f	\n"
+		"	mb				\n"
+		"	br		3f		\n"
+		"2:	mov		1, %0	\n"
+		"3:					\n"
+:		"=&r"(_res), "+m"(*lock)
+:
+:		"memory", "0");
+	return (int) _res;
+}
+
+#define S_UNLOCK(lock)	\
+do \
+{\
+	__asm__ __volatile__ ("	mb \n"); \
+	*((volatile slock_t *) (lock)) = 0; \
+} while (0)
+
+#endif /* __alpha || __alpha__ */
+
+
+#if defined(__mips__) && !defined(__sgi)	/* non-SGI MIPS */
+/* Note: on SGI we use the OS' mutex ABI, see below */
+/* Note: R10000 processors require a separate SYNC */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	register volatile slock_t *_l = lock;
+	register int _res;
+	register int _tmp;
+
+	__asm__ __volatile__(
+		"       .set push           \n"
+		"       .set mips2          \n"
+		"       .set noreorder      \n"
+		"       .set nomacro        \n"
+		"       ll      %0, %2      \n"
+		"       or      %1, %0, 1   \n"
+		"       sc      %1, %2      \n"
+		"       xori    %1, 1       \n"
+		"       or      %0, %0, %1  \n"
+		"       sync                \n"
+		"       .set pop              "
+:		"=&r" (_res), "=&r" (_tmp), "+R" (*_l)
+:
+:		"memory");
+	return _res;
+}
+
+/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
+#define S_UNLOCK(lock)	\
+do \
+{ \
+	__asm__ __volatile__( \
+		"       .set push           \n" \
+		"       .set mips2          \n" \
+		"       .set noreorder      \n" \
+		"       .set nomacro        \n" \
+		"       sync                \n" \
+		"       .set pop              "); \
+	*((volatile slock_t *) (lock)) = 0; \
+} while (0)
+
+#endif /* __mips__ && !__sgi */
+
+
+/* These live in s_lock.c, but only for gcc */
+
+
+#if defined(__m68k__) && !defined(__linux__)	/* non-Linux Motorola 68k */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+#endif
+
+
+#endif	/* __GNUC__ */
+
+
+
+/*
+ * ---------------------------------------------------------------------
+ * Platforms that use non-gcc inline assembly:
+ * ---------------------------------------------------------------------
+ */
+
+#if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
+
+
+#if defined(USE_UNIVEL_CC)		/* Unixware compiler */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock)	tas(lock)
+
+asm int
+tas(volatile slock_t *s_lock)
+{
+/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
+%mem s_lock
+	pushl %ebx
+	movl s_lock, %ebx
+	movl $255, %eax
+	lock
+	xchgb %al, (%ebx)
+	popl %ebx
+}
+
+#endif	 /* defined(USE_UNIVEL_CC) */
+
+
+#if defined(__alpha) || defined(__alpha__)	/* Tru64 Unix Alpha compiler */
+/*
+ * The Tru64 compiler doesn't support gcc-style inline asm, but it does
+ * have some builtin functions that accomplish much the same results.
+ * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
+ * regardless of the compiler in use.  LOCK_LONG and UNLOCK_LONG only
+ * operate on an int (ie, longword), but that's OK as long as we define
+ * S_INIT_LOCK to zero out the whole quadword.
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned long slock_t;
+
+#include <alpha/builtins.h>
+#define S_INIT_LOCK(lock)  (*(lock) = 0)
+#define TAS(lock)		   (__LOCK_LONG_RETRY((lock), 1) == 0)
+#define S_UNLOCK(lock)	   __UNLOCK_LONG(lock)
+
+#endif	 /* __alpha || __alpha__ */
+
+
+#if defined(__hppa) || defined(__hppa__)	/* HP PA-RISC, GCC and HP compilers */
+/*
+ * HP's PA-RISC
+ *
+ * See src/backend/port/hpux/tas.c.template for details about LDCWX.  Because
+ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
+ * struct.  The active word in the struct is whichever has the aligned address;
+ * the other three words just sit at -1.
+ *
+ * When using gcc, we can inline the required assembly code.
+ */
+#define HAS_TEST_AND_SET
+
+typedef struct
+{
+	int			sema[4];
+} slock_t;
+
+#define TAS_ACTIVE_WORD(lock)	((volatile int *) (((long) (lock) + 15) & ~15))
+
+#if defined(__GNUC__)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+	volatile int *lockword = TAS_ACTIVE_WORD(lock);
+	register int lockval;
+
+	__asm__ __volatile__(
+		"	ldcwx	0(0,%2),%0	\n"
+:		"=r"(lockval), "+m"(*lockword)
+:		"r"(lockword)
+:		"memory");
+	return (lockval == 0);
+}
+
+#endif /* __GNUC__ */
+
+#define S_UNLOCK(lock)	(*TAS_ACTIVE_WORD(lock) = -1)
+
+#define S_INIT_LOCK(lock) \
+	do { \
+		volatile slock_t *lock_ = (lock); \
+		lock_->sema[0] = -1; \
+		lock_->sema[1] = -1; \
+		lock_->sema[2] = -1; \
+		lock_->sema[3] = -1; \
+	} while (0)
+
+#define S_LOCK_FREE(lock)	(*TAS_ACTIVE_WORD(lock) != 0)
+
+#endif	 /* __hppa || __hppa__ */
+
+
+#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
+
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#include <ia64/sys/inline.h>
+#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
+
+#endif	/* HPUX on IA64, non gcc */
+
+
+#if defined(__sgi)	/* SGI compiler */
+/*
+ * SGI IRIX 5
+ * slock_t is defined as a unsigned long. We use the standard SGI
+ * mutex API.
+ *
+ * The following comment is left for historical reasons, but is probably
+ * not a good idea since the mutex ABI is supported.
+ *
+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
+ * for the R3000 chips out there.
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned long slock_t;
+
+#include "mutex.h"
+#define TAS(lock)	(test_and_set(lock,1))
+#define S_UNLOCK(lock)	(test_then_and(lock,0))
+#define S_INIT_LOCK(lock)	(test_then_and(lock,0))
+#define S_LOCK_FREE(lock)	(test_then_add(lock,0) == 0)
+#endif	 /* __sgi */
+
+
+#if defined(sinix)		/* Sinix */
+/*
+ * SINIX / Reliant UNIX
+ * slock_t is defined as a struct abilock_t, which has a single unsigned long
+ * member. (Basically same as SGI)
+ */
+#define HAS_TEST_AND_SET
+
+#include "abi_mutex.h"
+typedef abilock_t slock_t;
+
+#define TAS(lock)	(!acquire_lock(lock))
+#define S_UNLOCK(lock)	release_lock(lock)
+#define S_INIT_LOCK(lock)	init_lock(lock)
+#define S_LOCK_FREE(lock)	(stat_lock(lock) == UNLOCKED)
+#endif	 /* sinix */
+
+
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock)			_check_lock(lock, 0, 1)
+#define S_UNLOCK(lock)		_clear_lock(lock, 0)
+#endif	 /* _AIX */
+
+
+#if defined (nextstep)		/* Nextstep */
+#define HAS_TEST_AND_SET
+
+typedef struct mutex slock_t;
+
+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
+
+#define S_LOCK(lock)	mutex_lock(lock)
+#define S_UNLOCK(lock)	mutex_unlock(lock)
+#define S_INIT_LOCK(lock)	mutex_init(lock)
+/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
+#define S_LOCK_FREE(alock)	((alock)->lock == 0)
+#endif	 /* nextstep */
+
+
+/* These are in s_lock.c */
+
+
+#if defined(sun3)		/* Sun3 */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+#endif
+
+
+#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
+#define HAS_TEST_AND_SET
+
+#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
+typedef unsigned int slock_t;
+#else
+typedef unsigned char slock_t;
+#endif
+
+extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
+									  slock_t cmp);
+
+#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
+#endif
+
+
+#ifdef WIN32_ONLY_COMPILER
+typedef LONG slock_t;
+
+#define HAS_TEST_AND_SET
+#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
+
+#define SPIN_DELAY() spin_delay()
+
+static __forceinline void
+spin_delay(void)
+{
+	/* See comment for gcc code. Same code, MASM syntax */
+	__asm rep nop;
+}
+
+#endif
+
+  
+#endif	/* !defined(HAS_TEST_AND_SET) */
+
+
+/* Blow up if we didn't have any way to do spinlocks */
+#ifndef HAS_TEST_AND_SET
+/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
+#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
+/* #error PostgreSQL does not have native spinlock support on this platform.  To continue the compilation, rerun configure using --disable-spinlocks.  However, performance will be poor.  Please report this to pgsql-bugs@postgresql.org. */ 
+#endif
+
+
+#else	/* !HAVE_SPINLOCKS */
+
+
+/*
+ * Fake spinlock implementation using semaphores --- slow and prone
+ * to fall foul of kernel limits on number of semaphores, so don't use this
+ * unless you must!  The subroutines appear in spin.c.
+ */
+
+/* -- Removed for APC
+typedef PGSemaphoreData slock_t;
+
+extern bool s_lock_free_sema(volatile slock_t *lock);
+extern void s_unlock_sema(volatile slock_t *lock);
+extern void s_init_lock_sema(volatile slock_t *lock);
+extern int	tas_sema(volatile slock_t *lock);
+
+#define S_LOCK_FREE(lock)	s_lock_free_sema(lock)
+#define S_UNLOCK(lock)	 s_unlock_sema(lock)
+#define S_INIT_LOCK(lock)	s_init_lock_sema(lock)
+#define TAS(lock)	tas_sema(lock)
+*/
+
+#endif	/* HAVE_SPINLOCKS */
+
+
+/*
+ * Default Definitions - override these above as needed.
+ */
+
+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
+
+#if !defined(S_LOCK)
+#define S_LOCK(lock) \
+	do { \
+		if (TAS(lock)) \
+			s_lock((lock), __FILE__, __LINE__ TSRMLS_CC); \
+	} while (0)
+#endif	 /* S_LOCK */
+
+#if !defined(S_LOCK_FREE)
+#define S_LOCK_FREE(lock)	(*(lock) == 0)
+#endif	 /* S_LOCK_FREE */
+
+#if !defined(S_UNLOCK)
+#define S_UNLOCK(lock)		(*((volatile slock_t *) (lock)) = 0)
+#endif	 /* S_UNLOCK */
+
+#if !defined(S_INIT_LOCK)
+#define S_INIT_LOCK(lock)	S_UNLOCK(lock)
+#endif	 /* S_INIT_LOCK */
+
+#if !defined(SPIN_DELAY)
+#define SPIN_DELAY()	((void) 0)
+#endif	 /* SPIN_DELAY */
+
+#if !defined(TAS)
+extern int	tas(volatile slock_t *lock);		/* in port/.../tas.s, or
+												 * s_lock.c */
+
+#define TAS(lock)		tas(lock)
+#endif	 /* TAS */
+
+
+/*
+ * Platform-independent out-of-line support routines
+ */
+extern void s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC);
+
+/* Support for dynamic adjustment of spins_per_delay */
+#define DEFAULT_SPINS_PER_DELAY  100
+
+#if 0  /* -- Removed from APC use -- */
+extern void set_spins_per_delay(int shared_spins_per_delay);
+extern int	update_spins_per_delay(int shared_spins_per_delay);
+#endif
+
+#endif	 /* S_LOCK_H */
--- /dev/null
+++ b/ext/apc/php_apc.c
@@ -0,0 +1,1812 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>                             |
+  +----------------------------------------------------------------------+
+
+   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: php_apc.c 303642 2010-09-21 15:42:01Z kalle $ */
+
+#include "apc_zend.h"
+#include "apc_cache.h"
+#include "apc_iterator.h"
+#include "apc_main.h"
+#include "apc_sma.h"
+#include "apc_lock.h"
+#include "apc_bin.h"
+#include "php_globals.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/flock_compat.h"
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#include "SAPI.h"
+#include "rfc1867.h"
+#include "php_apc.h"
+#include "ext/standard/md5.h"
+
+#if HAVE_SIGACTION
+#include "apc_signal.h"
+#endif
+
+/* {{{ PHP_FUNCTION declarations */
+PHP_FUNCTION(apc_cache_info);
+PHP_FUNCTION(apc_clear_cache);
+PHP_FUNCTION(apc_sma_info);
+PHP_FUNCTION(apc_store);
+PHP_FUNCTION(apc_fetch);
+PHP_FUNCTION(apc_delete);
+PHP_FUNCTION(apc_delete_file);
+PHP_FUNCTION(apc_compile_file);
+PHP_FUNCTION(apc_define_constants);
+PHP_FUNCTION(apc_load_constants);
+PHP_FUNCTION(apc_add);
+PHP_FUNCTION(apc_inc);
+PHP_FUNCTION(apc_dec);
+PHP_FUNCTION(apc_cas);
+PHP_FUNCTION(apc_bin_dump);
+PHP_FUNCTION(apc_bin_load);
+PHP_FUNCTION(apc_bin_dumpfile);
+PHP_FUNCTION(apc_bin_loadfile);
+PHP_FUNCTION(apc_exists);
+/* }}} */
+
+/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
+ZEND_DECLARE_MODULE_GLOBALS(apc)
+
+/* True globals */
+apc_cache_t* apc_cache = NULL;
+apc_cache_t* apc_user_cache = NULL;
+
+static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
+{
+    apc_globals->filters = NULL;
+    apc_globals->compiled_filters = NULL;
+    apc_globals->initialized = 0;
+    apc_globals->cache_stack = apc_stack_create(0 TSRMLS_CC);
+    apc_globals->cache_by_default = 1;
+    apc_globals->fpstat = 1;
+    apc_globals->canonicalize = 1;
+    apc_globals->stat_ctime = 0;
+    apc_globals->write_lock = 1;
+    apc_globals->slam_defense = 1;
+    apc_globals->report_autofilter = 0;
+    apc_globals->include_once = 0;
+    apc_globals->apc_optimize_function = NULL;
+#ifdef MULTIPART_EVENT_FORMDATA
+    apc_globals->rfc1867 = 0;
+    memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data));
+#endif
+    memset(&apc_globals->copied_zvals, 0, sizeof(HashTable));
+    apc_globals->force_file_update = 0;
+    apc_globals->coredump_unmap = 0;
+    apc_globals->preload_path = NULL;
+    apc_globals->use_request_time = 1;
+    apc_globals->lazy_class_table = NULL;
+    apc_globals->lazy_function_table = NULL;
+}
+
+static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
+{
+    /* deallocate the ignore patterns */
+    if (apc_globals->filters != NULL) {
+        int i;
+        for (i=0; apc_globals->filters[i] != NULL; i++) {
+            apc_efree(apc_globals->filters[i] TSRMLS_CC);
+        }
+        apc_efree(apc_globals->filters TSRMLS_CC);
+    }
+
+    /* the stack should be empty */
+    assert(apc_stack_size(apc_globals->cache_stack) == 0);
+
+    /* apc cleanup */
+    apc_stack_destroy(apc_globals->cache_stack TSRMLS_CC);
+
+    /* the rest of the globals are cleaned up in apc_module_shutdown() */
+}
+
+static long apc_atol(const char *str, int str_len)
+{
+#if PHP_MAJOR_VERSION >= 6 || PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
+	return zend_atol(str, str_len);
+#else
+	/* Re-implement zend_atol() for 5.2.x */
+	long retval;
+
+	if (!str_len) {
+		str_len = strlen(str);
+	}
+
+	retval = strtol(str, NULL, 0);
+
+	if (str_len > 0) {
+		switch (str[str_len - 1]) {
+			case 'g':
+			case 'G':
+				retval *= 1024;
+				/* break intentionally missing */
+			case 'm':
+			case 'M':
+				retval *= 1024;
+				/* break intentionally missing */
+			case 'k':
+			case 'K':
+				retval *= 1024;
+				break;
+		}
+	}
+
+	return retval;
+#endif
+}
+
+/* }}} */
+
+/* {{{ PHP_INI */
+
+static PHP_INI_MH(OnUpdate_filters) /* {{{ */
+{
+    APCG(filters) = apc_tokenize(new_value, ',' TSRMLS_CC);
+    return SUCCESS;
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
+{
+#if APC_MMAP
+    if(zend_atoi(new_value, new_value_length)!=1) {
+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
+    }
+    APCG(shm_segments) = 1;
+#else
+    APCG(shm_segments) = zend_atoi(new_value, new_value_length);
+#endif
+    return SUCCESS;
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateShmSize) /* {{{ */
+{
+	long s = apc_atol(new_value, new_value_length);
+
+	if(s <= 0) {
+		return FAILURE;
+	}
+
+	if(s < 1048576L) {
+		/* if it's less than 1Mb, they are probably using the old syntax */
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_size now uses M/G suffixes, please update your ini files");
+		s = s * 1048576L;
+	}
+
+	APCG(shm_size) = s;
+
+	return SUCCESS;
+}
+/* }}} */
+
+#ifdef MULTIPART_EVENT_FORMDATA
+static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
+{
+    int tmp;
+    tmp = zend_atoi(new_value, new_value_length);
+    if(tmp < 0) {
+        apc_error("rfc1867_freq must be greater than or equal to zero." TSRMLS_CC);
+        return FAILURE;
+    }
+    if(new_value[new_value_length-1] == '%') {
+        if(tmp > 100) {
+            apc_error("rfc1867_freq cannot be over 100%%" TSRMLS_CC);
+            return FAILURE;
+        }
+        APCG(rfc1867_freq) = tmp / 100.0;
+    } else {
+        APCG(rfc1867_freq) = tmp;
+    }
+    return SUCCESS;
+}
+/* }}} */
+#endif
+
+PHP_INI_BEGIN()
+STD_PHP_INI_BOOLEAN("apc.enabled",      "1",    PHP_INI_SYSTEM, OnUpdateBool,              enabled,         zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    PHP_INI_SYSTEM, OnUpdateShmSegments,       shm_segments,    zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.shm_size",       "32M",  PHP_INI_SYSTEM, OnUpdateShmSize,           shm_size,        zend_apc_globals, apc_globals)
+#ifdef ZEND_ENGINE_2_4
+STD_PHP_INI_ENTRY("apc.shm_strings_buffer", "4M",   PHP_INI_SYSTEM, OnUpdateLong,           shm_strings_buffer,        zend_apc_globals, apc_globals)
+#endif
+STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool,     include_once,    zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateLong,            num_files_hint,  zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateLong,          user_entries_hint, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", PHP_INI_SYSTEM, OnUpdateLong,            gc_ttl,           zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.ttl",            "0",    PHP_INI_SYSTEM, OnUpdateLong,            ttl,              zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.user_ttl",       "0",    PHP_INI_SYSTEM, OnUpdateLong,            user_ttl,         zend_apc_globals, apc_globals)
+#if APC_MMAP
+STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
+#endif
+PHP_INI_ENTRY("apc.filters",        NULL,     PHP_INI_SYSTEM, OnUpdate_filters)
+STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1",  PHP_INI_ALL, OnUpdateBool,         cache_by_default, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateLong,file_update_protection,  zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.enable_cli", "0",      PHP_INI_SYSTEM, OnUpdateBool,           enable_cli,       zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.max_file_size", "1M",    PHP_INI_SYSTEM, OnUpdateLong,            max_file_size,    zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.stat", "1",            PHP_INI_SYSTEM, OnUpdateBool,           fpstat,           zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.canonicalize", "1",    PHP_INI_SYSTEM, OnUpdateBool,           canonicalize,     zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0",      PHP_INI_SYSTEM, OnUpdateBool,           stat_ctime,       zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.write_lock", "1",      PHP_INI_SYSTEM, OnUpdateBool,           write_lock,       zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.slam_defense", "1",    PHP_INI_SYSTEM, OnUpdateBool,           slam_defense,     zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool,         report_autofilter,zend_apc_globals, apc_globals)
+#ifdef MULTIPART_EVENT_FORMDATA
+STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.rfc1867_ttl", "3600", PHP_INI_SYSTEM, OnUpdateLong, rfc1867_ttl, zend_apc_globals, apc_globals)
+#endif
+STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
+STD_PHP_INI_ENTRY("apc.preload_path", (char*)NULL,              PHP_INI_SYSTEM, OnUpdateString,       preload_path,  zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.file_md5", "0", PHP_INI_SYSTEM, OnUpdateBool, file_md5,  zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.use_request_time", "1", PHP_INI_ALL, OnUpdateBool, use_request_time,  zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.lazy_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_functions, zend_apc_globals, apc_globals)
+STD_PHP_INI_BOOLEAN("apc.lazy_classes", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_classes, zend_apc_globals, apc_globals)
+PHP_INI_END()
+
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION(apc) */
+static PHP_MINFO_FUNCTION(apc)
+{
+    php_info_print_table_start();
+    php_info_print_table_header(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
+    php_info_print_table_row(2, "Version", PHP_APC_VERSION);
+#ifdef __DEBUG_APC__
+    php_info_print_table_row(2, "APC Debugging", "Enabled");
+#else
+    php_info_print_table_row(2, "APC Debugging", "Disabled");
+#endif
+#if APC_MMAP
+    php_info_print_table_row(2, "MMAP Support", "Enabled");
+    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
+#else
+    php_info_print_table_row(2, "MMAP Support", "Disabled");
+#endif
+    php_info_print_table_row(2, "Locking type", APC_LOCK_TYPE);
+    php_info_print_table_row(2, "Revision", "$Revision: 303642 $");
+    php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
+    php_info_print_table_end();
+    DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+#ifdef MULTIPART_EVENT_FORMDATA
+extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
+#endif
+
+/* {{{ PHP_MINIT_FUNCTION(apc) */
+static PHP_MINIT_FUNCTION(apc)
+{
+    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
+
+    REGISTER_INI_ENTRIES();
+
+    /* Disable APC in cli mode unless overridden by apc.enable_cli */
+    if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
+        APCG(enabled) = 0;
+    }
+
+    if (APCG(enabled)) {
+        if(APCG(initialized)) {
+            apc_process_init(module_number TSRMLS_CC);
+        } else {
+            apc_module_init(module_number TSRMLS_CC);
+            apc_zend_init(TSRMLS_C);
+            apc_process_init(module_number TSRMLS_CC);
+#ifdef MULTIPART_EVENT_FORMDATA
+            /* File upload progress tracking */
+            if(APCG(rfc1867)) {
+                php_rfc1867_callback = apc_rfc1867_progress;
+            }
+#endif
+            apc_iterator_init(module_number TSRMLS_CC);
+        }
+
+        zend_register_long_constant("APC_BIN_VERIFY_MD5", sizeof("APC_BIN_VERIFY_MD5"), APC_BIN_VERIFY_MD5, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
+        zend_register_long_constant("APC_BIN_VERIFY_CRC32", sizeof("APC_BIN_VERIFY_CRC32"), APC_BIN_VERIFY_CRC32, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
+    }
+
+    return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
+static PHP_MSHUTDOWN_FUNCTION(apc)
+{
+    if(APCG(enabled)) {
+        apc_process_shutdown(TSRMLS_C);
+        apc_zend_shutdown(TSRMLS_C);
+        apc_module_shutdown(TSRMLS_C);
+#ifndef ZTS
+        php_apc_shutdown_globals(&apc_globals);
+#endif
+#if HAVE_SIGACTION
+        apc_shutdown_signals(TSRMLS_C);
+#endif
+    }
+#ifdef ZTS
+    ts_free_id(apc_globals_id);
+#endif
+    UNREGISTER_INI_ENTRIES();
+    return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RINIT_FUNCTION(apc) */
+static PHP_RINIT_FUNCTION(apc)
+{
+    if(APCG(enabled)) {
+        apc_request_init(TSRMLS_C);
+
+#if HAVE_SIGACTION
+        apc_set_signals(TSRMLS_C);
+#endif
+    }
+    return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
+static PHP_RSHUTDOWN_FUNCTION(apc)
+{
+    if(APCG(enabled)) {
+        apc_request_shutdown(TSRMLS_C);
+    }
+    return SUCCESS;
+}
+/* }}} */
+
+/* {{{ proto array apc_cache_info([string type [, bool limited]]) */
+PHP_FUNCTION(apc_cache_info)
+{
+    apc_cache_info_t* info;
+    apc_cache_link_t* p;
+    zval* list;
+    char *cache_type;
+    int ct_len;
+    zend_bool limited=0;
+    char md5str[33];
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
+        return;
+    }
+
+    if(ZEND_NUM_ARGS()) {
+        if(!strcasecmp(cache_type,"user")) {
+            info = apc_cache_info(apc_user_cache, limited TSRMLS_CC);
+        } else if(!strcasecmp(cache_type,"filehits")) {
+#ifdef APC_FILEHITS
+            RETVAL_ZVAL(APCG(filehits), 1, 0);
+            return;
+#else
+            RETURN_FALSE;
+#endif
+        } else {
+            info = apc_cache_info(apc_cache, limited TSRMLS_CC);
+        }
+    } else {
+        info = apc_cache_info(apc_cache, limited TSRMLS_CC);
+    }
+
+    if(!info) {
+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available.  Perhaps APC is not enabled? Check apc.enabled in your ini file");
+        RETURN_FALSE;
+    }
+
+    array_init(return_value);
+    add_assoc_long(return_value, "num_slots", info->num_slots);
+    add_assoc_long(return_value, "ttl", info->ttl);
+
+    add_assoc_double(return_value, "num_hits", (double)info->num_hits);
+    add_assoc_double(return_value, "num_misses", (double)info->num_misses);
+    add_assoc_double(return_value, "num_inserts", (double)info->num_inserts);
+    add_assoc_double(return_value, "expunges", (double)info->expunges);
+    
+    add_assoc_long(return_value, "start_time", info->start_time);
+    add_assoc_double(return_value, "mem_size", (double)info->mem_size);
+    add_assoc_long(return_value, "num_entries", info->num_entries);
+#ifdef MULTIPART_EVENT_FORMDATA
+    add_assoc_long(return_value, "file_upload_progress", 1);
+#else
+    add_assoc_long(return_value, "file_upload_progress", 0);
+#endif
+#if APC_MMAP
+    add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
+#else
+    add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
+#endif
+#if APC_SEM_LOCKS
+    add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
+#elif APC_PTHREADMUTEX_LOCKS
+    add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
+#elif APC_SPIN_LOCKS
+    add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
+#else
+    add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
+#endif
+    if(limited) {
+        apc_cache_free_info(info TSRMLS_CC);
+        return;
+    }
+
+    ALLOC_INIT_ZVAL(list);
+    array_init(list);
+
+    for (p = info->list; p != NULL; p = p->next) {
+        zval* link;
+
+        ALLOC_INIT_ZVAL(link);
+        array_init(link);
+
+        if(p->type == APC_CACHE_ENTRY_FILE) {
+            add_assoc_string(link, "filename", p->data.file.filename, 1);
+#ifdef PHP_WIN32
+			{
+				char buf[20];
+				sprintf(buf, "%I64d",  p->data.file.device);
+				add_assoc_string(link, "device", buf, 1);
+
+				sprintf(buf, "%I64d",  p->data.file.inode);
+				add_assoc_string(link, "inode", buf, 1);
+			}
+#else
+            add_assoc_long(link, "device", p->data.file.device);
+            add_assoc_long(link, "inode", p->data.file.inode);
+#endif
+
+
+            add_assoc_string(link, "type", "file", 1);
+            if(APCG(file_md5)) {
+                make_digest(md5str, p->data.file.md5);
+                add_assoc_string(link, "md5", md5str, 1);
+            }
+        } else if(p->type == APC_CACHE_ENTRY_USER) {
+            add_assoc_string(link, "info", p->data.user.info, 1);
+            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
+            add_assoc_string(link, "type", "user", 1);
+        }
+
+        add_assoc_double(link, "num_hits", (double)p->num_hits);
+        
+        add_assoc_long(link, "mtime", p->mtime);
+        add_assoc_long(link, "creation_time", p->creation_time);
+        add_assoc_long(link, "deletion_time", p->deletion_time);
+        add_assoc_long(link, "access_time", p->access_time);
+        add_assoc_long(link, "ref_count", p->ref_count);
+        add_assoc_long(link, "mem_size", p->mem_size);
+        
+
+        add_next_index_zval(list, link);
+    }
+    add_assoc_zval(return_value, "cache_list", list);
+
+    ALLOC_INIT_ZVAL(list);
+    array_init(list);
+
+    for (p = info->deleted_list; p != NULL; p = p->next) {
+        zval* link;
+
+        ALLOC_INIT_ZVAL(link);
+        array_init(link);
+
+        if(p->type == APC_CACHE_ENTRY_FILE) {
+            add_assoc_string(link, "filename", p->data.file.filename, 1);
+#ifdef PHP_WIN32
+			{
+				char buf[20];
+				sprintf(buf, "%I64d",  p->data.file.device);
+				add_assoc_string(link, "device", buf, 1);
+
+				sprintf(buf, "%I64d",  p->data.file.inode);
+				add_assoc_string(link, "inode", buf, 1);
+			}
+#else
+            add_assoc_long(link, "device", p->data.file.device);
+            add_assoc_long(link, "inode", p->data.file.inode);
+#endif
+
+            add_assoc_string(link, "type", "file", 1);
+            if(APCG(file_md5)) {
+                make_digest(md5str, p->data.file.md5);
+                add_assoc_string(link, "md5", md5str, 1);
+            }
+        } else if(p->type == APC_CACHE_ENTRY_USER) {
+            add_assoc_string(link, "info", p->data.user.info, 1);
+            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
+            add_assoc_string(link, "type", "user", 1);
+        }
+        
+        add_assoc_double(link, "num_hits", (double)p->num_hits);
+        
+        add_assoc_long(link, "mtime", p->mtime);
+        add_assoc_long(link, "creation_time", p->creation_time);
+        add_assoc_long(link, "deletion_time", p->deletion_time);
+        add_assoc_long(link, "access_time", p->access_time);
+        add_assoc_long(link, "ref_count", p->ref_count);
+        add_assoc_long(link, "mem_size", p->mem_size);
+        add_next_index_zval(list, link);
+    }
+    add_assoc_zval(return_value, "deleted_list", list);
+
+    apc_cache_free_info(info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ proto void apc_clear_cache([string cache]) */
+PHP_FUNCTION(apc_clear_cache)
+{
+    char *cache_type;
+    int ct_len = 0;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
+        return;
+    }
+
+    if(ct_len) {
+        if(!strcasecmp(cache_type, "user")) {
+            apc_cache_clear(apc_user_cache TSRMLS_CC);
+            RETURN_TRUE;
+        }
+    }
+    apc_cache_clear(apc_cache TSRMLS_CC);
+    RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array apc_sma_info([bool limited]) */
+PHP_FUNCTION(apc_sma_info)
+{
+    apc_sma_info_t* info;
+    zval* block_lists;
+    int i;
+    zend_bool limited = 0;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
+        return;
+    }
+
+    info = apc_sma_info(limited TSRMLS_CC);
+
+    if(!info) {
+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
+        RETURN_FALSE;
+    }
+
+    array_init(return_value);
+    add_assoc_long(return_value, "num_seg", info->num_seg);
+    add_assoc_double(return_value, "seg_size", (double)info->seg_size);
+    add_assoc_double(return_value, "avail_mem", (double)apc_sma_get_avail_mem());
+
+    if(limited) {
+        apc_sma_free_info(info TSRMLS_CC);
+        return;
+    }
+
+#if ALLOC_DISTRIBUTION
+    {
+        size_t *adist = apc_sma_get_alloc_distribution();
+        zval* list;
+        ALLOC_INIT_ZVAL(list);
+        array_init(list);
+        for(i=0; i<30; i++) {
+            add_next_index_long(list, adist[i]);
+        }
+        add_assoc_zval(return_value, "adist", list);
+    }
+#endif
+    ALLOC_INIT_ZVAL(block_lists);
+    array_init(block_lists);
+
+    for (i = 0; i < info->num_seg; i++) {
+        apc_sma_link_t* p;
+        zval* list;
+
+        ALLOC_INIT_ZVAL(list);
+        array_init(list);
+
+        for (p = info->list[i]; p != NULL; p = p->next) {
+            zval* link;
+
+            ALLOC_INIT_ZVAL(link);
+            array_init(link);
+
+            add_assoc_long(link, "size", p->size);
+            add_assoc_long(link, "offset", p->offset);
+            add_next_index_zval(list, link);
+        }
+        add_next_index_zval(block_lists, list);
+    }
+    add_assoc_zval(return_value, "block_lists", block_lists);
+    apc_sma_free_info(info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ */
+int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC) 
+{
+    if(!APCG(enabled)) {
+        return 0;
+    }
+
+    HANDLE_BLOCK_INTERRUPTIONS();
+    APCG(current_cache) = apc_user_cache;
+    
+    if (!_apc_cache_user_update(apc_user_cache, strkey, strkey_len + 1, updater, data TSRMLS_CC)) {
+        HANDLE_UNBLOCK_INTERRUPTIONS();
+        return 0;
+    }
+
+    APCG(current_cache) = NULL;
+    HANDLE_UNBLOCK_INTERRUPTIONS();
+
+    return 1;
+}
+/* }}} */
+    
+/* {{{ _apc_store */
+int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
+    apc_cache_entry_t *entry;
+    apc_cache_key_t key;
+    time_t t;
+    apc_context_t ctxt={0,};
+    int ret = 1;
+
+    t = apc_time();
+
+    if(!APCG(enabled)) return 0;
+
+    HANDLE_BLOCK_INTERRUPTIONS();
+
+    APCG(current_cache) = apc_user_cache;
+
+    ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
+    if (!ctxt.pool) {
+        apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+        return 0;
+    }
+    ctxt.copy = APC_COPY_IN_USER;
+    ctxt.force_update = 0;
+
+    if(!ctxt.pool) {
+        ret = 0;
+        goto nocache;
+    }
+
+    if (!apc_cache_make_user_key(&key, strkey, strkey_len, t)) {
+        goto freepool;
+    }
+
+    if (apc_cache_is_last_key(apc_user_cache, &key, 0, t TSRMLS_CC)) {
+	    goto freepool;
+    }
+
+    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len, val, &ctxt, ttl TSRMLS_CC))) {
+        goto freepool;
+    }
+
+    if (!apc_cache_user_insert(apc_user_cache, key, entry, &ctxt, t, exclusive TSRMLS_CC)) {
+freepool:
+        apc_pool_destroy(ctxt.pool TSRMLS_CC);
+        ret = 0;
+    }
+
+nocache:
+
+    APCG(current_cache) = NULL;
+
+    HANDLE_UNBLOCK_INTERRUPTIONS();
+
+    return ret;
+}
+/* }}} */
+
+/* {{{ apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
+ */
+static void apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
+{
+    zval *key = NULL;
+    zval *val = NULL;
+    long ttl = 0L;
+    HashTable *hash;
+    HashPosition hpos;
+    zval **hentry;
+    char *hkey=NULL;
+    uint hkey_len;
+    ulong hkey_idx;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &key, &val, &ttl) == FAILURE) {
+        return;
+    }
+
+    if (!key) RETURN_FALSE;
+
+    if (Z_TYPE_P(key) == IS_ARRAY) {
+        hash = Z_ARRVAL_P(key);
+        array_init(return_value);
+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
+            zend_hash_get_current_key_ex(hash, &hkey, &hkey_len, &hkey_idx, 0, &hpos);
+            if (hkey) {
+                if(!_apc_store(hkey, hkey_len, *hentry, (unsigned int)ttl, exclusive TSRMLS_CC)) {
+                    add_assoc_long_ex(return_value, hkey, hkey_len, -1);  /* -1: insertion error */
+                }
+                hkey = NULL;
+            } else {
+                add_index_long(return_value, hkey_idx, -1);  /* -1: insertion error */
+            }
+            zend_hash_move_forward_ex(hash, &hpos);
+        }
+        return;
+    } else if (Z_TYPE_P(key) == IS_STRING) {
+        if (!val) RETURN_FALSE;
+        if(_apc_store(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, val, (unsigned int)ttl, exclusive TSRMLS_CC))
+            RETURN_TRUE;
+    } else {
+        apc_warning("apc_store expects key parameter to be a string or an array of key/value pairs." TSRMLS_CC);
+    }
+
+    RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto int apc_store(mixed key, mixed var [, long ttl ])
+ */
+PHP_FUNCTION(apc_store) {
+    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto int apc_add(mixed key, mixed var [, long ttl ])
+ */
+PHP_FUNCTION(apc_add) {
+    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ inc_updater */
+
+struct _inc_update_args {
+    long step;
+    long lval;
+};
+
+static int inc_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
+
+    struct _inc_update_args *args = (struct _inc_update_args*) data;
+    
+    zval* val = entry->data.user.val;
+
+    if(Z_TYPE_P(val) == IS_LONG) {
+        Z_LVAL_P(val) += args->step;
+        args->lval = Z_LVAL_P(val);
+        return 1;
+    }
+
+    return 0;
+}
+/* }}} */
+
+/* {{{ proto long apc_inc(string key [, long step [, bool& success]])
+ */
+PHP_FUNCTION(apc_inc) {
+    char *strkey;
+    int strkey_len;
+    struct _inc_update_args args = {1L, -1};
+    zval *success = NULL;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
+        return;
+    }
+
+    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
+        if(success) ZVAL_TRUE(success);
+        RETURN_LONG(args.lval);
+    }
+    
+    if(success) ZVAL_FALSE(success);
+    
+    RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto long apc_dec(string key [, long step [, bool &success]])
+ */
+PHP_FUNCTION(apc_dec) {
+    char *strkey;
+    int strkey_len;
+    struct _inc_update_args args = {1L, -1};
+    zval *success = NULL;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
+        return;
+    }
+
+    args.step = args.step * -1;
+
+    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
+        if(success) ZVAL_TRUE(success);
+        RETURN_LONG(args.lval);
+    }
+    
+    if(success) ZVAL_FALSE(success);
+    
+    RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ cas_updater */
+static int cas_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
+    long* vals = ((long*)data);
+    long old = vals[0];
+    long new = vals[1];
+    zval* val = entry->data.user.val;
+
+    if(Z_TYPE_P(val) == IS_LONG) {
+        if(Z_LVAL_P(val) == old) {
+            Z_LVAL_P(val) = new;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+/* }}} */
+
+/* {{{ proto int apc_cas(string key, int old, int new)
+ */
+PHP_FUNCTION(apc_cas) {
+    char *strkey;
+    int strkey_len;
+    long vals[2];
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &strkey, &strkey_len, &vals[0], &vals[1]) == FAILURE) {
+        return;
+    }
+
+    if(_apc_update(strkey, strkey_len, cas_updater, &vals TSRMLS_CC)) RETURN_TRUE;
+    RETURN_FALSE;
+}
+/* }}} */
+
+void *apc_erealloc_wrapper(void *ptr, size_t size) {
+    return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+}
+
+/* {{{ proto mixed apc_fetch(mixed key[, bool &success])
+ */
+PHP_FUNCTION(apc_fetch) {
+    zval *key;
+    zval *success = NULL;
+    HashTable *hash;
+    HashPosition hpos;
+    zval **hentry;
+    zval *result;
+    zval *result_entry;
+    char *strkey;
+    int strkey_len;
+    apc_cache_entry_t* entry;
+    time_t t;
+    apc_context_t ctxt = {0,};
+
+    if(!APCG(enabled)) RETURN_FALSE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == FAILURE) {
+        return;
+    }
+
+    t = apc_time();
+
+    if (success) {
+        ZVAL_BOOL(success, 0);
+    }
+
+    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC);
+    if (!ctxt.pool) {
+        apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+    ctxt.copy = APC_COPY_OUT_USER;
+    ctxt.force_update = 0;
+
+    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
+        convert_to_string(key);
+    }
+
+    if(Z_TYPE_P(key) == IS_STRING) {
+        strkey = Z_STRVAL_P(key);
+        strkey_len = Z_STRLEN_P(key);
+        if(!strkey_len) RETURN_FALSE;
+        entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC);
+        if(entry) {
+            /* deep-copy returned shm zval to emalloc'ed return_value */
+            apc_cache_fetch_zval(return_value, entry->data.user.val, &ctxt TSRMLS_CC);
+            apc_cache_release(apc_user_cache, entry TSRMLS_CC);
+        } else {
+            goto freepool;
+        }
+    } else if(Z_TYPE_P(key) == IS_ARRAY) {
+        hash = Z_ARRVAL_P(key);
+        MAKE_STD_ZVAL(result);
+        array_init(result); 
+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
+            if(Z_TYPE_PP(hentry) != IS_STRING) {
+                apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC);
+                goto freepool;
+            }
+            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1), t TSRMLS_CC);
+            if(entry) {
+                /* deep-copy returned shm zval to emalloc'ed return_value */
+                MAKE_STD_ZVAL(result_entry);
+                apc_cache_fetch_zval(result_entry, entry->data.user.val, &ctxt TSRMLS_CC);
+                apc_cache_release(apc_user_cache, entry TSRMLS_CC);
+                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
+            } /* don't set values we didn't find */
+            zend_hash_move_forward_ex(hash, &hpos);
+        }
+        RETVAL_ZVAL(result, 0, 1);
+    } else {
+        apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC);
+freepool:
+        apc_pool_destroy(ctxt.pool TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    if (success) {
+        ZVAL_BOOL(success, 1);
+    }
+
+    apc_pool_destroy(ctxt.pool TSRMLS_CC);
+    return;
+}
+/* }}} */
+
+/* {{{ proto mixed apc_exists(mixed key)
+ */
+PHP_FUNCTION(apc_exists) {
+    zval *key;
+    HashTable *hash;
+    HashPosition hpos;
+    zval **hentry;
+    char *strkey;
+    int strkey_len;
+    apc_cache_entry_t* entry;
+    zval *result;
+    zval *result_entry;
+    time_t t;
+
+    if(!APCG(enabled)) RETURN_FALSE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
+        return;
+    }
+
+    t = apc_time();
+
+    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
+        convert_to_string(key);
+    }
+
+    if(Z_TYPE_P(key) == IS_STRING) {
+        strkey = Z_STRVAL_P(key);
+        strkey_len = Z_STRLEN_P(key);
+        if(!strkey_len) RETURN_FALSE;
+        entry = apc_cache_user_exists(apc_user_cache, strkey, strkey_len + 1, t TSRMLS_CC);
+        if(entry) {
+            RETURN_TRUE;
+        }
+    } else if(Z_TYPE_P(key) == IS_ARRAY) {
+        hash = Z_ARRVAL_P(key);
+        MAKE_STD_ZVAL(result);
+        array_init(result); 
+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
+            if(Z_TYPE_PP(hentry) != IS_STRING) {
+                apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC);
+                RETURN_FALSE;
+            }
+
+            entry = apc_cache_user_exists(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t TSRMLS_CC);
+            if(entry) {
+                MAKE_STD_ZVAL(result_entry);
+                ZVAL_BOOL(result_entry, 1);
+                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
+            } /* don't set values we didn't find */
+            zend_hash_move_forward_ex(hash, &hpos);
+        }
+        RETURN_ZVAL(result, 0, 1);
+    } else {
+        apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC);
+    }
+
+    RETURN_FALSE;
+}
+/* }}} */
+
+
+/* {{{ proto mixed apc_delete(mixed keys)
+ */
+PHP_FUNCTION(apc_delete) {
+    zval *keys;
+
+    if(!APCG(enabled)) RETURN_FALSE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
+        return;
+    }
+
+    if (Z_TYPE_P(keys) == IS_STRING) {
+        if (!Z_STRLEN_P(keys)) RETURN_FALSE;
+        if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_P(keys), (Z_STRLEN_P(keys) + 1) TSRMLS_CC)) {
+            RETURN_TRUE;
+        } else {
+            RETURN_FALSE;
+        }
+    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
+        HashTable *hash = Z_ARRVAL_P(keys);
+        HashPosition hpos;
+        zval **hentry;
+        array_init(return_value);
+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
+            if(Z_TYPE_PP(hentry) != IS_STRING) {
+                apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
+                add_next_index_zval(return_value, *hentry);
+                Z_ADDREF_PP(hentry);
+            } else if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1) TSRMLS_CC) != 1) {
+                add_next_index_zval(return_value, *hentry);
+                Z_ADDREF_PP(hentry);
+            }
+            zend_hash_move_forward_ex(hash, &hpos);
+        }
+        return;
+    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
+        if (apc_iterator_delete(keys TSRMLS_CC)) {
+            RETURN_TRUE;
+        } else {
+            RETURN_FALSE;
+        }
+    } else {
+        apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
+    }
+}
+/* }}} */
+
+/* {{{ proto mixed apc_delete_file(mixed keys)
+ *       Deletes the given files from the opcode cache.  
+ *       Accepts a string, array of strings, or APCIterator object. 
+ *       Returns True/False, or for an Array an Array of failed files.
+ */
+PHP_FUNCTION(apc_delete_file) {
+    zval *keys;
+
+    if(!APCG(enabled)) RETURN_FALSE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
+        return;
+    }
+
+    if (Z_TYPE_P(keys) == IS_STRING) {
+        if (!Z_STRLEN_P(keys)) RETURN_FALSE;
+        if(apc_cache_delete(apc_cache, Z_STRVAL_P(keys), Z_STRLEN_P(keys) + 1 TSRMLS_CC) != 1) {
+            RETURN_FALSE;
+        } else {
+            RETURN_TRUE;
+        }
+    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
+        HashTable *hash = Z_ARRVAL_P(keys);
+        HashPosition hpos;
+        zval **hentry;
+        array_init(return_value);
+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
+            if(Z_TYPE_PP(hentry) != IS_STRING) {
+                apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
+                add_next_index_zval(return_value, *hentry);
+                Z_ADDREF_PP(hentry);
+            } else if(apc_cache_delete(apc_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1 TSRMLS_CC) != 1) {
+                add_next_index_zval(return_value, *hentry);
+                Z_ADDREF_PP(hentry);
+            }
+            zend_hash_move_forward_ex(hash, &hpos);
+        }
+        return;
+    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
+        if (apc_iterator_delete(keys TSRMLS_CC)) {
+            RETURN_TRUE;
+        } else {
+            RETURN_FALSE;
+        }
+    } else {
+        apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
+    }
+}
+/* }}} */
+
+static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
+    char *const_key;
+    unsigned int const_key_len;
+    zval **entry;
+    HashPosition pos;
+
+    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
+    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
+        zend_constant c;
+        int key_type;
+        ulong num_key;
+
+        key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
+        if(key_type != HASH_KEY_IS_STRING) {
+            zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
+            continue;
+        }
+        switch(Z_TYPE_PP(entry)) {
+            case IS_LONG:
+            case IS_DOUBLE:
+            case IS_STRING:
+            case IS_BOOL:
+            case IS_RESOURCE:
+            case IS_NULL:
+                break;
+            default:
+                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
+                continue;
+        }
+        c.value = **entry;
+        zval_copy_ctor(&c.value);
+        c.flags = case_sensitive;
+        c.name = zend_strndup(const_key, const_key_len);
+        c.name_len = const_key_len;
+        c.module_number = PHP_USER_CONSTANT;
+        zend_register_constant(&c TSRMLS_CC);
+
+        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
+    }
+}
+
+/* {{{ proto mixed apc_define_constants(string key, array constants [, bool case_sensitive])
+ */
+PHP_FUNCTION(apc_define_constants) {
+    char *strkey;
+    int strkey_len;
+    zval *constants = NULL;
+    zend_bool case_sensitive = 1;
+    int argc = ZEND_NUM_ARGS();
+
+    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
+        return;
+    }
+
+    if(!strkey_len) RETURN_FALSE;
+
+    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
+    if(_apc_store(strkey, strkey_len + 1, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
+    RETURN_FALSE;
+} /* }}} */
+
+/* {{{ proto mixed apc_load_constants(string key [, bool case_sensitive])
+ */
+PHP_FUNCTION(apc_load_constants) {
+    char *strkey;
+    int strkey_len;
+    apc_cache_entry_t* entry;
+    time_t t;
+    zend_bool case_sensitive = 1;
+
+    if(!APCG(enabled)) RETURN_FALSE;
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
+        return;
+    }
+
+    if(!strkey_len) RETURN_FALSE;
+
+    t = apc_time();
+
+    entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC);
+
+    if(entry) {
+        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
+        apc_cache_release(apc_user_cache, entry TSRMLS_CC);
+        RETURN_TRUE;
+    } else {
+        RETURN_FALSE;
+    }
+}
+/* }}} */
+
+/* {{{ proto mixed apc_compile_file(mixed filenames [, bool atomic])
+ */
+PHP_FUNCTION(apc_compile_file) {
+    zval *file;
+    zend_file_handle file_handle;
+    zend_op_array *op_array;
+    char** filters = NULL;
+    zend_bool cache_by_default = 1;
+    HashTable cg_function_table, cg_class_table;
+    HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
+    apc_cache_entry_t** cache_entries;
+    apc_cache_key_t* keys;
+    zend_op_array **op_arrays;
+    time_t t;
+    zval **hentry;
+    HashPosition hpos;
+    int i=0, c=0;
+    int *rval=NULL;
+    int count=0;
+    zend_bool atomic=1;
+    apc_context_t ctxt = {0,};
+    zend_execute_data *orig_current_execute_data;
+    int atomic_fail;
+
+    if(!APCG(enabled)) RETURN_FALSE;
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &file, &atomic) == FAILURE) {
+        return;
+    }
+
+    if (Z_TYPE_P(file) != IS_ARRAY && Z_TYPE_P(file) != IS_STRING) {
+        apc_warning("apc_compile_file argument must be a string or an array of strings" TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    HANDLE_BLOCK_INTERRUPTIONS();
+    APCG(current_cache) = apc_cache;
+
+    /* reset filters and cache_by_default */
+    filters = APCG(filters);
+    APCG(filters) = NULL;
+
+    cache_by_default = APCG(cache_by_default);
+    APCG(cache_by_default) = 1;
+
+    /* Replace function/class tables to avoid namespace conflicts */
+    zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
+    cg_orig_function_table = CG(function_table);
+    CG(function_table) = &cg_function_table;
+    zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
+    cg_orig_class_table = CG(class_table);
+    CG(class_table) = &cg_class_table;
+    eg_orig_function_table = EG(function_table);
+    EG(function_table) = CG(function_table);
+    eg_orig_class_table = EG(class_table);
+    EG(class_table) = CG(class_table);
+    APCG(force_file_update) = 1;
+
+    /* Compile the file(s), loading it into the cache */
+    if (Z_TYPE_P(file) == IS_STRING) {
+        file_handle.type = ZEND_HANDLE_FILENAME;
+        file_handle.filename = Z_STRVAL_P(file);
+        file_handle.free_filename = 0;
+        file_handle.opened_path = NULL;
+
+        orig_current_execute_data = EG(current_execute_data);
+        zend_try {
+            op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
+        } zend_catch {
+            EG(current_execute_data) = orig_current_execute_data;
+            EG(in_execution) = 1;
+            CG(unclean_shutdown) = 0;
+            apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
+            op_array = NULL;
+        } zend_end_try();
+        if(op_array != NULL) {
+            /* Free up everything */
+            destroy_op_array(op_array TSRMLS_CC);
+            efree(op_array);
+            RETVAL_TRUE;
+        } else {
+            RETVAL_FALSE;
+        }
+        zend_destroy_file_handle(&file_handle TSRMLS_CC);
+
+    } else { /* IS_ARRAY */
+
+        array_init(return_value);
+
+        t = apc_time();
+
+        op_arrays = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(zend_op_array*));
+        cache_entries = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_entry_t*));
+        keys = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_key_t));
+        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
+        while(zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos) == SUCCESS) {
+            if (Z_TYPE_PP(hentry) != IS_STRING) {
+                apc_warning("apc_compile_file array values must be strings, aborting." TSRMLS_CC);
+                break;
+            }
+            file_handle.type = ZEND_HANDLE_FILENAME;
+            file_handle.filename = Z_STRVAL_PP(hentry);
+            file_handle.free_filename = 0;
+            file_handle.opened_path = NULL;
+
+            if (!apc_cache_make_file_key(&(keys[i]), file_handle.filename, PG(include_path), t TSRMLS_CC)) {
+                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1);  /* -1: compilation error */
+                apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
+                break;
+            }
+
+            if (keys[i].type == APC_CACHE_KEY_FPFILE) {
+                keys[i].data.fpfile.fullpath = estrndup(keys[i].data.fpfile.fullpath, keys[i].data.fpfile.fullpath_len);
+            } else if (keys[i].type == APC_CACHE_KEY_USER) {
+                keys[i].data.user.identifier = estrndup(keys[i].data.user.identifier, keys[i].data.user.identifier_len);
+            }
+
+            orig_current_execute_data = EG(current_execute_data);
+            zend_try {
+                if (apc_compile_cache_entry(keys[i], &file_handle, ZEND_INCLUDE, t, &op_arrays[i], &cache_entries[i] TSRMLS_CC) != SUCCESS) {
+                    op_arrays[i] = NULL;
+                    cache_entries[i] = NULL;
+                    add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2);  /* -2: input or cache insertion error */
+                    apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
+                }
+            } zend_catch {
+                EG(current_execute_data) = orig_current_execute_data;
+                EG(in_execution) = 1;
+                CG(unclean_shutdown) = 0;
+                op_arrays[i] = NULL;
+                cache_entries[i] = NULL;
+                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1);  /* -1: compilation error */
+                apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
+            } zend_end_try();
+
+            zend_destroy_file_handle(&file_handle TSRMLS_CC);
+            if(op_arrays[i] != NULL) {
+                count++;
+            }
+
+            /* clean out the function/class tables */
+            zend_hash_clean(&cg_function_table);
+            zend_hash_clean(&cg_class_table);
+
+            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
+            i++;
+        }
+
+        /* atomically update the cache if no errors or not atomic */
+        ctxt.copy = APC_COPY_IN_OPCODE;
+        ctxt.force_update = 1;
+        if (count == i || !atomic) {
+            rval = apc_cache_insert_mult(apc_cache, keys, cache_entries, &ctxt, t, i TSRMLS_CC);
+            atomic_fail = 0;
+        } else {
+            atomic_fail = 1;
+        }
+
+        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
+        for(c=0; c < i; c++) {
+            zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos);
+            if (rval && rval[c] != 1) {
+                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2);  /* -2: input or cache insertion error */
+                if (cache_entries[c]) {
+                    apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC);
+                }
+            }
+            if (op_arrays[c]) {
+                destroy_op_array(op_arrays[c] TSRMLS_CC);
+                efree(op_arrays[c]);
+            }
+            if (atomic_fail && cache_entries[c]) {
+                apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC);
+            }
+            if (keys[c].type == APC_CACHE_KEY_FPFILE) {
+                efree((void*)keys[c].data.fpfile.fullpath);
+            } else if (keys[c].type == APC_CACHE_KEY_USER) {
+                efree((void*)keys[c].data.user.identifier);
+            }
+            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
+        }
+        efree(op_arrays);
+        efree(keys);
+        efree(cache_entries);
+        if (rval) {
+            efree(rval);
+        }
+
+    }
+
+    /* Return class/function tables to previous states, destroy temp tables */
+    APCG(force_file_update) = 0;
+    CG(function_table) = cg_orig_function_table;
+    zend_hash_destroy(&cg_function_table);
+    CG(class_table) = cg_orig_class_table;
+    zend_hash_destroy(&cg_class_table);
+    EG(function_table) = eg_orig_function_table;
+    EG(class_table) = eg_orig_class_table;
+
+    /* Restore global settings */
+    APCG(filters) = filters;
+    APCG(cache_by_default) = cache_by_default;
+
+    APCG(current_cache) = NULL;
+    HANDLE_UNBLOCK_INTERRUPTIONS();
+
+}
+/* }}} */
+
+/* {{{ proto mixed apc_bin_dump([array files [, array user_vars]])
+    Returns a binary dump of the given files and user variables from the APC cache.
+    A NULL for files or user_vars signals a dump of every entry, while array() will dump nothing.
+ */
+PHP_FUNCTION(apc_bin_dump) {
+
+    zval *z_files = NULL, *z_user_vars = NULL;
+    HashTable *h_files, *h_user_vars;
+    apc_bd_t *bd;
+
+    if(!APCG(enabled)) {
+        apc_warning("APC is not enabled, apc_bin_dump not available." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &z_files, &z_user_vars) == FAILURE) {
+        return;
+    }
+
+    h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
+    h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
+    bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
+    if(bd) {
+        RETVAL_STRINGL((char*)bd, bd->size-1, 0);
+    } else {
+        apc_error("Unknown error encountered during apc_bin_dump." TSRMLS_CC);
+        RETVAL_NULL();
+    }
+
+    return;
+}
+
+/* {{{ proto mixed apc_bin_dumpfile(array files, array user_vars, string filename, [int flags [, resource context]])
+    Output a binary dump of the given files and user variables from the APC cache to the named file.
+ */
+PHP_FUNCTION(apc_bin_dumpfile) {
+
+    zval *z_files = NULL, *z_user_vars = NULL;
+    HashTable *h_files, *h_user_vars;
+    char *filename = NULL;
+    int filename_len;
+    long flags=0;
+    zval *zcontext = NULL;
+    php_stream_context *context = NULL;
+    php_stream *stream;
+    int numbytes = 0;
+    apc_bd_t *bd;
+
+    if(!APCG(enabled)) {
+        apc_warning("APC is not enabled, apc_bin_dumpfile not available." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!s|lr!", &z_files, &z_user_vars, &filename, &filename_len, &flags, &zcontext) == FAILURE) {
+        return;
+    }
+
+    if(!filename_len) {
+        apc_error("apc_bin_dumpfile filename argument must be a valid filename." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
+    h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
+    bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
+    if(!bd) {
+        apc_error("Unknown error encountered during apc_bin_dumpfile." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+
+    /* Most of the following has been taken from the file_get/put_contents functions */
+
+    context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
+    stream = php_stream_open_wrapper_ex(filename, (flags & PHP_FILE_APPEND) ? "ab" : "wb",
+                                            ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+    if (stream == NULL) {
+        efree(bd);
+        apc_error("Unable to write to file in apc_bin_dumpfile." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    if (flags & LOCK_EX && php_stream_lock(stream, LOCK_EX)) {
+        php_stream_close(stream);
+        efree(bd);
+        apc_error("Unable to get a lock on file in apc_bin_dumpfile." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    numbytes = php_stream_write(stream, (char*)bd, bd->size);
+    if(numbytes != bd->size) {
+        numbytes = -1;
+    }
+
+    php_stream_close(stream);
+    efree(bd);
+
+    if(numbytes < 0) {
+        apc_error("Only %d of %d bytes written, possibly out of free disk space" TSRMLS_CC, numbytes, bd->size);
+        RETURN_FALSE;
+    }
+
+    RETURN_LONG(numbytes);
+}
+
+/* {{{ proto mixed apc_bin_load(string data, [int flags])
+    Load the given binary dump into the APC file/user cache.
+ */
+PHP_FUNCTION(apc_bin_load) {
+
+    int data_len;
+    char *data;
+    long flags = 0;
+
+    if(!APCG(enabled)) {
+        apc_warning("APC is not enabled, apc_bin_load not available." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags) == FAILURE) {
+        return;
+    }
+
+    if(!data_len || data_len != ((apc_bd_t*)data)->size -1) {
+        apc_error("apc_bin_load string argument does not appear to be a valid APC binary dump due to size (%d vs expected %d)." TSRMLS_CC, data_len, ((apc_bd_t*)data)->size -1);
+        RETURN_FALSE;
+    }
+
+    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
+
+    RETURN_TRUE;
+}
+
+/* {{{ proto mixed apc_bin_loadfile(string filename, [resource context, [int flags]])
+    Load the given binary dump from the named file into the APC file/user cache.
+ */
+PHP_FUNCTION(apc_bin_loadfile) {
+
+    char *filename;
+    int filename_len;
+    zval *zcontext = NULL;
+    long flags;
+    php_stream_context *context = NULL;
+    php_stream *stream;
+    char *data;
+    int len;
+
+    if(!APCG(enabled)) {
+        apc_warning("APC is not enabled, apc_bin_loadfile not available." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!l", &filename, &filename_len, &zcontext, &flags) == FAILURE) {
+        return;
+    }
+
+    if(!filename_len) {
+        apc_error("apc_bin_loadfile filename argument must be a valid filename." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    context = php_stream_context_from_zval(zcontext, 0);
+    stream = php_stream_open_wrapper_ex(filename, "rb",
+            ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+    if (!stream) {
+        apc_error("Unable to read from file in apc_bin_loadfile." TSRMLS_CC);
+        RETURN_FALSE;
+    }
+
+    len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0);
+    if(len == 0) {
+        apc_warning("File passed to apc_bin_loadfile was empty: %s." TSRMLS_CC, filename);
+        RETURN_FALSE;
+    } else if(len < 0) {
+        apc_warning("Error reading file passed to apc_bin_loadfile: %s." TSRMLS_CC, filename);
+        RETURN_FALSE;
+    } else if(len != ((apc_bd_t*)data)->size) {
+        apc_warning("file passed to apc_bin_loadfile does not appear to be valid due to size (%d vs expected %d)." TSRMLS_CC, len, ((apc_bd_t*)data)->size -1);
+        RETURN_FALSE;
+    }
+    php_stream_close(stream);
+
+    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
+    efree(data);
+
+    RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ arginfo */
+#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
+# define PHP_APC_ARGINFO
+#else
+# define PHP_APC_ARGINFO static
+#endif
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_store, 0, 0, 2)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(0, var)
+    ZEND_ARG_INFO(0, ttl)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_clear_cache, 0, 0, 0)
+    ZEND_ARG_INFO(0, info)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_sma_info, 0, 0, 0)
+    ZEND_ARG_INFO(0, limited)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_cache_info, 0, 0, 0)
+    ZEND_ARG_INFO(0, type)
+    ZEND_ARG_INFO(0, limited)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_define_constants, 0, 0, 2)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(0, constants)
+    ZEND_ARG_INFO(0, case_sensitive)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO(arginfo_apc_delete_file, 0)
+	ZEND_ARG_INFO(0, keys)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO(arginfo_apc_delete, 0)
+	ZEND_ARG_INFO(0, keys)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_fetch, 0, 0, 1)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(1, success)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_inc, 0, 0, 1)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(0, step)
+    ZEND_ARG_INFO(1, success)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO(arginfo_apc_cas, 0)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(0, old)
+    ZEND_ARG_INFO(0, new)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_load_constants, 0, 0, 1)
+    ZEND_ARG_INFO(0, key)
+    ZEND_ARG_INFO(0, case_sensitive)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_compile_file, 0, 0, 1)
+    ZEND_ARG_INFO(0, filenames)
+    ZEND_ARG_INFO(0, atomic)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dump, 0, 0, 0)
+    ZEND_ARG_INFO(0, files)
+    ZEND_ARG_INFO(0, user_vars)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dumpfile, 0, 0, 3)
+    ZEND_ARG_INFO(0, files)
+    ZEND_ARG_INFO(0, user_vars)
+    ZEND_ARG_INFO(0, filename)
+    ZEND_ARG_INFO(0, flags)
+    ZEND_ARG_INFO(0, context)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_load, 0, 0, 1)
+    ZEND_ARG_INFO(0, data)
+    ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_loadfile, 0, 0, 1)
+    ZEND_ARG_INFO(0, filename)
+    ZEND_ARG_INFO(0, context)
+    ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+PHP_APC_ARGINFO
+ZEND_BEGIN_ARG_INFO(arginfo_apc_exists, 0)
+	ZEND_ARG_INFO(0, keys)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ apc_functions[] */
+zend_function_entry apc_functions[] = {
+    PHP_FE(apc_cache_info,          arginfo_apc_cache_info)
+    PHP_FE(apc_clear_cache,         arginfo_apc_clear_cache)
+    PHP_FE(apc_sma_info,            arginfo_apc_sma_info)
+    PHP_FE(apc_store,               arginfo_apc_store)
+    PHP_FE(apc_fetch,               arginfo_apc_fetch)
+    PHP_FE(apc_delete,              arginfo_apc_delete)
+    PHP_FE(apc_delete_file,         arginfo_apc_delete_file)
+    PHP_FE(apc_define_constants,    arginfo_apc_define_constants)
+    PHP_FE(apc_load_constants,      arginfo_apc_load_constants)
+    PHP_FE(apc_compile_file,        arginfo_apc_compile_file)
+    PHP_FE(apc_add,                 arginfo_apc_store)
+    PHP_FE(apc_inc,                 arginfo_apc_inc)
+    PHP_FE(apc_dec,                 arginfo_apc_inc)
+    PHP_FE(apc_cas,                 arginfo_apc_cas)
+    PHP_FE(apc_bin_dump,            arginfo_apc_bin_dump)
+    PHP_FE(apc_bin_load,            arginfo_apc_bin_load)
+    PHP_FE(apc_bin_dumpfile,        arginfo_apc_bin_dumpfile)
+    PHP_FE(apc_bin_loadfile,        arginfo_apc_bin_loadfile)
+    PHP_FE(apc_exists,              arginfo_apc_exists)
+    {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ module definition structure */
+
+zend_module_entry apc_module_entry = {
+    STANDARD_MODULE_HEADER,
+    "apc",
+    apc_functions,
+    PHP_MINIT(apc),
+    PHP_MSHUTDOWN(apc),
+    PHP_RINIT(apc),
+    PHP_RSHUTDOWN(apc),
+    PHP_MINFO(apc),
+    PHP_APC_VERSION,
+    STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_APC
+ZEND_GET_MODULE(apc)
+#endif
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/php_apc.h
@@ -0,0 +1,54 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2010 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>              |
+  |          George Schlossnagle <george@omniti.com>                     |
+  |          Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   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: php_apc.h 305846 2010-11-30 09:36:57Z gopalv $ */
+
+#ifndef PHP_APC_H
+#define PHP_APC_H
+
+#include "apc_php.h"
+#include "apc_globals.h"
+
+#define PHP_APC_VERSION "3.1.6"
+
+extern zend_module_entry apc_module_entry;
+#define apc_module_ptr &apc_module_entry
+
+#define phpext_apc_ptr apc_module_ptr
+
+#endif /* PHP_APC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */
--- /dev/null
+++ b/ext/apc/TECHNOTES.txt
@@ -0,0 +1,361 @@
+APC Quick-Start Braindump
+
+This is a rapidly written braindump of how APC currently works in the
+form of a quick-start guide to start hacking on APC.
+
+1. Install and use APC a bit so you know what it does from the end-user's
+   perspective.  
+   user-space functions are all explained here: 
+
+2. Grab the current APC code from CVS:
+    
+    cvs -d:pserver:cvsread@cvs.php.net:/repository login
+    Password: phpfi
+    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
+
+   apc/php_apc.c has most of the code for the user-visible stuff.  It is
+   also a regular PHP extension in the sense that there are MINIT, MINFO, 
+   MSHUTDOWN, RSHUTDOWN, etc. functions.  
+
+3. Build it.
+
+   cd pecl/apc
+   phpize
+   ./configure --enable-apc --enable-mmap
+   make
+   cp modules/apc.so /usr/local/lib/php
+   apachectl restart
+
+4. Debugging Hints
+
+     apachectl stop
+     gdb /usr/bin/httpd
+     break ??
+     run -X
+
+   Grab the .gdbinit from the PHP source tree and have a look at the macros.
+
+5. Look through apc/apc_sma.c
+   It is a pretty standard memory allocator.
+
+   apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
+   caller just like malloc, realloc, strdup and free
+
+   On server startup the MINIT hook in php_apc.c calls apc_module_init() in
+   apc_main.c which in turn calls apc_sma_init().  apc_sma_init calls into
+   apc_mmap.c to mmap the specified sized segment (I tend to just use a single
+   segment).  apc_mmap.c should be self-explanatory.  It mmaps a temp file and
+   then unlinks that file right after the mmap to provide automatic shared memory
+   cleanup in case the process dies.
+
+   Once the region has been initialized we stick a header_t at the beginning
+   of the region.  It contains the total size in header->segsize and the number 
+   of bytes available in header->avail.  
+
+   After the header comes a bit of a hack.  A zero-sized block is inserted just
+   to make things easier later on.  And then a huge block that is basically
+   the size of the entire segment minus the two (for the 0-sized block, and this one)
+   block headers.
+
+   The code for this is:
+
+     header = (header_t*) shmaddr;
+     header->segsize = sma_segsize;
+     header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
+     memset(&header->lock,0,sizeof(header->lock));
+     sma_lock = &header->lock;
+     block = BLOCKAT(sizeof(header_t));
+     block->size = 0;
+     block->next = sizeof(header_t) + sizeof(block_t);
+     block = BLOCKAT(block->next);
+     block->size = header->avail;
+     block->next = 0;
+
+   So the shared memory looks like this:
+
+     +--------+-------+---------------------------------+
+     | header | block |             block               |
+     +--------+-------+---------------------------------+
+
+   sma_shmaddrs[0] gives you the address of header
+
+   The blocks are just a simple offset-based linked list (so no pointers):
+
+     typedef struct block_t block_t;
+     struct block_t {
+         size_t size;       /* size of this block */
+         size_t next;       /* offset in segment of next free block */
+         size_t canary;     /* canary to check for memory overwrites */
+#ifdef __APC_SMA_DEBUG__
+         int id;         /* identifier for the memory block */
+#endif
+     };
+
+   The BLOCKAT macro turns an offset into an actual address for you:
+
+     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
+
+   where shmaddr = sma_shaddrs[0]
+
+   And the OFFSET macro goes the other way:
+
+     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
+
+   Allocating a block with a call to apc_sma_allocate() walks through the
+   linked list of blocks until it finds one that is >= to the requested size.
+   The first call to apc_sma_allocate() will hit the second block.  We then
+   chop up that block so it looks like this:
+
+     +--------+-------+-------+-------------------------+
+     | header | block | block |         block           |
+     +--------+-------+-------+-------------------------+
+
+   Then we unlink that block from the linked list so it won't show up
+   as an available block on the next allocate.  So we actually have:
+
+     +--------+-------+       +-------------------------+
+     | header | block |------>|         block           |
+     +--------+-------+       +-------------------------+
+
+   And header->avail along with block->size of the remaining large
+   block are updated accordingly.  The arrow there representing the
+   link which now points to a block with an offset further along in
+   the segment.
+
+   When the block is freed using apc_sma_deallocate() the steps are
+   basically just reversed.  The block is put back and then the deallocate
+   code looks at the block before and after to see if the block immediately
+   before and after are free and if so the blocks are combined.  So you never
+   have 2 free blocks next to each other, apart from at the front with that
+   0-sized dummy block.  This mostly prevents fragmentation.  I have been
+   toying with the idea of always allocating block at 2^n boundaries to make
+   it more likely that they will be re-used to cut down on fragmentation further.
+   That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
+  
+   Of course, anytime we fiddle with our shared memory segment we lock using
+   the locking macros, LOCK() and UNLOCK().
+
+   That should mostly take care of the low-level shared memory handling.
+
+6. Next up is apc_main.c and apc_cache.c which implement the meat of the
+   cache logic.
+
+   The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
+   and apc_cache.c for actual cache manipulation.  
+  
+   After the shared memory segment is created and the caches are initialized,
+   apc_module_init() installs the my_compile_file() function overriding Zend's
+   version.  I'll talk about my_compile_file() and the rest of apc_compile.c
+   in the next section.  For now I will stick with apc_main.c and apc_cache.c
+   and talk about the actual caches.  A cache consists of a block of shared
+   memory returned by apc_sma_allocate() via apc_sma_malloc().  You will 
+   notice references to apc_emalloc().  apc_emalloc() is just a thin wrapper
+   around PHP's own emalloc() function which allocates per-process memory from
+   PHP's pool-based memory allocator.  Don't confuse apc_emalloc() and 
+   apc_sma_malloc() as the first is per-process and the second is shared memory.
+
+   The cache is stored in/described by this struct allocated locally using
+   emalloc():
+
+     struct apc_cache_t {
+         void* shmaddr;              /* process (local) address of shared cache */
+         header_t* header;           /* cache header (stored in SHM) */
+         slot_t** slots;             /* array of cache slots (stored in SHM) */
+         int num_slots;              /* number of slots in cache */
+         int gc_ttl;                 /* maximum time on GC list for a slot */
+         int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
+     };
+
+   Whenever you see functions that take a 'cache' argument, this is what they
+   take.  And apc_cache_create() returns a pointer to this populated struct.
+
+   At the beginning of the cache we have a header.  Remember, we are down a level now
+   from the sma stuff.  The sma stuff is the low-level shared-memory allocator which
+   has its own header which is completely separate and invisible to apc_cache.c.  
+   As far as apc_cache.c is concerned the block of memory it is working with could 
+   have come from a call to malloc().
+
+   The header looks like this:
+
+     typedef struct header_t header_t;
+     struct header_t {
+         int num_hits;               /* total successful hits in cache */
+         int num_misses;             /* total unsuccessful hits in cache */
+         slot_t* deleted_list;       /* linked list of to-be-deleted slots */
+     };
+
+   Since this is at the start of the shared memory segment, these values are accessible
+   across all the yapache processes and hence access to them has to be locked.
+
+   After the header we have an array of slots.  The number of slots is user-defined
+   through the apc.num_slots ini hint.  Each slot is described by:
+
+     typedef struct slot_t slot_t;
+     struct slot_t {
+         apc_cache_key_t key;        /* slot key */
+         apc_cache_entry_t* value;   /* slot value */
+         slot_t* next;               /* next slot in linked list */
+         int num_hits;               /* number of hits to this bucket */
+	 time_t creation_time;       /* time slot was initialized */
+	 time_t deletion_time;       /* time slot was removed from cache */
+	 time_t access_time;         /* time slot was last accessed */
+     };
+
+   The slot_t *next there is a linked list to other slots that happened to hash to the
+   same array position.
+
+   apc_cache_insert() shows what happens on a new cache insert.
+
+     slot = &cache->slots[hash(key) % cache->num_slots];
+
+   cache->slots is our array of slots in the segment.  hash() is simply:
+
+     static unsigned int hash(apc_cache_key_t key)
+     {
+         return key.data.file.device + key.data.file.inode;
+     }
+
+   That is, we use the file's device and inode to uniquely identify it.  Initially
+   we had used the file's full path, but getting that requires a realpath() call which
+   is amazingly expensive since it has to stat each component of the path to resolve
+   symlinks and get rid of relative path components.  By using the device+inode we
+   can uniquely identify a file with a single stat.
+
+   So, on an insert we find the array position in the slots array by hashing the device+inode.
+   If there are currently no other slots there, we just create the slot and stick it into
+   the array:
+
+     *slot = make_slot(key, value, *slot, t)
+
+   If there are other slots already at this position we walk the link list to get to
+   the end.  Here is the loop:
+
+     while (*slot) {
+         if (key_equals((*slot)->key.data.file, key.data.file)) {
+	     /* If existing slot for the same device+inode is different, remove it and insert the new version */
+	     if ((*slot)->key.mtime != key.mtime) {
+	         remove_slot(cache, slot);
+	         break;
+	     }
+	     UNLOCK(cache);
+	     return 0;
+	 } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
+             remove_slot(cache, slot);
+             continue;
+         }
+         slot = &(*slot)->next;
+     }
+
+   That first key_equals() check sees if we have an exact match meaning the file
+   is already in the cache.  Since we try to find the file in the cache before doing
+   an insert, this will generally only happen if another process managed to beat us
+   to inserting it.  If we have a newer version of the file at this point we remove
+   it an insert the new version.  If our version is not newer we just return without
+   doing anything.
+
+   While walking the linked list we also check to see if the cache has a TTL defined.
+   If while walking the linked list we see a slot that has expired, we remove it
+   since we are right there looking at it.  This is the only place we remove stale
+   entries unless the shared memory segment fills up and we force a full expunge via
+   apc_cache_expunge().  apc_cache_expunge() walks the entire slots array and walks
+   down every linked list removing stale slots to free up room.  This is obviously
+   slow and thus only happens when we have run out of room.
+
+   apc_cache_find() simply hashes and returns the entry if it is there.  If it is there
+   but older than the mtime in the entry we are looking for, we delete the one that is
+   there and return indicating we didn't find it.
+
+   Next we need to understand what an actual cache entry looks like.  Have a look at
+   apc_cache.h for the structs.  I sort of glossed over the key part earlier saying
+   that we just used the device+inode to find a hash slot.  It is actually a bit more
+   complex than that because we have two kinds of caches.  We have the standard file
+   cache containing opcode arrays, but we also have a user-controlled cache that the
+   user can insert whatever they want into via apc_store().  For the user cache we
+   obviously don't have a device+inode.  The actual identifier is provided by the user
+   as a char *.  So the key is actually a union that looks like this:
+
+     typedef union _apc_cache_key_data_t {
+         struct {
+             int device;             /* the filesystem device */
+             int inode;              /* the filesystem inode */
+         } file;
+         struct {
+             char *identifier;
+         } user;
+     } apc_cache_key_data_t;
+
+     struct apc_cache_key_t {
+         apc_cache_key_data_t data;
+         int mtime;                  /* the mtime of this cached entry */
+     };   
+
+   And we have two sets of functions to do inserts and finds.  apc_cache_user_find() 
+   and apc_cache_user_insert() operate on the user cache.
+
+   Ok, on to the actual cache entry.  Again, because we have two kinds of caches, we
+   also have the corresponding two kinds of cache entries described by this union:
+
+     typedef union _apc_cache_entry_value_t {
+         struct {
+             char *filename;             /* absolute path to source file */
+             zend_op_array* op_array;    /* op_array allocated in shared memory */
+             apc_function_t* functions;  /* array of apc_function_t's */
+             apc_class_t* classes;       /* array of apc_class_t's */
+         } file;
+         struct {
+             char *info;
+             zval *val;
+             unsigned int ttl;
+         } user;
+     } apc_cache_entry_value_t;
+
+   And then the actual cache entry:
+
+     struct apc_cache_entry_t {
+         apc_cache_entry_value_t data;
+         unsigned char type;
+         int ref_count;
+     };
+
+   The user entry is pretty simple and not all that important for now.  I will
+   concentrate on the file entries since that is what holds the actual compiled
+   opcode arrays along with the functions and classes required by the executor.
+
+   apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
+   The main thing to understand here is that we need more than just the opcode
+   array, we also need the functions and classes created by the compiler when it
+   created the opcode array.  As far as the executor is concerned, it doesn't know
+   that it isn't operating in normal mode being called right after the parse/compile
+   phase, so we need to recreate everything so it looks exactly like it would at
+   that point. 
+
+7. my_compile_file() and apc_compile.c
+
+   my_compile_file() in apc_main.c controls where we get the opcodes from.  If
+   the user-specified filters exclude the file from being cached, then we just
+   call the original compile function and return.  Otherwise we fetch the request
+   time from Apache to avoid an extra syscall, create the key so we can look up
+   the file in the cache.  If we find it we stick it on a local stack which we
+   use at cleanup time to make sure we return everything back to normal after a 
+   request and call cached_compile() which installs the functions and classes
+   associated with the op_array in this entry and then copy the op_array down
+   into our memory space for execution.
+
+   If we didn't find the file in the cache, we need to compile it and insert it.
+   To compile it we simply call the original compile function:
+
+      op_array = old_compile_file(h, type TSRMLS_CC);
+
+   To do the insert we need to copy the functions, classes and the opcode array
+   the compile phase created into shared memory.  This all happens in apc_compile.c
+   in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
+   functions.  Then we make the file entry and do the insert.  Both of these
+   operations were described in the previous section.  
+
+8. The Optimizer
+   
+   The optimizer has been deprecated.
+
+If you made it to the end of this, you should have a pretty good idea of where things are in
+the code.  I skimmed over a lot of things, so plan on spending some time reading through the code.
+
--- /dev/null
+++ b/ext/apc/tests/apc_001.phpt
@@ -0,0 +1,32 @@
+--TEST--
+APC: apc_store/fetch with strings
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$foo = 'hello world';
+var_dump($foo);
+apc_store('foo',$foo);
+$bar = apc_fetch('foo');
+var_dump($bar);
+$bar = 'nice';
+var_dump($bar);
+
+apc_store('foo\x00bar', $foo);
+$bar = apc_fetch('foo\x00bar');
+var_dump($bar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(11) "hello world"
+string(11) "hello world"
+string(4) "nice"
+string(11) "hello world"
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_002.phpt
@@ -0,0 +1,34 @@
+--TEST--
+APC: apc_store/fetch with objects
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+class foo { }
+$foo = new foo;
+var_dump($foo);
+apc_store('foo',$foo);
+unset($foo);
+$bar = apc_fetch('foo');
+var_dump($bar);
+$bar->a = true;
+var_dump($bar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(foo)#%d (0) {
+}
+object(foo)#%d (0) {
+}
+object(foo)#%d (1) {
+  ["a"]=>
+  bool(true)
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_003b.phpt
@@ -0,0 +1,117 @@
+--TEST--
+APC: apc_store/fetch with objects (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+class foo { }
+$foo = new foo;
+var_dump($foo);
+apc_store('foo',$foo);
+unset($foo);
+$bar = apc_fetch('foo');
+var_dump($bar);
+$bar->a = true;
+var_dump($bar);
+
+class bar extends foo
+{
+	public    $pub = 'bar';
+	protected $pro = 'bar';
+	private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
+	
+	function __construct()
+	{
+		$this->bar = true;
+	}
+	
+	function change()
+	{
+		$this->pri = 'mod';
+	}
+}
+
+class baz extends bar
+{
+	private $pri = 'baz';
+
+	function __construct()
+	{
+		parent::__construct();
+		$this->baz = true;
+	}
+}
+
+$baz = new baz;
+var_dump($baz);
+$baz->change();
+var_dump($baz);
+apc_store('baz', $baz);
+unset($baz);
+var_dump(apc_fetch('baz'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(foo)#%d (0) {
+}
+object(foo)#%d (0) {
+}
+object(foo)#%d (1) {
+  ["a"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri":"baz":private]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro":protected]=>
+  string(3) "bar"
+  ["pri":"bar":private]=>
+  string(3) "bar"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri":"baz":private]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro":protected]=>
+  string(3) "bar"
+  ["pri":"bar":private]=>
+  string(3) "mod"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri":"baz":private]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro":protected]=>
+  string(3) "bar"
+  ["pri":"bar":private]=>
+  string(3) "mod"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_003.phpt
@@ -0,0 +1,117 @@
+--TEST--
+APC: apc_store/fetch with objects (php pre-5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') >= 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+class foo { }
+$foo = new foo;
+var_dump($foo);
+apc_store('foo',$foo);
+unset($foo);
+$bar = apc_fetch('foo');
+var_dump($bar);
+$bar->a = true;
+var_dump($bar);
+
+class bar extends foo
+{
+	public    $pub = 'bar';
+	protected $pro = 'bar';
+	private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
+	
+	function __construct()
+	{
+		$this->bar = true;
+	}
+	
+	function change()
+	{
+		$this->pri = 'mod';
+	}
+}
+
+class baz extends bar
+{
+	private $pri = 'baz';
+
+	function __construct()
+	{
+		parent::__construct();
+		$this->baz = true;
+	}
+}
+
+$baz = new baz;
+var_dump($baz);
+$baz->change();
+var_dump($baz);
+apc_store('baz', $baz);
+unset($baz);
+var_dump(apc_fetch('baz'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(foo)#%d (0) {
+}
+object(foo)#%d (0) {
+}
+object(foo)#%d (1) {
+  ["a"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri:private"]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro:protected"]=>
+  string(3) "bar"
+  ["pri:private"]=>
+  string(3) "bar"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri:private"]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro:protected"]=>
+  string(3) "bar"
+  ["pri:private"]=>
+  string(3) "mod"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+object(baz)#%d (6) {
+  ["pri:private"]=>
+  string(3) "baz"
+  ["pub"]=>
+  string(3) "bar"
+  ["pro:protected"]=>
+  string(3) "bar"
+  ["pri:private"]=>
+  string(3) "mod"
+  ["bar"]=>
+  bool(true)
+  ["baz"]=>
+  bool(true)
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_004.phpt
@@ -0,0 +1,38 @@
+--TEST--
+APC: apc_store/fetch with bools 
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$foo = false;
+var_dump($foo);     /* false */
+apc_store('foo',$foo);
+//$success = "some string";
+
+$bar = apc_fetch('foo', $success);
+var_dump($foo);     /* false */
+var_dump($bar);     /* false */
+var_dump($success); /* true  */
+
+$bar = apc_fetch('not foo', $success);
+var_dump($foo);     /* false */
+var_dump($bar);     /* false */
+var_dump($success); /* false */
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_005.phpt
@@ -0,0 +1,50 @@
+--TEST--
+APC: apc_store/fetch with arrays of objects 
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$foo = array(new stdclass(), new stdclass());
+
+var_dump($foo);
+
+apc_store('foo',$foo);
+
+$bar = apc_fetch('foo');
+var_dump($foo);
+var_dump($bar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(2) {
+  [0]=>
+  object(stdClass)#1 (0) {
+  }
+  [1]=>
+  object(stdClass)#2 (0) {
+  }
+}
+array(2) {
+  [0]=>
+  object(stdClass)#1 (0) {
+  }
+  [1]=>
+  object(stdClass)#2 (0) {
+  }
+}
+array(2) {
+  [0]=>
+  object(stdClass)#3 (0) {
+  }
+  [1]=>
+  object(stdClass)#4 (0) {
+  }
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_006.phpt
@@ -0,0 +1,72 @@
+--TEST--
+APC: apc_store/fetch reference test
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+report_memleaks=0
+--FILE--
+<?php
+
+$a = 'a';
+$b = array($a);
+$c = array('c');
+$b[] = &$c;
+$b[] = &$c;
+$d = 'd';
+$b[] = &$d;
+$b[] = &$d;
+$b[] = &$d;
+$e = 'e';
+$b[] = $e;
+$b[] = $e;
+$f = array('f');
+$f[] = &$f;
+$b[] = &$f;
+apc_store('test', $b);
+$x = apc_fetch('test');
+debug_zval_dump($x);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(9) refcount(2){
+  [0]=>
+  string(1) "a" refcount(1)
+  [1]=>
+  &array(1) refcount(2){
+    [0]=>
+    string(1) "c" refcount(1)
+  }
+  [2]=>
+  &array(1) refcount(2){
+    [0]=>
+    string(1) "c" refcount(1)
+  }
+  [3]=>
+  &string(1) "d" refcount(3)
+  [4]=>
+  &string(1) "d" refcount(3)
+  [5]=>
+  &string(1) "d" refcount(3)
+  [6]=>
+  string(1) "e" refcount(2)
+  [7]=>
+  string(1) "e" refcount(2)
+  [8]=>
+  &array(2) refcount(2){
+    [0]=>
+    string(1) "f" refcount(1)
+    [1]=>
+    &array(2) refcount(2){
+      [0]=>
+      string(1) "f" refcount(1)
+      [1]=>
+      *RECURSION*
+    }
+  }
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_007.phpt
@@ -0,0 +1,46 @@
+--TEST--
+APC: apc_inc/apc_dec test
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+apc_store('foobar',2);
+echo "\$foobar = 2 \n";
+echo "\$foobar += 1 = ".apc_inc('foobar')."\n";
+echo "\$foobar += 10 = ".apc_inc('foobar', 10)."\n";
+
+echo "\$foobar -= 1 = ".apc_dec('foobar')."\n";
+echo "\$foobar -= 10 = ".apc_dec('foobar',10)."\n";
+
+echo "\$f__bar += 1 = ".(apc_inc('f__bar')?"ok":"fail")."\n";
+
+apc_store('perfection', "xyz");
+echo "\$perfection -= 1 = ".(apc_inc('perfection')?"ok":"epic fail")."\n";
+
+$success = false;
+
+echo "\$foobar += 1 = ".apc_inc('foobar', 1, $success)."\n";
+echo "pass by ref success ". $success . "\n";
+echo "\$foobar -= 1 = ".apc_dec('foobar', 1, $success)."\n";
+echo "pass by ref success ". $success . "\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+$foobar = 2 
+$foobar += 1 = 3
+$foobar += 10 = 13
+$foobar -= 1 = 12
+$foobar -= 10 = 2
+$f__bar += 1 = fail
+$perfection -= 1 = epic fail
+$foobar += 1 = 3
+pass by ref success 1
+$foobar -= 1 = 2
+pass by ref success 1
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_008.phpt
@@ -0,0 +1,34 @@
+--TEST--
+APC: apc_cas test
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+apc_store('foobar',2);
+echo "\$foobar = 2\n";
+echo "\$foobar == 1 ? 2 : 1 = ".(apc_cas('foobar', 1, 2)?"ok":"fail")."\n";
+echo "\$foobar == 2 ? 1 : 2 = ".(apc_cas('foobar', 2, 1)?"ok":"fail")."\n";
+echo "\$foobar = ".apc_fetch("foobar")."\n";
+
+echo "\$f__bar == 1 ? 2 : 1 = ".(apc_cas('f__bar', 1, 2)?"ok":"fail")."\n";
+
+apc_store('perfection', "xyz");
+echo "\$perfection == 2 ? 1 : 2 = ".(apc_cas('perfection', 2, 1)?"ok":"epic fail")."\n";
+
+echo "\$foobar = ".apc_fetch("foobar")."\n";
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+$foobar = 2
+$foobar == 1 ? 2 : 1 = fail
+$foobar == 2 ? 1 : 2 = ok
+$foobar = 1
+$f__bar == 1 ? 2 : 1 = fail
+$perfection == 2 ? 1 : 2 = epic fail
+$foobar = 1
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_009.phpt
@@ -0,0 +1,97 @@
+--TEST--
+APC: apc_delete_file test
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+apc.stat=On
+report_memleaks=0
+--FILE--
+<?php
+
+$files = array( 'apc_009.php',
+                'apc_009-1.php',
+                'apc_009-2.php',
+                'nofile.php',
+              );
+
+file_put_contents(dirname(__FILE__).'/apc_009-1.php', '<?php echo "test file";');
+file_put_contents(dirname(__FILE__).'/apc_009-2.php', '<?php syntaxerrorhere!');
+
+apc_compile_file($files[0]);
+check_file($files[0]);
+apc_delete_file($files[0]);
+check_file($files[0]);
+
+apc_compile_file($files[0]);
+apc_delete_file(array($files[0]));
+check_file($files[0]);
+
+apc_compile_file($files[0]);
+$it = new APCIterator('file');
+apc_delete_file($it);
+check_file($files[0]);
+
+var_dump(apc_compile_file(array($files[0], $files[1])));
+check_file(array($files[0], $files[1]));
+
+var_dump(apc_compile_file($files));
+check_file($files);
+
+function check_file($files) {
+
+  if (!is_array($files)) {
+    $files = array($files);
+  }
+
+  $info = apc_cache_info('file');
+
+  foreach ($files as $file) {
+    $match = 0;
+    foreach($info['cache_list'] as $cached_file) {
+      if (stristr($cached_file['filename'], $file)) $match = 1;
+    }
+    if ($match) {
+      echo "$file Found File\n";
+    } else {
+      echo "$file Not Found\n";
+    }
+  }
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+unlink('apc_009-1.php');
+unlink('apc_009-2.php');
+?>
+--EXPECTF--
+apc_009.php Found File
+apc_009.php Not Found
+apc_009.php Not Found
+apc_009.php Not Found
+array(0) {
+}
+apc_009.php Found File
+apc_009-1.php Found File
+
+Parse error: syntax error, unexpected '!' in %s/apc_009-2.php on line 1
+
+Warning: apc_compile_file(): Error compiling apc_009-2.php in apc_compile_file. in %s/apc_009.php on line 29
+
+Warning: apc_compile_file(): Error compiling nofile.php in apc_compile_file. in %s/apc_009.php on line 29
+array(2) {
+  ["apc_009-2.php"]=>
+  int(-1)
+  ["nofile.php"]=>
+  int(-1)
+}
+apc_009.php Found File
+apc_009-1.php Found File
+apc_009-2.php Not Found
+nofile.php Not Found
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_010.phpt
@@ -0,0 +1,83 @@
+--TEST--
+APC: apc_store/fetch/add with array of key/value pairs.
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$entries = array();
+$entries['key1'] = 'value1';
+$entries['key2'] = 'value2';
+$entries['key3'] = array('value3a','value3b');
+$entries['key4'] = 4;
+
+var_dump(apc_store($entries));
+$cached_values = apc_fetch(array_keys($entries));
+var_dump($cached_values);
+
+apc_delete('key2');
+apc_delete('key4');
+$cached_values = apc_fetch(array_keys($entries));
+var_dump($cached_values);
+var_dump(apc_add($entries));
+$cached_values = apc_fetch(array_keys($entries));
+var_dump($cached_values);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(0) {
+}
+array(4) {
+  ["key1"]=>
+  string(6) "value1"
+  ["key2"]=>
+  string(6) "value2"
+  ["key3"]=>
+  array(2) {
+    [0]=>
+    string(7) "value3a"
+    [1]=>
+    string(7) "value3b"
+  }
+  ["key4"]=>
+  int(4)
+}
+array(2) {
+  ["key1"]=>
+  string(6) "value1"
+  ["key3"]=>
+  array(2) {
+    [0]=>
+    string(7) "value3a"
+    [1]=>
+    string(7) "value3b"
+  }
+}
+array(2) {
+  ["key1"]=>
+  int(-1)
+  ["key3"]=>
+  int(-1)
+}
+array(4) {
+  ["key1"]=>
+  string(6) "value1"
+  ["key2"]=>
+  string(6) "value2"
+  ["key3"]=>
+  array(2) {
+    [0]=>
+    string(7) "value3a"
+    [1]=>
+    string(7) "value3b"
+  }
+  ["key4"]=>
+  int(4)
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc53_001.phpt
@@ -0,0 +1,33 @@
+--TEST--
+APC: classes with namespaces (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
+
+$a = new Foo\Bar\Baz();
+var_dump($a);
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(Foo\Bar\Baz)#1 (3) {
+  ["i"]=>
+  int(1)
+  ["f":protected]=>
+  float(3.14)
+  ["s":"Foo\Bar\Baz":private]=>
+  string(11) "hello world"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc53_002.phpt
@@ -0,0 +1,47 @@
+--TEST--
+APC: global spaces (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
+
+$a = new Foo\Bar\Baz();
+$a->foo();
+var_dump(Foo\Bar\sort());
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(4) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  int(4)
+}
+array(4) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  int(4)
+}
+string(8) "IT WORKS"
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc53_003.phpt
@@ -0,0 +1,31 @@
+--TEST--
+APC: anonymous functions (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$greet = function($name)
+{
+    printf("Hello %s\r\n", $name);
+};
+
+$greet('World');
+$greet('PHP');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Hello World
+Hello PHP
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc53_004.phpt
@@ -0,0 +1,33 @@
+--TEST--
+APC: closures (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+function multiplier($n) {
+	return function($i) use ($n) {
+		return $n * $i;
+	};
+}
+
+$doubler = multiplier(2);
+$tripler = multiplier(3);
+
+echo "double of 9 is ".$doubler(9)."\n";
+echo "triple of 4 is ".$tripler(4)."\n";
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+double of 9 is 18
+triple of 4 is 12
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc53_005.phpt
@@ -0,0 +1,35 @@
+--TEST--
+APC: goto (php 5.3)
+--SKIPIF--
+<?php
+    require_once(dirname(__FILE__) . '/skipif.inc'); 
+    if(version_compare(zend_version(), '2.3.0') < 0) {
+		echo "skip\n";
+	}
+?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$i = 0;
+a: 
+$i++;
+if($i % 3 == 0) goto b;
+echo "$i\n";
+b:
+if($i < 10) goto a;
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+1
+2
+4
+5
+7
+8
+10
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_bin_001.phpt
@@ -0,0 +1,24 @@
+--TEST--
+APC: bindump user cache
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+--FILE--
+<?php
+apc_clear_cache('file');
+apc_store('testkey','testvalue');
+apc_bin_dump();
+$dump = apc_bin_dump(array(), NULL);
+apc_clear_cache('user');
+var_dump(apc_fetch('testkey'));
+apc_bin_load($dump, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
+var_dump(apc_fetch('testkey'));
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+bool(false)
+string(9) "testvalue"
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/apc_bin_002-1.inc
@@ -0,0 +1,42 @@
+<?php
+
+$my_class = New my_class();
+$my_i_class = New my_i_class();
+
+echo "apc bindump 002 test\n";
+echo "\n";
+echo "global scope execution:            Success\n";
+echo "\n";
+echo "function execution:                ".my_function()."\n";
+echo "\n";
+
+echo "class static method:               ".my_class::my_static_method()."\n";
+echo "class dynamic method:              ".$my_class->my_method()."\n";
+echo "class static property:             ".my_class::$my_static_property."\n";
+echo "class dynamic property:            ".$my_class->my_property."\n";
+echo "class constant:                    ".my_class::my_constant."\n";
+echo "\n";
+echo "inherited class static method:     ".my_i_class::my_static_method()."\n";
+echo "inherited class dynamic method:    ".$my_i_class->my_method()."\n";
+echo "inherited class static property:   ".my_i_class::$my_static_property."\n";
+echo "inherited class dynamic property:  ".$my_i_class->my_property."\n";
+echo "inherited class constant:          ".my_i_class::my_constant."\n";
+echo "\n";
+
+
+
+function my_function() { return "Success"; }
+
+
+class my_class {
+  static $my_static_property = "Success";
+  var $my_property = "Success";
+  const my_constant = "Success";
+  static function my_static_method() { return "Success"; }
+  function my_method() { return "Success"; }
+}
+
+class my_i_class extends my_class {
+  function dummy() { return 1; }
+}
+
--- /dev/null
+++ b/ext/apc/tests/apc_bin_002-2.inc
@@ -0,0 +1,5 @@
+<?php
+
+echo "Failed to use cached version!\n";
+
+?>
--- /dev/null
+++ b/ext/apc/tests/apc_bin_002.phpt
@@ -0,0 +1,53 @@
+--TEST--
+APC: bindump file cache part 1
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.stat=0
+apc.cache_by_default=1
+apc.filters=
+report_memleaks = Off
+--FILE--
+<?php
+
+define('filename',dirname(__FILE__).'/apc_bin_002.inc');
+define('filename1',dirname(__FILE__).'/apc_bin_002-1.inc');
+define('filename2',dirname(__FILE__).'/apc_bin_002-2.inc');
+
+copy(filename1, filename);
+apc_compile_file(filename);
+$data = apc_bin_dump(NULL, NULL);
+
+apc_clear_cache();
+
+copy(filename2, filename);
+apc_bin_load($data, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
+include(filename);
+
+unlink(filename);
+
+?>
+===DONE===
+<?  php exit(0); ?>
+--EXPECTF--
+apc bindump 002 test
+
+global scope execution:            Success
+
+function execution:                Success
+
+class static method:               Success
+class dynamic method:              Success
+class static property:             Success
+class dynamic property:            Success
+class constant:                    Success
+
+inherited class static method:     Success
+inherited class dynamic method:    Success
+inherited class static property:   Success
+inherited class dynamic property:  Success
+inherited class constant:          Success
+
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_001.phpt
@@ -0,0 +1,110 @@
+--TEST--
+APC: APCIterator general
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$it = new APCIterator('user');
+for($i = 0; $i < 41; $i++) {
+  apc_store("key$i", "value$i");
+}
+foreach($it as $key=>$value) {
+  $vals[$key] = $value['key'];
+}
+ksort($vals);
+var_dump($vals);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+array(41) {
+  ["key0"]=>
+  string(4) "key0"
+  ["key1"]=>
+  string(4) "key1"
+  ["key10"]=>
+  string(5) "key10"
+  ["key11"]=>
+  string(5) "key11"
+  ["key12"]=>
+  string(5) "key12"
+  ["key13"]=>
+  string(5) "key13"
+  ["key14"]=>
+  string(5) "key14"
+  ["key15"]=>
+  string(5) "key15"
+  ["key16"]=>
+  string(5) "key16"
+  ["key17"]=>
+  string(5) "key17"
+  ["key18"]=>
+  string(5) "key18"
+  ["key19"]=>
+  string(5) "key19"
+  ["key2"]=>
+  string(4) "key2"
+  ["key20"]=>
+  string(5) "key20"
+  ["key21"]=>
+  string(5) "key21"
+  ["key22"]=>
+  string(5) "key22"
+  ["key23"]=>
+  string(5) "key23"
+  ["key24"]=>
+  string(5) "key24"
+  ["key25"]=>
+  string(5) "key25"
+  ["key26"]=>
+  string(5) "key26"
+  ["key27"]=>
+  string(5) "key27"
+  ["key28"]=>
+  string(5) "key28"
+  ["key29"]=>
+  string(5) "key29"
+  ["key3"]=>
+  string(4) "key3"
+  ["key30"]=>
+  string(5) "key30"
+  ["key31"]=>
+  string(5) "key31"
+  ["key32"]=>
+  string(5) "key32"
+  ["key33"]=>
+  string(5) "key33"
+  ["key34"]=>
+  string(5) "key34"
+  ["key35"]=>
+  string(5) "key35"
+  ["key36"]=>
+  string(5) "key36"
+  ["key37"]=>
+  string(5) "key37"
+  ["key38"]=>
+  string(5) "key38"
+  ["key39"]=>
+  string(5) "key39"
+  ["key4"]=>
+  string(4) "key4"
+  ["key40"]=>
+  string(5) "key40"
+  ["key5"]=>
+  string(4) "key5"
+  ["key6"]=>
+  string(4) "key6"
+  ["key7"]=>
+  string(4) "key7"
+  ["key8"]=>
+  string(4) "key8"
+  ["key9"]=>
+  string(4) "key9"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_002.phpt
@@ -0,0 +1,36 @@
+--TEST--
+APC: APCIterator regex
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$it = new APCIterator('user', '/key[0-9]0/');
+for($i = 0; $i < 41; $i++) {
+  apc_store("key$i", "value$i");
+}
+foreach($it as $key=>$value) {
+  $vals[$key] = $value['key'];
+}
+ksort($vals);
+var_dump($vals);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+array(4) {
+  ["key10"]=>
+  string(5) "key10"
+  ["key20"]=>
+  string(5) "key20"
+  ["key30"]=>
+  string(5) "key30"
+  ["key40"]=>
+  string(5) "key40"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_003.phpt
@@ -0,0 +1,110 @@
+--TEST--
+APC: APCIterator chunk size
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$it = new APCIterator('user', NULL, APC_ITER_ALL, 10);
+for($i = 0; $i < 41; $i++) {
+  apc_store("key$i", "value$i");
+}
+foreach($it as $key=>$value) {
+  $vals[$key] = $value['key'];
+}
+ksort($vals);
+var_dump($vals);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+array(41) {
+  ["key0"]=>
+  string(4) "key0"
+  ["key1"]=>
+  string(4) "key1"
+  ["key10"]=>
+  string(5) "key10"
+  ["key11"]=>
+  string(5) "key11"
+  ["key12"]=>
+  string(5) "key12"
+  ["key13"]=>
+  string(5) "key13"
+  ["key14"]=>
+  string(5) "key14"
+  ["key15"]=>
+  string(5) "key15"
+  ["key16"]=>
+  string(5) "key16"
+  ["key17"]=>
+  string(5) "key17"
+  ["key18"]=>
+  string(5) "key18"
+  ["key19"]=>
+  string(5) "key19"
+  ["key2"]=>
+  string(4) "key2"
+  ["key20"]=>
+  string(5) "key20"
+  ["key21"]=>
+  string(5) "key21"
+  ["key22"]=>
+  string(5) "key22"
+  ["key23"]=>
+  string(5) "key23"
+  ["key24"]=>
+  string(5) "key24"
+  ["key25"]=>
+  string(5) "key25"
+  ["key26"]=>
+  string(5) "key26"
+  ["key27"]=>
+  string(5) "key27"
+  ["key28"]=>
+  string(5) "key28"
+  ["key29"]=>
+  string(5) "key29"
+  ["key3"]=>
+  string(4) "key3"
+  ["key30"]=>
+  string(5) "key30"
+  ["key31"]=>
+  string(5) "key31"
+  ["key32"]=>
+  string(5) "key32"
+  ["key33"]=>
+  string(5) "key33"
+  ["key34"]=>
+  string(5) "key34"
+  ["key35"]=>
+  string(5) "key35"
+  ["key36"]=>
+  string(5) "key36"
+  ["key37"]=>
+  string(5) "key37"
+  ["key38"]=>
+  string(5) "key38"
+  ["key39"]=>
+  string(5) "key39"
+  ["key4"]=>
+  string(4) "key4"
+  ["key40"]=>
+  string(5) "key40"
+  ["key5"]=>
+  string(4) "key5"
+  ["key6"]=>
+  string(4) "key6"
+  ["key7"]=>
+  string(4) "key7"
+  ["key8"]=>
+  string(4) "key8"
+  ["key9"]=>
+  string(4) "key9"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_004.phpt
@@ -0,0 +1,36 @@
+--TEST--
+APC: APCIterator regex & chunk size & list
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$it = new APCIterator('user', '/key[0-9]0/', APC_ITER_ALL, 1, APC_LIST_ACTIVE);
+for($i = 0; $i < 41; $i++) {
+  apc_store("key$i", "value$i");
+}
+foreach($it as $key=>$value) {
+  $vals[$key] = $value['key'];
+}
+ksort($vals);
+var_dump($vals);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+array(4) {
+  ["key10"]=>
+  string(5) "key10"
+  ["key20"]=>
+  string(5) "key20"
+  ["key30"]=>
+  string(5) "key30"
+  ["key40"]=>
+  string(5) "key40"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_005.phpt
@@ -0,0 +1,112 @@
+--TEST--
+APC: APCIterator delete
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$vals = array();
+$vals2 = array();
+$it = new APCIterator('user', '/key[0-9]0/');
+for($i = 0; $i < 41; $i++) {
+  apc_store("key$i", "value$i");
+}
+apc_delete($it);
+$it2 = new APCIterator('user');
+foreach($it as $key=>$value) {
+  $vals[$key] = $value['key'];
+}
+foreach($it2 as $key=>$value) {
+  $vals2[$key] = $value['key'];
+}
+ksort($vals2);
+var_dump($vals);
+var_dump($vals2);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+array(0) {
+}
+array(37) {
+  ["key0"]=>
+  string(4) "key0"
+  ["key1"]=>
+  string(4) "key1"
+  ["key11"]=>
+  string(5) "key11"
+  ["key12"]=>
+  string(5) "key12"
+  ["key13"]=>
+  string(5) "key13"
+  ["key14"]=>
+  string(5) "key14"
+  ["key15"]=>
+  string(5) "key15"
+  ["key16"]=>
+  string(5) "key16"
+  ["key17"]=>
+  string(5) "key17"
+  ["key18"]=>
+  string(5) "key18"
+  ["key19"]=>
+  string(5) "key19"
+  ["key2"]=>
+  string(4) "key2"
+  ["key21"]=>
+  string(5) "key21"
+  ["key22"]=>
+  string(5) "key22"
+  ["key23"]=>
+  string(5) "key23"
+  ["key24"]=>
+  string(5) "key24"
+  ["key25"]=>
+  string(5) "key25"
+  ["key26"]=>
+  string(5) "key26"
+  ["key27"]=>
+  string(5) "key27"
+  ["key28"]=>
+  string(5) "key28"
+  ["key29"]=>
+  string(5) "key29"
+  ["key3"]=>
+  string(4) "key3"
+  ["key31"]=>
+  string(5) "key31"
+  ["key32"]=>
+  string(5) "key32"
+  ["key33"]=>
+  string(5) "key33"
+  ["key34"]=>
+  string(5) "key34"
+  ["key35"]=>
+  string(5) "key35"
+  ["key36"]=>
+  string(5) "key36"
+  ["key37"]=>
+  string(5) "key37"
+  ["key38"]=>
+  string(5) "key38"
+  ["key39"]=>
+  string(5) "key39"
+  ["key4"]=>
+  string(4) "key4"
+  ["key5"]=>
+  string(4) "key5"
+  ["key6"]=>
+  string(4) "key6"
+  ["key7"]=>
+  string(4) "key7"
+  ["key8"]=>
+  string(4) "key8"
+  ["key9"]=>
+  string(4) "key9"
+}
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_006.phpt
@@ -0,0 +1,1535 @@
+--TEST--
+APC: APCIterator formats 
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+apc.file_update_protection=0
+--FILE--
+<?php
+
+$formats = array( 
+                  APC_ITER_TYPE,
+                  APC_ITER_KEY,
+                  APC_ITER_FILENAME,
+                  APC_ITER_DEVICE,
+                  APC_ITER_INODE,
+                  APC_ITER_VALUE,
+                  APC_ITER_MD5,
+                  APC_ITER_NUM_HITS,
+                  APC_ITER_MTIME,
+                  APC_ITER_CTIME,
+                  APC_ITER_DTIME,
+                  APC_ITER_ATIME,
+                  APC_ITER_REFCOUNT,
+                  APC_ITER_MEM_SIZE,
+                  APC_ITER_TTL,
+                  APC_ITER_NONE,
+                  APC_ITER_ALL,
+                  APC_ITER_ALL & ~APC_ITER_TTL,
+                  APC_ITER_KEY | APC_ITER_NUM_HITS | APC_ITER_MEM_SIZE,
+                );
+
+$it_array = array();
+
+foreach ($formats as $idx => $format) {
+  $it_array[$idx] = new APCIterator('user', NULL, $format);
+}
+
+for($i = 0; $i < 11; $i++) {
+  apc_store("key$i", "value$i");
+}
+
+foreach ($it_array as $idx => $it) {
+  print_it($it, $idx);
+}
+
+function print_it($it, $idx) {
+  echo "IT #$idx\n";
+  echo "============================\n";
+  foreach ($it as $key=>$value) {
+    var_dump($key);
+    var_dump($value);
+  }
+  echo "============================\n\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+IT #0
+============================
+string(5) "key10"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key0"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key1"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key2"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key3"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key4"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key5"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key6"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key7"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key8"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+string(4) "key9"
+array(1) {
+  ["type"]=>
+  string(4) "user"
+}
+============================
+
+IT #1
+============================
+string(5) "key10"
+array(1) {
+  ["key"]=>
+  string(5) "key10"
+}
+string(4) "key0"
+array(1) {
+  ["key"]=>
+  string(4) "key0"
+}
+string(4) "key1"
+array(1) {
+  ["key"]=>
+  string(4) "key1"
+}
+string(4) "key2"
+array(1) {
+  ["key"]=>
+  string(4) "key2"
+}
+string(4) "key3"
+array(1) {
+  ["key"]=>
+  string(4) "key3"
+}
+string(4) "key4"
+array(1) {
+  ["key"]=>
+  string(4) "key4"
+}
+string(4) "key5"
+array(1) {
+  ["key"]=>
+  string(4) "key5"
+}
+string(4) "key6"
+array(1) {
+  ["key"]=>
+  string(4) "key6"
+}
+string(4) "key7"
+array(1) {
+  ["key"]=>
+  string(4) "key7"
+}
+string(4) "key8"
+array(1) {
+  ["key"]=>
+  string(4) "key8"
+}
+string(4) "key9"
+array(1) {
+  ["key"]=>
+  string(4) "key9"
+}
+============================
+
+IT #2
+============================
+string(5) "key10"
+array(0) {
+}
+string(4) "key0"
+array(0) {
+}
+string(4) "key1"
+array(0) {
+}
+string(4) "key2"
+array(0) {
+}
+string(4) "key3"
+array(0) {
+}
+string(4) "key4"
+array(0) {
+}
+string(4) "key5"
+array(0) {
+}
+string(4) "key6"
+array(0) {
+}
+string(4) "key7"
+array(0) {
+}
+string(4) "key8"
+array(0) {
+}
+string(4) "key9"
+array(0) {
+}
+============================
+
+IT #3
+============================
+string(5) "key10"
+array(0) {
+}
+string(4) "key0"
+array(0) {
+}
+string(4) "key1"
+array(0) {
+}
+string(4) "key2"
+array(0) {
+}
+string(4) "key3"
+array(0) {
+}
+string(4) "key4"
+array(0) {
+}
+string(4) "key5"
+array(0) {
+}
+string(4) "key6"
+array(0) {
+}
+string(4) "key7"
+array(0) {
+}
+string(4) "key8"
+array(0) {
+}
+string(4) "key9"
+array(0) {
+}
+============================
+
+IT #4
+============================
+string(5) "key10"
+array(0) {
+}
+string(4) "key0"
+array(0) {
+}
+string(4) "key1"
+array(0) {
+}
+string(4) "key2"
+array(0) {
+}
+string(4) "key3"
+array(0) {
+}
+string(4) "key4"
+array(0) {
+}
+string(4) "key5"
+array(0) {
+}
+string(4) "key6"
+array(0) {
+}
+string(4) "key7"
+array(0) {
+}
+string(4) "key8"
+array(0) {
+}
+string(4) "key9"
+array(0) {
+}
+============================
+
+IT #5
+============================
+string(5) "key10"
+array(1) {
+  ["value"]=>
+  string(7) "value10"
+}
+string(4) "key0"
+array(1) {
+  ["value"]=>
+  string(6) "value0"
+}
+string(4) "key1"
+array(1) {
+  ["value"]=>
+  string(6) "value1"
+}
+string(4) "key2"
+array(1) {
+  ["value"]=>
+  string(6) "value2"
+}
+string(4) "key3"
+array(1) {
+  ["value"]=>
+  string(6) "value3"
+}
+string(4) "key4"
+array(1) {
+  ["value"]=>
+  string(6) "value4"
+}
+string(4) "key5"
+array(1) {
+  ["value"]=>
+  string(6) "value5"
+}
+string(4) "key6"
+array(1) {
+  ["value"]=>
+  string(6) "value6"
+}
+string(4) "key7"
+array(1) {
+  ["value"]=>
+  string(6) "value7"
+}
+string(4) "key8"
+array(1) {
+  ["value"]=>
+  string(6) "value8"
+}
+string(4) "key9"
+array(1) {
+  ["value"]=>
+  string(6) "value9"
+}
+============================
+
+IT #6
+============================
+string(5) "key10"
+array(0) {
+}
+string(4) "key0"
+array(0) {
+}
+string(4) "key1"
+array(0) {
+}
+string(4) "key2"
+array(0) {
+}
+string(4) "key3"
+array(0) {
+}
+string(4) "key4"
+array(0) {
+}
+string(4) "key5"
+array(0) {
+}
+string(4) "key6"
+array(0) {
+}
+string(4) "key7"
+array(0) {
+}
+string(4) "key8"
+array(0) {
+}
+string(4) "key9"
+array(0) {
+}
+============================
+
+IT #7
+============================
+string(5) "key10"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key0"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key1"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key2"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key3"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key4"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key5"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key6"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key7"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key8"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+string(4) "key9"
+array(1) {
+  ["num_hits"]=>
+  int(0)
+}
+============================
+
+IT #8
+============================
+string(5) "key10"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key0"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key1"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key2"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key3"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key4"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key5"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key6"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key7"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key8"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+string(4) "key9"
+array(1) {
+  ["mtime"]=>
+  int(%d)
+}
+============================
+
+IT #9
+============================
+string(5) "key10"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key0"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key1"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key2"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key3"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key4"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key5"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key6"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key7"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key8"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+string(4) "key9"
+array(1) {
+  ["creation_time"]=>
+  int(%d)
+}
+============================
+
+IT #10
+============================
+string(5) "key10"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key0"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key1"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key2"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key3"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key4"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key5"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key6"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key7"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key8"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+string(4) "key9"
+array(1) {
+  ["deletion_time"]=>
+  int(0)
+}
+============================
+
+IT #11
+============================
+string(5) "key10"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key0"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key1"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key2"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key3"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key4"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key5"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key6"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key7"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key8"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+string(4) "key9"
+array(1) {
+  ["access_time"]=>
+  int(%d)
+}
+============================
+
+IT #12
+============================
+string(5) "key10"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key0"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key1"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key2"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key3"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key4"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key5"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key6"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key7"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key8"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+string(4) "key9"
+array(1) {
+  ["ref_count"]=>
+  int(0)
+}
+============================
+
+IT #13
+============================
+string(5) "key10"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key0"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key1"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key2"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key3"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key4"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key5"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key6"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key7"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key8"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key9"
+array(1) {
+  ["mem_size"]=>
+  int(%d)
+}
+============================
+
+IT #14
+============================
+string(5) "key10"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key0"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key1"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key2"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key3"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key4"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key5"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key6"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key7"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key8"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key9"
+array(1) {
+  ["ttl"]=>
+  int(0)
+}
+============================
+
+IT #15
+============================
+string(5) "key10"
+array(0) {
+}
+string(4) "key0"
+array(0) {
+}
+string(4) "key1"
+array(0) {
+}
+string(4) "key2"
+array(0) {
+}
+string(4) "key3"
+array(0) {
+}
+string(4) "key4"
+array(0) {
+}
+string(4) "key5"
+array(0) {
+}
+string(4) "key6"
+array(0) {
+}
+string(4) "key7"
+array(0) {
+}
+string(4) "key8"
+array(0) {
+}
+string(4) "key9"
+array(0) {
+}
+============================
+
+IT #16
+============================
+string(5) "key10"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(5) "key10"
+  ["value"]=>
+  string(7) "value10"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key0"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key0"
+  ["value"]=>
+  string(6) "value0"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key1"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key1"
+  ["value"]=>
+  string(6) "value1"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key2"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key2"
+  ["value"]=>
+  string(6) "value2"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key3"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key3"
+  ["value"]=>
+  string(6) "value3"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key4"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key4"
+  ["value"]=>
+  string(6) "value4"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key5"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key5"
+  ["value"]=>
+  string(6) "value5"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key6"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key6"
+  ["value"]=>
+  string(6) "value6"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key7"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key7"
+  ["value"]=>
+  string(6) "value7"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key8"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key8"
+  ["value"]=>
+  string(6) "value8"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+string(4) "key9"
+array(11) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key9"
+  ["value"]=>
+  string(6) "value9"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+  ["ttl"]=>
+  int(0)
+}
+============================
+
+IT #17
+============================
+string(5) "key10"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(5) "key10"
+  ["value"]=>
+  string(7) "value10"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key0"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key0"
+  ["value"]=>
+  string(6) "value0"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key1"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key1"
+  ["value"]=>
+  string(6) "value1"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key2"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key2"
+  ["value"]=>
+  string(6) "value2"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key3"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key3"
+  ["value"]=>
+  string(6) "value3"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key4"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key4"
+  ["value"]=>
+  string(6) "value4"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key5"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key5"
+  ["value"]=>
+  string(6) "value5"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key6"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key6"
+  ["value"]=>
+  string(6) "value6"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key7"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key7"
+  ["value"]=>
+  string(6) "value7"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key8"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key8"
+  ["value"]=>
+  string(6) "value8"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key9"
+array(10) {
+  ["type"]=>
+  string(4) "user"
+  ["key"]=>
+  string(4) "key9"
+  ["value"]=>
+  string(6) "value9"
+  ["num_hits"]=>
+  int(0)
+  ["mtime"]=>
+  int(%d)
+  ["creation_time"]=>
+  int(%d)
+  ["deletion_time"]=>
+  int(0)
+  ["access_time"]=>
+  int(%d)
+  ["ref_count"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+============================
+
+IT #18
+============================
+string(5) "key10"
+array(3) {
+  ["key"]=>
+  string(5) "key10"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key0"
+array(3) {
+  ["key"]=>
+  string(4) "key0"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key1"
+array(3) {
+  ["key"]=>
+  string(4) "key1"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key2"
+array(3) {
+  ["key"]=>
+  string(4) "key2"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key3"
+array(3) {
+  ["key"]=>
+  string(4) "key3"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key4"
+array(3) {
+  ["key"]=>
+  string(4) "key4"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key5"
+array(3) {
+  ["key"]=>
+  string(4) "key5"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key6"
+array(3) {
+  ["key"]=>
+  string(4) "key6"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key7"
+array(3) {
+  ["key"]=>
+  string(4) "key7"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key8"
+array(3) {
+  ["key"]=>
+  string(4) "key8"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+string(4) "key9"
+array(3) {
+  ["key"]=>
+  string(4) "key9"
+  ["num_hits"]=>
+  int(0)
+  ["mem_size"]=>
+  int(%d)
+}
+============================
+
+===DONE===
--- /dev/null
+++ b/ext/apc/tests/iterator_007.phpt
@@ -0,0 +1,36 @@
+--TEST--
+APC: APCIterator Overwriting the ctor
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+apc.enabled=1
+apc.enable_cli=1
+--FILE--
+<?php
+class foobar extends APCIterator {
+	public function __construct() {}
+}
+$obj = new foobar;
+var_dump(
+	$obj->rewind(),
+	$obj->current(),
+	$obj->key(),
+	$obj->next(),
+	$obj->valid(),
+	$obj->getTotalHits(),
+	$obj->getTotalSize(),
+	$obj->getTotalCount(),
+	apc_delete($obj)
+);
+?>
+--EXPECTF--
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+
--- /dev/null
+++ b/ext/apc/tests/php_5_3_ns.inc
@@ -0,0 +1,18 @@
+<?php
+namespace Foo\Bar;
+
+function sort() {
+	$a = array(3,2,1,4);
+	\sort($a);  // global scoping
+	var_dump($a);
+	return "IT WORKS";
+}
+class Baz {
+	public $i = 1;
+	protected $f = 3.14;
+	private $s = "hello world";
+
+	public function foo() {
+		sort();
+	}
+}
--- /dev/null
+++ b/ext/apc/tests/skipif.inc
@@ -0,0 +1,6 @@
+<?php
+
+if (!extension_loaded("apc")) die("skip");
+//if (!ini_get('apc.enabled')) die("skip apc not enabled");
+
+?>
--- /dev/null
+++ b/ext/apc/TODO
@@ -0,0 +1,32 @@
+Known Bugs
+ 
+1.   Gallery2 doesn't work with PHP5+APC.  There is something wrong
+     with the way methods are restored in some edge case I haven't
+     been able to figure out yet.
+     To reproduce install gallery2 and click down to an individual photo.
+
+2.   apc_store() probably needs some checks to skip trying to store
+     internal classes.  Something along the lines of:
+
+     if(Z_TYPE_P(val) == IS_OBJECT) {
+        zend_class_entry *ce = Z_OBJCE_P(val);
+        if(ce->type == ZEND_INTERNAL_CLASS) {
+            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
+            RETURN_FALSE;
+        }
+     }
+
+     in the apc_store() function in php_apc.c but I am wondering if it needs to do more
+     than that.
+
+Windows
+
+1.   The following configurations (build arguments) have not been implemented yet
+
+          (*) --enable-apc-mmap         Memory mapping support
+          (*) --enable-apc-sem          Semaphore locking support (FCNTL replacement)
+          (*) --enable-apc-phreadmutex	Thread mutexes, while implemented we should probably rename the internals to thread
+
+2.   Non-blocking locks is not supported either
+
+3.   Update fileinfo to support stat info in a more portable way (see PECL #17903)
\ No newline at end of file