1 diff -Naur a/ext/apc/apc_bin.c b/ext/apc/apc_bin.c
2 --- a/ext/apc/apc_bin.c 1970-01-01 01:00:00.000000000 +0100
3 +++ b/ext/apc/apc_bin.c 2012-07-20 00:10:35.000000000 +0200
6 + +----------------------------------------------------------------------+
8 + +----------------------------------------------------------------------+
9 + | Copyright (c) 2006-2011 The PHP Group |
10 + +----------------------------------------------------------------------+
11 + | This source file is subject to version 3.01 of the PHP license, |
12 + | that is bundled with this package in the file LICENSE, and is |
13 + | available through the world-wide-web at the following url: |
14 + | http://www.php.net/license/3_01.txt. |
15 + | If you did not receive a copy of the PHP license and are unable to |
16 + | obtain it through the world-wide-web, please send a note to |
17 + | license@php.net so we can mail you a copy immediately. |
18 + +----------------------------------------------------------------------+
19 + | Authors: Brian Shire <shire@php.net> |
20 + +----------------------------------------------------------------------+
24 +/* $Id: apc_bin.c 324017 2012-03-08 09:46:22Z pajoye $ */
26 +/* Creates a binary architecture specific output to a string or file containing
27 + * the current cache contents for both fies and user variables. This is accomplished
28 + * via the apc_copy_* functions and "swizzling" pointer values to a position
29 + * independent value, and unswizzling them on restoration.
32 +#include "apc_globals.h"
34 +#include "apc_zend.h"
37 +#include "apc_pool.h"
38 +#include "ext/standard/md5.h"
39 +#include "ext/standard/crc32.h"
41 +extern apc_cache_t* apc_cache;
42 +extern apc_cache_t* apc_user_cache;
44 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); /* this is hacky */
46 +#define APC_BINDUMP_DEBUG 0
49 +#if APC_BINDUMP_DEBUG
51 +#define SWIZZLE(bd, ptr) \
53 + if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
54 + printf("SWIZZLE: %x ~> ", ptr); \
55 + ptr = (void*)((long)(ptr) - (long)(bd)); \
56 + printf("%x in %s on line %d", ptr, __FILE__, __LINE__); \
57 + } else if((long)ptr > bd->size) { /* not swizzled */ \
58 + 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__); \
64 +#define UNSWIZZLE(bd, ptr) \
66 + printf("UNSWIZZLE: %x -> ", ptr); \
67 + ptr = (void*)((long)(ptr) + (long)(bd)); \
68 + printf("%x in %s on line %d \n", ptr, __FILE__, __LINE__); \
71 +#else /* !APC_BINDUMP_DEBUG */
73 +#define SWIZZLE(bd, ptr) \
75 + if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
76 + ptr = (void*)((long)(ptr) - (long)(bd)); \
77 + } else if((ulong)ptr > bd->size) { /* not swizzled */ \
78 + 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__); \
83 +#define UNSWIZZLE(bd, ptr) \
85 + ptr = (void*)((long)(ptr) + (long)(bd)); \
91 +static void *apc_bd_alloc(size_t size TSRMLS_DC);
92 +static void apc_bd_free(void *ptr TSRMLS_DC);
93 +static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC);
95 +typedef void (*apc_swizzle_cb_t)(apc_bd_t *bd, zend_llist *ll, void *ptr TSRMLS_DC);
97 +#if APC_BINDUMP_DEBUG
98 +#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, __FILE__, __LINE__ TSRMLS_CC)
100 +#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, NULL, 0 TSRMLS_CC)
103 +static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC);
104 +static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC);
105 +static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC);
106 +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);
107 +static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC);
108 +static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC);
109 +static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC);
110 +static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC);
111 +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);
113 +static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC);
114 +static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC);
118 + * callback for copy_* functions */
119 +static void *apc_bd_alloc(size_t size TSRMLS_DC) {
120 + return apc_bd_alloc_ex(NULL, size TSRMLS_CC);
125 + * callback for copy_* functions */
126 +static void apc_bd_free(void *ptr TSRMLS_DC) {
128 + if(zend_hash_index_find(&APCG(apc_bd_alloc_list), (ulong)ptr, (void**)&size) == FAILURE) {
129 + apc_error("apc_bd_free could not free pointer (not found in list: %x)" TSRMLS_CC, ptr);
132 + APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) - *size);
133 + zend_hash_index_del(&APCG(apc_bd_alloc_list), (ulong)ptr);
137 +/* {{{ apc_bd_alloc_ex
138 + * set ranges or allocate a block of data from an already (e)malloc'd range.
139 + * if ptr_new is not NULL, it will reset the pointer to start at ptr_new,
140 + * with a range of size. If ptr_new is NULL, returns the next available
141 + * block of given size.
143 +static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC) {
146 + rval = APCG(apc_bd_alloc_ptr);
147 + if(ptr_new != NULL) { /* reset ptrs */
148 + APCG(apc_bd_alloc_ptr) = ptr_new;
149 + APCG(apc_bd_alloc_ubptr) = (void*)((unsigned char *) ptr_new + size);
150 + } else { /* alloc block */
151 + APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) + size);
152 +#if APC_BINDUMP_DEBUG
153 + 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);
155 + if(APCG(apc_bd_alloc_ptr) > APCG(apc_bd_alloc_ubptr)) {
156 + 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));
159 + zend_hash_index_update(&APCG(apc_bd_alloc_list), (ulong)rval, &size, sizeof(size_t), NULL);
166 +/* {{{ _apc_swizzle_ptr */
167 +static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC) {
169 + if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) {
170 + zend_llist_add_element(ll, &ptr);
171 +#if APC_BINDUMP_DEBUG
172 + printf("[%06d] apc_swizzle_ptr: %x -> %x ", zend_llist_count(ll), ptr, *ptr);
173 + printf(" in %s on line %d \n", file, line);
175 + } else if((ulong)ptr > bd->size) {
176 + 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); \
183 +/* {{{ apc_swizzle_op_array */
184 +static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC) {
187 +#ifdef ZEND_ENGINE_2
188 + apc_swizzle_arg_info_array(bd, ll, op_array->arg_info, op_array->num_args TSRMLS_CC);
189 + apc_swizzle_ptr(bd, ll, &op_array->arg_info);
191 + if (op_array->arg_types) {
192 + apc_swizzle_ptr(bd, ll, &op_array->arg_types);
196 + apc_swizzle_ptr(bd, ll, &op_array->function_name);
197 + apc_swizzle_ptr(bd, ll, &op_array->filename);
198 + apc_swizzle_ptr(bd, ll, &op_array->refcount);
200 + /* swizzle op_array */
201 + for(i=0; i < op_array->last; i++) {
202 +#ifndef ZEND_ENGINE_2_4
203 + if(op_array->opcodes[i].result.op_type == IS_CONST) {
204 + apc_swizzle_zval(bd, ll, &op_array->opcodes[i].result.u.constant TSRMLS_CC);
206 + if(op_array->opcodes[i].op1.op_type == IS_CONST) {
207 + apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op1.u.constant TSRMLS_CC);
209 + if(op_array->opcodes[i].op2.op_type == IS_CONST) {
210 + apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op2.u.constant TSRMLS_CC);
213 + switch (op_array->opcodes[i].opcode) {
215 +#ifdef ZEND_ENGINE_2_4
216 + apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.jmp_addr);
218 + apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.u.jmp_addr);
223 + case ZEND_JMPNZ_EX:
224 +#ifdef ZEND_ENGINE_2_4
225 + apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.jmp_addr);
227 + apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.u.jmp_addr);
231 + apc_swizzle_ptr(bd, ll, &op_array->opcodes);
233 + /* break-continue array ptr */
234 + if(op_array->brk_cont_array) {
235 + apc_swizzle_ptr(bd, ll, &op_array->brk_cont_array);
238 + /* static voriables */
239 + if(op_array->static_variables) {
240 + apc_swizzle_hashtable(bd, ll, op_array->static_variables, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
241 + apc_swizzle_ptr(bd, ll, &op_array->static_variables);
244 +#ifdef ZEND_ENGINE_2
246 + if(op_array->try_catch_array) {
247 + apc_swizzle_ptr(bd, ll, &op_array->try_catch_array);
251 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
253 + if(op_array->vars) {
254 + for(i=0; (signed int) i < op_array->last_var; i++) {
255 + apc_swizzle_ptr(bd, ll, &op_array->vars[i].name);
257 + apc_swizzle_ptr(bd, ll, &op_array->vars);
261 +#ifdef ZEND_ENGINE_2
263 + if(op_array->doc_comment) {
264 + apc_swizzle_ptr(bd, ll, &op_array->doc_comment);
271 +/* {{{ apc_swizzle_function */
272 +static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC) {
273 + apc_swizzle_op_array(bd, ll, &func->op_array TSRMLS_CC);
274 +#ifdef ZEND_ENGINE_2
275 + if(func->common.scope) {
276 + apc_swizzle_ptr(bd, ll, &func->common.scope);
282 +/* {{{ apc_swizzle_class_entry */
283 +static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC) {
288 + apc_swizzle_ptr(bd, ll, &ce->name);
291 + if (ce->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(ce)) {
292 + apc_swizzle_ptr(bd, ll, &ZEND_CE_DOC_COMMENT(ce));
295 +#ifndef ZEND_ENGINE_2
296 + apc_swizzle_ptr(bd, ll, &ce->refcount);
299 + apc_swizzle_hashtable(bd, ll, &ce->function_table, (apc_swizzle_cb_t)apc_swizzle_function, 0 TSRMLS_CC);
300 +#ifdef ZEND_ENGINE_2_4
301 + if (ce->default_properties_table) {
302 + for (i = 0; i < ce->default_properties_count; i++) {
303 + if (ce->default_properties_table[i]) {
304 + apc_swizzle_ptr(bd, ll, &ce->default_properties_table[i]);
305 + apc_swizzle_zval(bd, ll, ce->default_properties_table[i] TSRMLS_CC);
310 + apc_swizzle_hashtable(bd, ll, &ce->default_properties, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
313 +#ifdef ZEND_ENGINE_2
314 + apc_swizzle_hashtable(bd, ll, &ce->properties_info, (apc_swizzle_cb_t)apc_swizzle_property_info, 0 TSRMLS_CC);
317 +#ifdef ZEND_ENGINE_2_4
318 + if (ce->default_static_members_table) {
319 + for (i = 0; i < ce->default_static_members_count; i++) {
320 + if (ce->default_static_members_table[i]) {
321 + apc_swizzle_ptr(bd, ll, &ce->default_static_members_table[i]);
322 + apc_swizzle_zval(bd, ll, ce->default_static_members_table[i] TSRMLS_CC);
326 + ce->static_members_table = ce->default_static_members_table;
328 + apc_swizzle_hashtable(bd, ll, &ce->default_static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
330 + if(ce->static_members != &ce->default_static_members) {
331 + apc_swizzle_hashtable(bd, ll, ce->static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
333 + apc_swizzle_ptr(bd, ll, &ce->static_members);
337 + apc_swizzle_hashtable(bd, ll, &ce->constants_table, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
339 + if(ce->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(ce)) {
340 + for(i=0; ZEND_CE_BUILTIN_FUNCTIONS(ce)[i].fname; i++) {
341 + apc_swizzle_function_entry(bd, ll, &ZEND_CE_BUILTIN_FUNCTIONS(ce)[i] TSRMLS_CC);
345 + apc_swizzle_ptr(bd, ll, &ce->constructor);
346 + apc_swizzle_ptr(bd, ll, &ce->destructor);
347 + apc_swizzle_ptr(bd, ll, &ce->clone);
348 + apc_swizzle_ptr(bd, ll, &ce->__get);
349 + apc_swizzle_ptr(bd, ll, &ce->__set);
350 + apc_swizzle_ptr(bd, ll, &ce->__unset);
351 + apc_swizzle_ptr(bd, ll, &ce->__isset);
352 + apc_swizzle_ptr(bd, ll, &ce->__call);
353 + apc_swizzle_ptr(bd, ll, &ce->serialize_func);
354 + apc_swizzle_ptr(bd, ll, &ce->unserialize_func);
356 +#ifdef ZEND_ENGINE_2_2
357 + apc_swizzle_ptr(bd, ll, &ce->__tostring);
360 + if (ce->type == ZEND_USER_CLASS) {
361 + apc_swizzle_ptr(bd, ll, &ZEND_CE_FILENAME(ce));
366 +/* {{{ apc_swizzle_property_info */
367 +static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC) {
368 + apc_swizzle_ptr(bd, ll, &pi->name);
369 + apc_swizzle_ptr(bd, ll, &pi->doc_comment);
371 +#ifdef ZEND_ENGINE_2_2
372 + apc_swizzle_ptr(bd, ll, &pi->ce);
377 +/* {{{ apc_swizzle_function_entry */
378 +static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC) {
379 + apc_swizzle_ptr(bd, ll, &fe->fname);
380 + apc_swizzle_arg_info_array(bd, ll, fe->arg_info, fe->num_args TSRMLS_CC);
381 + apc_swizzle_ptr(bd, ll, &fe->arg_info);
385 +/* {{{ apc_swizzle_arg_info_array */
386 +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) {
387 + if(arg_info_array) {
390 + for(i=0; i < num_args; i++) {
391 + apc_swizzle_ptr(bd, ll, &arg_info_array[i].name);
392 + apc_swizzle_ptr(bd, ll, &arg_info_array[i].class_name);
399 +/* {{{ apc_swizzle_hashtable */
400 +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) {
402 + Bucket **bp, **bp_prev;
404 + bp = &ht->pListHead;
407 + bp = &(*bp)->pListNext;
409 + swizzle_cb(bd, ll, *(void**)(*bp_prev)->pData TSRMLS_CC);
410 + apc_swizzle_ptr(bd, ll, (*bp_prev)->pData);
412 + swizzle_cb(bd, ll, (void**)(*bp_prev)->pData TSRMLS_CC);
414 + apc_swizzle_ptr(bd, ll, &(*bp_prev)->pData);
415 + if((*bp_prev)->pDataPtr) {
416 + apc_swizzle_ptr(bd, ll, &(*bp_prev)->pDataPtr);
418 + if((*bp_prev)->pListLast) {
419 + apc_swizzle_ptr(bd, ll, &(*bp_prev)->pListLast);
421 + if((*bp_prev)->pNext) {
422 + apc_swizzle_ptr(bd, ll, &(*bp_prev)->pNext);
424 + if((*bp_prev)->pLast) {
425 + apc_swizzle_ptr(bd, ll, &(*bp_prev)->pLast);
427 + apc_swizzle_ptr(bd, ll, bp_prev);
429 + for(i=0; i < ht->nTableSize; i++) {
430 + if(ht->arBuckets[i]) {
431 + apc_swizzle_ptr(bd, ll, &ht->arBuckets[i]);
434 + apc_swizzle_ptr(bd, ll, &ht->pListTail);
436 + apc_swizzle_ptr(bd, ll, &ht->arBuckets);
440 +/* {{{ apc_swizzle_zval */
441 +static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC) {
443 + if(APCG(copied_zvals).nTableSize) {
444 + if(zend_hash_index_exists(&APCG(copied_zvals), (ulong)zv)) {
447 + zend_hash_index_update(&APCG(copied_zvals), (ulong)zv, (void**)&zv, sizeof(zval*), NULL);
450 + switch(zv->type & IS_CONSTANT_TYPE_MASK) {
456 + /* nothing to do */
460 + apc_swizzle_ptr(bd, ll, &zv->value.str.val);
463 + case IS_CONSTANT_ARRAY:
464 + apc_swizzle_hashtable(bd, ll, zv->value.ht, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
465 + apc_swizzle_ptr(bd, ll, &zv->value.ht);
470 + assert(0); /* shouldn't happen */
475 +/* {{{ apc_swizzle_bd */
476 +static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC) {
478 + PHP_MD5_CTX context;
479 + unsigned char digest[16];
480 + register php_uint32 crc;
481 + php_uint32 crcinit = 0;
486 + count = zend_llist_count(ll);
487 + ptr_list = emalloc(count * sizeof(void**));
488 + ptr = zend_llist_get_first(ll);
489 + for(i=0; i < count; i++) {
490 +#if APC_BINDUMP_DEBUG
491 + printf("[%06d] ", i+1);
493 + SWIZZLE(bd, **ptr); /* swizzle ptr */
494 + if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) { /* exclude ptrs that aren't actually included in the ptr list */
495 +#if APC_BINDUMP_DEBUG
496 + printf("[------] ");
498 + SWIZZLE(bd, *ptr); /* swizzle ptr list */
499 + ptr_list[i] = *ptr;
501 + ptr = zend_llist_get_next(ll);
503 + SWIZZLE(bd, bd->entries);
506 + bd = erealloc(bd, bd->size + (count * sizeof(void**)));
507 + bd->num_swizzled_ptrs = count;
508 + bd->swizzled_ptrs = (void***)((unsigned char *)bd + bd->size -2); /* extra -1 for null termination */
509 + bd->size += count * sizeof(void**);
510 + memcpy(bd->swizzled_ptrs, ptr_list, count * sizeof(void**));
511 + SWIZZLE(bd, bd->swizzled_ptrs);
513 + bd->num_swizzled_ptrs = 0;
514 + bd->swizzled_ptrs = NULL;
516 + ((char*)bd)[bd->size-1] = 0; /* silence null termination for zval strings */
520 + /* Generate MD5/CRC32 checksum */
521 + for(i=0; i<16; i++) { bd->md5[i] = 0; }
523 + PHP_MD5Init(&context);
524 + PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
525 + PHP_MD5Final(digest, &context);
526 + crc = crcinit^0xFFFFFFFF;
528 + for(i=bd->size; i--; ++crc_p) {
529 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
531 + memcpy(bd->md5, digest, 16);
538 +/* {{{ apc_unswizzle_bd */
539 +static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC) {
541 + unsigned char md5_orig[16];
542 + unsigned char digest[16];
543 + PHP_MD5_CTX context;
544 + register php_uint32 crc;
545 + php_uint32 crcinit = 0;
546 + php_uint32 crc_orig;
549 + /* Verify the md5 or crc32 before we unswizzle */
550 + memcpy(md5_orig, bd->md5, 16);
551 + for(i=0; i<16; i++) { bd->md5[i] = 0; }
552 + crc_orig = bd->crc;
554 + if(flags & APC_BIN_VERIFY_MD5) {
555 + PHP_MD5Init(&context);
556 + PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
557 + PHP_MD5Final(digest, &context);
558 + if(memcmp(md5_orig, digest, 16)) {
559 + apc_error("MD5 checksum of binary dump failed." TSRMLS_CC);
563 + if(flags & APC_BIN_VERIFY_CRC32) {
564 + crc = crcinit^0xFFFFFFFF;
566 + for(i=bd->size; i--; ++crc_p) {
567 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
569 + if(crc_orig != crc) {
570 + apc_error("CRC32 checksum of binary dump failed." TSRMLS_CC);
574 + memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
575 + bd->crc = crc_orig;
577 + UNSWIZZLE(bd, bd->entries);
578 + UNSWIZZLE(bd, bd->swizzled_ptrs);
579 + for(i=0; i < bd->num_swizzled_ptrs; i++) {
580 + if(bd->swizzled_ptrs[i]) {
581 + UNSWIZZLE(bd, bd->swizzled_ptrs[i]);
582 + if(*bd->swizzled_ptrs[i] && (*bd->swizzled_ptrs[i] < (void*)bd)) {
583 + UNSWIZZLE(bd, *bd->swizzled_ptrs[i]);
594 +/* {{{ apc_bin_checkfilter */
595 +static int apc_bin_checkfilter(HashTable *filter, const char *key, uint key_len) {
598 + if(filter == NULL) {
602 + if(zend_hash_find(filter, (char*)key, key_len, (void**)&zptr) == SUCCESS) {
603 + if(Z_TYPE_PP(zptr) == IS_LONG && Z_LVAL_PP(zptr) == 0) {
614 +/* {{{ apc_bin_fixup_op_array */
615 +static inline void apc_bin_fixup_op_array(zend_op_array *op_array) {
617 + for (i = 0; i < op_array->last; i++) {
618 + op_array->opcodes[i].handler = zend_opcode_handlers[APC_OPCODE_HANDLER_DECODE(&op_array->opcodes[i])];
623 +/* {{{ apc_bin_fixup_class_entry */
624 +static inline void apc_bin_fixup_class_entry(zend_class_entry *ce) {
628 + /* fixup the opcodes in each method */
629 + zend_hash_internal_pointer_reset_ex(&ce->function_table, &hpos);
630 + while(zend_hash_get_current_data_ex(&ce->function_table, (void**)&fe, &hpos) == SUCCESS) {
631 + apc_bin_fixup_op_array(&fe->op_array);
632 + zend_hash_move_forward_ex(&ce->function_table, &hpos);
635 + /* fixup hashtable destructor pointers */
636 + ce->function_table.pDestructor = (dtor_func_t)zend_function_dtor;
637 +#ifndef ZEND_ENGINE_2_4
638 + ce->default_properties.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
640 + ce->properties_info.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
641 +#ifndef ZEND_ENGINE_2_4
642 + ce->default_static_members.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
643 + if (ce->static_members) {
644 + ce->static_members->pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
647 + ce->constants_table.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
651 +/* {{{ apc_bin_dump */
652 +apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC) {
657 + apc_bd_entry_t *ep;
661 + zend_function *efp, *sfp;
663 + apc_context_t ctxt;
666 + zend_llist_init(&ll, sizeof(void*), NULL, 0);
667 + zend_hash_init(&APCG(apc_bd_alloc_list), 0, NULL, NULL, 0);
669 + /* flip the hash for faster filter checking */
670 + files = apc_flip_hash(files);
671 + user_vars = apc_flip_hash(user_vars);
673 + /* get size and entry counts */
674 + for(i=0; i < apc_user_cache->num_slots; i++) {
675 + sp = apc_user_cache->slots[i];
676 + for(; sp != NULL; sp = sp->next) {
677 + if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) {
678 + size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
679 + size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
684 + for(i=0; i < apc_cache->num_slots; i++) {
685 + sp = apc_cache->slots[i];
686 + for(; sp != NULL; sp = sp->next) {
687 + if(sp->key.type == APC_CACHE_KEY_FPFILE) {
688 + if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
689 + size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
690 + size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
694 + /* TODO: Currently we don't support APC_CACHE_KEY_FILE type. We need to store the path and re-stat on load */
695 + apc_warning("Excluding some files from apc_bin_dump[file]. Cached files must be included using full path with apc.stat=0." TSRMLS_CC);
700 + size += sizeof(apc_bd_t) +1; /* +1 for null termination */
701 + bd = emalloc(size);
703 + pool_ptr = emalloc(sizeof(apc_pool));
704 + apc_bd_alloc_ex(pool_ptr, sizeof(apc_pool) TSRMLS_CC);
705 + 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 */
706 + if (!ctxt.pool) { /* TODO need to cleanup */
707 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
710 + ctxt.copy = APC_COPY_IN_USER; /* avoid stupid ALLOC_ZVAL calls here, hack */
711 + apc_bd_alloc_ex((void*)((long)bd + sizeof(apc_bd_t)), bd->size - sizeof(apc_bd_t) -1 TSRMLS_CC);
712 + bd->num_entries = count;
713 + bd->entries = apc_bd_alloc_ex(NULL, sizeof(apc_bd_entry_t) * count TSRMLS_CC);
716 + zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
718 + for(i=0; i < apc_user_cache->num_slots; i++) {
719 + sp = apc_user_cache->slots[i];
720 + for(; sp != NULL; sp = sp->next) {
721 + if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) {
722 + ep = &bd->entries[count];
723 + ep->type = sp->value->type;
724 + ep->val.user.info = apc_bd_alloc(sp->value->data.user.info_len TSRMLS_CC);
725 + memcpy(ep->val.user.info, sp->value->data.user.info, sp->value->data.user.info_len);
726 + ep->val.user.info_len = sp->value->data.user.info_len;
727 + ep->val.user.val = apc_copy_zval(NULL, sp->value->data.user.val, &ctxt TSRMLS_CC);
728 + ep->val.user.ttl = sp->value->data.user.ttl;
730 + /* swizzle pointers */
731 + apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.info);
732 + zend_hash_clean(&APCG(copied_zvals));
733 + apc_swizzle_zval(bd, &ll, bd->entries[count].val.user.val TSRMLS_CC);
734 + apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.val);
740 + zend_hash_destroy(&APCG(copied_zvals));
741 + APCG(copied_zvals).nTableSize=0;
744 + for(i=0; i < apc_cache->num_slots; i++) {
745 + for(sp=apc_cache->slots[i]; sp != NULL; sp = sp->next) {
746 + if(sp->key.type == APC_CACHE_KEY_FPFILE) {
747 + if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
748 + ep = &bd->entries[count];
749 + ep->type = sp->key.type;
750 + ep->val.file.filename = apc_bd_alloc(strlen(sp->value->data.file.filename) + 1 TSRMLS_CC);
751 + strcpy(ep->val.file.filename, sp->value->data.file.filename);
752 + ep->val.file.op_array = apc_copy_op_array(NULL, sp->value->data.file.op_array, &ctxt TSRMLS_CC);
754 + for(ep->num_functions=0; sp->value->data.file.functions[ep->num_functions].function != NULL;) { ep->num_functions++; }
755 + ep->val.file.functions = apc_bd_alloc(sizeof(apc_function_t) * ep->num_functions TSRMLS_CC);
756 + for(fcount=0; fcount < ep->num_functions; fcount++) {
757 + memcpy(&ep->val.file.functions[fcount], &sp->value->data.file.functions[fcount], sizeof(apc_function_t));
758 + 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);
759 + ep->val.file.functions[fcount].name_len = sp->value->data.file.functions[fcount].name_len;
760 + ep->val.file.functions[fcount].function = apc_bd_alloc(sizeof(zend_function) TSRMLS_CC);
761 + efp = ep->val.file.functions[fcount].function;
762 + sfp = sp->value->data.file.functions[fcount].function;
763 + switch(sfp->type) {
764 + case ZEND_INTERNAL_FUNCTION:
765 + case ZEND_OVERLOADED_FUNCTION:
766 + efp->op_array = sfp->op_array;
768 + case ZEND_USER_FUNCTION:
769 + case ZEND_EVAL_CODE:
770 + apc_copy_op_array(&efp->op_array, &sfp->op_array, &ctxt TSRMLS_CC);
775 +#ifdef ZEND_ENGINE_2
776 + efp->common.prototype = NULL;
777 + efp->common.fn_flags = sfp->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
779 + apc_swizzle_ptr(bd, &ll, &ep->val.file.functions[fcount].name);
780 + apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions[fcount].function);
781 + apc_swizzle_op_array(bd, &ll, &efp->op_array TSRMLS_CC);
785 + for(ep->num_classes=0; sp->value->data.file.classes[ep->num_classes].class_entry != NULL;) { ep->num_classes++; }
786 + ep->val.file.classes = apc_bd_alloc(sizeof(apc_class_t) * ep->num_classes TSRMLS_CC);
787 + for(fcount=0; fcount < ep->num_classes; fcount++) {
788 + 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);
789 + ep->val.file.classes[fcount].name_len = sp->value->data.file.classes[fcount].name_len;
790 + ep->val.file.classes[fcount].class_entry = apc_copy_class_entry(NULL, sp->value->data.file.classes[fcount].class_entry, &ctxt TSRMLS_CC);
791 + ep->val.file.classes[fcount].parent_name = apc_xstrdup(sp->value->data.file.classes[fcount].parent_name, apc_bd_alloc TSRMLS_CC);
793 + apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].name);
794 + apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].parent_name);
795 + apc_swizzle_class_entry(bd, &ll, ep->val.file.classes[fcount].class_entry TSRMLS_CC);
796 + apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].class_entry);
799 + apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.filename);
800 + apc_swizzle_op_array(bd, &ll, bd->entries[count].val.file.op_array TSRMLS_CC);
801 + apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.op_array);
802 + apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions);
803 + apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.classes);
807 + /* TODO: Currently we don't support APC_CACHE_KEY_FILE type. We need to store the path and re-stat on load */
813 + /* append swizzle pointer list to bd */
814 + bd = apc_swizzle_bd(bd, &ll TSRMLS_CC);
815 + zend_llist_destroy(&ll);
816 + zend_hash_destroy(&APCG(apc_bd_alloc_list));
819 + zend_hash_destroy(files);
823 + zend_hash_destroy(user_vars);
833 +/* {{{ apc_bin_load */
834 +int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC) {
836 + apc_bd_entry_t *ep;
840 + zend_op_array *alloc_op_array = NULL;
841 + apc_function_t *alloc_functions = NULL;
842 + apc_class_t *alloc_classes = NULL;
843 + apc_cache_entry_t *cache_entry;
844 + apc_cache_key_t cache_key;
845 + apc_context_t ctxt;
847 + if (bd->swizzled) {
848 + if(apc_unswizzle_bd(bd, flags TSRMLS_CC) < 0) {
855 + for(i = 0; i < bd->num_entries; i++) {
856 + ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
857 + if (!ctxt.pool) { /* TODO need to cleanup previous pools */
858 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
861 + ep = &bd->entries[i];
862 + switch (ep->type) {
863 + case APC_CACHE_KEY_FILE:
864 + /* 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?) */
866 + case APC_CACHE_KEY_FPFILE:
867 + ctxt.copy = APC_COPY_IN_OPCODE;
869 + HANDLE_BLOCK_INTERRUPTIONS();
870 +#if NONBLOCKING_LOCK_AVAILABLE
871 + if(APCG(write_lock)) {
872 + if(!apc_cache_write_lock(apc_cache TSRMLS_CC)) {
873 + HANDLE_UNBLOCK_INTERRUPTIONS();
878 + if(! (alloc_op_array = apc_copy_op_array(NULL, ep->val.file.op_array, &ctxt TSRMLS_CC))) {
881 + apc_bin_fixup_op_array(alloc_op_array);
883 + if(! (alloc_functions = apc_sma_malloc(sizeof(apc_function_t) * (ep->num_functions + 1) TSRMLS_CC))) {
886 + for(i2=0; i2 < ep->num_functions; i2++) {
887 + 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))) {
890 + alloc_functions[i2].name_len = ep->val.file.functions[i2].name_len;
891 + if(! (alloc_functions[i2].function = apc_sma_malloc(sizeof(zend_function) TSRMLS_CC))) {
894 + switch(ep->val.file.functions[i2].function->type) {
895 + case ZEND_INTERNAL_FUNCTION:
896 + case ZEND_OVERLOADED_FUNCTION:
897 + alloc_functions[i2].function->op_array = ep->val.file.functions[i2].function->op_array;
899 + case ZEND_USER_FUNCTION:
900 + case ZEND_EVAL_CODE:
901 + if (!apc_copy_op_array(&alloc_functions[i2].function->op_array, &ep->val.file.functions[i2].function->op_array, &ctxt TSRMLS_CC)) {
904 + apc_bin_fixup_op_array(&alloc_functions[i2].function->op_array);
909 +#ifdef ZEND_ENGINE_2
910 + alloc_functions[i2].function->common.prototype=NULL;
911 + alloc_functions[i2].function->common.fn_flags=ep->val.file.functions[i2].function->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
914 + alloc_functions[i2].name = NULL;
915 + alloc_functions[i2].function = NULL;
917 + if(! (alloc_classes = apc_sma_malloc(sizeof(apc_class_t) * (ep->num_classes + 1) TSRMLS_CC))) {
920 + for(i2=0; i2 < ep->num_classes; i2++) {
921 + 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))) {
924 + alloc_classes[i2].name_len = ep->val.file.classes[i2].name_len;
925 + if(! (alloc_classes[i2].class_entry = apc_copy_class_entry(NULL, ep->val.file.classes[i2].class_entry, &ctxt TSRMLS_CC))) {
928 + apc_bin_fixup_class_entry(alloc_classes[i2].class_entry);
929 + if(! (alloc_classes[i2].parent_name = apc_xstrdup(ep->val.file.classes[i2].parent_name, apc_sma_malloc TSRMLS_CC))) {
930 + if(ep->val.file.classes[i2].parent_name != NULL) {
935 + alloc_classes[i2].name = NULL;
936 + alloc_classes[i2].class_entry = NULL;
938 + if(!(cache_entry = apc_cache_make_file_entry(ep->val.file.filename, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
942 + if (!apc_cache_make_file_key(&cache_key, ep->val.file.filename, PG(include_path), t TSRMLS_CC)) {
946 + if ((ret = apc_cache_insert(apc_cache, cache_key, cache_entry, &ctxt, t TSRMLS_CC)) != 1) {
952 +#if NONBLOCKING_LOCK_AVAILABLE
953 + if(APCG(write_lock)) {
954 + apc_cache_write_unlock(apc_cache TSRMLS_CC);
957 + HANDLE_UNBLOCK_INTERRUPTIONS();
960 + case APC_CACHE_KEY_USER:
961 + ctxt.copy = APC_COPY_IN_USER;
962 + _apc_store(ep->val.user.info, ep->val.user.info_len, ep->val.user.val, ep->val.user.ttl, 0 TSRMLS_CC);
972 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
973 + apc_warning("Unable to allocate memory for apc binary load/dump functionality." TSRMLS_CC);
974 +#if NONBLOCKING_LOCK_AVAILABLE
975 + if(APCG(write_lock)) {
976 + apc_cache_write_unlock(apc_cache TSRMLS_CC);
979 + HANDLE_UNBLOCK_INTERRUPTIONS();
987 + * c-basic-offset: 4
989 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
990 + * vim<600: expandtab sw=4 ts=4 sts=4
992 diff -Naur a/ext/apc/apc_bin.h b/ext/apc/apc_bin.h
993 --- a/ext/apc/apc_bin.h 1970-01-01 01:00:00.000000000 +0100
994 +++ b/ext/apc/apc_bin.h 2012-07-20 00:10:35.000000000 +0200
997 + +----------------------------------------------------------------------+
999 + +----------------------------------------------------------------------+
1000 + | Copyright (c) 2006-2011 The PHP Group |
1001 + +----------------------------------------------------------------------+
1002 + | This source file is subject to version 3.01 of the PHP license, |
1003 + | that is bundled with this package in the file LICENSE, and is |
1004 + | available through the world-wide-web at the following url: |
1005 + | http://www.php.net/license/3_01.txt |
1006 + | If you did not receive a copy of the PHP license and are unable to |
1007 + | obtain it through the world-wide-web, please send a note to |
1008 + | license@php.net so we can mail you a copy immediately. |
1009 + +----------------------------------------------------------------------+
1010 + | Authors: Brian Shire <shire@php.net> |
1011 + +----------------------------------------------------------------------+
1015 +/* $Id: apc_bin.h 307048 2011-01-03 23:53:17Z kalle $ */
1017 +#ifndef APC_BINDUMP_H
1018 +#define APC_BINDUMP_H
1021 +#include "apc_php.h"
1022 +#include "ext/standard/basic_functions.h"
1024 +/* APC binload flags */
1025 +#define APC_BIN_VERIFY_MD5 1 << 0
1026 +#define APC_BIN_VERIFY_CRC32 1 << 1
1028 +typedef struct _apc_bd_entry_t {
1029 + unsigned char type;
1030 + uint num_functions;
1032 + apc_cache_entry_value_t val;
1035 +typedef struct _apc_bd_t {
1036 + unsigned int size;
1038 + unsigned char md5[16];
1040 + unsigned int num_entries;
1041 + apc_bd_entry_t *entries;
1042 + int num_swizzled_ptrs;
1043 + void ***swizzled_ptrs;
1046 +apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC);
1047 +int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC);
1052 + * Local variables:
1054 + * c-basic-offset: 4
1056 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1057 + * vim<600: expandtab sw=4 ts=4 sts=4
1059 diff -Naur a/ext/apc/apc.c b/ext/apc/apc.c
1060 --- a/ext/apc/apc.c 1970-01-01 01:00:00.000000000 +0100
1061 +++ b/ext/apc/apc.c 2012-07-20 00:10:35.000000000 +0200
1064 + +----------------------------------------------------------------------+
1066 + +----------------------------------------------------------------------+
1067 + | Copyright (c) 2006-2011 The PHP Group |
1068 + +----------------------------------------------------------------------+
1069 + | This source file is subject to version 3.01 of the PHP license, |
1070 + | that is bundled with this package in the file LICENSE, and is |
1071 + | available through the world-wide-web at the following url: |
1072 + | http://www.php.net/license/3_01.txt |
1073 + | If you did not receive a copy of the PHP license and are unable to |
1074 + | obtain it through the world-wide-web, please send a note to |
1075 + | license@php.net so we can mail you a copy immediately. |
1076 + +----------------------------------------------------------------------+
1077 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
1078 + | George Schlossnagle <george@omniti.com> |
1079 + | Rasmus Lerdorf <rasmus@php.net> |
1080 + | Arun C. Murthy <arunc@yahoo-inc.com> |
1081 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
1082 + +----------------------------------------------------------------------+
1084 + This software was contributed to PHP by Community Connect Inc. in 2002
1085 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1086 + Future revisions and derivatives of this source code must acknowledge
1087 + Community Connect Inc. as the original contributor of this module by
1088 + leaving this note intact in the source code.
1090 + All other licensing and usage conditions are those of the PHP Group.
1094 +/* $Id: apc.c 326710 2012-07-19 20:51:04Z rasmus $ */
1097 +#include "apc_zend.h"
1098 +#include "apc_cache.h"
1099 +#include "apc_globals.h"
1102 +#if HAVE_PCRE || HAVE_BUNDLED_PCRE
1103 +/* Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
1104 +# if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
1105 +# include "apc_php_pcre.h"
1107 +# include "ext/pcre/php_pcre.h"
1109 +# include "ext/standard/php_smart_str.h"
1112 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
1114 +/* {{{ memory allocation wrappers */
1116 +void* apc_emalloc(size_t n TSRMLS_DC)
1118 + void* p = malloc(n);
1120 + apc_error("apc_emalloc: malloc failed to allocate %u bytes:" TSRMLS_CC, n);
1126 +void* apc_erealloc(void* p, size_t n TSRMLS_DC)
1129 + new = realloc(p, n);
1130 + if (new == NULL) {
1131 + apc_error("apc_erealloc: realloc failed to allocate %u bytes:" TSRMLS_CC, n);
1137 +void apc_efree(void* p TSRMLS_DC)
1140 + apc_error("apc_efree: attempt to free null pointer" TSRMLS_CC);
1146 +char* APC_ALLOC apc_estrdup(const char* s TSRMLS_DC)
1155 + dup = (char*) malloc(len+1);
1156 + if (dup == NULL) {
1157 + apc_error("apc_estrdup: malloc failed to allocate %u bytes:" TSRMLS_CC, len+1);
1160 + memcpy(dup, s, len);
1165 +void* APC_ALLOC apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC)
1167 + return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f TSRMLS_CC) : NULL;
1170 +void* APC_ALLOC apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC)
1174 + if (p != NULL && (q = f(n TSRMLS_CC)) != NULL) {
1183 +/* {{{ console display functions */
1185 +# define APC_PRINT_FUNCTION_PARAMETER TSRMLS_C
1187 +# define APC_PRINT_FUNCTION_PARAMETER format
1190 +#define APC_PRINT_FUNCTION(name, verbosity) \
1191 + void apc_##name(const char *format TSRMLS_DC, ...) \
1195 + va_start(args, APC_PRINT_FUNCTION_PARAMETER); \
1196 + php_verror(NULL, "", verbosity, format, args TSRMLS_CC); \
1200 +APC_PRINT_FUNCTION(error, E_ERROR)
1201 +APC_PRINT_FUNCTION(warning, E_WARNING)
1202 +APC_PRINT_FUNCTION(notice, E_NOTICE)
1204 +#ifdef __DEBUG_APC__
1205 +APC_PRINT_FUNCTION(debug, E_NOTICE)
1207 +void apc_debug(const char *format TSRMLS_DC, ...) {}
1211 +/* {{{ string and text manipulation */
1213 +char* apc_append(const char* s, const char* t TSRMLS_DC)
1222 + p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char) TSRMLS_CC);
1223 + memcpy(p, s, slen);
1224 + memcpy(p + slen, t, tlen + 1);
1229 +char* apc_substr(const char* s, int start, int length TSRMLS_DC)
1232 + int src_len = strlen(s);
1234 + /* bring start into range */
1238 + else if (start >= src_len) {
1239 + start = src_len - 1;
1242 + /* bring length into range */
1243 + if (length < 0 || src_len - start < length) {
1244 + length = src_len - start;
1247 + /* create the substring */
1248 + substr = apc_xmemcpy(s + start, length + 1, apc_emalloc TSRMLS_CC);
1249 + substr[length] = '\0';
1253 +char** apc_tokenize(const char* s, char delim TSRMLS_DC)
1255 + char** tokens; /* array of tokens, NULL terminated */
1256 + int size; /* size of tokens array */
1257 + int n; /* index of next token in tokens array */
1258 + int cur; /* current position in input string */
1259 + int end; /* final legal position in input string */
1260 + int next; /* position of next delimiter in input */
1269 + end = strlen(s) - 1;
1271 + tokens = (char**) apc_emalloc(size * sizeof(char*) TSRMLS_CC);
1274 + while (cur <= end) {
1275 + /* search for the next delimiter */
1276 + char* p = strchr(s + cur, delim);
1277 + next = p ? p-s : end+1;
1279 + /* resize token array if necessary */
1280 + if (n == size-1) {
1282 + tokens = (char**) apc_erealloc(tokens, size * sizeof(char*) TSRMLS_CC);
1285 + /* save the current token */
1286 + tokens[n] = apc_substr(s, cur, next-cur TSRMLS_CC);
1288 + tokens[++n] = NULL;
1298 +/* {{{ apc_win32_restat */
1300 +static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
1303 + BY_HANDLE_FILE_INFORMATION hInfo;
1305 + hFile = CreateFile(fileinfo->fullpath, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1308 + apc_debug("Cannot create a file HANDLE for %s\n" TSRMLS_CC, fileinfo->fullpath);
1312 + if (!GetFileInformationByHandle(hFile, &hInfo)) {
1313 + apc_debug("Cannot get file information from handle\n" TSRMLS_CC);
1314 + CloseHandle(hFile);
1318 + CloseHandle(hFile);
1320 + fileinfo->st_buf.sb.st_dev = hInfo.dwVolumeSerialNumber;
1321 + fileinfo->st_buf.sb.st_ino = (((apc_ino_t)(hInfo.nFileIndexHigh) << 32) | (apc_ino_t) hInfo.nFileIndexLow);
1326 +static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
1333 +/* {{{ apc_search_paths */
1334 +/* similar to php_stream_stat_path */
1335 +#define APC_URL_STAT(wrapper, filename, pstatbuf) \
1336 + ((wrapper)->wops->url_stat((wrapper), (filename), PHP_STREAM_URL_STAT_QUIET, (pstatbuf), NULL TSRMLS_CC))
1338 +/* copy out to path_buf if path_for_open isn't the same as filename */
1339 +#define COPY_IF_CHANGED(p) \
1340 + (char*) (((p) == filename) ? filename : \
1341 + (strlcpy((char*)fileinfo->path_buf, (p), sizeof(fileinfo->path_buf))) \
1342 + ? (fileinfo->path_buf) : NULL)
1344 +/* len checks can be skipped here because filename is NUL terminated */
1345 +#define IS_RELATIVE_PATH(filename, len) \
1346 + ((filename) && (filename[0] == '.' && \
1347 + (IS_SLASH(filename[1]) || \
1348 + (filename[1] == '.' && \
1349 + IS_SLASH(filename[2])))))
1351 +/* {{{ stupid stringifcation */
1352 +#if DEFAULT_SLASH == '/'
1353 + #define DEFAULT_SLASH_STRING "/"
1354 +#elif DEFAULT_SLASH == '\\'
1355 + #define DEFAULT_SLASH_STRING "\\"
1357 + #error "Unknown value for DEFAULT_SLASH"
1361 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC)
1363 + char** paths = NULL;
1365 + int exec_fname_length;
1368 + php_stream_wrapper *wrapper = NULL;
1369 + char *path_for_open = NULL;
1371 + assert(filename && fileinfo);
1374 + wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC);
1376 + if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) {
1380 + if(wrapper != &php_plain_files_wrapper) {
1381 + if(APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
1382 + fileinfo->fullpath = COPY_IF_CHANGED(path_for_open);
1383 + return apc_restat(fileinfo TSRMLS_CC);
1385 + return -1; /* cannot stat */
1388 + if (IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) &&
1389 + APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
1390 + fileinfo->fullpath = COPY_IF_CHANGED(path_for_open);
1391 + return apc_restat(fileinfo TSRMLS_CC);
1394 + if (!IS_RELATIVE_PATH(path_for_open, strlen(path_for_open))) {
1395 + paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR TSRMLS_CC);
1399 + /* for each directory in paths, look for filename inside */
1400 + for (i = 0; paths[i]; i++) {
1401 + snprintf(fileinfo->path_buf, sizeof(fileinfo->path_buf), "%s%c%s", paths[i], DEFAULT_SLASH, path_for_open);
1402 + if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
1403 + fileinfo->fullpath = (char*) fileinfo->path_buf;
1408 + /* in cli mode PHP explicitly checks the cwd, so we should as well */
1409 + if(APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
1410 + snprintf(fileinfo->path_buf, sizeof(fileinfo->path_buf), ".%c%s", DEFAULT_SLASH, path_for_open);
1411 + if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
1412 + fileinfo->fullpath = (char*) fileinfo->path_buf;
1417 + /* read cwd and try to fake up fullpath */
1418 + fileinfo->path_buf[0] = '\0';
1419 + if(VCWD_GETCWD(fileinfo->path_buf, sizeof(fileinfo->path_buf))) {
1420 + strlcat(fileinfo->path_buf, DEFAULT_SLASH_STRING, sizeof(fileinfo->path_buf));
1421 + strlcat(fileinfo->path_buf, path_for_open, sizeof(fileinfo->path_buf));
1422 + if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
1423 + fileinfo->fullpath = (char*) fileinfo->path_buf;
1424 + return apc_restat(fileinfo TSRMLS_CC);
1429 + /* check in path of the calling scripts' current working directory */
1430 + /* modified from main/streams/plain_wrapper.c */
1431 + if(!found && zend_is_executing(TSRMLS_C)) {
1432 + exec_fname = zend_get_executed_filename(TSRMLS_C);
1433 + exec_fname_length = strlen(exec_fname);
1434 + while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
1435 + if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
1436 + /* not: [no active file] or no path */
1437 + memcpy(fileinfo->path_buf, exec_fname, exec_fname_length);
1438 + fileinfo->path_buf[exec_fname_length] = DEFAULT_SLASH;
1439 + strlcpy(fileinfo->path_buf +exec_fname_length +1, path_for_open,sizeof(fileinfo->path_buf)-exec_fname_length-1);
1440 + /* apc_warning("filename: %s, exec_fname: %s, fileinfo->path_buf: %s" TSRMLS_CC, path_for_open, exec_fname, fileinfo->path_buf); */
1441 + if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) {
1442 + fileinfo->fullpath = (char*) fileinfo->path_buf;
1449 + /* free the value returned by apc_tokenize */
1450 + for (i = 0; paths[i]; i++) {
1451 + apc_efree(paths[i] TSRMLS_CC);
1453 + apc_efree(paths TSRMLS_CC);
1456 + return found ? apc_restat(fileinfo TSRMLS_CC) : -1;
1461 +/* {{{ regular expression wrapper functions */
1463 +#if (HAVE_PCRE || HAVE_BUNDLED_PCRE)
1469 +#define APC_ADD_PATTERN(match, pat) do {\
1470 + if(match.len > 1) {\
1471 + smart_str_appendc(&match, '|');\
1473 + smart_str_appendc(&match, '(');\
1475 + if(*pat == '/') smart_str_appendc(&match, '\\');\
1477 + smart_str_appendc(&match, *(pat++));\
1479 + smart_str_appendc(&match, ')');\
1482 +#define APC_COMPILE_PATTERN(re, match) do {\
1483 + if(match.len > 2) { /* more than just "//" */\
1484 + if (((re) = pcre_get_compiled_regex(match.c, NULL, NULL TSRMLS_CC)) == NULL) {\
1485 + apc_warning("apc_regex_compile_array: invalid expression '%s'" TSRMLS_CC, match.c); \
1486 + smart_str_free(&match);\
1494 +void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
1498 + smart_str pmatch = {0,};
1499 + smart_str nmatch = {0,};
1505 + regs = (apc_regex*) apc_emalloc(sizeof(apc_regex) TSRMLS_CC);
1507 + smart_str_appendc(&pmatch, '/');
1508 + smart_str_appendc(&nmatch, '/');
1510 + for (npat = 0; patterns[npat] != NULL; npat++) {
1511 + pattern = patterns[npat];
1512 + if(pattern[0] == '+') {
1513 + pattern += sizeof(char);
1514 + APC_ADD_PATTERN(pmatch, pattern);
1516 + if(pattern[0] == '-') pattern += sizeof(char);
1517 + APC_ADD_PATTERN(nmatch, pattern);
1520 + smart_str_appendc(&pmatch, '/');
1521 + smart_str_appendc(&nmatch, '/');
1523 + smart_str_0(&nmatch);
1524 + smart_str_0(&pmatch);
1526 + APC_COMPILE_PATTERN(regs->preg, pmatch);
1527 + APC_COMPILE_PATTERN(regs->nreg, nmatch);
1529 + smart_str_free(&pmatch);
1530 + smart_str_free(&nmatch);
1532 + return (void*) regs;
1535 +void apc_regex_destroy_array(void* p TSRMLS_DC)
1538 + apc_regex* regs = (apc_regex*) p;
1539 + apc_efree(regs TSRMLS_CC);
1543 +#define APC_MATCH_PATTERN(re, input, output) do {\
1544 + if (re && pcre_exec(re, NULL, (input), strlen(input), 0, 0, NULL, 0) >= 0) {\
1550 +int apc_regex_match_array(void* p, const char* input)
1557 + regs = (apc_regex*) p;
1559 + APC_MATCH_PATTERN(regs->preg, input, APC_POSITIVE_MATCH);
1560 + APC_MATCH_PATTERN(regs->nreg, input, APC_NEGATIVE_MATCH);
1564 +#else /* no pcre */
1565 +void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
1567 + if(patterns && patterns[0] != NULL) {
1568 + apc_warning("pcre missing, disabling filters" TSRMLS_CC);
1572 +void apc_regex_destroy_array(void* p)
1576 +int apc_regex_match_array(void* p, const char* input)
1583 +/* {{{ crc32 implementation */
1585 +/* this table was generated by crc32gen() */
1586 +static unsigned int crc32tab[] = {
1587 + /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
1588 + /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
1589 + /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
1590 + /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
1591 + /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
1592 + /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
1593 + /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
1594 + /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
1595 + /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
1596 + /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
1597 + /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
1598 + /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
1599 + /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
1600 + /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
1601 + /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
1602 + /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
1603 + /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
1604 + /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
1605 + /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
1606 + /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
1607 + /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
1608 + /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
1609 + /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
1610 + /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
1611 + /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
1612 + /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
1613 + /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
1614 + /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
1615 + /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
1616 + /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
1617 + /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
1618 + /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
1619 + /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
1620 + /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
1621 + /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
1622 + /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
1623 + /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
1624 + /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
1625 + /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
1626 + /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
1627 + /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
1628 + /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
1629 + /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
1630 + /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
1631 + /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
1632 + /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
1633 + /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
1634 + /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
1635 + /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
1636 + /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
1637 + /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
1638 + /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
1639 + /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
1640 + /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
1641 + /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
1642 + /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
1643 + /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
1644 + /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
1645 + /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
1646 + /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
1647 + /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
1648 + /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
1649 + /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
1650 + /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
1653 +unsigned int apc_crc32(const char* buf, int len)
1659 + /* preconditioning */
1662 + for (i = 0; i < len; i++) {
1663 + k = (crc ^ buf[i]) & 0x000000FF;
1664 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
1667 + /* postconditioning */
1671 +/* crc32gen: generate the nth (0..255) crc32 table value */
1673 +static unsigned long crc32gen(int n)
1676 + unsigned long crc;
1679 + for (i = 8; i >= 0; i--) {
1681 + crc = (crc >> 1) ^ 0xEDB88320;
1694 +/* {{{ apc_flip_hash() */
1695 +HashTable* apc_flip_hash(HashTable *hash) {
1696 + zval **entry, *data;
1697 + HashTable *new_hash;
1700 + if(hash == NULL) return hash;
1702 + MAKE_STD_ZVAL(data);
1703 + ZVAL_LONG(data, 1);
1705 + new_hash = emalloc(sizeof(HashTable));
1706 + zend_hash_init(new_hash, hash->nTableSize, NULL, ZVAL_PTR_DTOR, 0);
1708 + zend_hash_internal_pointer_reset_ex(hash, &pos);
1709 + while (zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) {
1710 + if(Z_TYPE_PP(entry) == IS_STRING) {
1711 + zend_hash_update(new_hash, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) +1, &data, sizeof(data), NULL);
1713 + zend_hash_index_update(new_hash, Z_LVAL_PP(entry), &data, sizeof(data), NULL);
1716 + zend_hash_move_forward_ex(hash, &pos);
1718 + zval_ptr_dtor(&data);
1726 + * Local variables:
1728 + * c-basic-offset: 4
1730 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
1731 + * vim<600: expandtab sw=4 ts=4 sts=4
1733 diff -Naur a/ext/apc/apc_cache.c b/ext/apc/apc_cache.c
1734 --- a/ext/apc/apc_cache.c 1970-01-01 01:00:00.000000000 +0100
1735 +++ b/ext/apc/apc_cache.c 2012-07-20 00:10:35.000000000 +0200
1738 + +----------------------------------------------------------------------+
1740 + +----------------------------------------------------------------------+
1741 + | Copyright (c) 2006-2011 The PHP Group |
1742 + +----------------------------------------------------------------------+
1743 + | This source file is subject to version 3.01 of the PHP license, |
1744 + | that is bundled with this package in the file LICENSE, and is |
1745 + | available through the world-wide-web at the following url: |
1746 + | http://www.php.net/license/3_01.txt |
1747 + | If you did not receive a copy of the PHP license and are unable to |
1748 + | obtain it through the world-wide-web, please send a note to |
1749 + | license@php.net so we can mail you a copy immediately. |
1750 + +----------------------------------------------------------------------+
1751 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
1752 + | Rasmus Lerdorf <rasmus@php.net> |
1753 + | Arun C. Murthy <arunc@yahoo-inc.com> |
1754 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
1755 + +----------------------------------------------------------------------+
1757 + This software was contributed to PHP by Community Connect Inc. in 2002
1758 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1759 + Future revisions and derivatives of this source code must acknowledge
1760 + Community Connect Inc. as the original contributor of this module by
1761 + leaving this note intact in the source code.
1763 + All other licensing and usage conditions are those of the PHP Group.
1767 +/* $Id: apc_cache.c 325482 2012-05-01 00:09:36Z rasmus $ */
1769 +#include "apc_cache.h"
1770 +#include "apc_zend.h"
1771 +#include "apc_sma.h"
1772 +#include "apc_globals.h"
1775 +#include "ext/standard/md5.h"
1777 +/* TODO: rehash when load factor exceeds threshold */
1779 +#define CHECK(p) { if ((p) == NULL) return NULL; }
1781 +/* {{{ key_equals */
1782 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
1785 +static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC);
1788 +static unsigned long hash(apc_cache_key_t key)
1790 + return (unsigned long)(key.data.file.device + key.data.file.inode);
1794 +/* {{{ string_nhash_8 */
1795 +#define string_nhash_8(s,len) (unsigned long)(zend_inline_hash_func((s), len))
1798 +/* {{{ murmurhash */
1800 +static inline unsigned long murmurhash(const char *skey, size_t keylen)
1802 + const long m = 0x7fd652ad;
1803 + const long r = 16;
1804 + unsigned int h = 0xdeadbeef;
1806 + while(keylen >= 4)
1808 + h += *(unsigned int*)skey;
1819 + h += skey[2] << 16;
1821 + h += skey[1] << 8;
1839 +/* {{{ make_prime */
1840 +static int const primes[] = {
1865 +static int make_prime(int n)
1867 + int *k = (int*)primes;
1869 + if((*k) > n) return *k;
1876 +/* {{{ make_slot */
1877 +slot_t* make_slot(apc_cache_key_t *key, apc_cache_entry_t* value, slot_t* next, time_t t TSRMLS_DC)
1879 + slot_t* p = apc_pool_alloc(value->pool, sizeof(slot_t));
1881 + if (!p) return NULL;
1883 + if(key->type == APC_CACHE_KEY_USER) {
1884 + char *identifier = (char*) apc_pmemcpy(key->data.user.identifier, key->data.user.identifier_len, value->pool TSRMLS_CC);
1885 + if (!identifier) {
1888 + key->data.user.identifier = identifier;
1889 + } else if(key->type == APC_CACHE_KEY_FPFILE) {
1890 + char *fullpath = (char*) apc_pstrdup(key->data.fpfile.fullpath, value->pool TSRMLS_CC);
1894 + key->data.fpfile.fullpath = fullpath;
1900 + p->creation_time = t;
1901 + p->access_time = t;
1902 + p->deletion_time = 0;
1907 +/* {{{ free_slot */
1908 +static void free_slot(slot_t* slot TSRMLS_DC)
1910 + apc_pool_destroy(slot->value->pool TSRMLS_CC);
1914 +/* {{{ remove_slot */
1915 +static void remove_slot(apc_cache_t* cache, slot_t** slot TSRMLS_DC)
1917 + slot_t* dead = *slot;
1918 + *slot = (*slot)->next;
1920 + cache->header->mem_size -= dead->value->mem_size;
1921 + CACHE_FAST_DEC(cache, cache->header->num_entries);
1922 + if (dead->value->ref_count <= 0) {
1923 + free_slot(dead TSRMLS_CC);
1926 + dead->next = cache->header->deleted_list;
1927 + dead->deletion_time = time(0);
1928 + cache->header->deleted_list = dead;
1933 +/* {{{ process_pending_removals */
1934 +static void process_pending_removals(apc_cache_t* cache TSRMLS_DC)
1939 + /* This function scans the list of removed cache entries and deletes any
1940 + * entry whose reference count is zero (indicating that it is no longer
1941 + * being executed) or that has been on the pending list for more than
1942 + * cache->gc_ttl seconds (we issue a warning in the latter case).
1945 + if (!cache->header->deleted_list)
1948 + slot = &cache->header->deleted_list;
1951 + while (*slot != NULL) {
1952 + int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
1954 + if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
1955 + slot_t* dead = *slot;
1957 + if (dead->value->ref_count > 0) {
1958 + switch(dead->value->type) {
1959 + case APC_CACHE_ENTRY_FILE:
1960 + apc_debug("GC cache entry '%s' (dev=%d ino=%d) was on gc-list for %d seconds" TSRMLS_CC,
1961 + dead->value->data.file.filename, dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
1963 + case APC_CACHE_ENTRY_USER:
1964 + apc_debug("GC cache entry '%s' was on gc-list for %d seconds" TSRMLS_CC, dead->value->data.user.info, gc_sec);
1968 + *slot = dead->next;
1969 + free_slot(dead TSRMLS_CC);
1972 + slot = &(*slot)->next;
1978 +/* {{{ prevent_garbage_collection */
1979 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
1981 + /* set reference counts on zend objects to an arbitrarily high value to
1982 + * prevent garbage collection after execution */
1984 + enum { BIG_VALUE = 1000 };
1986 + if(entry->data.file.op_array) {
1987 + entry->data.file.op_array->refcount[0] = BIG_VALUE;
1989 + if (entry->data.file.functions) {
1991 + apc_function_t* fns = entry->data.file.functions;
1992 + for (i=0; fns[i].function != NULL; i++) {
1993 + *(fns[i].function->op_array.refcount) = BIG_VALUE;
1996 + if (entry->data.file.classes) {
1998 + apc_class_t* classes = entry->data.file.classes;
1999 + for (i=0; classes[i].class_entry != NULL; i++) {
2000 + classes[i].class_entry->refcount = BIG_VALUE;
2006 +/* {{{ apc_cache_create */
2007 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC)
2009 + apc_cache_t* cache;
2013 + num_slots = make_prime(size_hint > 0 ? size_hint : 2000);
2015 + cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t) TSRMLS_CC);
2016 + cache_size = sizeof(cache_header_t) + num_slots*sizeof(slot_t*);
2018 + cache->shmaddr = apc_sma_malloc(cache_size TSRMLS_CC);
2019 + if(!cache->shmaddr) {
2020 + apc_error("Unable to allocate shared memory for cache structures. (Perhaps your shared memory size isn't large enough?). " TSRMLS_CC);
2023 + memset(cache->shmaddr, 0, cache_size);
2025 + cache->header = (cache_header_t*) cache->shmaddr;
2026 + cache->header->num_hits = 0;
2027 + cache->header->num_misses = 0;
2028 + cache->header->deleted_list = NULL;
2029 + cache->header->start_time = time(NULL);
2030 + cache->header->expunges = 0;
2031 + cache->header->busy = 0;
2033 + cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(cache_header_t));
2034 + cache->num_slots = num_slots;
2035 + cache->gc_ttl = gc_ttl;
2037 + CREATE_LOCK(cache->header->lock);
2038 +#if NONBLOCKING_LOCK_AVAILABLE
2039 + CREATE_LOCK(cache->header->wrlock);
2041 + memset(cache->slots, 0, sizeof(slot_t*)*num_slots);
2042 + cache->expunge_cb = apc_cache_expunge;
2043 + cache->has_lock = 0;
2049 +/* {{{ apc_cache_destroy */
2050 +void apc_cache_destroy(apc_cache_t* cache TSRMLS_DC)
2052 + DESTROY_LOCK(cache->header->lock);
2053 +#if NONBLOCKING_LOCK_AVAILABLE
2054 + DESTROY_LOCK(cache->header->wrlock);
2056 + apc_efree(cache TSRMLS_CC);
2060 +/* {{{ apc_cache_clear */
2061 +void apc_cache_clear(apc_cache_t* cache TSRMLS_DC)
2065 + if(!cache) return;
2067 + CACHE_LOCK(cache);
2068 + cache->header->busy = 1;
2069 + cache->header->num_hits = 0;
2070 + cache->header->num_misses = 0;
2071 + cache->header->start_time = time(NULL);
2072 + cache->header->expunges = 0;
2074 + for (i = 0; i < cache->num_slots; i++) {
2075 + slot_t* p = cache->slots[i];
2077 + remove_slot(cache, &p TSRMLS_CC);
2079 + cache->slots[i] = NULL;
2082 + memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2084 + cache->header->busy = 0;
2085 + CACHE_UNLOCK(cache);
2089 +/* {{{ apc_cache_expunge */
2090 +static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC)
2097 + if(!cache) return;
2101 + * If cache->ttl is not set, we wipe out the entire cache when
2102 + * we run out of space.
2104 + CACHE_SAFE_LOCK(cache);
2105 + process_pending_removals(cache TSRMLS_CC);
2106 + if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) {
2107 + /* probably a queued up expunge, we don't need to do this */
2108 + CACHE_SAFE_UNLOCK(cache);
2111 + cache->header->busy = 1;
2112 + CACHE_FAST_INC(cache, cache->header->expunges);
2114 + for (i = 0; i < cache->num_slots; i++) {
2115 + slot_t* p = cache->slots[i];
2117 + remove_slot(cache, &p TSRMLS_CC);
2119 + cache->slots[i] = NULL;
2121 + memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2122 + cache->header->busy = 0;
2123 + CACHE_SAFE_UNLOCK(cache);
2127 + * If the ttl for the cache is set we walk through and delete stale
2128 + * entries. For the user cache that is slightly confusing since
2129 + * we have the individual entry ttl's we can look at, but that would be
2130 + * too much work. So if you want the user cache expunged, set a high
2131 + * default apc.user_ttl and still provide a specific ttl for each entry
2135 + CACHE_SAFE_LOCK(cache);
2136 + process_pending_removals(cache TSRMLS_CC);
2137 + if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) {
2138 + /* probably a queued up expunge, we don't need to do this */
2139 + CACHE_SAFE_UNLOCK(cache);
2142 + cache->header->busy = 1;
2143 + CACHE_FAST_INC(cache, cache->header->expunges);
2144 + for (i = 0; i < cache->num_slots; i++) {
2145 + p = &cache->slots[i];
2148 + * For the user cache we look at the individual entry ttl values
2149 + * and if not set fall back to the default ttl for the user cache
2151 + if((*p)->value->type == APC_CACHE_ENTRY_USER) {
2152 + if((*p)->value->data.user.ttl) {
2153 + if((time_t) ((*p)->creation_time + (*p)->value->data.user.ttl) < t) {
2154 + remove_slot(cache, p TSRMLS_CC);
2157 + } else if(cache->ttl) {
2158 + if((*p)->creation_time + cache->ttl < t) {
2159 + remove_slot(cache, p TSRMLS_CC);
2163 + } else if((*p)->access_time < (t - cache->ttl)) {
2164 + remove_slot(cache, p TSRMLS_CC);
2171 + if (!apc_sma_get_avail_size(size)) {
2172 + /* TODO: re-do this to remove goto across locked sections */
2175 + memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2176 + cache->header->busy = 0;
2177 + CACHE_SAFE_UNLOCK(cache);
2182 +/* {{{ apc_cache_insert */
2183 +static inline int _apc_cache_insert(apc_cache_t* cache,
2184 + apc_cache_key_t key,
2185 + apc_cache_entry_t* value,
2186 + apc_context_t* ctxt,
2196 + apc_debug("Inserting [%s]\n" TSRMLS_CC, value->data.file.filename);
2198 + process_pending_removals(cache TSRMLS_CC);
2200 + slot = &cache->slots[key.h % cache->num_slots];
2203 + if(key.type == (*slot)->key.type) {
2204 + if(key.type == APC_CACHE_KEY_FILE) {
2205 + if(key_equals((*slot)->key.data.file, key.data.file)) {
2206 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
2207 + if (ctxt->force_update || (*slot)->key.mtime != key.mtime) {
2208 + remove_slot(cache, slot TSRMLS_CC);
2212 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
2213 + remove_slot(cache, slot TSRMLS_CC);
2216 + } else { /* APC_CACHE_KEY_FPFILE */
2217 + if((key.h == (*slot)->key.h) &&
2218 + !memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
2219 + /* Hrm.. it's already here, remove it and insert new one */
2220 + remove_slot(cache, slot TSRMLS_CC);
2222 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
2223 + remove_slot(cache, slot TSRMLS_CC);
2228 + slot = &(*slot)->next;
2231 + if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) {
2235 + value->mem_size = ctxt->pool->size;
2236 + cache->header->mem_size += ctxt->pool->size;
2237 + CACHE_FAST_INC(cache, cache->header->num_entries);
2238 + CACHE_FAST_INC(cache, cache->header->num_inserts);
2244 +/* {{{ apc_cache_insert */
2245 +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)
2248 + CACHE_LOCK(cache);
2249 + rval = _apc_cache_insert(cache, key, value, ctxt, t TSRMLS_CC);
2250 + CACHE_UNLOCK(cache);
2255 +/* {{{ apc_cache_insert */
2256 +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)
2261 + rval = emalloc(sizeof(int) * num_entries);
2262 + CACHE_LOCK(cache);
2263 + for (i=0; i < num_entries; i++) {
2265 + ctxt->pool = values[i]->pool;
2266 + rval[i] = _apc_cache_insert(cache, keys[i], values[i], ctxt, t TSRMLS_CC);
2269 + CACHE_UNLOCK(cache);
2275 +/* {{{ apc_cache_user_insert */
2276 +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)
2279 + unsigned int keylen = key.data.user.identifier_len;
2280 + apc_keyid_t *lastkey = &cache->header->lastkey;
2286 + if(apc_cache_busy(cache)) {
2287 + /* cache cleanup in progress, do not wait */
2291 + if(apc_cache_is_last_key(cache, &key, t TSRMLS_CC)) {
2292 + /* potential cache slam */
2296 + CACHE_LOCK(cache);
2298 + memset(lastkey, 0, sizeof(apc_keyid_t));
2300 + lastkey->h = key.h;
2301 + lastkey->keylen = keylen;
2302 + lastkey->mtime = t;
2304 + lastkey->tid = tsrm_thread_id();
2306 + lastkey->pid = getpid();
2309 + /* we do not reset lastkey after the insert. Whether it is inserted
2310 + * or not, another insert in the same second is always a bad idea.
2313 + process_pending_removals(cache TSRMLS_CC);
2315 + slot = &cache->slots[key.h % cache->num_slots];
2318 + if (((*slot)->key.h == key.h) &&
2319 + (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, keylen))) {
2321 + * At this point we have found the user cache entry. If we are doing
2322 + * an exclusive insert (apc_add) we are going to bail right away if
2323 + * the user entry already exists and it has no ttl, or
2324 + * there is a ttl and the entry has not timed out yet.
2326 + if(exclusive && ( !(*slot)->value->data.user.ttl ||
2327 + ( (*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t )
2331 + remove_slot(cache, slot TSRMLS_CC);
2335 + * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of
2336 + * slot entries so we don't always have to skip past a bunch of stale entries. We check
2337 + * for staleness here and get rid of them by first checking to see if the cache has a global
2338 + * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
2339 + * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
2341 + if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) ||
2342 + ((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
2343 + remove_slot(cache, slot TSRMLS_CC);
2346 + slot = &(*slot)->next;
2349 + if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) {
2353 + value->mem_size = ctxt->pool->size;
2354 + cache->header->mem_size += ctxt->pool->size;
2356 + CACHE_FAST_INC(cache, cache->header->num_entries);
2357 + CACHE_FAST_INC(cache, cache->header->num_inserts);
2359 + CACHE_UNLOCK(cache);
2364 + CACHE_UNLOCK(cache);
2370 +/* {{{ apc_cache_find_slot */
2371 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC)
2374 + volatile slot_t* retval = NULL;
2376 + CACHE_RDLOCK(cache);
2377 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
2378 + else slot = &cache->slots[key.h % cache->num_slots];
2381 + if(key.type == (*slot)->key.type) {
2382 + if(key.type == APC_CACHE_KEY_FILE) {
2383 + if(key_equals((*slot)->key.data.file, key.data.file)) {
2384 + if((*slot)->key.mtime != key.mtime) {
2385 + #if (USE_READ_LOCKS == 0)
2386 + /* this is merely a memory-friendly optimization, if we do have a write-lock
2387 + * might as well move this to the deleted_list right-away. Otherwise an insert
2388 + * of the same key wil do it (or an expunge, *eventually*).
2390 + remove_slot(cache, slot TSRMLS_CC);
2392 + CACHE_SAFE_INC(cache, cache->header->num_misses);
2393 + CACHE_RDUNLOCK(cache);
2396 + CACHE_SAFE_INC(cache, (*slot)->num_hits);
2397 + CACHE_SAFE_INC(cache, (*slot)->value->ref_count);
2398 + (*slot)->access_time = t;
2399 + prevent_garbage_collection((*slot)->value);
2400 + CACHE_FAST_INC(cache, cache->header->num_hits);
2402 + CACHE_RDUNLOCK(cache);
2403 + return (slot_t*)retval;
2405 + } else { /* APC_CACHE_KEY_FPFILE */
2406 + if(((*slot)->key.h == key.h) &&
2407 + !memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
2409 + CACHE_SAFE_INC(cache, (*slot)->num_hits);
2410 + CACHE_SAFE_INC(cache, (*slot)->value->ref_count);
2411 + (*slot)->access_time = t;
2412 + prevent_garbage_collection((*slot)->value);
2413 + CACHE_FAST_INC(cache, cache->header->num_hits);
2415 + CACHE_RDUNLOCK(cache);
2416 + return (slot_t*)retval;
2420 + slot = &(*slot)->next;
2422 + CACHE_FAST_INC(cache, cache->header->num_misses);
2423 + CACHE_RDUNLOCK(cache);
2428 +/* {{{ apc_cache_find */
2429 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC)
2431 + slot_t * slot = apc_cache_find_slot(cache, key, t TSRMLS_CC);
2432 + apc_debug("apc_cache_find [%i]\n" TSRMLS_CC, key.h);
2433 + return (slot) ? slot->value : NULL;
2437 +/* {{{ apc_cache_user_find */
2438 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC)
2441 + volatile apc_cache_entry_t* value = NULL;
2444 + if(apc_cache_busy(cache))
2446 + /* cache cleanup in progress */
2450 + CACHE_RDLOCK(cache);
2452 + h = string_nhash_8(strkey, keylen);
2454 + slot = &cache->slots[h % cache->num_slots];
2457 + if ((h == (*slot)->key.h) &&
2458 + !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
2459 + /* Check to make sure this entry isn't expired by a hard TTL */
2460 + if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
2461 + #if (USE_READ_LOCKS == 0)
2462 + /* this is merely a memory-friendly optimization, if we do have a write-lock
2463 + * might as well move this to the deleted_list right-away. Otherwise an insert
2464 + * of the same key wil do it (or an expunge, *eventually*).
2466 + remove_slot(cache, slot TSRMLS_CC);
2468 + CACHE_FAST_INC(cache, cache->header->num_misses);
2469 + CACHE_RDUNLOCK(cache);
2472 + /* Otherwise we are fine, increase counters and return the cache entry */
2473 + CACHE_SAFE_INC(cache, (*slot)->num_hits);
2474 + CACHE_SAFE_INC(cache, (*slot)->value->ref_count);
2475 + (*slot)->access_time = t;
2477 + CACHE_FAST_INC(cache, cache->header->num_hits);
2478 + value = (*slot)->value;
2479 + CACHE_RDUNLOCK(cache);
2480 + return (apc_cache_entry_t*)value;
2482 + slot = &(*slot)->next;
2485 + CACHE_FAST_INC(cache, cache->header->num_misses);
2486 + CACHE_RDUNLOCK(cache);
2491 +/* {{{ apc_cache_user_exists */
2492 +apc_cache_entry_t* apc_cache_user_exists(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC)
2495 + volatile apc_cache_entry_t* value = NULL;
2498 + if(apc_cache_busy(cache))
2500 + /* cache cleanup in progress */
2504 + CACHE_RDLOCK(cache);
2506 + h = string_nhash_8(strkey, keylen);
2508 + slot = &cache->slots[h % cache->num_slots];
2511 + if ((h == (*slot)->key.h) &&
2512 + !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
2513 + /* Check to make sure this entry isn't expired by a hard TTL */
2514 + if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
2515 + CACHE_UNLOCK(cache);
2518 + /* Return the cache entry ptr */
2519 + value = (*slot)->value;
2520 + CACHE_RDUNLOCK(cache);
2521 + return (apc_cache_entry_t*)value;
2523 + slot = &(*slot)->next;
2525 + CACHE_RDUNLOCK(cache);
2530 +/* {{{ apc_cache_user_update */
2531 +int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, apc_cache_updater_t updater, void* data TSRMLS_DC)
2537 + if(apc_cache_busy(cache))
2539 + /* cache cleanup in progress */
2543 + CACHE_LOCK(cache);
2545 + h = string_nhash_8(strkey, keylen);
2546 + slot = &cache->slots[h % cache->num_slots];
2549 + if ((h == (*slot)->key.h) &&
2550 + !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
2551 + switch(Z_TYPE_P((*slot)->value->data.user.val) & ~IS_CONSTANT_INDEX) {
2553 + case IS_CONSTANT_ARRAY:
2556 + if(APCG(serializer)) {
2560 + /* fall through */
2563 + /* fall through */
2566 + retval = updater(cache, (*slot)->value, data);
2567 + (*slot)->key.mtime = apc_time();
2571 + CACHE_UNLOCK(cache);
2574 + slot = &(*slot)->next;
2576 + CACHE_UNLOCK(cache);
2581 +/* {{{ apc_cache_user_delete */
2582 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC)
2587 + CACHE_LOCK(cache);
2589 + h = string_nhash_8(strkey, keylen);
2591 + slot = &cache->slots[h % cache->num_slots];
2594 + if ((h == (*slot)->key.h) &&
2595 + !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
2596 + remove_slot(cache, slot TSRMLS_CC);
2597 + CACHE_UNLOCK(cache);
2600 + slot = &(*slot)->next;
2603 + CACHE_UNLOCK(cache);
2608 +/* {{{ apc_cache_delete */
2609 +int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC)
2613 + apc_cache_key_t key;
2617 + /* try to create a cache key; if we fail, give up on caching */
2618 + if (!apc_cache_make_file_key(&key, filename, PG(include_path), t TSRMLS_CC)) {
2619 + apc_warning("Could not stat file %s, unable to delete from cache." TSRMLS_CC, filename);
2623 + CACHE_LOCK(cache);
2625 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
2626 + else slot = &cache->slots[key.h % cache->num_slots];
2629 + if(key.type == (*slot)->key.type) {
2630 + if(key.type == APC_CACHE_KEY_FILE) {
2631 + if(key_equals((*slot)->key.data.file, key.data.file)) {
2632 + remove_slot(cache, slot TSRMLS_CC);
2633 + CACHE_UNLOCK(cache);
2636 + } else { /* APC_CACHE_KEY_FPFILE */
2637 + if(((*slot)->key.h == key.h) &&
2638 + (!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1))) {
2639 + remove_slot(cache, slot TSRMLS_CC);
2640 + CACHE_UNLOCK(cache);
2645 + slot = &(*slot)->next;
2648 + memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2650 + CACHE_UNLOCK(cache);
2656 +/* {{{ apc_cache_release */
2657 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry TSRMLS_DC)
2659 + CACHE_SAFE_DEC(cache, entry->ref_count);
2663 +/* {{{ apc_cache_make_file_key */
2664 +int apc_cache_make_file_key(apc_cache_key_t* key,
2665 + const char* filename,
2666 + const char* include_path,
2670 + struct stat *tmp_buf=NULL;
2671 + struct apc_fileinfo_t *fileinfo = NULL;
2674 + assert(key != NULL);
2676 + if (!filename || !SG(request_info).path_translated) {
2677 + apc_debug("No filename and no path_translated - bailing\n" TSRMLS_CC);
2681 + len = strlen(filename);
2682 + if(APCG(fpstat)==0) {
2683 + if(IS_ABSOLUTE_PATH(filename,len) || strstr(filename, "://")) {
2684 + key->data.fpfile.fullpath = filename;
2685 + key->data.fpfile.fullpath_len = len;
2686 + key->h = string_nhash_8(key->data.fpfile.fullpath, key->data.fpfile.fullpath_len);
2688 + key->type = APC_CACHE_KEY_FPFILE;
2690 + } else if(APCG(canonicalize)) {
2692 + fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
2694 + if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) {
2695 + apc_warning("apc failed to locate %s - bailing" TSRMLS_CC, filename);
2699 + if(!VCWD_REALPATH(fileinfo->fullpath, APCG(canon_path))) {
2700 + apc_warning("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename);
2704 + key->data.fpfile.fullpath = APCG(canon_path);
2705 + key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
2706 + key->h = string_nhash_8(key->data.fpfile.fullpath, key->data.fpfile.fullpath_len);
2708 + key->type = APC_CACHE_KEY_FPFILE;
2711 + /* fall through to stat mode */
2714 + fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
2716 + assert(fileinfo != NULL);
2718 + if(!strcmp(SG(request_info).path_translated, filename)) {
2719 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
2723 + fileinfo->st_buf.sb = *tmp_buf;
2725 + if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) {
2726 + apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC, filename,SG(request_info).path_translated);
2731 + if(APCG(max_file_size) < fileinfo->st_buf.sb.st_size) {
2732 + apc_debug("File is too big %s (%d - %ld) - bailing\n" TSRMLS_CC, filename,t,fileinfo->st_buf.sb.st_size);
2737 + * This is a bit of a hack.
2739 + * Here I am checking to see if the file is at least 2 seconds old.
2740 + * The idea is that if the file is currently being written to then its
2741 + * mtime is going to match or at most be 1 second off of the current
2742 + * request time and we want to avoid caching files that have not been
2743 + * completely written. Of course, people should be using atomic
2744 + * mechanisms to push files onto live web servers, but adding this
2745 + * tiny safety is easier than educating the world. This is now
2746 + * configurable, but the default is still 2 seconds.
2748 + if(APCG(file_update_protection) && (t - fileinfo->st_buf.sb.st_mtime < APCG(file_update_protection)) && !APCG(force_file_update)) {
2749 + apc_debug("File is too new %s (%d - %d) - bailing\n" TSRMLS_CC,filename,t,fileinfo->st_buf.sb.st_mtime);
2753 + key->data.file.device = fileinfo->st_buf.sb.st_dev;
2754 + key->data.file.inode = fileinfo->st_buf.sb.st_ino;
2755 + key->h = (unsigned long) key->data.file.device + (unsigned long) key->data.file.inode;
2758 + * If working with content management systems that like to munge the mtime,
2759 + * it might be appropriate to key off of the ctime to be immune to systems
2760 + * that try to backdate a template. If the mtime is set to something older
2761 + * than the previous mtime of a template we will obviously never see this
2762 + * "older" template. At some point the Smarty templating system did this.
2763 + * I generally disagree with using the ctime here because you lose the
2764 + * ability to warm up new content by saving it to a temporary file, hitting
2765 + * it once to cache it and then renaming it into its permanent location so
2766 + * set the apc.stat_ctime=true to enable this check.
2768 + if(APCG(stat_ctime)) {
2769 + 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;
2771 + key->mtime = fileinfo->st_buf.sb.st_mtime;
2773 + key->type = APC_CACHE_KEY_FILE;
2777 + if(fileinfo != NULL) {
2778 + apc_php_free(fileinfo TSRMLS_CC);
2785 + if(fileinfo != NULL) {
2786 + apc_php_free(fileinfo TSRMLS_CC);
2793 +/* {{{ apc_cache_make_user_key */
2794 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
2796 + assert(key != NULL);
2801 + key->data.user.identifier = identifier;
2802 + key->data.user.identifier_len = identifier_len;
2803 + key->h = string_nhash_8(key->data.user.identifier, key->data.user.identifier_len);
2805 + key->type = APC_CACHE_KEY_USER;
2810 +/* {{{ apc_cache_make_file_entry */
2811 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2812 + zend_op_array* op_array,
2813 + apc_function_t* functions,
2814 + apc_class_t* classes,
2815 + apc_context_t* ctxt
2818 + apc_cache_entry_t* entry;
2819 + apc_pool* pool = ctxt->pool;
2821 + entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
2822 + if (!entry) return NULL;
2824 + entry->data.file.filename = apc_pstrdup(filename, pool TSRMLS_CC);
2825 + if(!entry->data.file.filename) {
2826 + apc_debug("apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n" TSRMLS_CC);
2829 + apc_debug("apc_cache_make_file_entry: entry->data.file.filename is [%s]\n" TSRMLS_CC,entry->data.file.filename);
2830 + entry->data.file.op_array = op_array;
2831 + entry->data.file.functions = functions;
2832 + entry->data.file.classes = classes;
2834 + entry->data.file.halt_offset = apc_file_halt_offset(filename TSRMLS_CC);
2836 + entry->type = APC_CACHE_ENTRY_FILE;
2837 + entry->ref_count = 0;
2838 + entry->mem_size = 0;
2839 + entry->pool = pool;
2844 +/* {{{ apc_cache_store_zval */
2845 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
2847 + if (Z_TYPE_P(src) == IS_ARRAY) {
2848 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
2849 + zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
2850 + dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2851 + zend_hash_destroy(&APCG(copied_zvals));
2852 + APCG(copied_zvals).nTableSize=0;
2854 + dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2862 +/* {{{ apc_cache_fetch_zval */
2863 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
2865 + if (Z_TYPE_P(src) == IS_ARRAY) {
2866 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
2867 + zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
2868 + dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2869 + zend_hash_destroy(&APCG(copied_zvals));
2870 + APCG(copied_zvals).nTableSize=0;
2872 + dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2880 +/* {{{ apc_cache_make_user_entry */
2881 +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)
2883 + apc_cache_entry_t* entry;
2884 + apc_pool* pool = ctxt->pool;
2886 + entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
2887 + if (!entry) return NULL;
2889 + entry->data.user.info = apc_pmemcpy(info, info_len, pool TSRMLS_CC);
2890 + entry->data.user.info_len = info_len;
2891 + if(!entry->data.user.info) {
2894 + entry->data.user.val = apc_cache_store_zval(NULL, val, ctxt TSRMLS_CC);
2895 + if(!entry->data.user.val) {
2898 + INIT_PZVAL(entry->data.user.val);
2899 + entry->data.user.ttl = ttl;
2900 + entry->type = APC_CACHE_ENTRY_USER;
2901 + entry->ref_count = 0;
2902 + entry->mem_size = 0;
2903 + entry->pool = pool;
2909 +static zval* apc_cache_link_info(apc_cache_t *cache, slot_t* p TSRMLS_DC)
2911 + zval *link = NULL;
2914 + ALLOC_INIT_ZVAL(link);
2922 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
2923 + add_assoc_string(link, "type", "file", 1);
2924 + if(p->key.type == APC_CACHE_KEY_FILE) {
2929 + sprintf(buf, "%I64d", p->key.data.file.device);
2930 + add_assoc_string(link, "device", buf, 1);
2932 + sprintf(buf, "%I64d", p->key.data.file.inode);
2933 + add_assoc_string(link, "inode", buf, 1);
2936 + add_assoc_long(link, "device", p->key.data.file.device);
2937 + add_assoc_long(link, "inode", p->key.data.file.inode);
2940 + add_assoc_string(link, "filename", p->value->data.file.filename, 1);
2941 + } else { /* This is a no-stat fullpath file entry */
2942 + add_assoc_long(link, "device", 0);
2943 + add_assoc_long(link, "inode", 0);
2944 + add_assoc_string(link, "filename", (char*)p->key.data.fpfile.fullpath, 1);
2946 + if (APCG(file_md5)) {
2947 + make_digest(md5str, p->key.md5);
2948 + add_assoc_string(link, "md5", md5str, 1);
2950 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
2951 + add_assoc_stringl(link, "info", p->value->data.user.info, p->value->data.user.info_len-1, 1);
2952 + add_assoc_long(link, "ttl", (long)p->value->data.user.ttl);
2953 + add_assoc_string(link, "type", "user", 1);
2956 + add_assoc_double(link, "num_hits", (double)p->num_hits);
2957 + add_assoc_long(link, "mtime", p->key.mtime);
2958 + add_assoc_long(link, "creation_time", p->creation_time);
2959 + add_assoc_long(link, "deletion_time", p->deletion_time);
2960 + add_assoc_long(link, "access_time", p->access_time);
2961 + add_assoc_long(link, "ref_count", p->value->ref_count);
2962 + add_assoc_long(link, "mem_size", p->value->mem_size);
2968 +/* {{{ apc_cache_info */
2969 +zval* apc_cache_info(apc_cache_t* cache, zend_bool limited TSRMLS_DC)
2971 + zval *info = NULL;
2972 + zval *list = NULL;
2973 + zval *deleted_list = NULL;
2974 + zval *slots = NULL;
2978 + if(!cache) return NULL;
2980 + CACHE_RDLOCK(cache);
2982 + ALLOC_INIT_ZVAL(info);
2985 + CACHE_RDUNLOCK(cache);
2990 + add_assoc_long(info, "num_slots", cache->num_slots);
2991 + add_assoc_long(info, "ttl", cache->ttl);
2993 + add_assoc_double(info, "num_hits", (double)cache->header->num_hits);
2994 + add_assoc_double(info, "num_misses", (double)cache->header->num_misses);
2995 + add_assoc_double(info, "num_inserts", (double)cache->header->num_inserts);
2996 + add_assoc_double(info, "expunges", (double)cache->header->expunges);
2998 + add_assoc_long(info, "start_time", cache->header->start_time);
2999 + add_assoc_double(info, "mem_size", (double)cache->header->mem_size);
3000 + add_assoc_long(info, "num_entries", cache->header->num_entries);
3001 +#ifdef MULTIPART_EVENT_FORMDATA
3002 + add_assoc_long(info, "file_upload_progress", 1);
3004 + add_assoc_long(info, "file_upload_progress", 0);
3007 + add_assoc_stringl(info, "memory_type", "mmap", sizeof("mmap")-1, 1);
3009 + add_assoc_stringl(info, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
3011 + add_assoc_stringl(info, "locking_type", APC_LOCK_TYPE, sizeof(APC_LOCK_TYPE)-1, 1);
3014 + /* For each hashtable slot */
3015 + ALLOC_INIT_ZVAL(list);
3018 + ALLOC_INIT_ZVAL(slots);
3019 + array_init(slots);
3021 + for (i = 0; i < cache->num_slots; i++) {
3022 + p = cache->slots[i];
3024 + for (; p != NULL; p = p->next) {
3025 + zval *link = apc_cache_link_info(cache, p TSRMLS_CC);
3026 + add_next_index_zval(list, link);
3030 + add_index_long(slots, (ulong)i, j);
3034 + /* For each slot pending deletion */
3035 + ALLOC_INIT_ZVAL(deleted_list);
3036 + array_init(deleted_list);
3038 + for (p = cache->header->deleted_list; p != NULL; p = p->next) {
3039 + zval *link = apc_cache_link_info(cache, p TSRMLS_CC);
3040 + add_next_index_zval(deleted_list, link);
3043 + add_assoc_zval(info, "cache_list", list);
3044 + add_assoc_zval(info, "deleted_list", deleted_list);
3045 + add_assoc_zval(info, "slot_distribution", slots);
3048 + CACHE_RDUNLOCK(cache);
3053 +/* {{{ apc_cache_unlock */
3054 +void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC)
3056 + CACHE_UNLOCK(cache);
3060 +/* {{{ apc_cache_busy */
3061 +zend_bool apc_cache_busy(apc_cache_t* cache)
3063 + return cache->header->busy;
3067 +/* {{{ apc_cache_is_last_key */
3068 +zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t TSRMLS_DC)
3070 + apc_keyid_t *lastkey = &cache->header->lastkey;
3071 + unsigned int keylen = key->data.user.identifier_len;
3073 + THREAD_T tid = tsrm_thread_id();
3074 + #define FROM_DIFFERENT_THREAD(k) (memcmp(&((k)->tid), &tid, sizeof(THREAD_T))!=0)
3076 + pid_t pid = getpid();
3077 + #define FROM_DIFFERENT_THREAD(k) (pid != (k)->pid)
3081 + /* unlocked reads, but we're not shooting for 100% success with this */
3082 + if(lastkey->h == key->h && keylen == lastkey->keylen) {
3083 + if(lastkey->mtime == t && FROM_DIFFERENT_THREAD(lastkey)) {
3084 + /* potential cache slam */
3085 + if(APCG(slam_defense)) {
3086 + apc_debug("Potential cache slam averted for key '%s'" TSRMLS_CC, key->data.user.identifier);
3096 +#if NONBLOCKING_LOCK_AVAILABLE
3097 +/* {{{ apc_cache_write_lock */
3098 +zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC)
3100 + return apc_lck_nb_lock(cache->header->wrlock);
3104 +/* {{{ apc_cache_write_unlock */
3105 +void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC)
3107 + apc_lck_unlock(cache->header->wrlock);
3113 + * Local variables:
3115 + * c-basic-offset: 4
3117 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
3118 + * vim<600: expandtab sw=4 ts=4 sts=4
3120 diff -Naur a/ext/apc/apc_cache.h b/ext/apc/apc_cache.h
3121 --- a/ext/apc/apc_cache.h 1970-01-01 01:00:00.000000000 +0100
3122 +++ b/ext/apc/apc_cache.h 2012-07-20 00:10:35.000000000 +0200
3125 + +----------------------------------------------------------------------+
3127 + +----------------------------------------------------------------------+
3128 + | Copyright (c) 2006-2011 The PHP Group |
3129 + +----------------------------------------------------------------------+
3130 + | This source file is subject to version 3.01 of the PHP license, |
3131 + | that is bundled with this package in the file LICENSE, and is |
3132 + | available through the world-wide-web at the following url: |
3133 + | http://www.php.net/license/3_01.txt. |
3134 + | If you did not receive a copy of the PHP license and are unable to |
3135 + | obtain it through the world-wide-web, please send a note to |
3136 + | license@php.net so we can mail you a copy immediately. |
3137 + +----------------------------------------------------------------------+
3138 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
3139 + | Rasmus Lerdorf <rasmus@php.net> |
3140 + +----------------------------------------------------------------------+
3142 + This software was contributed to PHP by Community Connect Inc. in 2002
3143 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
3144 + Future revisions and derivatives of this source code must acknowledge
3145 + Community Connect Inc. as the original contributor of this module by
3146 + leaving this note intact in the source code.
3148 + All other licensing and usage conditions are those of the PHP Group.
3152 +/* $Id: apc_cache.h 324329 2012-03-18 15:29:37Z mike $ */
3154 +#ifndef APC_CACHE_H
3155 +#define APC_CACHE_H
3158 + * This module defines the shared memory file cache. Basically all of the
3159 + * logic for storing and retrieving cache entries lives here.
3163 +#include "apc_compile.h"
3164 +#include "apc_lock.h"
3165 +#include "apc_pool.h"
3166 +#include "apc_main.h"
3169 +#define APC_CACHE_ENTRY_FILE 1
3170 +#define APC_CACHE_ENTRY_USER 2
3172 +#define APC_CACHE_KEY_FILE 1
3173 +#define APC_CACHE_KEY_USER 2
3174 +#define APC_CACHE_KEY_FPFILE 3
3177 +typedef unsigned __int64 apc_ino_t;
3178 +typedef unsigned __int64 apc_dev_t;
3180 +typedef ino_t apc_ino_t;
3181 +typedef dev_t apc_dev_t;
3184 +/* {{{ cache locking macros */
3185 +#define CACHE_LOCK(cache) { LOCK(cache->header->lock); cache->has_lock = 1; }
3186 +#define CACHE_UNLOCK(cache) { UNLOCK(cache->header->lock); cache->has_lock = 0; }
3187 +#define CACHE_SAFE_LOCK(cache) { if ((++cache->has_lock) == 1) LOCK(cache->header->lock); }
3188 +#define CACHE_SAFE_UNLOCK(cache) { if ((--cache->has_lock) == 0) UNLOCK(cache->header->lock); }
3190 +#if (RDLOCK_AVAILABLE == 1) && defined(HAVE_ATOMIC_OPERATIONS)
3191 +#define USE_READ_LOCKS 1
3192 +#define CACHE_RDLOCK(cache) { RDLOCK(cache->header->lock); cache->has_lock = 0; }
3193 +#define CACHE_RDUNLOCK(cache) { RDUNLOCK(cache->header->lock); cache->has_lock = 0; }
3194 +#define CACHE_SAFE_INC(cache, obj) { ATOMIC_INC(obj); }
3195 +#define CACHE_SAFE_DEC(cache, obj) { ATOMIC_DEC(obj); }
3197 +#define USE_READ_LOCKS 0
3198 +#define CACHE_RDLOCK(cache) { LOCK(cache->header->lock); cache->has_lock = 1; }
3199 +#define CACHE_RDUNLOCK(cache) { UNLOCK(cache->header->lock); cache->has_lock = 0; }
3200 +#define CACHE_SAFE_INC(cache, obj) { CACHE_SAFE_LOCK(cache); obj++; CACHE_SAFE_UNLOCK(cache);}
3201 +#define CACHE_SAFE_DEC(cache, obj) { CACHE_SAFE_LOCK(cache); obj--; CACHE_SAFE_UNLOCK(cache);}
3204 +#define CACHE_FAST_INC(cache, obj) { obj++; }
3205 +#define CACHE_FAST_DEC(cache, obj) { obj--; }
3208 +/* {{{ struct definition: apc_cache_key_t */
3209 +#define T apc_cache_t*
3210 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
3212 +typedef union _apc_cache_key_data_t {
3214 + apc_dev_t device; /* the filesystem device */
3215 + apc_ino_t inode; /* the filesystem inode */
3218 + const char *identifier;
3219 + int identifier_len;
3222 + const char *fullpath;
3225 +} apc_cache_key_data_t;
3227 +typedef struct apc_cache_key_t apc_cache_key_t;
3228 +struct apc_cache_key_t {
3229 + apc_cache_key_data_t data;
3230 + unsigned long h; /* pre-computed hash value */
3231 + time_t mtime; /* the mtime of this cached entry */
3232 + unsigned char type;
3233 + unsigned char md5[16]; /* md5 hash of the source file */
3237 +typedef struct apc_keyid_t apc_keyid_t;
3239 +struct apc_keyid_t {
3241 + unsigned int keylen;
3251 +/* {{{ struct definition: apc_cache_entry_t */
3252 +typedef union _apc_cache_entry_value_t {
3254 + char *filename; /* absolute path to source file */
3255 + zend_op_array* op_array; /* op_array allocated in shared memory */
3256 + apc_function_t* functions; /* array of apc_function_t's */
3257 + apc_class_t* classes; /* array of apc_class_t's */
3258 + long halt_offset; /* value of __COMPILER_HALT_OFFSET__ for the file */
3266 +} apc_cache_entry_value_t;
3268 +typedef struct apc_cache_entry_t apc_cache_entry_t;
3269 +struct apc_cache_entry_t {
3270 + apc_cache_entry_value_t data;
3271 + unsigned char type;
3279 + * apc_cache_create creates the shared memory compiler cache. This function
3280 + * should be called just once (ideally in the web server parent process, e.g.
3281 + * in apache), otherwise you will end up with multiple caches (which won't
3282 + * necessarily break anything). Returns a pointer to the cache object.
3284 + * size_hint is a "hint" at the total number of source files that will be
3285 + * cached. It determines the physical size of the hash table. Passing 0 for
3286 + * this argument will use a reasonable default value.
3288 + * gc_ttl is the maximum time a cache entry may speed on the garbage
3289 + * collection list. This is basically a work around for the inherent
3290 + * unreliability of our reference counting mechanism (see apc_cache_release).
3292 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
3293 + * is needed. This helps in cleaning up the cache and ensuring that entries
3294 + * hit frequently stay cached and ones not hit very often eventually disappear.
3296 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC);
3299 + * apc_cache_destroy releases any OS resources associated with a cache object.
3300 + * Under apache, this function can be safely called by the child processes
3303 +extern void apc_cache_destroy(T cache TSRMLS_DC);
3306 + * apc_cache_clear empties a cache. This can safely be called at any time,
3307 + * even while other server processes are executing cached source files.
3309 +extern void apc_cache_clear(T cache TSRMLS_DC);
3312 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
3313 + * Internally, the filename is translated to a canonical representation, so
3314 + * that relative and absolute filenames will map to a single key. Returns
3315 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
3316 + * returned, the caller must free the cache entry by calling
3317 + * apc_cache_free_entry (see below).
3319 + * key is the value created by apc_cache_make_file_key for file keys.
3321 + * value is a cache entry returned by apc_cache_make_entry (see below).
3323 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
3324 + apc_cache_entry_t* value, apc_context_t* ctxt, time_t t TSRMLS_DC);
3326 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
3327 + apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC);
3329 +extern int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys,
3330 + apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries TSRMLS_DC);
3333 + * apc_cache_find searches for a cache entry by filename, and returns a
3334 + * pointer to the entry if found, NULL otherwise.
3336 + * key is a value created by apc_cache_make_file_key for file keys.
3338 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t TSRMLS_DC);
3341 + * apc_cache_user_find searches for a cache entry by its hashed identifier,
3342 + * and returns a pointer to the entry if found, NULL otherwise.
3345 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
3348 + * apc_cache_user_exists searches for a cache entry by its hashed identifier,
3349 + * and returns a pointer to the entry if found, NULL otherwise. This is a
3350 + * quick non-locking version of apc_cache_user_find that does not modify the
3351 + * shared memory segment in any way.
3354 +extern apc_cache_entry_t* apc_cache_user_exists(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
3357 + * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it.
3359 +extern int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC);
3360 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC);
3362 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
3366 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC);
3369 + * apc_cache_release decrements the reference count associated with a cache
3370 + * entry. Calling apc_cache_find automatically increments the reference count,
3371 + * and this function must be called post-execution to return the count to its
3372 + * original value. Failing to do so will prevent the entry from being
3373 + * garbage-collected.
3375 + * entry is the cache entry whose ref count you want to decrement.
3377 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry TSRMLS_DC);
3380 + * apc_cache_make_file_key creates a key object given a relative or absolute
3381 + * filename and an optional list of auxillary paths to search. include_path is
3382 + * searched if the filename cannot be found relative to the current working
3385 + * key points to caller-allocated storage (must not be null).
3387 + * filename is the path to the source file.
3389 + * include_path is a colon-separated list of directories to search.
3391 + * and finally we pass in the current request time so we can avoid
3392 + * caching files with a current mtime which tends to indicate that
3393 + * they are still being written to.
3395 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
3396 + const char* filename,
3397 + const char* include_path,
3402 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
3403 + * and the compilation results returned by the PHP compiler.
3405 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
3406 + zend_op_array* op_array,
3407 + apc_function_t* functions,
3408 + apc_class_t* classes,
3409 + apc_context_t* ctxt
3413 +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);
3416 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
3417 + * and the zval to be stored.
3419 +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);
3421 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
3423 +/* {{{ struct definition: slot_t */
3424 +typedef struct slot_t slot_t;
3426 + apc_cache_key_t key; /* slot key */
3427 + apc_cache_entry_t* value; /* slot value */
3428 + slot_t* next; /* next slot in linked list */
3429 + unsigned long num_hits; /* number of hits to this bucket */
3430 + time_t creation_time; /* time slot was initialized */
3431 + time_t deletion_time; /* time slot was removed from cache */
3432 + time_t access_time; /* time slot was last accessed */
3436 +/* {{{ struct definition: cache_header_t
3437 + Any values that must be shared among processes should go in here. */
3438 +typedef struct cache_header_t cache_header_t;
3439 +struct cache_header_t {
3440 + apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */
3441 + apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */
3442 + unsigned long num_hits; /* total successful hits in cache */
3443 + unsigned long num_misses; /* total unsuccessful hits in cache */
3444 + unsigned long num_inserts; /* total successful inserts in cache */
3445 + unsigned long expunges; /* total number of expunges */
3446 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
3447 + time_t start_time; /* time the above counters were reset */
3448 + zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */
3449 + int num_entries; /* Statistic on the number of entries */
3450 + size_t mem_size; /* Statistic on the memory size used by this cache */
3451 + apc_keyid_t lastkey; /* the key that is being inserted (user cache) */
3455 +typedef void (*apc_expunge_cb_t)(T cache, size_t n TSRMLS_DC);
3457 +/* {{{ struct definition: apc_cache_t */
3458 +struct apc_cache_t {
3459 + void* shmaddr; /* process (local) address of shared cache */
3460 + cache_header_t* header; /* cache header (stored in SHM) */
3461 + slot_t** slots; /* array of cache slots (stored in SHM) */
3462 + int num_slots; /* number of slots in cache */
3463 + int gc_ttl; /* maximum time on GC list for a slot */
3464 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
3465 + apc_expunge_cb_t expunge_cb; /* cache specific expunge callback to free up sma memory */
3466 + uint has_lock; /* flag for possible recursive locks within the same process */
3470 +extern zval* apc_cache_info(T cache, zend_bool limited TSRMLS_DC);
3471 +extern void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC);
3472 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
3473 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC);
3474 +extern void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC);
3475 +extern zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t TSRMLS_DC);
3477 +/* used by apc_rfc1867 to update data in-place - not to be used elsewhere */
3479 +typedef int (*apc_cache_updater_t)(apc_cache_t*, apc_cache_entry_t*, void* data);
3480 +extern int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen,
3481 + apc_cache_updater_t updater, void* data TSRMLS_DC);
3488 + * Local variables:
3490 + * c-basic-offset: 4
3492 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
3493 + * vim<600: expandtab sw=4 ts=4 sts=4
3495 diff -Naur a/ext/apc/apc_compile.c b/ext/apc/apc_compile.c
3496 --- a/ext/apc/apc_compile.c 1970-01-01 01:00:00.000000000 +0100
3497 +++ b/ext/apc/apc_compile.c 2012-07-20 00:10:35.000000000 +0200
3500 + +----------------------------------------------------------------------+
3502 + +----------------------------------------------------------------------+
3503 + | Copyright (c) 2006-2011 The PHP Group |
3504 + +----------------------------------------------------------------------+
3505 + | This source file is subject to version 3.01 of the PHP license, |
3506 + | that is bundled with this package in the file LICENSE, and is |
3507 + | available through the world-wide-web at the following url: |
3508 + | http://www.php.net/license/3_01.txt. |
3509 + | If you did not receive a copy of the PHP license and are unable to |
3510 + | obtain it through the world-wide-web, please send a note to |
3511 + | license@php.net so we can mail you a copy immediately. |
3512 + +----------------------------------------------------------------------+
3513 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
3514 + | Rasmus Lerdorf <rasmus@php.net> |
3515 + | Arun C. Murthy <arunc@yahoo-inc.com> |
3516 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
3517 + +----------------------------------------------------------------------+
3519 + This software was contributed to PHP by Community Connect Inc. in 2002
3520 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
3521 + Future revisions and derivatives of this source code must acknowledge
3522 + Community Connect Inc. as the original contributor of this module by
3523 + leaving this note intact in the source code.
3525 + All other licensing and usage conditions are those of the PHP Group.
3529 +/* $Id: apc_compile.c 326703 2012-07-19 17:06:12Z rasmus $ */
3531 +#include "apc_compile.h"
3532 +#include "apc_globals.h"
3533 +#include "apc_zend.h"
3534 +#include "apc_php.h"
3535 +#include "apc_string.h"
3536 +#include "ext/standard/php_var.h"
3537 +#include "ext/standard/php_smart_str.h"
3539 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_context_t* TSRMLS_DC);
3540 +//typedef void (*ht_free_fun_t)(void*, apc_context_t*);
3541 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
3543 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
3545 +#define CHECK(p) { if ((p) == NULL) return NULL; }
3547 +/* {{{ internal function declarations */
3549 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC);
3552 + * The "copy" functions perform deep-copies on a particular data structure
3553 + * (passed as the second argument). They also optionally allocate space for
3554 + * the destination data structure if the first argument is null.
3556 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_context_t* TSRMLS_DC);
3557 +static zval* my_copy_zval(zval*, const zval*, apc_context_t* TSRMLS_DC);
3558 +#ifndef ZEND_ENGINE_2_4
3559 +static znode* my_copy_znode(znode*, znode*, apc_context_t* TSRMLS_DC);
3561 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_context_t* TSRMLS_DC);
3562 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC);
3563 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, const zend_function_entry*, apc_context_t* TSRMLS_DC);
3564 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_context_t* TSRMLS_DC);
3565 +static HashTable* my_copy_hashtable_ex(HashTable*, HashTable* TSRMLS_DC, ht_copy_fun_t, int, apc_context_t*, ht_check_copy_fun_t, ...);
3566 +#define my_copy_hashtable( dst, src, copy_fn, holds_ptr, ctxt) \
3567 + my_copy_hashtable_ex(dst, src TSRMLS_CC, copy_fn, holds_ptr, ctxt, NULL)
3568 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* TSRMLS_DC);
3569 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* TSRMLS_DC);
3570 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, const zend_arg_info*, uint, apc_context_t* TSRMLS_DC);
3571 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, const zend_arg_info*, apc_context_t* TSRMLS_DC);
3574 + * The "fixup" functions need for ZEND_ENGINE_2
3576 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
3577 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
3578 +/* my_fixup_function_for_execution is the same as my_fixup_function
3579 + * but named differently for clarity
3581 +#define my_fixup_function_for_execution my_fixup_function
3583 +#ifdef ZEND_ENGINE_2_2
3584 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
3585 +#define my_fixup_property_info_for_execution my_fixup_property_info
3589 + * These functions return "1" if the member/function is
3590 + * defined/overridden in the 'current' class and not inherited.
3592 +static int my_check_copy_function(Bucket* src, va_list args);
3593 +static int my_check_copy_property_info(Bucket* src, va_list args);
3594 +#ifndef ZEND_ENGINE_2_4
3595 +static int my_check_copy_default_property(Bucket* p, va_list args);
3596 +static int my_check_copy_static_member(Bucket* src, va_list args);
3598 +static int my_check_copy_constant(Bucket* src, va_list args);
3602 +/* {{{ apc php serializers */
3603 +int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS)
3605 + smart_str strbuf = {0};
3606 + php_serialize_data_t var_hash;
3607 + PHP_VAR_SERIALIZE_INIT(var_hash);
3608 + php_var_serialize(&strbuf, (zval**)&value, &var_hash TSRMLS_CC);
3609 + PHP_VAR_SERIALIZE_DESTROY(var_hash);
3611 + *buf = (unsigned char*)strbuf.c;
3612 + *buf_len = strbuf.len;
3613 + smart_str_0(&strbuf);
3619 +int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS)
3621 + const unsigned char *tmp = buf;
3622 + php_unserialize_data_t var_hash;
3623 + PHP_VAR_UNSERIALIZE_INIT(var_hash);
3624 + if(!php_var_unserialize(value, &tmp, buf + buf_len, &var_hash TSRMLS_CC)) {
3625 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
3626 + zval_dtor(*value);
3627 + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %ld bytes", (long)(tmp - buf), (long)buf_len);
3628 + (*value)->type = IS_NULL;
3631 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
3636 +/* {{{ check_op_array_integrity */
3638 +static void check_op_array_integrity(zend_op_array* src)
3642 + /* These sorts of checks really aren't particularly effective, but they
3643 + * can provide a welcome sanity check when debugging. Just don't enable
3644 + * for production use! */
3646 + assert(src->refcount != NULL);
3647 + assert(src->opcodes != NULL);
3648 + assert(src->last > 0);
3650 + for (i = 0; i < src->last; i++) {
3651 + zend_op* op = &src->opcodes[i];
3652 + znode* nodes[] = { &op->result, &op->op1, &op->op2 };
3653 + for (j = 0; j < 3; j++) {
3654 + assert(nodes[j]->op_type == IS_CONST ||
3655 + nodes[j]->op_type == IS_VAR ||
3656 + nodes[j]->op_type == IS_TMP_VAR ||
3657 + nodes[j]->op_type == IS_UNUSED);
3659 + if (nodes[j]->op_type == IS_CONST) {
3660 + int type = nodes[j]->u.constant.type;
3661 + assert(type == IS_RESOURCE ||
3662 + type == IS_BOOL ||
3663 + type == IS_LONG ||
3664 + type == IS_DOUBLE ||
3665 + type == IS_NULL ||
3666 + type == IS_CONSTANT ||
3667 + type == IS_STRING ||
3668 + type == FLAG_IS_BC ||
3669 + type == IS_ARRAY ||
3670 + type == IS_CONSTANT_ARRAY ||
3671 + type == IS_OBJECT);
3679 +/* {{{ my_bitwise_copy_function */
3680 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
3682 + apc_pool* pool = ctxt->pool;
3684 + assert(src != NULL);
3687 + CHECK(dst = (zend_function*) apc_pool_alloc(pool, sizeof(src[0])));
3690 + /* We only need to do a bitwise copy */
3691 + memcpy(dst, src, sizeof(src[0]));
3697 +/* {{{ my_copy_zval_ptr */
3698 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_context_t* ctxt TSRMLS_DC)
3701 + apc_pool* pool = ctxt->pool;
3702 + int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
3704 + assert(src != NULL);
3707 + CHECK(dst = (zval**) apc_pool_alloc(pool, sizeof(zval*)));
3711 + ALLOC_ZVAL(dst[0]);
3714 + CHECK((dst[0] = (zval*) apc_pool_alloc(pool, sizeof(zval))));
3717 + CHECK((dst_new = my_copy_zval(*dst, *src, ctxt TSRMLS_CC)));
3719 + if(dst_new != *dst) {
3721 + FREE_ZVAL(dst[0]);
3730 +/* {{{ my_serialize_object */
3731 +static zval* my_serialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3733 + smart_str buf = {0};
3734 + apc_pool* pool = ctxt->pool;
3735 + apc_serialize_t serialize = APC_SERIALIZER_NAME(php);
3736 + void *config = NULL;
3738 + if(APCG(serializer)) { /* TODO: move to ctxt */
3739 + serialize = APCG(serializer)->serialize;
3740 + config = APCG(serializer)->config;
3743 + if(serialize((unsigned char**)&buf.c, &buf.len, src, config TSRMLS_CC)) {
3744 + dst->type = src->type & ~IS_CONSTANT_INDEX;
3745 + dst->value.str.len = buf.len;
3746 + CHECK(dst->value.str.val = apc_pmemcpy(buf.c, (buf.len + 1), pool TSRMLS_CC));
3749 + if(buf.c) smart_str_free(&buf);
3755 +/* {{{ my_unserialize_object */
3756 +static zval* my_unserialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3758 + apc_unserialize_t unserialize = APC_UNSERIALIZER_NAME(php);
3759 + unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
3760 + void *config = NULL;
3762 + if(APCG(serializer)) { /* TODO: move to ctxt */
3763 + unserialize = APCG(serializer)->unserialize;
3764 + config = APCG(serializer)->config;
3767 + if(unserialize(&dst, p, Z_STRLEN_P(src), config TSRMLS_CC)) {
3771 + dst->type = IS_NULL;
3777 +static char *apc_string_pmemcpy(char *str, size_t len, apc_pool* pool TSRMLS_DC)
3779 +#ifdef ZEND_ENGINE_2_4
3781 + if (pool->type != APC_UNPOOL) {
3782 + char * ret = (char*)apc_new_interned_string((const char*)str, len TSRMLS_CC);
3789 + return apc_pmemcpy(str, len, pool TSRMLS_CC);
3792 +/* {{{ my_copy_zval */
3793 +static APC_HOTSPOT zval* my_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3796 + apc_pool* pool = ctxt->pool;
3798 + assert(dst != NULL);
3799 + assert(src != NULL);
3801 + memcpy(dst, src, sizeof(src[0]));
3803 + if(APCG(copied_zvals).nTableSize) {
3804 + if(zend_hash_index_find(&APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3805 + if(Z_ISREF_P((zval*)src)) {
3806 + Z_SET_ISREF_PP(tmp);
3812 + zend_hash_index_update(&APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
3816 + if(ctxt->copy == APC_COPY_OUT_USER || ctxt->copy == APC_COPY_IN_USER) {
3817 + /* deep copies are refcount(1), but moved up for recursive
3818 + * arrays, which end up being add_ref'd during its copy. */
3819 + Z_SET_REFCOUNT_P(dst, 1);
3820 + Z_UNSET_ISREF_P(dst);
3822 + /* code uses refcount=2 for consts */
3823 + Z_SET_REFCOUNT_P(dst, Z_REFCOUNT_P((zval*)src));
3824 + Z_SET_ISREF_TO_P(dst, Z_ISREF_P((zval*)src));
3827 + switch (src->type & IS_CONSTANT_TYPE_MASK) {
3837 + if (src->value.str.val) {
3838 + CHECK(dst->value.str.val = apc_string_pmemcpy(src->value.str.val,
3839 + src->value.str.len+1,
3845 + case IS_CONSTANT_ARRAY:
3846 + if(APCG(serializer) == NULL ||
3847 + ctxt->copy == APC_COPY_IN_OPCODE || ctxt->copy == APC_COPY_OUT_OPCODE) {
3849 + CHECK(dst->value.ht =
3850 + my_copy_hashtable(NULL,
3852 + (ht_copy_fun_t) my_copy_zval_ptr,
3857 + /* fall through to object case */
3862 + dst->type = IS_NULL;
3863 + if(ctxt->copy == APC_COPY_IN_USER) {
3864 + dst = my_serialize_object(dst, src, ctxt TSRMLS_CC);
3865 + } else if(ctxt->copy == APC_COPY_OUT_USER) {
3866 + dst = my_unserialize_object(dst, src, ctxt TSRMLS_CC);
3878 +#ifdef ZEND_ENGINE_2_4
3879 +/* {{{ my_copy_znode */
3880 +static void my_check_znode(zend_uchar op_type, apc_context_t* ctxt TSRMLS_DC)
3882 + assert(op_type == IS_CONST ||
3883 + op_type == IS_VAR ||
3884 + op_type == IS_CV ||
3885 + op_type == IS_TMP_VAR ||
3886 + op_type == IS_UNUSED);
3890 +/* {{{ my_copy_zend_op */
3891 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC)
3893 + assert(dst != NULL);
3894 + assert(src != NULL);
3896 + memcpy(dst, src, sizeof(src[0]));
3898 + my_check_znode(dst->result_type & ~EXT_TYPE_UNUSED, ctxt TSRMLS_CC);
3899 + my_check_znode(dst->op1_type, ctxt TSRMLS_CC);
3900 + my_check_znode(dst->op2_type, ctxt TSRMLS_CC);
3906 +/* {{{ my_copy_znode */
3907 +static znode* my_copy_znode(znode* dst, znode* src, apc_context_t* ctxt TSRMLS_DC)
3909 + assert(dst != NULL);
3910 + assert(src != NULL);
3912 + memcpy(dst, src, sizeof(src[0]));
3915 + assert(dst ->op_type == IS_CONST ||
3916 + dst ->op_type == IS_VAR ||
3917 + dst ->op_type == IS_CV ||
3918 + dst ->op_type == IS_TMP_VAR ||
3919 + dst ->op_type == IS_UNUSED);
3921 + assert(dst ->op_type == IS_CONST ||
3922 + dst ->op_type == IS_VAR ||
3923 + dst ->op_type == IS_TMP_VAR ||
3924 + dst ->op_type == IS_UNUSED);
3927 + if (src->op_type == IS_CONST) {
3928 + if(!my_copy_zval(&dst->u.constant, &src->u.constant, ctxt TSRMLS_CC)) {
3937 +/* {{{ my_copy_zend_op */
3938 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC)
3940 + assert(dst != NULL);
3941 + assert(src != NULL);
3943 + memcpy(dst, src, sizeof(src[0]));
3945 + CHECK(my_copy_znode(&dst->result, &src->result, ctxt TSRMLS_CC));
3946 + CHECK(my_copy_znode(&dst->op1, &src->op1, ctxt TSRMLS_CC));
3947 + CHECK(my_copy_znode(&dst->op2, &src->op2, ctxt TSRMLS_CC));
3954 +/* {{{ my_copy_function */
3955 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
3957 + assert(src != NULL);
3959 + CHECK(dst = my_bitwise_copy_function(dst, src, ctxt TSRMLS_CC));
3961 + switch (src->type) {
3962 + case ZEND_INTERNAL_FUNCTION:
3963 + case ZEND_OVERLOADED_FUNCTION:
3964 + /* shallow copy because op_array is internal */
3965 + dst->op_array = src->op_array;
3968 + case ZEND_USER_FUNCTION:
3969 + case ZEND_EVAL_CODE:
3970 + CHECK(apc_copy_op_array(&dst->op_array,
3979 + * op_array bitwise copying overwrites what ever you modified
3980 + * before apc_copy_op_array - which is why this code is outside
3981 + * my_bitwise_copy_function.
3984 + /* zend_do_inheritance will re-look this up, because the pointers
3985 + * in prototype are from a function table of another class. It just
3986 + * helps if that one is from EG(class_table).
3988 + dst->common.prototype = NULL;
3990 + /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
3991 + * have to carry around a prototype. Thankfully zend_do_inheritance
3992 + * sets this properly as well
3994 + dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
4001 +/* {{{ my_copy_function_entry */
4002 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, const zend_function_entry* src, apc_context_t* ctxt TSRMLS_DC)
4004 + assert(src != NULL);
4007 + CHECK(dst = (zend_function_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0])));
4010 + /* Start with a bitwise copy */
4011 + memcpy(dst, src, sizeof(src[0]));
4013 + dst->fname = NULL;
4014 + dst->arg_info = NULL;
4017 + CHECK((dst->fname = apc_pstrdup(src->fname, ctxt->pool TSRMLS_CC)));
4020 + if (src->arg_info) {
4021 + CHECK((dst->arg_info = my_copy_arg_info_array(NULL,
4024 + ctxt TSRMLS_CC)));
4031 +/* {{{ my_copy_property_info */
4032 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC)
4034 + apc_pool* pool = ctxt->pool;
4036 + assert(src != NULL);
4039 + CHECK(dst = (zend_property_info*) apc_pool_alloc(pool, sizeof(*src)));
4042 + /* Start with a bitwise copy */
4043 + memcpy(dst, src, sizeof(*src));
4046 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
4047 + dst->doc_comment = NULL;
4051 + /* private members are stored inside property_info as a mangled
4052 + * string of the form:
4053 + * \0<classname>\0<membername>\0
4055 + CHECK((dst->name = apc_string_pmemcpy(src->name, src->name_length+1, pool TSRMLS_CC)));
4058 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
4059 + if (src->doc_comment) {
4060 + CHECK((dst->doc_comment = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC)));
4068 +/* {{{ my_copy_property_info_for_execution */
4069 +static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC)
4071 + assert(src != NULL);
4074 + CHECK(dst = (zend_property_info*) apc_pool_alloc(ctxt->pool, sizeof(*src)));
4077 + /* We need only a shallow copy */
4078 + memcpy(dst, src, sizeof(*src));
4084 +/* {{{ my_copy_arg_info_array */
4085 +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)
4091 + CHECK(dst = (zend_arg_info*) apc_pool_alloc(ctxt->pool, (sizeof(*src) * num_args)));
4094 + /* Start with a bitwise copy */
4095 + memcpy(dst, src, sizeof(*src)*num_args);
4097 + for(i=0; i < num_args; i++) {
4098 + CHECK((my_copy_arg_info( &dst[i], &src[i], ctxt TSRMLS_CC)));
4105 +/* {{{ my_copy_arg_info */
4106 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, const zend_arg_info* src, apc_context_t* ctxt TSRMLS_DC)
4108 + apc_pool* pool = ctxt->pool;
4110 + assert(src != NULL);
4113 + CHECK(dst = (zend_arg_info*) apc_pool_alloc(pool, sizeof(*src)));
4116 + /* Start with a bitwise copy */
4117 + memcpy(dst, src, sizeof(*src));
4120 + dst->class_name = NULL;
4123 + CHECK((dst->name = apc_string_pmemcpy((char *) src->name, src->name_len+1, pool TSRMLS_CC)));
4126 + if (src->class_name) {
4127 + CHECK((dst->class_name = apc_string_pmemcpy((char *) src->class_name, src->class_name_len+1, pool TSRMLS_CC)));
4134 +/* {{{ apc_copy_class_entry */
4135 +zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
4137 + return my_copy_class_entry(dst, src, ctxt TSRMLS_CC);
4140 +/* {{{ my_copy_class_entry */
4141 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
4144 + apc_pool* pool = ctxt->pool;
4146 + assert(src != NULL);
4149 + CHECK(dst = (zend_class_entry*) apc_pool_alloc(pool, sizeof(*src)));
4152 + /* Start with a bitwise copy */
4153 + memcpy(dst, src, sizeof(*src));
4156 + memset(&dst->function_table, 0, sizeof(dst->function_table));
4157 + ZEND_CE_DOC_COMMENT(dst) = NULL;
4158 + ZEND_CE_FILENAME(dst) = NULL;
4159 + memset(&dst->properties_info, 0, sizeof(dst->properties_info));
4160 + memset(&dst->constants_table, 0, sizeof(dst->constants_table));
4163 + CHECK((dst->name = apc_pstrdup(src->name, pool TSRMLS_CC)));
4166 + if(!(my_copy_hashtable_ex(&dst->function_table,
4167 + &src->function_table TSRMLS_CC,
4168 + (ht_copy_fun_t) my_copy_function,
4171 + (ht_check_copy_fun_t) my_check_copy_function,
4176 + /* the interfaces are populated at runtime using ADD_INTERFACE */
4177 + dst->interfaces = NULL;
4179 + /* the current count includes inherited interfaces as well,
4180 + the real dynamic ones are the first <n> which are zero'd
4181 + out in zend_do_end_class_declaration */
4182 + for(i = 0 ; (uint)i < src->num_interfaces ; i++) {
4183 + if(src->interfaces[i])
4185 + dst->num_interfaces = i;
4190 + /* these will either be set inside my_fixup_hashtable or
4191 + * they will be copied out from parent inside zend_do_inheritance
4193 + dst->parent = NULL;
4194 + dst->constructor = NULL;
4195 + dst->destructor = NULL;
4196 + dst->clone = NULL;
4197 + dst->__get = NULL;
4198 + dst->__set = NULL;
4199 + dst->__unset = NULL;
4200 + dst->__isset = NULL;
4201 + dst->__call = NULL;
4202 +#ifdef ZEND_ENGINE_2_2
4203 + dst->__tostring = NULL;
4205 +#ifdef ZEND_ENGINE_2_3
4206 + dst->__callstatic = NULL;
4209 + /* unset function proxies */
4210 + dst->serialize_func = NULL;
4211 + dst->unserialize_func = NULL;
4213 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
4215 +#ifdef ZEND_ENGINE_2_4
4216 + dst->default_properties_count = src->default_properties_count;
4217 + if (src->default_properties_count) {
4218 + CHECK(dst->default_properties_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_properties_count)));
4219 + for (i = 0; i < src->default_properties_count; i++) {
4220 + if (src->default_properties_table[i]) {
4221 + my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC);
4223 + dst->default_properties_table[i] = NULL;
4227 + dst->default_properties_table = NULL;
4230 + memset(&dst->default_properties, 0, sizeof(dst->default_properties));
4231 + CHECK((my_copy_hashtable_ex(&dst->default_properties,
4232 + &src->default_properties TSRMLS_CC,
4233 + (ht_copy_fun_t) my_copy_zval_ptr,
4236 + (ht_check_copy_fun_t) my_check_copy_default_property,
4240 + CHECK((my_copy_hashtable_ex(&dst->properties_info,
4241 + &src->properties_info TSRMLS_CC,
4242 + (ht_copy_fun_t) my_copy_property_info,
4245 + (ht_check_copy_fun_t) my_check_copy_property_info,
4248 +#ifdef ZEND_ENGINE_2_2
4249 + /* php5.2 introduced a scope attribute for property info */
4250 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4253 +#ifdef ZEND_ENGINE_2_4
4254 + dst->default_static_members_count = src->default_static_members_count;
4256 + if (src->default_static_members_count) {
4257 + CHECK(dst->default_static_members_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_static_members_count)));
4258 + for (i = 0; i < src->default_static_members_count; i++) {
4259 + if (src->default_static_members_table[i]) {
4260 + my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC);
4262 + dst->default_static_members_table[i] = NULL;
4266 + dst->default_static_members_table = NULL;
4268 + dst->static_members_table = dst->default_static_members_table;
4270 + memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
4271 + dst->static_members = NULL;
4272 + CHECK(my_copy_hashtable_ex(&dst->default_static_members,
4273 + &src->default_static_members TSRMLS_CC,
4274 + (ht_copy_fun_t) my_copy_zval_ptr,
4277 + (ht_check_copy_fun_t) my_check_copy_static_member,
4279 + &src->default_static_members));
4281 + if(src->static_members != &src->default_static_members)
4283 + CHECK((dst->static_members = my_copy_hashtable_ex(NULL,
4284 + src->static_members TSRMLS_CC,
4285 + (ht_copy_fun_t) my_copy_zval_ptr,
4288 + (ht_check_copy_fun_t) my_check_copy_static_member,
4290 + src->static_members)));
4294 + dst->static_members = &dst->default_static_members;
4298 + CHECK((my_copy_hashtable_ex(&dst->constants_table,
4299 + &src->constants_table TSRMLS_CC,
4300 + (ht_copy_fun_t) my_copy_zval_ptr,
4303 + (ht_check_copy_fun_t) my_check_copy_constant,
4306 + if (src->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(src)) {
4307 + CHECK(ZEND_CE_DOC_COMMENT(dst) =
4308 + apc_pmemcpy(ZEND_CE_DOC_COMMENT(src), (ZEND_CE_DOC_COMMENT_LEN(src) + 1), pool TSRMLS_CC));
4311 + if (src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)) {
4314 + for (n = 0; src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)[n].fname != NULL; n++) {}
4316 + CHECK((ZEND_CE_BUILTIN_FUNCTIONS(dst) =
4317 + (zend_function_entry*) apc_pool_alloc(pool, ((n + 1) * sizeof(zend_function_entry)))));
4319 + for (i = 0; i < n; i++) {
4320 + CHECK(my_copy_function_entry((zend_function_entry*)(&ZEND_CE_BUILTIN_FUNCTIONS(dst)[i]),
4321 + &ZEND_CE_BUILTIN_FUNCTIONS(src)[i],
4324 + *(char**)&(ZEND_CE_BUILTIN_FUNCTIONS(dst)[n].fname) = NULL;
4327 + if (src->type == ZEND_USER_CLASS && ZEND_CE_FILENAME(src)) {
4328 + CHECK((ZEND_CE_FILENAME(dst) = apc_pstrdup(ZEND_CE_FILENAME(src), pool TSRMLS_CC)));
4335 +/* {{{ my_copy_hashtable_ex */
4336 +static APC_HOTSPOT HashTable* my_copy_hashtable_ex(HashTable* dst,
4337 + HashTable* src TSRMLS_DC,
4338 + ht_copy_fun_t copy_fn,
4340 + apc_context_t* ctxt,
4341 + ht_check_copy_fun_t check_fn,
4344 + Bucket* curr = NULL;
4345 + Bucket* prev = NULL;
4346 + Bucket* newp = NULL;
4348 + apc_pool* pool = ctxt->pool;
4350 + assert(src != NULL);
4353 + CHECK(dst = (HashTable*) apc_pool_alloc(pool, sizeof(src[0])));
4356 + memcpy(dst, src, sizeof(src[0]));
4358 + /* allocate buckets for the new hashtable */
4359 + CHECK((dst->arBuckets = apc_pool_alloc(pool, (dst->nTableSize * sizeof(Bucket*)))));
4361 + memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
4362 + dst->pInternalPointer = NULL;
4363 + dst->pListHead = NULL;
4365 + for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
4366 + int n = curr->h % dst->nTableSize;
4370 + va_start(args, check_fn);
4372 + /* Call the check_fn to see if the current bucket
4373 + * needs to be copied out
4375 + if(!check_fn(curr, args)) {
4376 + dst->nNumOfElements--;
4384 + /* create a copy of the bucket 'curr' */
4385 +#ifdef ZEND_ENGINE_2_4
4386 + if (!curr->nKeyLength) {
4387 + CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
4388 + } else if (IS_INTERNED(curr->arKey)) {
4389 + CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
4391 + } else if (pool->type != APC_UNPOOL) {
4394 + CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
4395 + arKey = apc_new_interned_string(curr->arKey, curr->nKeyLength TSRMLS_CC);
4397 + CHECK((newp->arKey = (char*) apc_pmemcpy(curr->arKey, curr->nKeyLength, pool TSRMLS_CC)));
4399 + newp->arKey = arKey;
4403 + CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
4404 + CHECK((newp->arKey = (char*) apc_pmemcpy(curr->arKey, curr->nKeyLength, pool TSRMLS_CC)));
4407 + CHECK((newp = (Bucket*) apc_pmemcpy(curr,
4408 + (sizeof(Bucket) + curr->nKeyLength - 1),
4409 + pool TSRMLS_CC)));
4412 + /* insert 'newp' into the linked list at its hashed index */
4413 + if (dst->arBuckets[n]) {
4414 + newp->pNext = dst->arBuckets[n];
4415 + newp->pLast = NULL;
4416 + newp->pNext->pLast = newp;
4419 + newp->pNext = newp->pLast = NULL;
4422 + dst->arBuckets[n] = newp;
4424 + /* copy the bucket data using our 'copy_fn' callback function */
4425 + CHECK((newp->pData = copy_fn(NULL, curr->pData, ctxt TSRMLS_CC)));
4428 + memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
4431 + newp->pDataPtr = NULL;
4434 + /* insert 'newp' into the table-thread linked list */
4435 + newp->pListLast = prev;
4436 + newp->pListNext = NULL;
4439 + prev->pListNext = newp;
4443 + dst->pListHead = newp;
4450 + dst->pListTail = newp;
4452 + zend_hash_internal_pointer_reset(dst);
4458 +/* {{{ my_copy_static_variables */
4459 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
4461 + if (src->static_variables == NULL) {
4465 + return my_copy_hashtable(NULL,
4466 + src->static_variables,
4467 + (ht_copy_fun_t) my_copy_zval_ptr,
4473 +/* {{{ apc_copy_zval */
4474 +zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
4476 + apc_pool* pool = ctxt->pool;
4477 + int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
4479 + assert(src != NULL);
4486 + CHECK(dst = (zval*) apc_pool_alloc(pool, sizeof(zval)));
4490 + CHECK(dst = my_copy_zval(dst, src, ctxt TSRMLS_CC));
4495 +/* {{{ apc_fixup_op_array_jumps */
4496 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
4500 + for (i=0; i < dst->last; ++i) {
4501 + zend_op *zo = &(dst->opcodes[i]);
4502 + /*convert opline number to jump address*/
4503 + switch (zo->opcode) {
4504 +#ifdef ZEND_ENGINE_2_3
4508 + /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
4509 +#ifdef ZEND_ENGINE_2_4
4510 + zo->op1.jmp_addr = dst->opcodes + (zo->op1.jmp_addr - src->opcodes);
4512 + zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
4517 + case ZEND_JMPZ_EX:
4518 + case ZEND_JMPNZ_EX:
4519 +#ifdef ZEND_ENGINE_2_3
4520 + case ZEND_JMP_SET:
4522 +#ifdef ZEND_ENGINE_2_4
4523 + case ZEND_JMP_SET_VAR:
4525 +#ifdef ZEND_ENGINE_2_4
4526 + zo->op2.jmp_addr = dst->opcodes + (zo->op2.jmp_addr - src->opcodes);
4528 + zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
4538 +/* {{{ apc_copy_op_array */
4539 +zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
4542 + apc_fileinfo_t *fileinfo = NULL;
4543 + char canon_path[MAXPATHLEN];
4544 + char *fullpath = NULL;
4545 + apc_opflags_t * flags = NULL;
4546 + apc_pool* pool = ctxt->pool;
4548 + assert(src != NULL);
4551 + CHECK(dst = (zend_op_array*) apc_pool_alloc(pool, sizeof(src[0])));
4554 + if(APCG(apc_optimize_function)) {
4555 + APCG(apc_optimize_function)(src TSRMLS_CC);
4558 + /* start with a bitwise copy of the array */
4559 + memcpy(dst, src, sizeof(src[0]));
4561 + dst->function_name = NULL;
4562 + dst->filename = NULL;
4563 + dst->refcount = NULL;
4564 + dst->opcodes = NULL;
4565 + dst->brk_cont_array = NULL;
4566 + dst->static_variables = NULL;
4567 + dst->try_catch_array = NULL;
4568 + dst->arg_info = NULL;
4569 + dst->doc_comment = NULL;
4570 +#ifdef ZEND_ENGINE_2_1
4574 + /* copy the arg types array (if set) */
4575 + if (src->arg_info) {
4576 + CHECK(dst->arg_info = my_copy_arg_info_array(NULL,
4582 + if (src->function_name) {
4583 + CHECK(dst->function_name = apc_pstrdup(src->function_name, pool TSRMLS_CC));
4585 + if (src->filename) {
4586 + CHECK(dst->filename = apc_pstrdup(src->filename, pool TSRMLS_CC));
4589 + CHECK(dst->refcount = apc_pmemcpy(src->refcount,
4590 + sizeof(src->refcount[0]),
4593 +#ifdef ZEND_ENGINE_2_4
4594 + if (src->literals) {
4595 + zend_literal *p, *q, *end;
4597 + q = src->literals;
4598 + p = dst->literals = (zend_literal*) apc_pool_alloc(pool, (sizeof(zend_literal) * src->last_literal));
4599 + end = p + src->last_literal;
4602 + my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
4609 + /* deep-copy the opcodes */
4610 + CHECK(dst->opcodes = (zend_op*) apc_pool_alloc(pool, (sizeof(zend_op) * src->last)));
4612 + if(apc_reserved_offset != -1) {
4613 + /* Insanity alert: the void* pointer is cast into an apc_opflags_t
4614 + * struct. apc_zend_init() checks to ensure that it fits in a void* */
4615 + flags = (apc_opflags_t*) & (dst->reserved[apc_reserved_offset]);
4616 + memset(flags, 0, sizeof(apc_opflags_t));
4617 + /* assert(sizeof(apc_opflags_t) <= sizeof(dst->reserved)); */
4620 + for (i = 0; (uint) i < src->last; i++) {
4621 + zend_op *zo = &(src->opcodes[i]);
4622 + /* a lot of files are merely constant arrays with no jumps */
4623 + switch (zo->opcode) {
4624 +#ifdef ZEND_ENGINE_2_3
4630 + case ZEND_JMPZ_EX:
4631 + case ZEND_JMPNZ_EX:
4632 +#ifdef ZEND_ENGINE_2_3
4633 + case ZEND_JMP_SET:
4635 +#ifdef ZEND_ENGINE_2_4
4636 + case ZEND_JMP_SET_VAR:
4638 + if(flags != NULL) {
4639 + flags->has_jumps = 1;
4642 + /* auto_globals_jit was not in php-4.3.* */
4643 + case ZEND_FETCH_R:
4644 + case ZEND_FETCH_W:
4645 + case ZEND_FETCH_IS:
4646 + case ZEND_FETCH_FUNC_ARG:
4647 + case ZEND_FETCH_RW:
4648 + case ZEND_FETCH_UNSET:
4649 + if(PG(auto_globals_jit) && flags != NULL)
4651 + /* The fetch is only required if auto_globals_jit=1 */
4652 +#ifdef ZEND_ENGINE_2_4
4653 + if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL &&
4654 + zo->op1_type == IS_CONST &&
4655 + Z_TYPE_P(zo->op1.zv) == IS_STRING) {
4656 + if (Z_STRVAL_P(zo->op1.zv)[0] == '_') {
4657 +# define SET_IF_AUTOGLOBAL(member) \
4658 + if(!strcmp(Z_STRVAL_P(zo->op1.zv), #member)) \
4659 + flags->member = 1 /* no ';' here */
4661 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
4662 + zo->op1.op_type == IS_CONST &&
4663 + zo->op1.u.constant.type == IS_STRING) {
4664 + znode * varname = &zo->op1;
4665 + if (varname->u.constant.value.str.val[0] == '_') {
4666 +# define SET_IF_AUTOGLOBAL(member) \
4667 + if(!strcmp(varname->u.constant.value.str.val, #member)) \
4668 + flags->member = 1 /* no ';' here */
4670 + SET_IF_AUTOGLOBAL(_GET);
4671 + else SET_IF_AUTOGLOBAL(_POST);
4672 + else SET_IF_AUTOGLOBAL(_COOKIE);
4673 + else SET_IF_AUTOGLOBAL(_SERVER);
4674 + else SET_IF_AUTOGLOBAL(_ENV);
4675 + else SET_IF_AUTOGLOBAL(_FILES);
4676 + else SET_IF_AUTOGLOBAL(_REQUEST);
4677 + else SET_IF_AUTOGLOBAL(_SESSION);
4678 +#ifdef ZEND_ENGINE_2_4
4679 + else if(zend_is_auto_global(
4680 + Z_STRVAL_P(zo->op1.zv),
4681 + Z_STRLEN_P(zo->op1.zv)
4684 + else if(zend_is_auto_global(
4685 + varname->u.constant.value.str.val,
4686 + varname->u.constant.value.str.len
4690 + flags->unknown_global = 1;
4692 +#ifdef ZEND_ENGINE_2_4
4693 + } else SET_IF_AUTOGLOBAL(GLOBALS);
4700 + case ZEND_RECV_INIT:
4701 +#ifdef ZEND_ENGINE_2_4
4702 + if(zo->op2_type == IS_CONST &&
4703 + Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY) {
4705 + if(zo->op2.op_type == IS_CONST &&
4706 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
4708 + if(flags != NULL) {
4709 + flags->deep_copy = 1;
4714 +#ifdef ZEND_ENGINE_2_4
4715 + if((zo->op1_type == IS_CONST &&
4716 + Z_TYPE_P(zo->op1.zv) == IS_CONSTANT_ARRAY) ||
4717 + (zo->op2_type == IS_CONST &&
4718 + Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY)) {
4720 + if((zo->op1.op_type == IS_CONST &&
4721 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
4722 + (zo->op2.op_type == IS_CONST &&
4723 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
4725 + if(flags != NULL) {
4726 + flags->deep_copy = 1;
4732 + if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, ctxt TSRMLS_CC))) {
4736 +#ifdef ZEND_ENGINE_2_4
4737 + if (zo->op1_type == IS_CONST) {
4738 + dst->opcodes[i].op1.literal = src->opcodes[i].op1.literal - src->literals + dst->literals;
4740 + if (zo->op2_type == IS_CONST) {
4741 + dst->opcodes[i].op2.literal = src->opcodes[i].op2.literal - src->literals + dst->literals;
4743 + if (zo->result_type == IS_CONST) {
4744 + dst->opcodes[i].result.literal = src->opcodes[i].result.literal - src->literals + dst->literals;
4748 + /* This code breaks apc's rule#1 - cache what you compile */
4749 + if((APCG(fpstat)==0) && APCG(canonicalize)) {
4750 + /* not pool allocated, because the pool allocations eat up shm space */
4751 + fileinfo = (apc_fileinfo_t*) apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
4752 +#ifdef ZEND_ENGINE_2_4
4753 + if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
4754 + (zo->op1_type == IS_CONST && Z_TYPE_P(zo->op1.zv) == IS_STRING)) {
4755 + /* constant includes */
4756 + if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(zo->op1.zv),Z_STRLEN_P(zo->op1.zv))) {
4757 + if (apc_search_paths(Z_STRVAL_P(zo->op1.zv), PG(include_path), fileinfo TSRMLS_CC) == 0) {
4759 + if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
4760 + (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
4761 + /* constant includes */
4762 + if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) {
4763 + if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), fileinfo TSRMLS_CC) == 0) {
4765 + if((fullpath = realpath(fileinfo->fullpath, canon_path))) {
4766 + /* everything has to go through a realpath() */
4767 + zend_op *dzo = &(dst->opcodes[i]);
4768 +#ifdef ZEND_ENGINE_2_4
4769 + dzo->op1.literal = (zend_literal*) apc_pool_alloc(pool, sizeof(zend_literal));
4770 + Z_STRLEN_P(dzo->op1.zv) = strlen(fullpath);
4771 + Z_STRVAL_P(dzo->op1.zv) = apc_pstrdup(fullpath, pool TSRMLS_CC);
4772 + Z_TYPE_P(dzo->op1.zv) = IS_STRING;
4773 + Z_SET_REFCOUNT_P(dzo->op1.zv, 2);
4774 + Z_SET_ISREF_P(dzo->op1.zv);
4775 + dzo->op1.literal->hash_value = zend_hash_func(Z_STRVAL_P(dzo->op1.zv), Z_STRLEN_P(dzo->op1.zv)+1);
4777 + dzo->op1.u.constant.value.str.len = strlen(fullpath);
4778 + dzo->op1.u.constant.value.str.val = apc_pstrdup(fullpath, pool TSRMLS_CC);
4784 + apc_php_free(fileinfo TSRMLS_CC);
4788 + if(flags == NULL || flags->has_jumps) {
4789 + apc_fixup_op_array_jumps(dst,src);
4792 + /* copy the break-continue array */
4793 + if (src->brk_cont_array) {
4794 + CHECK(dst->brk_cont_array = apc_pmemcpy(src->brk_cont_array,
4795 + sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
4799 + /* copy the table of static variables */
4800 + if (src->static_variables) {
4801 + CHECK(dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC));
4804 + if (src->try_catch_array) {
4805 + CHECK(dst->try_catch_array = apc_pmemcpy(src->try_catch_array,
4806 + sizeof(src->try_catch_array[0]) * src->last_try_catch,
4810 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
4812 + CHECK(dst->vars = apc_pmemcpy(src->vars,
4813 + sizeof(src->vars[0]) * src->last_var,
4816 + for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
4818 + for(i = 0; i < src->last_var; i++) {
4819 + CHECK(dst->vars[i].name = apc_string_pmemcpy(src->vars[i].name,
4820 + src->vars[i].name_len + 1,
4826 + if (src->doc_comment) {
4827 + CHECK(dst->doc_comment
4828 + = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC));
4836 +/* {{{ apc_copy_new_functions */
4837 +apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC)
4839 + apc_function_t* array;
4840 + int new_count; /* number of new functions in table */
4842 + apc_pool* pool = ctxt->pool;
4844 + new_count = zend_hash_num_elements(CG(function_table)) - old_count;
4845 + assert(new_count >= 0);
4849 + apc_pool_alloc(pool, (sizeof(apc_function_t) * (new_count + 1))));
4851 + if (new_count == 0) {
4852 + array[0].function = NULL;
4856 + /* Skip the first `old_count` functions in the table */
4857 + zend_hash_internal_pointer_reset(CG(function_table));
4858 + for (i = 0; i < old_count; i++) {
4859 + zend_hash_move_forward(CG(function_table));
4862 + /* Add the next `new_count` functions to our array */
4863 + for (i = 0; i < new_count; i++) {
4866 + zend_function* fun;
4868 + zend_hash_get_current_key_ex(CG(function_table),
4875 + zend_hash_get_current_data(CG(function_table), (void**) &fun);
4877 + CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC));
4878 + array[i].name_len = (int) key_size-1;
4879 + CHECK(array[i].function = my_copy_function(NULL, fun, ctxt TSRMLS_CC));
4880 + zend_hash_move_forward(CG(function_table));
4883 + array[i].function = NULL;
4888 +/* {{{ apc_copy_new_classes */
4889 +apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t *ctxt TSRMLS_DC)
4891 + apc_class_t* array;
4892 + int new_count; /* number of new classes in table */
4894 + apc_pool* pool = ctxt->pool;
4896 + new_count = zend_hash_num_elements(CG(class_table)) - old_count;
4897 + assert(new_count >= 0);
4901 + apc_pool_alloc(pool, (sizeof(apc_class_t) * (new_count + 1))));
4903 + if (new_count == 0) {
4904 + array[0].class_entry = NULL;
4908 + /* Skip the first `old_count` classes in the table */
4909 + zend_hash_internal_pointer_reset(CG(class_table));
4910 + for (i = 0; i < old_count; i++) {
4911 + zend_hash_move_forward(CG(class_table));
4914 + /* Add the next `new_count` classes to our array */
4915 + for (i = 0; i < new_count; i++) {
4918 + zend_class_entry* elem = NULL;
4920 + array[i].class_entry = NULL;
4922 + zend_hash_get_current_key_ex(CG(class_table),
4929 + zend_hash_get_current_data(CG(class_table), (void**) &elem);
4932 + elem = *((zend_class_entry**)elem);
4934 + CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC));
4935 + array[i].name_len = (int) key_size-1;
4936 + CHECK(array[i].class_entry = my_copy_class_entry(NULL, elem, ctxt TSRMLS_CC));
4939 + * If the class has a pointer to its parent class, save the parent
4940 + * name so that we can enable compile-time inheritance when we reload
4941 + * the child class; otherwise, set the parent name to null and scan
4942 + * the op_array to determine if this class inherits from some base
4943 + * class at execution-time.
4946 + if (elem->parent) {
4947 + CHECK(array[i].parent_name = apc_pstrdup(elem->parent->name, pool TSRMLS_CC));
4950 + array[i].parent_name = NULL;
4953 + zend_hash_move_forward(CG(class_table));
4956 + array[i].class_entry = NULL;
4961 +/* Used only by my_prepare_op_array_for_execution */
4962 +#ifdef ZEND_ENGINE_2_4
4963 +# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
4964 + /* The fetch is only required if auto_globals_jit=1 */ \
4965 + if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL && \
4966 + zo->op1_type == IS_CONST && \
4967 + Z_TYPE_P(zo->op1.zv) == IS_STRING && \
4968 + Z_STRVAL_P(zo->op1.zv)[0] == '_') { \
4969 + (void)zend_is_auto_global(Z_STRVAL_P(zo->op1.zv), \
4970 + Z_STRLEN_P(zo->op1.zv) \
4974 +# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
4975 + /* The fetch is only required if auto_globals_jit=1 */ \
4976 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
4977 + zo->op1.op_type == IS_CONST && \
4978 + zo->op1.u.constant.type == IS_STRING && \
4979 + zo->op1.u.constant.value.str.val[0] == '_') { \
4981 + znode* varname = &zo->op1; \
4982 + (void)zend_is_auto_global(varname->u.constant.value.str.val, \
4983 + varname->u.constant.value.str.len \
4988 +/* {{{ my_prepare_op_array_for_execution */
4989 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
4991 + /* combine my_fetch_global_vars and my_copy_data_exceptions.
4992 + * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4993 + * - If the opcode stream contain mutable data, ensure a copy.
4994 + * - Fixup array jumps in the same loop.
4999 + apc_opflags_t * flags = apc_reserved_offset != -1 ?
5000 + (apc_opflags_t*) & (src->reserved[apc_reserved_offset]) : NULL;
5001 + int needcopy = flags ? flags->deep_copy : 1;
5002 + /* auto_globals_jit was not in php4 */
5003 + int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
5005 +#define FETCH_AUTOGLOBAL(member) do { \
5006 + if(flags && flags->member == 1) { \
5007 + zend_is_auto_global(#member,\
5008 + (sizeof(#member) - 1)\
5013 + FETCH_AUTOGLOBAL(_GET);
5014 + FETCH_AUTOGLOBAL(_POST);
5015 + FETCH_AUTOGLOBAL(_COOKIE);
5016 + FETCH_AUTOGLOBAL(_SERVER);
5017 + FETCH_AUTOGLOBAL(_ENV);
5018 + FETCH_AUTOGLOBAL(_FILES);
5019 + FETCH_AUTOGLOBAL(_REQUEST);
5020 + FETCH_AUTOGLOBAL(_SESSION);
5021 +#ifdef ZEND_ENGINE_2_4
5022 + FETCH_AUTOGLOBAL(GLOBALS);
5027 +#ifdef ZEND_ENGINE_2_4
5028 + if (src->literals) {
5029 + zend_literal *p, *q, *end;
5031 + q = src->literals;
5032 + p = dst->literals = (zend_literal*) apc_xmemcpy(src->literals,
5033 + sizeof(zend_literal) * src->last_literal,
5034 + apc_php_malloc TSRMLS_CC);
5035 + end = p + src->last_literal;
5037 + if (Z_TYPE(q->constant) == IS_CONSTANT_ARRAY) {
5038 + my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
5046 + dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
5047 + sizeof(zend_op) * src->last,
5048 + apc_php_malloc TSRMLS_CC);
5049 + zo = src->opcodes;
5050 + dzo = dst->opcodes;
5053 +#ifdef ZEND_ENGINE_2_4
5054 + if(zo->op1_type == IS_CONST) {
5055 + dzo->op1.literal = zo->op1.literal - src->literals + dst->literals;
5057 + if(zo->op2_type == IS_CONST) {
5058 + dzo->op2.literal = zo->op2.literal - src->literals + dst->literals;
5060 + if(zo->result_type == IS_CONST) {
5061 + dzo->result.literal = zo->result.literal - src->literals + dst->literals;
5064 + if( ((zo->op1.op_type == IS_CONST &&
5065 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
5066 + ((zo->op2.op_type == IS_CONST &&
5067 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
5069 + if(!(my_copy_zend_op(dzo, zo, ctxt TSRMLS_CC))) {
5070 + assert(0); /* emalloc failed or a bad constant array */
5075 + switch(zo->opcode) {
5076 +#ifdef ZEND_ENGINE_2_3
5080 +#ifdef ZEND_ENGINE_2_4
5081 + dzo->op1.jmp_addr = dst->opcodes +
5082 + (zo->op1.jmp_addr - src->opcodes);
5084 + dzo->op1.u.jmp_addr = dst->opcodes +
5085 + (zo->op1.u.jmp_addr - src->opcodes);
5090 + case ZEND_JMPZ_EX:
5091 + case ZEND_JMPNZ_EX:
5092 +#ifdef ZEND_ENGINE_2_3
5093 + case ZEND_JMP_SET:
5095 +#ifdef ZEND_ENGINE_2_4
5096 + case ZEND_JMP_SET_VAR:
5098 +#ifdef ZEND_ENGINE_2_4
5099 + dzo->op2.jmp_addr = dst->opcodes +
5100 + (zo->op2.jmp_addr - src->opcodes);
5102 + dzo->op2.u.jmp_addr = dst->opcodes +
5103 + (zo->op2.u.jmp_addr - src->opcodes);
5106 + case ZEND_FETCH_R:
5107 + case ZEND_FETCH_W:
5108 + case ZEND_FETCH_IS:
5109 + case ZEND_FETCH_FUNC_ARG:
5110 + if(do_prepare_fetch_global)
5112 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
5122 + } else { /* !needcopy */
5123 + /* The fetch is only required if auto_globals_jit=1 */
5124 + if(do_prepare_fetch_global)
5126 + zo = src->opcodes;
5129 + if(zo->opcode == ZEND_FETCH_R ||
5130 + zo->opcode == ZEND_FETCH_W ||
5131 + zo->opcode == ZEND_FETCH_IS ||
5132 + zo->opcode == ZEND_FETCH_FUNC_ARG
5134 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
5146 +/* {{{ apc_copy_op_array_for_execution */
5147 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
5150 + dst = (zend_op_array*) emalloc(sizeof(src[0]));
5152 + memcpy(dst, src, sizeof(src[0]));
5153 + dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC);
5156 + dst->refcount = apc_pmemcpy(src->refcount,
5157 + sizeof(src->refcount[0]),
5158 + ctxt->pool TSRMLS_CC);
5160 + my_prepare_op_array_for_execution(dst,src, ctxt TSRMLS_CC);
5166 +/* {{{ apc_copy_function_for_execution */
5167 +zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC)
5169 + zend_function* dst;
5171 + dst = (zend_function*) emalloc(sizeof(src[0]));
5172 + memcpy(dst, src, sizeof(src[0]));
5173 + apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array), ctxt TSRMLS_CC);
5178 +/* {{{ apc_copy_function_for_execution_ex */
5179 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
5181 + if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
5182 + return apc_copy_function_for_execution(src, ctxt TSRMLS_CC);
5186 +/* {{{ apc_copy_class_entry_for_execution */
5187 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC)
5189 +#ifdef ZEND_ENGINE_2_4
5192 + zend_class_entry* dst = (zend_class_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0]));
5193 + memcpy(dst, src, sizeof(src[0]));
5195 + if(src->num_interfaces)
5197 + /* These are slots to be populated later by ADD_INTERFACE insns */
5198 + dst->interfaces = apc_php_malloc(
5199 + (sizeof(zend_class_entry*) * src->num_interfaces) TSRMLS_CC);
5200 + memset(dst->interfaces, 0,
5201 + sizeof(zend_class_entry*) * src->num_interfaces);
5205 + /* assert(dst->interfaces == NULL); */
5208 + /* Deep-copy the class properties, because they will be modified */
5210 +#ifdef ZEND_ENGINE_2_4
5211 + dst->name = apc_string_pmemcpy((char*)src->name, src->name_length+1, ctxt->pool TSRMLS_CC);
5212 + dst->default_properties_count = src->default_properties_count;
5213 + if (src->default_properties_count) {
5214 + dst->default_properties_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_properties_count) TSRMLS_CC);
5215 + for (i = 0; i < src->default_properties_count; i++) {
5216 + if (src->default_properties_table[i]) {
5217 + my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC);
5219 + dst->default_properties_table[i] = NULL;
5223 + dst->default_properties_table = NULL;
5226 + my_copy_hashtable(&dst->default_properties,
5227 + &src->default_properties,
5228 + (ht_copy_fun_t) my_copy_zval_ptr,
5233 + /* For derived classes, we must also copy the function hashtable (although
5234 + * we can merely bitwise copy the functions it contains) */
5236 + my_copy_hashtable(&dst->function_table,
5237 + &src->function_table,
5238 + (ht_copy_fun_t) apc_copy_function_for_execution_ex,
5242 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
5244 + /* zend_do_inheritance merges properties_info.
5245 + * Need only shallow copying as it doesn't hold the pointers.
5247 + my_copy_hashtable(&dst->properties_info,
5248 + &src->properties_info,
5249 + (ht_copy_fun_t) my_copy_property_info_for_execution,
5253 +#ifdef ZEND_ENGINE_2_2
5254 + /* php5.2 introduced a scope attribute for property info */
5255 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
5258 + /* if inheritance results in a hash_del, it might result in
5259 + * a pefree() of the pointers here. Deep copying required.
5262 + my_copy_hashtable(&dst->constants_table,
5263 + &src->constants_table,
5264 + (ht_copy_fun_t) my_copy_zval_ptr,
5268 +#ifdef ZEND_ENGINE_2_4
5269 + dst->default_static_members_count = src->default_static_members_count;
5270 + if (src->default_static_members_count) {
5271 + dst->default_static_members_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_static_members_count) TSRMLS_CC);
5272 + for (i = 0; i < src->default_static_members_count; i++) {
5273 + if (src->default_static_members_table[i]) {
5274 + my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC);
5276 + dst->default_static_members_table[i] = NULL;
5280 + dst->default_static_members_table = NULL;
5282 + dst->static_members_table = dst->default_static_members_table;
5284 + my_copy_hashtable(&dst->default_static_members,
5285 + &src->default_static_members,
5286 + (ht_copy_fun_t) my_copy_zval_ptr,
5290 + if(src->static_members != &(src->default_static_members))
5292 + dst->static_members = my_copy_hashtable(NULL,
5293 + src->static_members,
5294 + (ht_copy_fun_t) my_copy_zval_ptr,
5300 + dst->static_members = &(dst->default_static_members);
5308 +/* {{{ apc_free_class_entry_after_execution */
5309 +void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC)
5311 + if(src->num_interfaces > 0 && src->interfaces) {
5312 + apc_php_free(src->interfaces TSRMLS_CC);
5313 + src->interfaces = NULL;
5314 + src->num_interfaces = 0;
5316 + /* my_destroy_hashtable() does not play nice with refcounts */
5318 +#ifdef ZEND_ENGINE_2_4
5319 + if (src->default_static_members_table) {
5322 + for (i = 0; i < src->default_static_members_count; i++) {
5323 + zval_ptr_dtor(&src->default_static_members_table[i]);
5325 + efree(src->default_static_members_table);
5326 + src->default_static_members_table = NULL;
5328 + src->static_members_table = NULL;
5329 + if (src->default_properties_table) {
5332 + for (i = 0; i < src->default_properties_count; i++) {
5333 + if (src->default_properties_table[i]) {
5334 + zval_ptr_dtor(&src->default_properties_table[i]);
5337 + efree(src->default_properties_table);
5338 + src->default_properties_table = NULL;
5341 + zend_hash_clean(&src->default_static_members);
5342 + if(src->static_members != &(src->default_static_members))
5344 + zend_hash_destroy(src->static_members);
5345 + apc_php_free(src->static_members TSRMLS_CC);
5346 + src->static_members = NULL;
5350 + src->static_members = NULL;
5353 + zend_hash_clean(&src->default_properties);
5355 + zend_hash_clean(&src->constants_table);
5357 + /* TODO: more cleanup */
5361 +/* {{{ apc_file_halt_offset */
5362 +long apc_file_halt_offset(const char *filename TSRMLS_DC)
5367 + char haltoff[] = "__COMPILER_HALT_OFFSET__";
5370 + zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, filename, strlen(filename), 0);
5372 + if (zend_hash_find(EG(zend_constants), name, len+1, (void **) &c) == SUCCESS) {
5373 + value = Z_LVAL(c->value);
5382 +/* {{{ apc_do_halt_compiler_register */
5383 +void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC)
5386 + char haltoff[] = "__COMPILER_HALT_OFFSET__";
5389 + if(halt_offset > 0) {
5391 + zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1,
5392 + filename, strlen(filename), 0);
5394 + zend_register_long_constant(name, len+1, halt_offset, CONST_CS, 0 TSRMLS_CC);
5403 +/* {{{ my_fixup_function */
5404 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
5406 + zend_function* zf = p->pData;
5408 + #define SET_IF_SAME_NAME(member) \
5410 + if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
5411 + dst->member = zf; \
5416 + if(zf->common.scope == src)
5419 + /* Fixing up the default functions for objects here since
5420 + * we need to compare with the newly allocated functions
5422 + * caveat: a sub-class method can have the same name as the
5423 + * parent's constructor and create problems.
5426 + if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
5427 + else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
5428 + else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
5431 + SET_IF_SAME_NAME(__get);
5432 + SET_IF_SAME_NAME(__set);
5433 + SET_IF_SAME_NAME(__unset);
5434 + SET_IF_SAME_NAME(__isset);
5435 + SET_IF_SAME_NAME(__call);
5436 +#ifdef ZEND_ENGINE_2_2
5437 + SET_IF_SAME_NAME(__tostring);
5439 +#ifdef ZEND_ENGINE_2_3
5440 + SET_IF_SAME_NAME(__callstatic);
5443 + zf->common.scope = dst;
5447 + /* no other function should reach here */
5451 + #undef SET_IF_SAME_NAME
5455 +#ifdef ZEND_ENGINE_2_2
5456 +/* {{{ my_fixup_property_info */
5457 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
5459 + zend_property_info* property_info = (zend_property_info*)p->pData;
5461 + if(property_info->ce == src)
5463 + property_info->ce = dst;
5467 + assert(0); /* should never happen */
5473 +/* {{{ my_fixup_hashtable */
5474 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
5479 + for (i = 0; i < ht->nTableSize; i++) {
5480 + if(!ht->arBuckets) break;
5481 + p = ht->arBuckets[i];
5482 + while (p != NULL) {
5483 + fixup(p, src, dst);
5491 +/* {{{ my_check_copy_function */
5492 +static int my_check_copy_function(Bucket* p, va_list args)
5494 + zend_class_entry* src = va_arg(args, zend_class_entry*);
5495 + zend_function* zf = (zend_function*)p->pData;
5497 + return (zf->common.scope == src);
5501 +#ifndef ZEND_ENGINE_2_4
5502 +/* {{{ my_check_copy_default_property */
5503 +static int my_check_copy_default_property(Bucket* p, va_list args)
5505 + zend_class_entry* src = va_arg(args, zend_class_entry*);
5506 + zend_class_entry* parent = src->parent;
5507 + zval ** child_prop = (zval**)p->pData;
5508 + zval ** parent_prop = NULL;
5511 + zend_hash_quick_find(&parent->default_properties, p->arKey,
5512 + p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
5514 + if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
5520 + /* possibly not in the parent */
5526 +/* {{{ my_check_copy_property_info */
5527 +static int my_check_copy_property_info(Bucket* p, va_list args)
5529 + zend_class_entry* src = va_arg(args, zend_class_entry*);
5530 + zend_class_entry* parent = src->parent;
5531 + zend_property_info* child_info = (zend_property_info*)p->pData;
5532 + zend_property_info* parent_info = NULL;
5534 +#ifdef ZEND_ENGINE_2_2
5535 + /* so much easier */
5536 + return (child_info->ce == src);
5540 + zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
5541 + p->h, (void **) &parent_info)==SUCCESS) {
5542 + if(parent_info->flags & ZEND_ACC_PRIVATE)
5546 + if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
5547 + (child_info->flags & ZEND_ACC_PPP_MASK))
5549 + /* TODO: figure out whether ACC_CHANGED is more appropriate
5556 + /* property doesn't exist in parent, copy into cached child */
5561 +#ifndef ZEND_ENGINE_2_4
5562 +/* {{{ my_check_copy_static_member */
5563 +static int my_check_copy_static_member(Bucket* p, va_list args)
5565 + zend_class_entry* src = va_arg(args, zend_class_entry*);
5566 + HashTable * ht = va_arg(args, HashTable*);
5567 + zend_class_entry* parent = src->parent;
5568 + HashTable * parent_ht = NULL;
5569 + char * member_name;
5570 + char * class_name = NULL;
5572 + zend_property_info *parent_info = NULL;
5573 + zend_property_info *child_info = NULL;
5574 + zval ** parent_prop = NULL;
5575 + zval ** child_prop = (zval**)(p->pData);
5581 + /* these do not need free'ing */
5582 +#ifdef ZEND_ENGINE_2_2
5583 + zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
5585 + zend_unmangle_property_name(p->arKey, &class_name, &member_name);
5588 + /* please refer do_inherit_property_access_check in zend_compile.c
5589 + * to understand why we lookup in properties_info.
5591 + if((zend_hash_find(&parent->properties_info, member_name,
5592 + strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
5594 + (zend_hash_find(&src->properties_info, member_name,
5595 + strlen(member_name)+1, (void**)&child_info) == SUCCESS))
5597 + if(ht == &(src->default_static_members))
5599 + parent_ht = &parent->default_static_members;
5603 + parent_ht = parent->static_members;
5606 + if(zend_hash_quick_find(parent_ht, p->arKey,
5607 + p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
5609 + /* they point to the same zval */
5610 + if(*parent_prop == *child_prop)
5622 +/* {{{ my_check_copy_constant */
5623 +static int my_check_copy_constant(Bucket* p, va_list args)
5625 + zend_class_entry* src = va_arg(args, zend_class_entry*);
5626 + zend_class_entry* parent = src->parent;
5627 + zval ** child_const = (zval**)p->pData;
5628 + zval ** parent_const = NULL;
5631 + zend_hash_quick_find(&parent->constants_table, p->arKey,
5632 + p->nKeyLength, p->h, (void **) &parent_const)==SUCCESS) {
5634 + if((parent_const && child_const) && (*parent_const) == (*child_const))
5640 + /* possibly not in the parent */
5645 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
5646 + * register a optimizer callback function, returns the previous callback
5648 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
5649 + apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
5650 + APCG(apc_optimize_function) = optimizer;
5651 + return old_optimizer;
5656 + * Local variables:
5658 + * c-basic-offset: 4
5660 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
5661 + * vim<600: expandtab sw=4 ts=4 sts=4
5663 diff -Naur a/ext/apc/apc_compile.h b/ext/apc/apc_compile.h
5664 --- a/ext/apc/apc_compile.h 1970-01-01 01:00:00.000000000 +0100
5665 +++ b/ext/apc/apc_compile.h 2012-07-20 00:10:35.000000000 +0200
5668 + +----------------------------------------------------------------------+
5670 + +----------------------------------------------------------------------+
5671 + | Copyright (c) 2006-2011 The PHP Group |
5672 + +----------------------------------------------------------------------+
5673 + | This source file is subject to version 3.01 of the PHP license, |
5674 + | that is bundled with this package in the file LICENSE, and is |
5675 + | available through the world-wide-web at the following url: |
5676 + | http://www.php.net/license/3_01.txt |
5677 + | If you did not receive a copy of the PHP license and are unable to |
5678 + | obtain it through the world-wide-web, please send a note to |
5679 + | license@php.net so we can mail you a copy immediately. |
5680 + +----------------------------------------------------------------------+
5681 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5682 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5683 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5684 + +----------------------------------------------------------------------+
5686 + This software was contributed to PHP by Community Connect Inc. in 2002
5687 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5688 + Future revisions and derivatives of this source code must acknowledge
5689 + Community Connect Inc. as the original contributor of this module by
5690 + leaving this note intact in the source code.
5692 + All other licensing and usage conditions are those of the PHP Group.
5696 +/* $Id: apc_compile.h 307185 2011-01-06 21:13:11Z gopalv $ */
5698 +#ifndef APC_COMPILE_H
5699 +#define APC_COMPILE_H
5702 + * This module encapsulates most of the complexity involved in deep-copying
5703 + * the Zend compiler data structures. The routines are allocator-agnostic, so
5704 + * the same function can be used for copying to and from shared memory.
5708 +#include "apc_php.h"
5709 +#include "apc_main.h"
5710 +#include "apc_serializer.h"
5712 +/* {{{ struct definition: apc_function_t */
5713 +typedef struct apc_function_t apc_function_t;
5714 +struct apc_function_t {
5715 + char* name; /* the function name */
5716 + int name_len; /* length of name */
5717 + zend_function* function; /* the zend function data structure */
5721 +/* {{{ struct definition: apc_class_t */
5722 +typedef struct apc_class_t apc_class_t;
5723 +struct apc_class_t {
5724 + char* name; /* the class name */
5725 + int name_len; /* length of name */
5726 + char* parent_name; /* the parent class name */
5727 + zend_class_entry* class_entry; /* the zend class data structure */
5731 +/* {{{ struct definition: apc_opflags_t */
5732 +typedef struct apc_opflags_t apc_opflags_t;
5733 +struct apc_opflags_t {
5734 + unsigned int has_jumps : 1; /* has jump offsets */
5735 + unsigned int deep_copy : 1; /* needs deep copy */
5737 + /* autoglobal bits */
5738 + unsigned int _POST : 1;
5739 + unsigned int _GET : 1;
5740 + unsigned int _COOKIE : 1;
5741 + unsigned int _SERVER : 1;
5742 + unsigned int _ENV : 1;
5743 + unsigned int _FILES : 1;
5744 + unsigned int _REQUEST : 1;
5745 + unsigned int _SESSION : 1;
5746 +#ifdef ZEND_ENGINE_2_4
5747 + unsigned int GLOBALS : 1;
5749 + unsigned int unknown_global : 1;
5754 + * These are the top-level copy functions.
5757 +extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
5758 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC);
5759 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC);
5760 +extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t* ctxt TSRMLS_DC);
5761 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC);
5765 + * Deallocation functions corresponding to the copy functions above.
5768 +extern void apc_free_op_array(zend_op_array* src, apc_context_t* ctxt);
5769 +extern void apc_free_functions(apc_function_t* src, apc_context_t* ctxt);
5770 +extern void apc_free_classes(apc_class_t* src, apc_context_t* ctxt);
5771 +extern void apc_free_zval(zval* src, apc_context_t* ctxt);
5775 + * These "copy-for-execution" functions must be called after retrieving an
5776 + * object from the shared cache. They do the minimal amount of work necessary
5777 + * to allow multiple processes to concurrently execute the same VM data
5781 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
5782 +extern zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC);
5783 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC);
5786 + * The "free-after-execution" function performs a cursory clean up of the class data
5787 + * This is required to minimize memory leak warnings and to ensure correct destructor
5788 + * ordering of some variables.
5790 +extern void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC);
5793 + * Optimization callback definition and registration function.
5795 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
5796 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
5799 + * To handle __COMPILER_HALT_OFFSET__
5801 +long apc_file_halt_offset(const char* filename TSRMLS_DC);
5802 +void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC);
5805 + * apc serialization functions
5807 +int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS);
5808 +int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS);
5812 + * Local variables:
5814 + * c-basic-offset: 4
5816 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
5817 + * vim<600: expandtab sw=4 ts=4 sts=4
5819 diff -Naur a/ext/apc/apc_debug.c b/ext/apc/apc_debug.c
5820 --- a/ext/apc/apc_debug.c 1970-01-01 01:00:00.000000000 +0100
5821 +++ b/ext/apc/apc_debug.c 2012-07-20 00:10:35.000000000 +0200
5824 + +----------------------------------------------------------------------+
5826 + +----------------------------------------------------------------------+
5827 + | Copyright (c) 2006-2011 The PHP Group |
5828 + +----------------------------------------------------------------------+
5829 + | This source file is subject to version 3.01 of the PHP license, |
5830 + | that is bundled with this package in the file LICENSE, and is |
5831 + | available through the world-wide-web at the following url: |
5832 + | http://www.php.net/license/3_01.txt |
5833 + | If you did not receive a copy of the PHP license and are unable to |
5834 + | obtain it through the world-wide-web, please send a note to |
5835 + | license@php.net so we can mail you a copy immediately. |
5836 + +----------------------------------------------------------------------+
5837 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5838 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5839 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5840 + +----------------------------------------------------------------------+
5842 + This software was contributed to PHP by Community Connect Inc. in 2002
5843 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5844 + Future revisions and derivatives of this source code must acknowledge
5845 + Community Connect Inc. as the original contributor of this module by
5846 + leaving this note intact in the source code.
5848 + All other licensing and usage conditions are those of the PHP Group.
5851 +/* $Id: apc_debug.c 307048 2011-01-03 23:53:17Z kalle $ */
5855 +#include "zend_compile.h"
5857 +#if defined(__DEBUG_APC__)
5859 +/* keep track of vld_dump_oparray() signature */
5860 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
5864 +void dump(zend_op_array *op_array TSRMLS_DC)
5866 +#if defined(__DEBUG_APC__)
5867 + vld_dump_f dump_op_array;
5868 + DL_HANDLE handle = NULL;
5871 + handle = GetModuleHandle(NULL);
5874 + apc_warning("unable to fetch current module handle." TSRMLS_CC);
5878 + dump_op_array = (vld_dump_f) DL_FETCH_SYMBOL(handle, "vld_dump_oparray");
5881 + DL_UNLOAD(handle);
5884 + if(dump_op_array) {
5885 + dump_op_array(op_array TSRMLS_CC);
5890 + apc_warning("vld is not installed or something even worse." TSRMLS_CC);
5893 diff -Naur a/ext/apc/apc_debug.h b/ext/apc/apc_debug.h
5894 --- a/ext/apc/apc_debug.h 1970-01-01 01:00:00.000000000 +0100
5895 +++ b/ext/apc/apc_debug.h 2012-07-20 00:10:35.000000000 +0200
5898 + +----------------------------------------------------------------------+
5900 + +----------------------------------------------------------------------+
5901 + | Copyright (c) 2006-2011 The PHP Group |
5902 + +----------------------------------------------------------------------+
5903 + | This source file is subject to version 3.01 of the PHP license, |
5904 + | that is bundled with this package in the file LICENSE, and is |
5905 + | available through the world-wide-web at the following url: |
5906 + | http://www.php.net/license/3_01.txt |
5907 + | If you did not receive a copy of the PHP license and are unable to |
5908 + | obtain it through the world-wide-web, please send a note to |
5909 + | license@php.net so we can mail you a copy immediately. |
5910 + +----------------------------------------------------------------------+
5911 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5912 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5913 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5914 + +----------------------------------------------------------------------+
5916 + This software was contributed to PHP by Community Connect Inc. in 2002
5917 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5918 + Future revisions and derivatives of this source code must acknowledge
5919 + Community Connect Inc. as the original contributor of this module by
5920 + leaving this note intact in the source code.
5922 + All other licensing and usage conditions are those of the PHP Group.
5925 +void dump(zend_op_array * TSRMLS_DC);
5926 diff -Naur a/ext/apc/apc_fcntl.c b/ext/apc/apc_fcntl.c
5927 --- a/ext/apc/apc_fcntl.c 1970-01-01 01:00:00.000000000 +0100
5928 +++ b/ext/apc/apc_fcntl.c 2012-07-20 00:10:35.000000000 +0200
5931 + +----------------------------------------------------------------------+
5933 + +----------------------------------------------------------------------+
5934 + | Copyright (c) 2006-2011 The PHP Group |
5935 + +----------------------------------------------------------------------+
5936 + | This source file is subject to version 3.01 of the PHP license, |
5937 + | that is bundled with this package in the file LICENSE, and is |
5938 + | available through the world-wide-web at the following url: |
5939 + | http://www.php.net/license/3_01.txt |
5940 + | If you did not receive a copy of the PHP license and are unable to |
5941 + | obtain it through the world-wide-web, please send a note to |
5942 + | license@php.net so we can mail you a copy immediately. |
5943 + +----------------------------------------------------------------------+
5944 + | Authors: George Schlossnagle <george@omniti.com> |
5945 + | Rasmus Lerdorf <rasmus@php.net> |
5946 + +----------------------------------------------------------------------+
5948 + This software was contributed to PHP by Community Connect Inc. in 2002
5949 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5950 + Future revisions and derivatives of this source code must acknowledge
5951 + Community Connect Inc. as the original contributor of this module by
5952 + leaving this note intact in the source code.
5954 + All other licensing and usage conditions are those of the PHP Group.
5958 +/* $Id: apc_fcntl.c 307048 2011-01-03 23:53:17Z kalle $ */
5962 +#ifdef APC_FCNTL_LOCKS
5964 +#include "apc_fcntl.h"
5965 +#include <unistd.h>
5968 +int apc_fcntl_create(const char* pathname TSRMLS_DC)
5971 + if(pathname == NULL) {
5972 + char lock_path[] = "/tmp/.apc.XXXXXX";
5973 + mktemp(lock_path);
5974 + fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5976 + unlink(lock_path);
5979 + apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, lock_path);
5983 + fd = open(pathname, O_RDWR|O_CREAT, 0666);
5988 + apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, pathname);
5992 +void apc_fcntl_destroy(int fd)
5997 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
6000 + struct flock lock;
6002 + lock.l_type = type;
6003 + lock.l_start = offset;
6004 + lock.l_whence = whence;
6008 + do { ret = fcntl(fd, cmd, &lock) ; }
6009 + while(ret < 0 && errno == EINTR);
6013 +void apc_fcntl_lock(int fd TSRMLS_DC)
6015 + if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
6016 + apc_error("apc_fcntl_lock failed:" TSRMLS_CC);
6020 +void apc_fcntl_rdlock(int fd TSRMLS_DC)
6022 + if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
6023 + apc_error("apc_fcntl_rdlock failed:" TSRMLS_CC);
6027 +zend_bool apc_fcntl_nonblocking_lock(int fd TSRMLS_DC)
6029 + if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
6030 + if(errno==EACCES||errno==EAGAIN) return 0;
6031 + else apc_error("apc_fcntl_lock failed:" TSRMLS_CC);
6036 +void apc_fcntl_unlock(int fd TSRMLS_DC)
6038 + if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
6039 + apc_error("apc_fcntl_unlock failed:" TSRMLS_CC);
6043 +#endif /* APC_FCNTL_LOCKS */
6046 + * Local variables:
6048 + * c-basic-offset: 4
6050 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6051 + * vim<600: expandtab sw=4 ts=4 sts=4
6053 diff -Naur a/ext/apc/apc_fcntl.h b/ext/apc/apc_fcntl.h
6054 --- a/ext/apc/apc_fcntl.h 1970-01-01 01:00:00.000000000 +0100
6055 +++ b/ext/apc/apc_fcntl.h 2012-07-20 00:10:35.000000000 +0200
6058 + +----------------------------------------------------------------------+
6060 + +----------------------------------------------------------------------+
6061 + | Copyright (c) 2006-2011 The PHP Group |
6062 + +----------------------------------------------------------------------+
6063 + | This source file is subject to version 3.01 of the PHP license, |
6064 + | that is bundled with this package in the file LICENSE, and is |
6065 + | available through the world-wide-web at the following url: |
6066 + | http://www.php.net/license/3_01.txt. |
6067 + | If you did not receive a copy of the PHP license and are unable to |
6068 + | obtain it through the world-wide-web, please send a note to |
6069 + | license@php.net so we can mail you a copy immediately. |
6070 + +----------------------------------------------------------------------+
6071 + | Authors: George Schlossnagle <george@omniti.com> |
6072 + | Rasmus Lerdorf <rasmus@php.net> |
6073 + +----------------------------------------------------------------------+
6075 + This software was contributed to PHP by Community Connect Inc. in 2002
6076 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6077 + Future revisions and derivatives of this source code must acknowledge
6078 + Community Connect Inc. as the original contributor of this module by
6079 + leaving this note intact in the source code.
6081 + All other licensing and usage conditions are those of the PHP Group.
6085 +/* $Id: apc_fcntl.h 307048 2011-01-03 23:53:17Z kalle $ */
6087 +#ifndef APC_FCNTL_H
6088 +#define APC_FCNTL_H
6091 +extern int apc_fcntl_create(const char* pathname TSRMLS_DC);
6092 +extern void apc_fcntl_destroy(int fd);
6093 +extern void apc_fcntl_lock(int fd TSRMLS_DC);
6094 +extern void apc_fcntl_rdlock(int fd TSRMLS_DC);
6095 +extern void apc_fcntl_unlock(int fd TSRMLS_DC);
6096 +extern unsigned char apc_fcntl_nonblocking_lock(int fd TSRMLS_DC);
6100 + * Local variables:
6102 + * c-basic-offset: 4
6104 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6105 + * vim<600: expandtab sw=4 ts=4 sts=4
6107 diff -Naur a/ext/apc/apc_fcntl_win32.c b/ext/apc/apc_fcntl_win32.c
6108 --- a/ext/apc/apc_fcntl_win32.c 1970-01-01 01:00:00.000000000 +0100
6109 +++ b/ext/apc/apc_fcntl_win32.c 2012-07-20 00:10:35.000000000 +0200
6112 + +----------------------------------------------------------------------+
6114 + +----------------------------------------------------------------------+
6115 + | Copyright (c) 2006-2011 The PHP Group |
6116 + +----------------------------------------------------------------------+
6117 + | This source file is subject to version 3.01 of the PHP license, |
6118 + | that is bundled with this package in the file LICENSE, and is |
6119 + | available through the world-wide-web at the following url: |
6120 + | http://www.php.net/license/3_01.txt |
6121 + | If you did not receive a copy of the PHP license and are unable to |
6122 + | obtain it through the world-wide-web, please send a note to |
6123 + | license@php.net so we can mail you a copy immediately. |
6124 + +----------------------------------------------------------------------+
6125 + | Authors: George Schlossnagle <george@omniti.com> |
6126 + | Edin Kadribasic <edink@php.net> |
6127 + | Pierre Joye <pierre@php.net> |
6128 + +----------------------------------------------------------------------+
6130 + This software was contributed to PHP by Community Connect Inc. in 2002
6131 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6132 + Future revisions and derivatives of this source code must acknowledge
6133 + Community Connect Inc. as the original contributor of this module by
6134 + leaving this note intact in the source code.
6136 + All other licensing and usage conditions are those of the PHP Group.
6140 +/* $Id: apc_fcntl_win32.c 309203 2011-03-14 06:47:16Z pajoye $ */
6143 +#include "apc_fcntl.h"
6145 +#include <win32/flock.h>
6148 +#include <sys/types.h>
6149 +#include <sys/stat.h>
6151 +int apc_fcntl_create(const char* pathname TSRMLS_DC)
6153 + char lock_file[MAXPATHLEN];
6155 + DWORD tmp_dirname_len;
6156 + char lock_filename_tpl[] = ".apc.XXXXXX";
6157 + char *lock_filename;
6159 + tmp_dirname_len = GetTempPath(MAXPATHLEN, lock_file);
6160 + if (!tmp_dirname_len) {
6164 + lock_filename = _mktemp(lock_filename_tpl);
6165 + if (lock_filename == NULL) {
6169 + snprintf(lock_file + tmp_dirname_len, MAXPATHLEN - tmp_dirname_len - 1, "%s", lock_filename);
6171 + fd = CreateFile(lock_file,
6172 + GENERIC_READ | GENERIC_WRITE,
6173 + FILE_SHARE_READ | FILE_SHARE_WRITE,
6176 + FILE_ATTRIBUTE_NORMAL,
6179 + if (fd == INVALID_HANDLE_VALUE) {
6180 + apc_error("apc_fcntl_create: could not open %s" TSRMLS_CC, lock_file);
6187 +void apc_fcntl_destroy(int fd)
6189 + CloseHandle((HANDLE)fd);
6192 +void apc_fcntl_lock(int fd TSRMLS_DC)
6194 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
6196 + if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
6197 + apc_error("apc_fcntl_lock failed errno:%d" TSRMLS_CC, GetLastError());
6201 +void apc_fcntl_rdlock(int fd TSRMLS_DC)
6203 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
6205 + if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
6206 + apc_error("apc_fcntl_rdlock failed errno:%d" TSRMLS_CC, GetLastError());
6210 +void apc_fcntl_unlock(int fd TSRMLS_DC)
6212 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
6214 + if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
6215 + DWORD error_code = GetLastError();
6216 + /* Ignore already unlocked error */
6217 + if (error_code != ERROR_NOT_LOCKED) {
6218 + apc_error("apc_fcntl_unlock failed errno:%d" TSRMLS_CC, error_code);
6224 + * Local variables:
6226 + * c-basic-offset: 4
6228 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6229 + * vim<600: expandtab sw=4 ts=4 sts=4
6231 diff -Naur a/ext/apc/apc_globals.h b/ext/apc/apc_globals.h
6232 --- a/ext/apc/apc_globals.h 1970-01-01 01:00:00.000000000 +0100
6233 +++ b/ext/apc/apc_globals.h 2012-07-20 00:10:35.000000000 +0200
6236 + +----------------------------------------------------------------------+
6238 + +----------------------------------------------------------------------+
6239 + | Copyright (c) 2006-2011 The PHP Group |
6240 + +----------------------------------------------------------------------+
6241 + | This source file is subject to version 3.01 of the PHP license, |
6242 + | that is bundled with this package in the file LICENSE, and is |
6243 + | available through the world-wide-web at the following url: |
6244 + | http://www.php.net/license/3_01.txt. |
6245 + | If you did not receive a copy of the PHP license and are unable to |
6246 + | obtain it through the world-wide-web, please send a note to |
6247 + | license@php.net so we can mail you a copy immediately. |
6248 + +----------------------------------------------------------------------+
6249 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6250 + | George Schlossnagle <george@omniti.com> |
6251 + | Rasmus Lerdorf <rasmus@php.net> |
6252 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6253 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6254 + +----------------------------------------------------------------------+
6256 + This software was contributed to PHP by Community Connect Inc. in 2002
6257 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6258 + Future revisions and derivatives of this source code must acknowledge
6259 + Community Connect Inc. as the original contributor of this module by
6260 + leaving this note intact in the source code.
6262 + All other licensing and usage conditions are those of the PHP Group.
6266 +/* $Id: apc_globals.h 307215 2011-01-07 09:54:00Z gopalv $ */
6268 +#ifndef APC_GLOBALS_H
6269 +#define APC_GLOBALS_H
6271 +#include "apc_cache.h"
6272 +#include "apc_stack.h"
6273 +#include "apc_php.h"
6274 +#include "apc_main.h"
6276 +/* {{{ struct apc_rfc1867_data */
6278 +typedef struct _apc_rfc1867_data apc_rfc1867_data;
6280 +struct _apc_rfc1867_data {
6281 + char tracking_key[64];
6283 + size_t content_length;
6284 + char filename[128];
6286 + char *temp_filename;
6287 + int cancel_upload;
6288 + double start_time;
6289 + size_t bytes_processed;
6290 + size_t prev_bytes_processed;
6298 +ZEND_BEGIN_MODULE_GLOBALS(apc)
6299 + /* configuration parameters */
6300 + zend_bool enabled; /* if true, apc is enabled (defaults to true) */
6301 + long shm_segments; /* number of shared memory segments to use */
6302 + long shm_size; /* size of each shared memory segment (in MB) */
6303 + long num_files_hint; /* parameter to apc_cache_create */
6304 + long user_entries_hint;
6305 + long gc_ttl; /* parameter to apc_cache_create */
6306 + long ttl; /* parameter to apc_cache_create */
6309 + char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */
6311 + char** filters; /* array of regex filters that prevent caching */
6312 + void* compiled_filters; /* compiled regex filters */
6314 + /* module variables */
6315 + zend_bool initialized; /* true if module was initialized */
6316 + apc_stack_t* cache_stack; /* the stack of cached executable code */
6317 + zend_bool cache_by_default; /* true if files should be cached unless filtered out */
6318 + /* false if files should only be cached if filtered in */
6319 + long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
6320 + zend_bool enable_cli; /* Flag to override turning APC off for CLI */
6321 + long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */
6322 + zend_bool fpstat; /* true if fullpath includes should be stat'ed */
6323 + zend_bool canonicalize; /* true if relative paths should be canonicalized in no-stat mode */
6324 + zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */
6325 + zend_bool write_lock; /* true for a global write lock */
6326 + zend_bool slam_defense; /* true for user cache slam defense */
6327 + zend_bool report_autofilter; /* true for auto-filter warnings */
6328 + zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
6329 + apc_optimize_function_t apc_optimize_function; /* optimizer function callback */
6330 +#ifdef MULTIPART_EVENT_FORMDATA
6331 + zend_bool rfc1867; /* Flag to enable rfc1867 handler */
6332 + char* rfc1867_prefix; /* Key prefix */
6333 + char* rfc1867_name; /* Name of hidden field to activate upload progress/key suffix */
6334 + double rfc1867_freq; /* Update frequency as percentage or bytes */
6335 + long rfc1867_ttl; /* TTL for rfc1867 entries */
6336 + apc_rfc1867_data rfc1867_data;/* Per-request data */
6338 + HashTable copied_zvals; /* my_copy recursion detection list */
6339 + zend_bool force_file_update; /* force files to be updated during apc_compile_file */
6340 + char canon_path[MAXPATHLEN]; /* canonical path for key data */
6341 +#ifdef APC_FILEHITS
6342 + zval *filehits; /* Files that came from the cache for this request */
6344 + zend_bool coredump_unmap; /* Trap signals that coredump and unmap shared memory */
6345 + apc_cache_t *current_cache; /* current cache being modified/read */
6346 + char *preload_path;
6347 + zend_bool file_md5; /* record md5 hash of files */
6348 + void *apc_bd_alloc_ptr; /* bindump alloc() ptr */
6349 + void *apc_bd_alloc_ubptr; /* bindump alloc() upper bound ptr */
6350 + HashTable apc_bd_alloc_list; /* bindump alloc() ptr list */
6351 + zend_bool use_request_time; /* use the SAPI request start time for TTL */
6352 + zend_bool lazy_functions; /* enable/disable lazy function loading */
6353 + HashTable *lazy_function_table; /* lazy function entry table */
6354 + zend_bool lazy_classes; /* enable/disable lazy class loading */
6355 + HashTable *lazy_class_table; /* lazy class entry table */
6356 +#ifdef ZEND_ENGINE_2_4
6357 + long shm_strings_buffer;
6359 + char *serializer_name; /* the serializer config option */
6360 + apc_serializer_t *serializer;/* the actual serializer in use */
6361 +ZEND_END_MODULE_GLOBALS(apc)
6363 +/* (the following declaration is defined in php_apc.c) */
6364 +ZEND_EXTERN_MODULE_GLOBALS(apc)
6367 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
6369 +# define APCG(v) (apc_globals.v)
6373 +extern apc_cache_t* apc_cache; /* the global compiler cache */
6374 +extern apc_cache_t* apc_user_cache; /* the global user content cache */
6375 +extern void* apc_compiled_filters; /* compiled filters */
6380 + * Local variables:
6382 + * c-basic-offset: 4
6384 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6385 + * vim<600: expandtab sw=4 ts=4 sts=4
6387 diff -Naur a/ext/apc/apc.h b/ext/apc/apc.h
6388 --- a/ext/apc/apc.h 1970-01-01 01:00:00.000000000 +0100
6389 +++ b/ext/apc/apc.h 2012-07-20 00:10:35.000000000 +0200
6392 + +----------------------------------------------------------------------+
6394 + +----------------------------------------------------------------------+
6395 + | Copyright (c) 2006-2011 The PHP Group |
6396 + +----------------------------------------------------------------------+
6397 + | This source file is subject to version 3.01 of the PHP license, |
6398 + | that is bundled with this package in the file LICENSE, and is |
6399 + | available through the world-wide-web at the following url: |
6400 + | http://www.php.net/license/3_01.txt |
6401 + | If you did not receive a copy of the PHP license and are unable to |
6402 + | obtain it through the world-wide-web, please send a note to |
6403 + | license@php.net so we can mail you a copy immediately. |
6404 + +----------------------------------------------------------------------+
6405 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6406 + | George Schlossnagle <george@omniti.com> |
6407 + | Rasmus Lerdorf <rasmus@php.net> |
6408 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6409 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6410 + +----------------------------------------------------------------------+
6412 + This software was contributed to PHP by Community Connect Inc. in 2002
6413 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6414 + Future revisions and derivatives of this source code must acknowledge
6415 + Community Connect Inc. as the original contributor of this module by
6416 + leaving this note intact in the source code.
6418 + All other licensing and usage conditions are those of the PHP Group.
6422 +/* $Id: apc.h 307264 2011-01-08 13:20:20Z gopalv $ */
6428 + * This module defines utilities and helper functions used elsewhere in APC.
6431 +/* Commonly needed C library headers. */
6432 +#include <assert.h>
6434 +#include <stdarg.h>
6436 +#include <stdlib.h>
6437 +#include <string.h>
6440 +/* UNIX headers (needed for struct stat) */
6441 +#include <sys/types.h>
6442 +#include <sys/stat.h>
6444 +#include <unistd.h>
6447 +#ifdef HAVE_CONFIG_H
6448 +#include <config.h>
6452 +#include "main/php_streams.h"
6454 +/* typedefs for extensible memory allocators */
6455 +typedef void* (*apc_malloc_t)(size_t TSRMLS_DC);
6456 +typedef void (*apc_free_t) (void * TSRMLS_DC);
6458 +/* wrappers for memory allocation routines */
6459 +extern void* apc_emalloc(size_t n TSRMLS_DC);
6460 +extern void* apc_erealloc(void* p, size_t n TSRMLS_DC);
6461 +extern void apc_efree(void* p TSRMLS_DC);
6462 +extern char* apc_estrdup(const char* s TSRMLS_DC);
6463 +extern void* apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC);
6464 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC);
6466 +/* console display functions */
6467 +extern void apc_error(const char *format TSRMLS_DC, ...);
6468 +extern void apc_warning(const char *format TSRMLS_DC, ...);
6469 +extern void apc_notice(const char *format TSRMLS_DC, ...);
6470 +extern void apc_debug(const char *format TSRMLS_DC, ...);
6472 +/* string and text manipulation */
6473 +extern char* apc_append(const char* s, const char* t TSRMLS_DC);
6474 +extern char* apc_substr(const char* s, int start, int length TSRMLS_DC);
6475 +extern char** apc_tokenize(const char* s, char delim TSRMLS_DC);
6477 +/* filesystem functions */
6479 +typedef struct apc_fileinfo_t
6482 + char path_buf[MAXPATHLEN];
6483 + php_stream_statbuf st_buf;
6486 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC);
6488 +/* regular expression wrapper functions */
6489 +extern void* apc_regex_compile_array(char* patterns[] TSRMLS_DC);
6490 +extern void apc_regex_destroy_array(void* p TSRMLS_DC);
6491 +extern int apc_regex_match_array(void* p, const char* input);
6493 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
6494 +extern unsigned int apc_crc32(const char* buf, int len);
6496 +/* apc_flip_hash flips keys and values for faster searching */
6497 +extern HashTable* apc_flip_hash(HashTable *hash);
6499 +#define APC_NEGATIVE_MATCH 1
6500 +#define APC_POSITIVE_MATCH 2
6502 +#define apc_time() \
6503 + (APCG(use_request_time) ? (time_t) sapi_get_request_time(TSRMLS_C) : time(0));
6505 +#if defined(__GNUC__)
6506 +# define APC_UNUSED __attribute__((unused))
6507 +# define APC_USED __attribute__((used))
6508 +# define APC_ALLOC __attribute__((malloc))
6509 +# define APC_HOTSPOT __attribute__((hot))
6511 +# define APC_UNUSED
6514 +# define APC_HOTSPOT
6520 + * Local variables:
6522 + * c-basic-offset: 4
6524 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6525 + * vim<600: expandtab sw=4 ts=4 sts=4
6527 diff -Naur a/ext/apc/apc_iterator.c b/ext/apc/apc_iterator.c
6528 --- a/ext/apc/apc_iterator.c 1970-01-01 01:00:00.000000000 +0100
6529 +++ b/ext/apc/apc_iterator.c 2012-07-20 00:10:35.000000000 +0200
6532 + +----------------------------------------------------------------------+
6534 + +----------------------------------------------------------------------+
6535 + | Copyright (c) 2006-2011 The PHP Group |
6536 + +----------------------------------------------------------------------+
6537 + | This source file is subject to version 3.01 of the PHP license, |
6538 + | that is bundled with this package in the file LICENSE, and is |
6539 + | available through the world-wide-web at the following url: |
6540 + | http://www.php.net/license/3_01.txt |
6541 + | If you did not receive a copy of the PHP license and are unable to |
6542 + | obtain it through the world-wide-web, please send a note to |
6543 + | license@php.net so we can mail you a copy immediately. |
6544 + +----------------------------------------------------------------------+
6545 + | Authors: Brian Shire <shire@php.net> |
6546 + +----------------------------------------------------------------------+
6550 +/* $Id: apc_iterator.c 324326 2012-03-18 13:19:50Z pajoye $ */
6552 +#include "php_apc.h"
6553 +#include "apc_iterator.h"
6554 +#include "apc_cache.h"
6555 +#include "apc_zend.h"
6557 +#include "ext/standard/md5.h"
6559 +#include "zend_interfaces.h"
6561 +zend_class_entry *apc_iterator_ce;
6562 +zend_object_handlers apc_iterator_object_handlers;
6565 +/* {{{ apc_iterator_item */
6566 +static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp TSRMLS_DC) {
6569 + slot_t *slot = *slot_pp;
6570 + apc_context_t ctxt = {0, };
6571 + apc_iterator_item_t *item = ecalloc(1, sizeof(apc_iterator_item_t));
6573 + if (slot->key.type == APC_CACHE_KEY_FILE) {
6574 + /* keys should be unique and with stat=1 we could have multiple files with the same name, so use '<device> <inode>' instead */
6576 + item->key_len = spprintf(&item->key, 0, "%I64d %I64d", slot->key.data.file.device, slot->key.data.file.inode);
6578 + item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode);
6580 + item->filename_key = estrdup(slot->value->data.file.filename);
6581 + } else if (slot->key.type == APC_CACHE_KEY_USER) {
6582 + item->key = estrndup((char*)slot->key.data.user.identifier, slot->key.data.user.identifier_len);
6583 + item->key_len = slot->key.data.user.identifier_len;
6584 + item->filename_key = item->key;
6585 + } else if (slot->key.type == APC_CACHE_KEY_FPFILE) {
6586 + item->key = estrndup((char*)slot->key.data.fpfile.fullpath, slot->key.data.fpfile.fullpath_len);
6587 + item->key_len = slot->key.data.fpfile.fullpath_len;
6588 + item->filename_key = item->key;
6590 + apc_error("Internal error, invalid entry type." TSRMLS_CC);
6593 + ALLOC_INIT_ZVAL(item->value);
6594 + array_init(item->value);
6596 + if (APC_ITER_TYPE & iterator->format) {
6597 + if(slot->value->type == APC_CACHE_ENTRY_FILE) {
6598 + add_assoc_string(item->value, "type", "file", 1);
6599 + } else if(slot->value->type == APC_CACHE_ENTRY_USER) {
6600 + add_assoc_string(item->value, "type", "user", 1);
6603 + if (APC_ITER_FILENAME & iterator->format) {
6604 + if(slot->value->type == APC_CACHE_ENTRY_FILE) {
6605 + if (slot->key.type == APC_CACHE_KEY_FILE) {
6606 + add_assoc_string(item->value, "filename", slot->value->data.file.filename, 1);
6607 + } else { /* APC_CACHE_FPFILE */
6608 + add_assoc_string(item->value, "filename", (char*)slot->key.data.fpfile.fullpath, 1);
6612 + if (APC_ITER_DEVICE & iterator->format) {
6613 + if(slot->key.type == APC_CACHE_KEY_FILE) {
6616 + sprintf(buf, "%I64d", slot->key.data.file.device);
6617 + add_assoc_string(item->value, "device", buf, 1);
6619 + add_assoc_long(item->value, "device", slot->key.data.file.device);
6623 + if (APC_ITER_INODE & iterator->format) {
6624 + if(slot->key.type == APC_CACHE_KEY_FILE) {
6627 + sprintf(buf, "%I64d", slot->key.data.file.device);
6628 + add_assoc_string(item->value, "device", buf, 1);
6630 + add_assoc_long(item->value, "inode", slot->key.data.file.inode);
6634 + if (APC_ITER_KEY & iterator->format) {
6635 + add_assoc_stringl(item->value, "key", item->key, (item->key_len - 1), 1);
6637 + if (APC_ITER_VALUE & iterator->format) {
6638 + if(slot->value->type == APC_CACHE_ENTRY_USER) {
6640 + ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC);
6641 + ctxt.copy = APC_COPY_OUT_USER;
6643 + MAKE_STD_ZVAL(zvalue);
6644 + apc_cache_fetch_zval(zvalue, slot->value->data.user.val, &ctxt TSRMLS_CC);
6645 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
6646 + add_assoc_zval(item->value, "value", zvalue);
6649 + if (APC_ITER_MD5 & iterator->format) {
6650 + if(slot->value->type == APC_CACHE_ENTRY_FILE) {
6651 + if(APCG(file_md5) && slot->key.md5) {
6652 + make_digest(md5str, slot->key.md5);
6653 + add_assoc_string(item->value, "md5", md5str, 1);
6657 + if (APC_ITER_NUM_HITS & iterator->format) {
6658 + add_assoc_long(item->value, "num_hits", slot->num_hits);
6660 + if (APC_ITER_MTIME & iterator->format) {
6661 + add_assoc_long(item->value, "mtime", slot->key.mtime);
6663 + if (APC_ITER_CTIME & iterator->format) {
6664 + add_assoc_long(item->value, "creation_time", slot->creation_time);
6666 + if (APC_ITER_DTIME & iterator->format) {
6667 + add_assoc_long(item->value, "deletion_time", slot->deletion_time);
6669 + if (APC_ITER_ATIME & iterator->format) {
6670 + add_assoc_long(item->value, "access_time", slot->access_time);
6672 + if (APC_ITER_REFCOUNT & iterator->format) {
6673 + add_assoc_long(item->value, "ref_count", slot->value->ref_count);
6675 + if (APC_ITER_MEM_SIZE & iterator->format) {
6676 + add_assoc_long(item->value, "mem_size", slot->value->mem_size);
6678 + if (APC_ITER_TTL & iterator->format) {
6679 + if(slot->value->type == APC_CACHE_ENTRY_USER) {
6680 + add_assoc_long(item->value, "ttl", slot->value->data.user.ttl);
6688 +/* {{{ apc_iterator_clone */
6689 +static zend_object_value apc_iterator_clone(zval *zobject TSRMLS_DC) {
6690 + zend_object_value value = {0};
6691 + apc_error("APCIterator object cannot be cloned." TSRMLS_CC);
6696 +/* {{{ apc_iterator_item_dtor */
6697 +static void apc_iterator_item_dtor(apc_iterator_item_t *item) {
6698 + if (item->filename_key && item->filename_key != item->key) {
6699 + efree(item->filename_key);
6704 + if (item->value) {
6705 + zval_ptr_dtor(&item->value);
6711 +/* {{{ apc_iterator_destroy */
6712 +static void apc_iterator_destroy(void *object, zend_object_handle handle TSRMLS_DC) {
6713 + apc_iterator_t *iterator = (apc_iterator_t*)object;
6715 + if (iterator->initialized == 0) {
6719 + while (apc_stack_size(iterator->stack) > 0) {
6720 + apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
6722 + if (iterator->regex) {
6723 + efree(iterator->regex);
6725 + if (iterator->search_hash) {
6726 + zend_hash_destroy(iterator->search_hash);
6727 + efree(iterator->search_hash);
6729 + iterator->initialized = 0;
6734 +/* {{{ acp_iterator_free */
6735 +static void apc_iterator_free(void *object TSRMLS_DC) {
6736 + zend_object_std_dtor(object TSRMLS_CC);
6741 +/* {{{ apc_iterator_create */
6742 +static zend_object_value apc_iterator_create(zend_class_entry *ce TSRMLS_DC) {
6743 + zend_object_value retval;
6744 + apc_iterator_t *iterator;
6746 + iterator = emalloc(sizeof(apc_iterator_t));
6747 + iterator->obj.ce = ce;
6748 + ALLOC_HASHTABLE(iterator->obj.properties);
6749 + zend_hash_init(iterator->obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
6750 +#ifdef ZEND_ENGINE_2_4
6751 + iterator->obj.properties_table = NULL;
6753 + iterator->obj.guards = NULL;
6754 + iterator->initialized = 0;
6755 + retval.handle = zend_objects_store_put(iterator, apc_iterator_destroy, apc_iterator_free, NULL TSRMLS_CC);
6756 + retval.handlers = &apc_iterator_object_handlers;
6762 +/* {{{ apc_iterator_search_match
6763 + * Verify if the key matches oru search parameters
6765 +static int apc_iterator_search_match(apc_iterator_t *iterator, slot_t **slot) {
6768 + char *fname_key = NULL;
6769 + int fname_key_len = 0;
6772 + if ((*slot)->key.type == APC_CACHE_KEY_FILE) {
6773 + key = (*slot)->value->data.file.filename;
6774 + key_len = strlen(key);
6775 + fname_key_len = spprintf(&fname_key, 0, "%ld %ld", (*slot)->key.data.file.device, (*slot)->key.data.file.inode);
6776 + } else if ((*slot)->key.type == APC_CACHE_KEY_USER) {
6777 + key = (char*)(*slot)->key.data.user.identifier;
6778 + key_len = (*slot)->key.data.user.identifier_len;
6779 + } else if ((*slot)->key.type == APC_CACHE_KEY_FPFILE) {
6780 + key = (char*)(*slot)->key.data.fpfile.fullpath;
6781 + key_len = (*slot)->key.data.fpfile.fullpath_len;
6786 +#ifdef ITERATOR_PCRE
6787 + if (iterator->regex) {
6788 + rval = (pcre_exec(iterator->re, NULL, key, strlen(key), 0, 0, NULL, 0) >= 0);
6792 + if (iterator->search_hash) {
6793 + rval = zend_hash_exists(iterator->search_hash, key, key_len);
6794 + if (!rval && fname_key) {
6795 + rval = zend_hash_exists(iterator->search_hash, fname_key, fname_key_len+1);
6803 +/* {{{ apc_iterator_check_expiry */
6804 +static int apc_iterator_check_expiry(apc_cache_t* cache, slot_t **slot, time_t t)
6806 + if((*slot)->value->type == APC_CACHE_ENTRY_USER) {
6807 + if((*slot)->value->data.user.ttl) {
6808 + if((time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
6811 + } else if(cache->ttl) {
6812 + if((*slot)->creation_time + cache->ttl < t) {
6816 + } else if((*slot)->access_time < (t - cache->ttl)) {
6824 +/* {{{ apc_iterator_fetch_active */
6825 +static int apc_iterator_fetch_active(apc_iterator_t *iterator TSRMLS_DC) {
6828 + apc_iterator_item_t *item;
6833 + while (apc_stack_size(iterator->stack) > 0) {
6834 + apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
6837 + CACHE_LOCK(iterator->cache);
6838 + while(count <= iterator->chunk_size && iterator->slot_idx < iterator->cache->num_slots) {
6839 + slot = &iterator->cache->slots[iterator->slot_idx];
6841 + if (apc_iterator_check_expiry(iterator->cache, slot, t)) {
6842 + if (apc_iterator_search_match(iterator, slot)) {
6844 + item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
6846 + apc_stack_push(iterator->stack, item TSRMLS_CC);
6850 + slot = &(*slot)->next;
6852 + iterator->slot_idx++;
6854 + CACHE_UNLOCK(iterator->cache);
6855 + iterator->stack_idx = 0;
6860 +/* {{{ apc_iterator_fetch_deleted */
6861 +static int apc_iterator_fetch_deleted(apc_iterator_t *iterator TSRMLS_DC) {
6864 + apc_iterator_item_t *item;
6866 + CACHE_LOCK(iterator->cache);
6867 + slot = &iterator->cache->header->deleted_list;
6868 + while ((*slot) && count <= iterator->slot_idx) {
6870 + slot = &(*slot)->next;
6873 + while ((*slot) && count < iterator->chunk_size) {
6874 + if (apc_iterator_search_match(iterator, slot)) {
6876 + item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
6878 + apc_stack_push(iterator->stack, item TSRMLS_CC);
6881 + slot = &(*slot)->next;
6883 + CACHE_UNLOCK(iterator->cache);
6884 + iterator->slot_idx += count;
6885 + iterator->stack_idx = 0;
6890 +/* {{{ apc_iterator_totals */
6891 +static void apc_iterator_totals(apc_iterator_t *iterator TSRMLS_DC) {
6895 + CACHE_LOCK(iterator->cache);
6896 + for (i=0; i < iterator->cache->num_slots; i++) {
6897 + slot = &iterator->cache->slots[i];
6899 + if (apc_iterator_search_match(iterator, slot)) {
6900 + iterator->size += (*slot)->value->mem_size;
6901 + iterator->hits += (*slot)->num_hits;
6902 + iterator->count++;
6904 + slot = &(*slot)->next;
6907 + CACHE_UNLOCK(iterator->cache);
6908 + iterator->totals_flag = 1;
6912 +/* {{{ proto object APCIterator::__costruct(string cache [, mixed search [, long format [, long chunk_size [, long list ]]]]) */
6913 +PHP_METHOD(apc_iterator, __construct) {
6914 + zval *object = getThis();
6915 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
6917 + int cachetype_len;
6918 + long format = APC_ITER_ALL;
6919 + long chunk_size=0;
6920 + zval *search = NULL;
6921 + long list = APC_LIST_ACTIVE;
6923 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zlll", &cachetype, &cachetype_len, &search, &format, &chunk_size, &list) == FAILURE) {
6927 + if (!APCG(enabled)) {
6928 + apc_error("APC must be enabled to use APCIterator." TSRMLS_CC);
6931 + if (chunk_size < 0) {
6932 + apc_error("APCIterator chunk size must be 0 or greater." TSRMLS_CC);
6936 + if (format > APC_ITER_ALL) {
6937 + apc_error("APCIterator format is invalid." TSRMLS_CC);
6941 + if (list == APC_LIST_ACTIVE) {
6942 + iterator->fetch = apc_iterator_fetch_active;
6943 + } else if (list == APC_LIST_DELETED) {
6944 + iterator->fetch = apc_iterator_fetch_deleted;
6946 + apc_warning("APCIterator invalid list type." TSRMLS_CC);
6950 + if(!strcasecmp(cachetype,"user")) {
6951 + iterator->cache = apc_user_cache;
6953 + iterator->cache = apc_cache;
6956 + iterator->slot_idx = 0;
6957 + iterator->stack_idx = 0;
6958 + iterator->key_idx = 0;
6959 + iterator->chunk_size = chunk_size == 0 ? APC_DEFAULT_CHUNK_SIZE : chunk_size;
6960 + iterator->stack = apc_stack_create(chunk_size TSRMLS_CC);
6961 + iterator->format = format;
6962 + iterator->totals_flag = 0;
6963 + iterator->count = 0;
6964 + iterator->size = 0;
6965 + iterator->hits = 0;
6966 + iterator->regex = NULL;
6967 + iterator->regex_len = 0;
6968 + iterator->search_hash = NULL;
6969 + if (search && Z_TYPE_P(search) == IS_STRING && Z_STRLEN_P(search)) {
6970 +#ifdef ITERATOR_PCRE
6971 + iterator->regex = estrndup(Z_STRVAL_P(search), Z_STRLEN_P(search));
6972 + iterator->regex_len = Z_STRLEN_P(search);
6973 + iterator->re = pcre_get_compiled_regex(Z_STRVAL_P(search), NULL, NULL TSRMLS_CC);
6975 + if(!iterator->re) {
6976 + apc_error("Could not compile regular expression: %s" TSRMLS_CC, Z_STRVAL_P(search));
6979 + apc_error("Regular expressions support is not enabled, please enable PCRE for APCIterator regex support" TSRMLS_CC);
6981 + } else if (search && Z_TYPE_P(search) == IS_ARRAY) {
6982 + Z_ADDREF_P(search);
6983 + iterator->search_hash = apc_flip_hash(Z_ARRVAL_P(search));
6985 + iterator->initialized = 1;
6989 +/* {{{ proto APCIterator::rewind() */
6990 +PHP_METHOD(apc_iterator, rewind) {
6991 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
6993 + if (zend_parse_parameters_none() == FAILURE) {
6997 + if (iterator->initialized == 0) {
7001 + iterator->slot_idx = 0;
7002 + iterator->stack_idx = 0;
7003 + iterator->key_idx = 0;
7004 + iterator->fetch(iterator TSRMLS_CC);
7008 +/* {{{ proto boolean APCIterator::valid() */
7009 +PHP_METHOD(apc_iterator, valid) {
7010 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7012 + if (zend_parse_parameters_none() == FAILURE) {
7016 + if (iterator->initialized == 0) {
7020 + if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7021 + iterator->fetch(iterator TSRMLS_CC);
7024 + RETURN_BOOL(apc_stack_size(iterator->stack) == 0 ? 0 : 1);
7028 +/* {{{ proto mixed APCIterator::current() */
7029 +PHP_METHOD(apc_iterator, current) {
7030 + apc_iterator_item_t *item;
7031 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7033 + if (zend_parse_parameters_none() == FAILURE) {
7037 + if (iterator->initialized == 0) {
7041 + if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7042 + if (iterator->fetch(iterator TSRMLS_CC) == 0) {
7047 + item = apc_stack_get(iterator->stack, iterator->stack_idx);
7048 + RETURN_ZVAL(item->value, 1, 0);
7052 +/* {{{ proto string APCIterator::key() */
7053 +PHP_METHOD(apc_iterator, key) {
7054 + apc_iterator_item_t *item;
7055 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7057 + if (zend_parse_parameters_none() == FAILURE) {
7061 + if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
7065 + if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7066 + if (iterator->fetch(iterator TSRMLS_CC) == 0) {
7071 + item = apc_stack_get(iterator->stack, iterator->stack_idx);
7074 + RETURN_STRINGL(item->key, (item->key_len-1), 1);
7076 + RETURN_LONG(iterator->key_idx);
7081 +/* {{{ proto APCIterator::next() */
7082 +PHP_METHOD(apc_iterator, next) {
7083 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7085 + if (zend_parse_parameters_none() == FAILURE) {
7089 + if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
7093 + iterator->stack_idx++;
7094 + iterator->key_idx++;
7100 +/* {{{ proto long APCIterator::getTotalHits() */
7101 +PHP_METHOD(apc_iterator, getTotalHits) {
7102 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7104 + if (zend_parse_parameters_none() == FAILURE) {
7108 + if (iterator->initialized == 0) {
7112 + if (iterator->totals_flag == 0) {
7113 + apc_iterator_totals(iterator TSRMLS_CC);
7116 + RETURN_LONG(iterator->hits);
7120 +/* {{{ proto long APCIterator::getTotalSize() */
7121 +PHP_METHOD(apc_iterator, getTotalSize) {
7122 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7124 + if (zend_parse_parameters_none() == FAILURE) {
7128 + if (iterator->initialized == 0) {
7132 + if (iterator->totals_flag == 0) {
7133 + apc_iterator_totals(iterator TSRMLS_CC);
7136 + RETURN_LONG(iterator->size);
7140 +/* {{{ proto long APCIterator::getTotalCount() */
7141 +PHP_METHOD(apc_iterator, getTotalCount) {
7142 + apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
7144 + if (zend_parse_parameters_none() == FAILURE) {
7148 + if (iterator->initialized == 0) {
7152 + if (iterator->totals_flag == 0) {
7153 + apc_iterator_totals(iterator TSRMLS_CC);
7156 + RETURN_LONG(iterator->count);
7161 +#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
7162 +# define PHP_APC_ARGINFO
7164 +# define PHP_APC_ARGINFO static
7168 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator___construct, 0, 0, 1)
7169 + ZEND_ARG_INFO(0, cache)
7170 + ZEND_ARG_INFO(0, search)
7171 + ZEND_ARG_INFO(0, format)
7172 + ZEND_ARG_INFO(0, chunk_size)
7173 + ZEND_ARG_INFO(0, list)
7174 +ZEND_END_ARG_INFO()
7177 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator_void, 0, 0, 0)
7178 +ZEND_END_ARG_INFO()
7181 +/* {{{ apc_iterator_functions */
7182 +static zend_function_entry apc_iterator_functions[] = {
7183 + PHP_ME(apc_iterator, __construct, arginfo_apc_iterator___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
7184 + PHP_ME(apc_iterator, rewind, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7185 + PHP_ME(apc_iterator, current, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7186 + PHP_ME(apc_iterator, key, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7187 + PHP_ME(apc_iterator, next, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7188 + PHP_ME(apc_iterator, valid, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7189 + PHP_ME(apc_iterator, getTotalHits, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7190 + PHP_ME(apc_iterator, getTotalSize, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7191 + PHP_ME(apc_iterator, getTotalCount, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC)
7192 + {NULL, NULL, NULL}
7196 +/* {{{ apc_iterator_init */
7197 +int apc_iterator_init(int module_number TSRMLS_DC) {
7198 + zend_class_entry ce;
7200 + INIT_CLASS_ENTRY(ce, APC_ITERATOR_NAME, apc_iterator_functions);
7201 + apc_iterator_ce = zend_register_internal_class(&ce TSRMLS_CC);
7202 + apc_iterator_ce->create_object = apc_iterator_create;
7203 + zend_class_implements(apc_iterator_ce TSRMLS_CC, 1, zend_ce_iterator);
7205 + zend_register_long_constant("APC_LIST_ACTIVE", sizeof("APC_LIST_ACTIVE"), APC_LIST_ACTIVE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7206 + zend_register_long_constant("APC_LIST_DELETED", sizeof("APC_LIST_DELETED"), APC_LIST_DELETED, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7208 + zend_register_long_constant("APC_ITER_TYPE", sizeof("APC_ITER_TYPE"), APC_ITER_TYPE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7209 + zend_register_long_constant("APC_ITER_KEY", sizeof("APC_ITER_KEY"), APC_ITER_KEY, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7210 + zend_register_long_constant("APC_ITER_FILENAME", sizeof("APC_ITER_FILENAME"), APC_ITER_FILENAME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7211 + zend_register_long_constant("APC_ITER_DEVICE", sizeof("APC_ITER_DEVICE"), APC_ITER_DEVICE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7212 + zend_register_long_constant("APC_ITER_INODE", sizeof("APC_ITER_INODE"), APC_ITER_INODE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7213 + zend_register_long_constant("APC_ITER_VALUE", sizeof("APC_ITER_VALUE"), APC_ITER_VALUE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7214 + zend_register_long_constant("APC_ITER_MD5", sizeof("APC_ITER_MD5"), APC_ITER_MD5, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7215 + 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);
7216 + zend_register_long_constant("APC_ITER_MTIME", sizeof("APC_ITER_MTIME"), APC_ITER_MTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7217 + zend_register_long_constant("APC_ITER_CTIME", sizeof("APC_ITER_CTIME"), APC_ITER_CTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7218 + zend_register_long_constant("APC_ITER_DTIME", sizeof("APC_ITER_DTIME"), APC_ITER_DTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7219 + zend_register_long_constant("APC_ITER_ATIME", sizeof("APC_ITER_ATIME"), APC_ITER_ATIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7220 + zend_register_long_constant("APC_ITER_REFCOUNT", sizeof("APC_ITER_REFCOUNT"), APC_ITER_REFCOUNT, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7221 + 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);
7222 + zend_register_long_constant("APC_ITER_TTL", sizeof("APC_ITER_TTL"), APC_ITER_TTL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7223 + zend_register_long_constant("APC_ITER_NONE", sizeof("APC_ITER_NONE"), APC_ITER_NONE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7224 + zend_register_long_constant("APC_ITER_ALL", sizeof("APC_ITER_ALL"), APC_ITER_ALL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
7226 + memcpy(&apc_iterator_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
7227 + apc_iterator_object_handlers.clone_obj = apc_iterator_clone;
7234 +int apc_iterator_delete(zval *zobj TSRMLS_DC) {
7235 + apc_iterator_t *iterator;
7236 + zend_class_entry *ce = Z_OBJCE_P(zobj);
7237 + apc_iterator_item_t *item;
7239 + if (!ce || !instanceof_function(ce, apc_iterator_ce TSRMLS_CC)) {
7240 + apc_error("apc_delete object argument must be instance of APCIterator" TSRMLS_CC);
7243 + iterator = (apc_iterator_t*)zend_object_store_get_object(zobj TSRMLS_CC);
7245 + if (iterator->initialized == 0) {
7249 + while (iterator->fetch(iterator TSRMLS_CC)) {
7250 + while (iterator->stack_idx < apc_stack_size(iterator->stack)) {
7251 + item = apc_stack_get(iterator->stack, iterator->stack_idx++);
7252 + if (iterator->cache == apc_cache) {
7253 + apc_cache_delete(apc_cache, item->filename_key, strlen(item->filename_key) + 1 TSRMLS_CC);
7255 + apc_cache_user_delete(apc_user_cache, item->key, item->key_len TSRMLS_CC);
7265 + * Local variables:
7267 + * c-basic-offset: 4
7269 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
7270 + * vim<600: expandtab sw=4 ts=4 sts=4
7272 diff -Naur a/ext/apc/apc_iterator.h b/ext/apc/apc_iterator.h
7273 --- a/ext/apc/apc_iterator.h 1970-01-01 01:00:00.000000000 +0100
7274 +++ b/ext/apc/apc_iterator.h 2012-07-20 00:10:35.000000000 +0200
7277 + +----------------------------------------------------------------------+
7279 + +----------------------------------------------------------------------+
7280 + | Copyright (c) 2006-2011 The PHP Group |
7281 + +----------------------------------------------------------------------+
7282 + | This source file is subject to version 3.01 of the PHP license, |
7283 + | that is bundled with this package in the file LICENSE, and is |
7284 + | available through the world-wide-web at the following url: |
7285 + | http://www.php.net/license/3_01.txt |
7286 + | If you did not receive a copy of the PHP license and are unable to |
7287 + | obtain it through the world-wide-web, please send a note to |
7288 + | license@php.net so we can mail you a copy immediately. |
7289 + +----------------------------------------------------------------------+
7290 + | Authors: Brian Shire <shire@.php.net> |
7291 + +----------------------------------------------------------------------+
7295 +/* $Id: apc_iterator.h 307048 2011-01-03 23:53:17Z kalle $ */
7297 +#ifndef APC_ITERATOR_H
7298 +#define APC_ITERATOR_H
7301 +#include "apc_stack.h"
7303 +#if HAVE_PCRE || HAVE_BUNDLED_PCRE
7304 +/* Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
7305 +# if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
7306 +# include "apc_php_pcre.h"
7308 +# include "ext/pcre/php_pcre.h"
7310 +# include "ext/standard/php_smart_str.h"
7311 +# define ITERATOR_PCRE 1
7315 +#define APC_ITERATOR_NAME "APCIterator"
7317 +#define APC_DEFAULT_CHUNK_SIZE 100
7319 +#define APC_LIST_ACTIVE 0x1
7320 +#define APC_LIST_DELETED 0x2
7322 +#define APC_ITER_TYPE (1L << 0)
7323 +#define APC_ITER_KEY (1L << 1)
7324 +#define APC_ITER_FILENAME (1L << 2)
7325 +#define APC_ITER_DEVICE (1L << 3)
7326 +#define APC_ITER_INODE (1L << 4)
7327 +#define APC_ITER_VALUE (1L << 5)
7328 +#define APC_ITER_MD5 (1L << 6)
7329 +#define APC_ITER_NUM_HITS (1L << 7)
7330 +#define APC_ITER_MTIME (1L << 8)
7331 +#define APC_ITER_CTIME (1L << 9)
7332 +#define APC_ITER_DTIME (1L << 10)
7333 +#define APC_ITER_ATIME (1L << 11)
7334 +#define APC_ITER_REFCOUNT (1L << 12)
7335 +#define APC_ITER_MEM_SIZE (1L << 13)
7336 +#define APC_ITER_TTL (1L << 14)
7338 +#define APC_ITER_NONE (0x00000000L)
7339 +#define APC_ITER_ALL (0xffffffffL)
7341 +typedef void* (*apc_iterator_item_cb_t)(slot_t **slot);
7344 +/* {{{ apc_iterator_t */
7345 +typedef struct _apc_iterator_t {
7346 + zend_object obj; /* must always be first */
7347 + short int initialized; /* sanity check in case __construct failed */
7348 + long format; /* format bitmask of the return values ie: key, value, info */
7349 + int (*fetch)(struct _apc_iterator_t *iterator TSRMLS_DC);
7350 + /* fetch callback to fetch items from cache slots or lists */
7351 + apc_cache_t *cache; /* cache which we are iterating on */
7352 + long slot_idx; /* index to the slot array or linked list */
7353 + long chunk_size; /* number of entries to pull down per fetch */
7354 + apc_stack_t *stack; /* stack of entries pulled from cache */
7355 + int stack_idx; /* index into the current stack */
7356 +#ifdef ITERATOR_PCRE
7357 + pcre *re; /* regex filter on entry identifiers */
7359 + char *regex; /* original regex expression or NULL */
7360 + int regex_len; /* regex length */
7361 + HashTable *search_hash; /* hash of keys to iterate over */
7362 + long key_idx; /* incrementing index for numerical keys */
7363 + short int totals_flag; /* flag if totals have been calculated */
7364 + long hits; /* hit total */
7365 + size_t size; /* size total */
7366 + long count; /* count total */
7370 +/* {{{ apc_iterator_item */
7371 +typedef struct _apc_iterator_item_t {
7372 + char *key; /* string key */
7373 + long key_len; /* strlen of key */
7374 + char *filename_key; /* filename key used for deletion */
7376 +} apc_iterator_item_t;
7380 +extern int apc_iterator_init(int module_number TSRMLS_DC);
7381 +extern int apc_iterator_delete(zval *zobj TSRMLS_DC);
7386 + * Local variables:
7388 + * c-basic-offset: 4
7390 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
7391 + * vim<600: expandtab sw=4 ts=4 sts=4
7393 diff -Naur a/ext/apc/apc_lock.h b/ext/apc/apc_lock.h
7394 --- a/ext/apc/apc_lock.h 1970-01-01 01:00:00.000000000 +0100
7395 +++ b/ext/apc/apc_lock.h 2012-07-20 00:10:35.000000000 +0200
7398 + +----------------------------------------------------------------------+
7400 + +----------------------------------------------------------------------+
7401 + | Copyright (c) 2006-2011 The PHP Group |
7402 + +----------------------------------------------------------------------+
7403 + | This source file is subject to version 3.01 of the PHP license, |
7404 + | that is bundled with this package in the file LICENSE, and is |
7405 + | available through the world-wide-web at the following url: |
7406 + | http://www.php.net/license/3_01.txt |
7407 + | If you did not receive a copy of the PHP license and are unable to |
7408 + | obtain it through the world-wide-web, please send a note to |
7409 + | license@php.net so we can mail you a copy immediately. |
7410 + +----------------------------------------------------------------------+
7411 + | Authors: George Schlossnagle <george@omniti.com> |
7412 + | Rasmus Lerdorf <rasmus@php.net> |
7413 + | Pierre Joye <pierre@php.net> |
7414 + +----------------------------------------------------------------------+
7416 + This software was contributed to PHP by Community Connect Inc. in 2002
7417 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
7418 + Future revisions and derivatives of this source code must acknowledge
7419 + Community Connect Inc. as the original contributor of this module by
7420 + leaving this note intact in the source code.
7422 + All other licensing and usage conditions are those of the PHP Group.
7426 +/* $Id: apc_lock.h 311339 2011-05-22 17:18:49Z gopalv $ */
7431 +#ifdef HAVE_CONFIG_H
7432 +# include <config.h>
7436 +#include "apc_sem.h"
7437 +#include "apc_fcntl.h"
7438 +#include "apc_pthreadmutex.h"
7439 +#include "apc_pthreadrwlock.h"
7440 +#include "apc_spin.h"
7441 +#include "apc_windows_srwlock_kernel.h"
7443 +/* {{{ generic locking macros */
7444 +#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock)
7445 +#define DESTROY_LOCK(lock) apc_lck_destroy(lock)
7446 +#define LOCK(lock) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(lock); }
7447 +#define RDLOCK(lock) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(lock); }
7448 +#define UNLOCK(lock) { apc_lck_unlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
7449 +#define RDUNLOCK(lock) { apc_lck_rdunlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
7452 +/* atomic operations : rdlocks are impossible without these */
7453 +#if HAVE_ATOMIC_OPERATIONS
7455 +# define ATOMIC_INC(a) InterlockedIncrement(&a)
7456 +# define ATOMIC_DEC(a) InterlockedDecrement(&a)
7458 +# define ATOMIC_INC(a) __sync_add_and_fetch(&a, 1)
7459 +# define ATOMIC_DEC(a) __sync_sub_and_fetch(&a, 1)
7463 +#if defined(APC_SEM_LOCKS)
7464 +# define APC_LOCK_TYPE "IPC Semaphore"
7465 +# define RDLOCK_AVAILABLE 0
7466 +# define NONBLOCKING_LOCK_AVAILABLE 1
7467 +# define apc_lck_t int
7468 +# define apc_lck_create(a,b,c,d) d=apc_sem_create((b),(c) TSRMLS_CC)
7469 +# define apc_lck_destroy(a) apc_sem_destroy(a)
7470 +# define apc_lck_lock(a) apc_sem_lock(a TSRMLS_CC)
7471 +# define apc_lck_nb_lock(a) apc_sem_nonblocking_lock(a TSRMLS_CC)
7472 +# define apc_lck_rdlock(a) apc_sem_lock(a TSRMLS_CC)
7473 +# define apc_lck_unlock(a) apc_sem_unlock(a TSRMLS_CC)
7474 +# define apc_lck_rdunlock(a) apc_sem_unlock(a TSRMLS_CC)
7475 +#elif defined(APC_PTHREADMUTEX_LOCKS)
7476 +# define APC_LOCK_TYPE "pthread mutex Locks"
7477 +# define RDLOCK_AVAILABLE 0
7478 +# define NONBLOCKING_LOCK_AVAILABLE 1
7479 +# define apc_lck_t pthread_mutex_t
7480 +# define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d TSRMLS_CC)
7481 +# define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a)
7482 +# define apc_lck_lock(a) apc_pthreadmutex_lock(&a TSRMLS_CC)
7483 +# define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a TSRMLS_CC)
7484 +# define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a TSRMLS_CC)
7485 +# define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a TSRMLS_CC)
7486 +# define apc_lck_rdunlock(a) apc_pthreadmutex_unlock(&a TSRMLS_CC)
7487 +#elif defined(APC_PTHREADRW_LOCKS)
7488 +# define APC_LOCK_TYPE "pthread read/write Locks"
7489 +# define RDLOCK_AVAILABLE 1
7490 +# define NONBLOCKING_LOCK_AVAILABLE 1
7491 +# define apc_lck_t pthread_rwlock_t
7492 +# define apc_lck_create(a,b,c,d) apc_pthreadrwlock_create((pthread_rwlock_t*)&d TSRMLS_CC)
7493 +# define apc_lck_destroy(a) apc_pthreadrwlock_destroy(&a)
7494 +# define apc_lck_lock(a) apc_pthreadrwlock_lock(&a TSRMLS_CC)
7495 +# define apc_lck_nb_lock(a) apc_pthreadrwlock_nonblocking_lock(&a TSRMLS_CC)
7496 +# define apc_lck_rdlock(a) apc_pthreadrwlock_rdlock(&a TSRMLS_CC)
7497 +# define apc_lck_unlock(a) apc_pthreadrwlock_unlock(&a TSRMLS_CC)
7498 +# define apc_lck_rdunlock(a) apc_pthreadrwlock_unlock(&a TSRMLS_CC)
7499 +#elif defined(APC_SPIN_LOCKS)
7500 +# define APC_LOCK_TYPE "spin Locks"
7501 +# define RDLOCK_AVAILABLE 0
7502 +# define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
7503 +# define apc_lck_t slock_t
7504 +# define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
7505 +# define apc_lck_destroy(a) apc_slock_destroy(&a)
7506 +# define apc_lck_lock(a) apc_slock_lock(&a TSRMLS_CC)
7507 +# define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a)
7508 +# define apc_lck_rdlock(a) apc_slock_lock(&a TSRMLS_CC)
7509 +# define apc_lck_unlock(a) apc_slock_unlock(&a)
7510 +# define apc_lck_rdunlock(a) apc_slock_unlock(&a)
7511 +#elif defined(APC_SRWLOCK_NATIVE) && defined(PHP_WIN32)
7512 +# define APC_LOCK_TYPE "Windows Slim RWLOCK (native)"
7513 +# define RDLOCK_AVAILABLE 1
7514 +# define NONBLOCKING_LOCK_AVAILABLE 0
7515 +# define apc_lck_t SRWLOCK
7516 +# define apc_lck_create(a,b,c,d) InitializeSRWLock((SRWLOCK*)&(d))
7517 +# define apc_lck_destroy(a)
7518 +# define apc_lck_lock(a) AcquireSRWLockExclusive(&a)
7519 +# define apc_lck_rdlock(a) AcquireSRWLockShared(&a)
7520 +# define apc_lck_unlock(a) ReleaseSRWLockExclusive(&a)
7521 +# define apc_lck_rdunlock(a) ReleaseSRWLockShared(&a)
7522 +# if NONBLOCKING_LOCK_AVAILABLE==1 /* Only in win7/2008 */
7523 +# define apc_lck_nb_lock(a) (TryAcquireSRWLockExclusive(&a TSRMLS_CC) == 0 ? 1 : 0);
7525 +#elif defined(APC_SRWLOCK_KERNEL) && defined(PHP_WIN32)
7526 +# define APC_LOCK_TYPE "Windows Slim RWLOCK (kernel)"
7527 +# define RDLOCK_AVAILABLE 1
7528 +# define NONBLOCKING_LOCK_AVAILABLE 0
7529 +# define apc_lck_t apc_windows_cs_rwlock_t
7530 +# define apc_lck_create(a,b,c,d) apc_windows_cs_create((apc_windows_cs_rwlock_t*)&(d) TSRMLS_CC)
7531 +# define apc_lck_destroy(a) apc_windows_cs_destroy(&a);
7532 +# define apc_lck_lock(a) apc_windows_cs_lock(&a TSRMLS_CC)
7533 +# define apc_lck_rdlock(a) apc_windows_cs_rdlock(&a TSRMLS_CC)
7534 +# define apc_lck_unlock(a) apc_windows_cs_unlock_wr(&a TSRMLS_CC)
7535 +# define apc_lck_rdunlock(a) apc_windows_cs_unlock_rd(&a TSRMLS_CC)
7537 +# define APC_LOCK_TYPE "File Locks"
7538 +# ifdef HAVE_ATOMIC_OPERATIONS
7539 +# define RDLOCK_AVAILABLE 1
7542 +# define NONBLOCKING_LOCK_AVAILABLE 0
7544 +# define NONBLOCKING_LOCK_AVAILABLE 1
7546 +# define apc_lck_t int
7547 +# define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a) TSRMLS_CC)
7548 +# define apc_lck_destroy(a) apc_fcntl_destroy(a)
7549 +# define apc_lck_lock(a) apc_fcntl_lock(a TSRMLS_CC)
7550 +# define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a TSRMLS_CC)
7551 +# define apc_lck_rdlock(a) apc_fcntl_rdlock(a TSRMLS_CC)
7552 +# define apc_lck_unlock(a) apc_fcntl_unlock(a TSRMLS_CC)
7553 +# define apc_lck_rdunlock(a) apc_fcntl_unlock(a TSRMLS_CC)
7557 diff -Naur a/ext/apc/apc_main.c b/ext/apc/apc_main.c
7558 --- a/ext/apc/apc_main.c 1970-01-01 01:00:00.000000000 +0100
7559 +++ b/ext/apc/apc_main.c 2012-07-20 00:10:35.000000000 +0200
7562 + +----------------------------------------------------------------------+
7564 + +----------------------------------------------------------------------+
7565 + | Copyright (c) 2006-2011 The PHP Group |
7566 + +----------------------------------------------------------------------+
7567 + | This source file is subject to version 3.01 of the PHP license, |
7568 + | that is bundled with this package in the file LICENSE, and is |
7569 + | available through the world-wide-web at the following url: |
7570 + | http://www.php.net/license/3_01.txt |
7571 + | If you did not receive a copy of the PHP license and are unable to |
7572 + | obtain it through the world-wide-web, please send a note to |
7573 + | license@php.net so we can mail you a copy immediately. |
7574 + +----------------------------------------------------------------------+
7575 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
7576 + | Rasmus Lerdorf <rasmus@php.net> |
7577 + | Arun C. Murthy <arunc@yahoo-inc.com> |
7578 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
7579 + +----------------------------------------------------------------------+
7581 + This software was contributed to PHP by Community Connect Inc. in 2002
7582 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
7583 + Future revisions and derivatives of this source code must acknowledge
7584 + Community Connect Inc. as the original contributor of this module by
7585 + leaving this note intact in the source code.
7587 + All other licensing and usage conditions are those of the PHP Group.
7591 +/* $Id: apc_main.c 324326 2012-03-18 13:19:50Z pajoye $ */
7593 +#include "apc_php.h"
7594 +#include "apc_main.h"
7596 +#include "apc_lock.h"
7597 +#include "apc_cache.h"
7598 +#include "apc_compile.h"
7599 +#include "apc_globals.h"
7600 +#include "apc_sma.h"
7601 +#include "apc_stack.h"
7602 +#include "apc_zend.h"
7603 +#include "apc_pool.h"
7604 +#include "apc_string.h"
7606 +#include "php_scandir.h"
7607 +#include "ext/standard/php_var.h"
7608 +#include "ext/standard/md5.h"
7610 +#define APC_MAX_SERIALIZERS 16
7612 +/* {{{ module variables */
7614 +/* pointer to the original Zend engine compile_file function */
7615 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
7616 +static zend_compile_t *old_compile_file;
7617 +static apc_serializer_t apc_serializers[APC_MAX_SERIALIZERS] = {{0,}};
7621 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
7622 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
7624 + zend_compile_t *retval = old_compile_file;
7626 + if (ptr != NULL) old_compile_file = ptr;
7631 +/* {{{ install_function */
7632 +static int install_function(apc_function_t fn, apc_context_t* ctxt, int lazy TSRMLS_DC)
7636 +#if APC_HAVE_LOOKUP_HOOKS
7637 + if(lazy && fn.name[0] != '\0' && strncmp(fn.name, "__autoload", fn.name_len) != 0) {
7638 + status = zend_hash_add(APCG(lazy_function_table),
7642 + sizeof(apc_function_t),
7648 + zend_function *func = apc_copy_function_for_execution(fn.function, ctxt TSRMLS_CC);
7649 + status = zend_hash_add(EG(function_table),
7653 + sizeof(fn.function[0]),
7658 + if (status == FAILURE) {
7659 + /* apc_error("Cannot redeclare %s()" TSRMLS_CC, fn.name); */
7666 +/* {{{ apc_lookup_function_hook */
7667 +int apc_lookup_function_hook(char *name, int len, ulong hash, zend_function **fe) {
7668 + apc_function_t *fn;
7669 + int status = FAILURE;
7670 + apc_context_t ctxt = {0,};
7673 + ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
7674 + ctxt.copy = APC_COPY_OUT_OPCODE;
7676 + if(zend_hash_quick_find(APCG(lazy_function_table), name, len, hash, (void**)&fn) == SUCCESS) {
7677 + *fe = apc_copy_function_for_execution(fn->function, &ctxt TSRMLS_CC);
7678 + status = zend_hash_add(EG(function_table),
7682 + sizeof(zend_function),
7690 +/* {{{ install_class */
7691 +static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC)
7693 + zend_class_entry* class_entry = cl.class_entry;
7694 + zend_class_entry* parent = NULL;
7696 + zend_class_entry** allocated_ce = NULL;
7698 + /* Special case for mangled names. Mangled names are unique to a file.
7699 + * There is no way two classes with the same mangled name will occur,
7700 + * unless a file is included twice. And if in case, a file is included
7701 + * twice, all mangled name conflicts can be ignored and the class redeclaration
7702 + * error may be deferred till runtime of the corresponding DECLARE_CLASS
7706 + if(cl.name_len != 0 && cl.name[0] == '\0') {
7707 + if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
7712 + if(lazy && cl.name_len != 0 && cl.name[0] != '\0') {
7713 + status = zend_hash_add(APCG(lazy_class_table),
7717 + sizeof(apc_class_t),
7719 + if(status == FAILURE) {
7720 + zend_error(E_ERROR, "Cannot redeclare class %s", cl.name);
7726 + * XXX: We need to free this somewhere...
7728 + allocated_ce = apc_php_malloc(sizeof(zend_class_entry*) TSRMLS_CC);
7730 + if(!allocated_ce) {
7736 + apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC);
7739 + /* restore parent class pointer for compile-time inheritance */
7740 + if (cl.parent_name != NULL) {
7741 + zend_class_entry** parent_ptr = NULL;
7743 + * __autoload brings in the old issues with mixed inheritance.
7744 + * When a statically inherited class triggers autoload, it runs
7745 + * afoul of a potential require_once "parent.php" in the previous
7746 + * line, which when executed provides the parent class, but right
7747 + * now goes and hits __autoload which could fail.
7749 + * missing parent == re-compile.
7751 + * whether __autoload is enabled or not, because __autoload errors
7752 + * cause php to die.
7754 + * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
7755 + * zend_lookup_class_ex does it internally anyway!
7757 + status = zend_lookup_class_ex(cl.parent_name,
7758 + strlen(cl.parent_name),
7759 +#ifdef ZEND_ENGINE_2_4
7763 + &parent_ptr TSRMLS_CC);
7764 + if (status == FAILURE) {
7765 + if(APCG(report_autofilter)) {
7766 + apc_warning("Dynamic inheritance detected for class %s" TSRMLS_CC, cl.name);
7768 + class_entry->parent = NULL;
7772 + parent = *parent_ptr;
7773 + class_entry->parent = parent;
7774 + zend_do_inheritance(class_entry, parent TSRMLS_CC);
7780 + status = zend_hash_add(EG(class_table),
7784 + sizeof(zend_class_entry*),
7787 + if (status == FAILURE) {
7788 + apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name);
7794 +/* {{{ apc_lookup_class_hook */
7795 +int apc_lookup_class_hook(char *name, int len, ulong hash, zend_class_entry ***ce) {
7798 + apc_context_t ctxt = {0,};
7801 + if(zend_is_compiling(TSRMLS_C)) { return FAILURE; }
7803 + if(zend_hash_quick_find(APCG(lazy_class_table), name, len, hash, (void**)&cl) == FAILURE) {
7807 + ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
7808 + ctxt.copy = APC_COPY_OUT_OPCODE;
7810 + if(install_class(*cl, &ctxt, 0 TSRMLS_CC) == FAILURE) {
7811 + apc_warning("apc_lookup_class_hook: could not install %s" TSRMLS_CC, name);
7815 + if(zend_hash_quick_find(EG(class_table), name, len, hash, (void**)ce) == FAILURE) {
7816 + apc_warning("apc_lookup_class_hook: known error trying to fetch class %s" TSRMLS_CC, name);
7825 +/* {{{ uninstall_class */
7826 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
7830 + status = zend_hash_del(EG(class_table),
7833 + if (status == FAILURE) {
7834 + apc_error("Cannot delete class %s" TSRMLS_CC, cl.name);
7840 +/* {{{ copy_function_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
7841 +static int copy_function_name(apc_function_t *pf TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
7843 + zval *internal_ar = va_arg(args, zval *),
7844 + *user_ar = va_arg(args, zval *);
7845 + zend_function *func = pf->function;
7847 + if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
7851 + if (func->type == ZEND_INTERNAL_FUNCTION) {
7852 + add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
7853 + } else if (func->type == ZEND_USER_FUNCTION) {
7854 + add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
7860 +/* {{{ copy_class_or_interface_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
7861 +static int copy_class_or_interface_name(apc_class_t *cl TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
7863 + zval *array = va_arg(args, zval *);
7864 + zend_uint mask = va_arg(args, zend_uint);
7865 + zend_uint comply = va_arg(args, zend_uint);
7866 + zend_uint comply_mask = (comply)? mask:0;
7867 + zend_class_entry *ce = cl->class_entry;
7869 + if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
7870 + && (comply_mask == (ce->ce_flags & mask))) {
7871 + add_next_index_stringl(array, ce->name, ce->name_length, 1);
7873 + return ZEND_HASH_APPLY_KEEP;
7879 +/* {{{ apc_defined_function_hook */
7880 +int apc_defined_function_hook(zval *internal, zval *user) {
7882 + zend_hash_apply_with_arguments(APCG(lazy_function_table)
7883 +#ifdef ZEND_ENGINE_2_3
7886 + ,(apply_func_args_t) copy_function_name, 2, internal, user);
7891 +/* {{{ apc_declared_class_hook */
7892 +int apc_declared_class_hook(zval *classes, zend_uint mask, zend_uint comply) {
7894 + zend_hash_apply_with_arguments(APCG(lazy_class_table)
7895 +#ifdef ZEND_ENGINE_2_3
7898 + , (apply_func_args_t) copy_class_or_interface_name, 3, classes, mask, comply);
7903 +/* {{{ cached_compile */
7904 +static zend_op_array* cached_compile(zend_file_handle* h,
7906 + apc_context_t* ctxt TSRMLS_DC)
7908 + apc_cache_entry_t* cache_entry;
7911 + cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
7912 + assert(cache_entry != NULL);
7914 + if (cache_entry->data.file.classes) {
7915 + int lazy_classes = APCG(lazy_classes);
7916 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
7917 + if(install_class(cache_entry->data.file.classes[i], ctxt, lazy_classes TSRMLS_CC) == FAILURE) {
7918 + goto default_compile;
7923 + if (cache_entry->data.file.functions) {
7924 + int lazy_functions = APCG(lazy_functions);
7925 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
7926 + install_function(cache_entry->data.file.functions[i], ctxt, lazy_functions TSRMLS_CC);
7930 + apc_do_halt_compiler_register(cache_entry->data.file.filename, cache_entry->data.file.halt_offset TSRMLS_CC);
7933 + return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array, ctxt TSRMLS_CC);
7937 + if(cache_entry->data.file.classes) {
7938 + for(ii = 0; ii < i ; ii++) {
7939 + uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
7943 + apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
7945 + apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
7947 + /* cannot free up cache data yet, it maybe in use */
7953 +/* {{{ apc_compile_cache_entry */
7954 +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) {
7955 + int num_functions, num_classes;
7956 + apc_function_t* alloc_functions;
7957 + zend_op_array* alloc_op_array;
7958 + apc_class_t* alloc_classes;
7960 + apc_context_t ctxt;
7962 + /* remember how many functions and classes existed before compilation */
7963 + num_functions = zend_hash_num_elements(CG(function_table));
7964 + num_classes = zend_hash_num_elements(CG(class_table));
7966 + /* compile the file using the default compile function, *
7967 + * we set *op_array here so we return opcodes during *
7968 + * a failure. We should not return prior to this line. */
7969 + *op_array = old_compile_file(h, type TSRMLS_CC);
7970 + if (*op_array == NULL) {
7974 + ctxt.pool = apc_pool_create(APC_MEDIUM_POOL, apc_sma_malloc, apc_sma_free,
7975 + apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
7977 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
7980 + ctxt.copy = APC_COPY_IN_OPCODE;
7982 + if(APCG(file_md5)) {
7984 + unsigned char buf[1024];
7985 + PHP_MD5_CTX context;
7986 + php_stream *stream;
7989 + if(h->opened_path) {
7990 + filename = h->opened_path;
7992 + filename = h->filename;
7994 + stream = php_stream_open_wrapper(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
7996 + PHP_MD5Init(&context);
7997 + while((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
7998 + PHP_MD5Update(&context, buf, n);
8000 + PHP_MD5Final(key->md5, &context);
8001 + php_stream_close(stream);
8003 + apc_warning("Error while reading '%s' for md5 generation." TSRMLS_CC, filename);
8006 + apc_warning("Unable to open '%s' for md5 generation." TSRMLS_CC, filename);
8010 + if(!(alloc_op_array = apc_copy_op_array(NULL, *op_array, &ctxt TSRMLS_CC))) {
8014 + if(!(alloc_functions = apc_copy_new_functions(num_functions, &ctxt TSRMLS_CC))) {
8017 + if(!(alloc_classes = apc_copy_new_classes(*op_array, num_classes, &ctxt TSRMLS_CC))) {
8021 + path = h->opened_path;
8022 + if(!path && key->type == APC_CACHE_KEY_FPFILE) path = (char*)key->data.fpfile.fullpath;
8023 + if(!path) path=h->filename;
8025 + apc_debug("2. h->opened_path=[%s] h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
8027 + if(!(*cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
8034 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
8042 +/* {{{ my_compile_file
8043 + Overrides zend_compile_file */
8044 +static zend_op_array* my_compile_file(zend_file_handle* h,
8045 + int type TSRMLS_DC)
8047 + apc_cache_key_t key;
8048 + apc_cache_entry_t* cache_entry;
8049 + zend_op_array* op_array = NULL;
8051 + apc_context_t ctxt = {0,};
8053 + const char* filename = NULL;
8055 + if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
8056 + return old_compile_file(h, type TSRMLS_CC);
8059 + if(h->opened_path) {
8060 + filename = h->opened_path;
8062 + filename = h->filename;
8065 + /* check our regular expression filters */
8066 + if (APCG(filters) && APCG(compiled_filters) && filename) {
8067 + int ret = apc_regex_match_array(APCG(compiled_filters), filename);
8069 + if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
8070 + return old_compile_file(h, type TSRMLS_CC);
8072 + } else if(!APCG(cache_by_default)) {
8073 + return old_compile_file(h, type TSRMLS_CC);
8075 + APCG(current_cache) = apc_cache;
8080 + apc_debug("1. h->opened_path=[%s] h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
8082 + /* try to create a cache key; if we fail, give up on caching */
8083 + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
8084 + return old_compile_file(h, type TSRMLS_CC);
8087 + if(!APCG(force_file_update)) {
8088 + /* search for the file in the cache */
8089 + cache_entry = apc_cache_find(apc_cache, key, t TSRMLS_CC);
8090 + ctxt.force_update = 0;
8092 + cache_entry = NULL;
8093 + ctxt.force_update = 1;
8096 + if (cache_entry != NULL) {
8099 + ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free,
8100 + apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
8102 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
8103 + return old_compile_file(h, type TSRMLS_CC);
8105 + ctxt.copy = APC_COPY_OUT_OPCODE;
8107 + zend_hash_add(&EG(included_files), cache_entry->data.file.filename,
8108 + strlen(cache_entry->data.file.filename)+1,
8109 + (void *)&dummy, sizeof(int), NULL);
8111 + apc_stack_push(APCG(cache_stack), cache_entry TSRMLS_CC);
8112 + op_array = cached_compile(h, type, &ctxt TSRMLS_CC);
8115 +#ifdef APC_FILEHITS
8116 + /* If the file comes from the cache, add it to the global request file list */
8117 + add_next_index_string(APCG(filehits), h->filename, 1);
8119 + /* this is an unpool, which has no cleanup - this only free's the pool header */
8120 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
8122 + /* We might leak fds without this hack */
8123 + if (h->type != ZEND_HANDLE_FILENAME) {
8124 + zend_llist_add_element(&CG(open_files), h);
8128 + if(APCG(report_autofilter)) {
8129 + apc_warning("Autofiltering %s" TSRMLS_CC,
8130 + (h->opened_path ? h->opened_path : h->filename));
8131 + apc_warning("Recompiling %s" TSRMLS_CC, cache_entry->data.file.filename);
8133 + /* TODO: check what happens with EG(included_files) */
8136 + /* Make sure the mtime reflects the files last known mtime, and we respect max_file_size in the case of fpstat==0 */
8137 + if(key.type == APC_CACHE_KEY_FPFILE) {
8138 + apc_fileinfo_t fileinfo;
8139 + struct stat *tmp_buf = NULL;
8140 + if(!strcmp(SG(request_info).path_translated, h->filename)) {
8141 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
8144 + fileinfo.st_buf.sb = *tmp_buf;
8146 + if (apc_search_paths(h->filename, PG(include_path), &fileinfo TSRMLS_CC) != 0) {
8147 + apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC,h->filename,SG(request_info).path_translated);
8148 + return old_compile_file(h, type TSRMLS_CC);
8151 + if (APCG(max_file_size) < fileinfo.st_buf.sb.st_size) {
8152 + apc_debug("File is too big %s (%ld) - bailing\n" TSRMLS_CC, h->filename, fileinfo.st_buf.sb.st_size);
8153 + return old_compile_file(h, type TSRMLS_CC);
8155 + key.mtime = fileinfo.st_buf.sb.st_mtime;
8158 + HANDLE_BLOCK_INTERRUPTIONS();
8160 +#if NONBLOCKING_LOCK_AVAILABLE
8161 + if(APCG(write_lock)) {
8162 + if(!apc_cache_write_lock(apc_cache TSRMLS_CC)) {
8163 + HANDLE_UNBLOCK_INTERRUPTIONS();
8164 + return old_compile_file(h, type TSRMLS_CC);
8170 + if (apc_compile_cache_entry(&key, h, type, t, &op_array, &cache_entry TSRMLS_CC) == SUCCESS) {
8171 + ctxt.pool = cache_entry->pool;
8172 + ctxt.copy = APC_COPY_IN_OPCODE;
8173 + if (apc_cache_insert(apc_cache, key, cache_entry, &ctxt, t TSRMLS_CC) != 1) {
8174 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
8179 + bailout=1; /* in the event of a bailout, ensure we don't create a dead-lock */
8182 + APCG(current_cache) = NULL;
8184 +#if NONBLOCKING_LOCK_AVAILABLE
8185 + if(APCG(write_lock)) {
8186 + apc_cache_write_unlock(apc_cache TSRMLS_CC);
8189 + HANDLE_UNBLOCK_INTERRUPTIONS();
8191 + if (bailout) zend_bailout();
8197 +/* {{{ data preload */
8199 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8201 +static zval* data_unserialize(const char *filename TSRMLS_DC)
8206 + char *contents, *tmp;
8208 + php_unserialize_data_t var_hash;
8210 + if(VCWD_STAT(filename, &sb) == -1) {
8214 + fp = fopen(filename, "rb");
8216 + len = sizeof(char)*sb.st_size;
8218 + tmp = contents = malloc(len);
8224 + if(fread(contents, 1, len, fp) < 1) {
8229 + MAKE_STD_ZVAL(retval);
8231 + PHP_VAR_UNSERIALIZE_INIT(var_hash);
8233 + /* I wish I could use json */
8234 + if(!php_var_unserialize(&retval, (const unsigned char**)&tmp, (const unsigned char*)(contents+len), &var_hash TSRMLS_CC)) {
8235 + zval_ptr_dtor(&retval);
8239 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
8247 +static int apc_load_data(const char *data_file TSRMLS_DC)
8250 + char key[MAXPATHLEN] = {0,};
8251 + unsigned int key_len;
8254 + p = strrchr(data_file, DEFAULT_SLASH);
8257 + strlcpy(key, p+1, sizeof(key));
8258 + p = strrchr(key, '.');
8262 + key_len = strlen(key);
8264 + data = data_unserialize(data_file TSRMLS_CC);
8266 + _apc_store(key, key_len, data, 0, 1 TSRMLS_CC);
8275 +static int apc_walk_dir(const char *path TSRMLS_DC)
8277 + char file[MAXPATHLEN]={0,};
8280 + struct dirent **namelist = NULL;
8282 + if ((ndir = php_scandir(path, &namelist, 0, php_alphasort)) > 0)
8284 + for (i = 0; i < ndir; i++)
8286 + /* check for extension */
8287 + if (!(p = strrchr(namelist[i]->d_name, '.'))
8288 + || (p && strcmp(p, ".data")))
8290 + free(namelist[i]);
8293 + snprintf(file, MAXPATHLEN, "%s%c%s",
8294 + path, DEFAULT_SLASH, namelist[i]->d_name);
8295 + if(!apc_load_data(file TSRMLS_CC))
8299 + free(namelist[i]);
8307 +void apc_data_preload(TSRMLS_D)
8309 + if(!APCG(preload_path)) return;
8311 + apc_walk_dir(APCG(preload_path) TSRMLS_CC);
8315 +/* {{{ apc_serializer hooks */
8316 +static int _apc_register_serializer(const char* name, apc_serialize_t serialize,
8317 + apc_unserialize_t unserialize,
8318 + void *config TSRMLS_DC)
8321 + apc_serializer_t *serializer;
8323 + for(i = 0; i < APC_MAX_SERIALIZERS; i++) {
8324 + serializer = &apc_serializers[i];
8325 + if(!serializer->name) {
8327 + serializer->name = name; /* assumed to be const */
8328 + serializer->serialize = serialize;
8329 + serializer->unserialize = unserialize;
8330 + serializer->config = config;
8331 + apc_serializers[i+1].name = NULL;
8339 +apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC)
8342 + apc_serializer_t *serializer;
8344 + for(i = 0; i < APC_MAX_SERIALIZERS; i++) {
8345 + serializer = &apc_serializers[i];
8346 + if(serializer->name && (strcmp(serializer->name, name) == 0)) {
8347 + return serializer;
8353 +apc_serializer_t* apc_get_serializers(TSRMLS_D)
8355 + return &(apc_serializers[0]);
8359 +/* {{{ module init and shutdown */
8361 +int apc_module_init(int module_number TSRMLS_DC)
8363 + /* apc initialization */
8365 + apc_sma_init(APCG(shm_segments), APCG(shm_size), APCG(mmap_file_mask) TSRMLS_CC);
8367 + apc_sma_init(APCG(shm_segments), APCG(shm_size), NULL TSRMLS_CC);
8369 + apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl) TSRMLS_CC);
8370 + apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl) TSRMLS_CC);
8372 + /* override compilation */
8373 + old_compile_file = zend_compile_file;
8374 + zend_compile_file = my_compile_file;
8375 + REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
8376 + REGISTER_LONG_CONSTANT("\000apc_compile_file", (long)&my_compile_file, CONST_PERSISTENT | CONST_CS);
8377 + REGISTER_LONG_CONSTANT(APC_SERIALIZER_CONSTANT, (long)&_apc_register_serializer, CONST_PERSISTENT | CONST_CS);
8379 + /* test out the constant function pointer */
8380 + apc_register_serializer("php", APC_SERIALIZER_NAME(php), APC_UNSERIALIZER_NAME(php), NULL TSRMLS_CC);
8382 + assert(apc_serializers[0].name != NULL);
8386 + apc_data_preload(TSRMLS_C);
8388 +#if APC_HAVE_LOOKUP_HOOKS
8389 + if(APCG(lazy_functions)) {
8390 + zend_set_lookup_function_hook(apc_lookup_function_hook TSRMLS_CC);
8391 + zend_set_defined_function_hook(apc_defined_function_hook TSRMLS_CC);
8393 + if(APCG(lazy_classes)) {
8394 + zend_set_lookup_class_hook(apc_lookup_class_hook TSRMLS_CC);
8395 + zend_set_declared_class_hook(apc_declared_class_hook TSRMLS_CC);
8398 + if(APCG(lazy_functions) || APCG(lazy_classes)) {
8399 + apc_warning("Lazy function/class loading not available with this version of PHP, please disable APC lazy loading." TSRMLS_CC);
8400 + APCG(lazy_functions) = APCG(lazy_classes) = 0;
8404 +#ifdef ZEND_ENGINE_2_4
8406 + apc_interned_strings_init(TSRMLS_C);
8410 + APCG(initialized) = 1;
8414 +int apc_module_shutdown(TSRMLS_D)
8416 + if (!APCG(initialized))
8419 + /* restore compilation */
8420 + zend_compile_file = old_compile_file;
8423 + * In case we got interrupted by a SIGTERM or something else during execution
8424 + * we may have cache entries left on the stack that we need to check to make
8425 + * sure that any functions or classes these may have added to the global function
8426 + * and class tables are removed before we blow away the memory that hold them.
8428 + * This is merely to remove memory leak warnings - as the process is terminated
8429 + * immediately after shutdown. The following while loop can be removed without
8430 + * affecting anything else.
8432 + while (apc_stack_size(APCG(cache_stack)) > 0) {
8434 + apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
8435 + if (cache_entry->data.file.functions) {
8436 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
8437 + zend_hash_del(EG(function_table),
8438 + cache_entry->data.file.functions[i].name,
8439 + cache_entry->data.file.functions[i].name_len+1);
8442 + if (cache_entry->data.file.classes) {
8443 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
8444 + zend_hash_del(EG(class_table),
8445 + cache_entry->data.file.classes[i].name,
8446 + cache_entry->data.file.classes[i].name_len+1);
8449 + apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
8452 +#ifdef ZEND_ENGINE_2_4
8454 + apc_interned_strings_shutdown(TSRMLS_C);
8458 + apc_cache_destroy(apc_cache TSRMLS_CC);
8459 + apc_cache_destroy(apc_user_cache TSRMLS_CC);
8460 + apc_sma_cleanup(TSRMLS_C);
8462 + APCG(initialized) = 0;
8468 +/* {{{ process init and shutdown */
8469 +int apc_process_init(int module_number TSRMLS_DC)
8474 +int apc_process_shutdown(TSRMLS_D)
8481 +/* {{{ apc_deactivate */
8482 +static void apc_deactivate(TSRMLS_D)
8484 + /* The execution stack was unwound, which prevented us from decrementing
8485 + * the reference counts on active cache entries in `my_execute`.
8487 + while (apc_stack_size(APCG(cache_stack)) > 0) {
8489 + zend_class_entry* zce = NULL;
8490 + void ** centry = (void*)(&zce);
8491 + zend_class_entry** pzce = NULL;
8493 + apc_cache_entry_t* cache_entry =
8494 + (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
8496 + if (cache_entry->data.file.classes) {
8497 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
8498 + centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
8499 + if(zend_hash_find(EG(class_table),
8500 + cache_entry->data.file.classes[i].name,
8501 + cache_entry->data.file.classes[i].name_len+1,
8502 + (void**)centry) == FAILURE)
8504 + /* double inclusion of conditional classes ends up failing
8505 + * this lookup the second time around.
8512 + zend_hash_del(EG(class_table),
8513 + cache_entry->data.file.classes[i].name,
8514 + cache_entry->data.file.classes[i].name_len+1);
8516 + apc_free_class_entry_after_execution(zce TSRMLS_CC);
8519 + apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
8524 +/* {{{ request init and shutdown */
8526 +int apc_request_init(TSRMLS_D)
8528 + apc_stack_clear(APCG(cache_stack));
8529 + if (!APCG(compiled_filters) && APCG(filters)) {
8530 + /* compile regex filters here to avoid race condition between MINIT of PCRE and APC.
8531 + * This should be moved to apc_cache_create() if this race condition between modules is resolved */
8532 + APCG(compiled_filters) = apc_regex_compile_array(APCG(filters) TSRMLS_CC);
8535 + if (!APCG(serializer) && APCG(serializer_name)) {
8536 + /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */
8537 + APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC);
8540 +#if APC_HAVE_LOOKUP_HOOKS
8541 + if(APCG(lazy_functions)) {
8542 + APCG(lazy_function_table) = emalloc(sizeof(HashTable));
8543 + zend_hash_init(APCG(lazy_function_table), 0, NULL, NULL, 0);
8545 + if(APCG(lazy_classes)) {
8546 + APCG(lazy_class_table) = emalloc(sizeof(HashTable));
8547 + zend_hash_init(APCG(lazy_class_table), 0, NULL, NULL, 0);
8551 +#ifdef APC_FILEHITS
8552 + ALLOC_INIT_ZVAL(APCG(filehits));
8553 + array_init(APCG(filehits));
8559 +int apc_request_shutdown(TSRMLS_D)
8561 +#if APC_HAVE_LOOKUP_HOOKS
8562 + if(APCG(lazy_class_table)) {
8563 + zend_hash_destroy(APCG(lazy_class_table));
8564 + efree(APCG(lazy_class_table));
8566 + if(APCG(lazy_function_table)) {
8567 + zend_hash_destroy(APCG(lazy_function_table));
8568 + efree(APCG(lazy_function_table));
8572 + apc_deactivate(TSRMLS_C);
8574 +#ifdef APC_FILEHITS
8575 + zval_ptr_dtor(&APCG(filehits));
8584 + * Local variables:
8586 + * c-basic-offset: 4
8588 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8589 + * vim<600: expandtab sw=4 ts=4 sts=4
8591 diff -Naur a/ext/apc/apc_main.h b/ext/apc/apc_main.h
8592 --- a/ext/apc/apc_main.h 1970-01-01 01:00:00.000000000 +0100
8593 +++ b/ext/apc/apc_main.h 2012-07-20 00:10:35.000000000 +0200
8596 + +----------------------------------------------------------------------+
8598 + +----------------------------------------------------------------------+
8599 + | Copyright (c) 2006-2011 The PHP Group |
8600 + +----------------------------------------------------------------------+
8601 + | This source file is subject to version 3.01 of the PHP license, |
8602 + | that is bundled with this package in the file LICENSE, and is |
8603 + | available through the world-wide-web at the following url: |
8604 + | http://www.php.net/license/3_01.txt |
8605 + | If you did not receive a copy of the PHP license and are unable to |
8606 + | obtain it through the world-wide-web, please send a note to |
8607 + | license@php.net so we can mail you a copy immediately. |
8608 + +----------------------------------------------------------------------+
8609 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8610 + | George Schlossnagle <george@omniti.com> |
8611 + | Rasmus Lerdorf <rasmus@php.net> |
8612 + | Arun C. Murthy <arunc@yahoo-inc.com> |
8613 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
8614 + +----------------------------------------------------------------------+
8616 + This software was contributed to PHP by Community Connect Inc. in 2002
8617 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8618 + Future revisions and derivatives of this source code must acknowledge
8619 + Community Connect Inc. as the original contributor of this module by
8620 + leaving this note intact in the source code.
8622 + All other licensing and usage conditions are those of the PHP Group.
8626 +/* $Id: apc_main.h 308594 2011-02-23 12:35:33Z gopalv $ */
8631 +#include "apc_pool.h"
8632 +#include "apc_serializer.h"
8635 + * This module provides the primary interface between PHP and APC.
8638 +extern int apc_module_init(int module_number TSRMLS_DC);
8639 +extern int apc_module_shutdown(TSRMLS_D);
8640 +extern int apc_process_init(int module_number TSRMLS_DC);
8641 +extern int apc_process_shutdown(TSRMLS_D);
8642 +extern int apc_request_init(TSRMLS_D);
8643 +extern int apc_request_shutdown(TSRMLS_D);
8645 +typedef enum _apc_copy_type {
8647 + APC_COPY_IN_OPCODE,
8648 + APC_COPY_OUT_OPCODE,
8653 +typedef struct _apc_context_t
8656 + apc_copy_type copy;
8657 + unsigned int force_update:1;
8660 +/* {{{ struct apc_serializer_t */
8661 +typedef struct apc_serializer_t apc_serializer_t;
8662 +struct apc_serializer_t {
8664 + apc_serialize_t serialize;
8665 + apc_unserialize_t unserialize;
8670 +apc_serializer_t* apc_get_serializers(TSRMLS_D);
8671 +apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC);
8676 + * Local variables:
8678 + * c-basic-offset: 4
8680 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8681 + * vim<600: expandtab sw=4 ts=4 sts=4
8683 diff -Naur a/ext/apc/apc_mmap.c b/ext/apc/apc_mmap.c
8684 --- a/ext/apc/apc_mmap.c 1970-01-01 01:00:00.000000000 +0100
8685 +++ b/ext/apc/apc_mmap.c 2012-07-20 00:10:35.000000000 +0200
8688 + +----------------------------------------------------------------------+
8690 + +----------------------------------------------------------------------+
8691 + | Copyright (c) 2006-2011 The PHP Group |
8692 + +----------------------------------------------------------------------+
8693 + | This source file is subject to version 3.01 of the PHP license, |
8694 + | that is bundled with this package in the file LICENSE, and is |
8695 + | available through the world-wide-web at the following url: |
8696 + | http://www.php.net/license/3_01.txt |
8697 + | If you did not receive a copy of the PHP license and are unable to |
8698 + | obtain it through the world-wide-web, please send a note to |
8699 + | license@php.net so we can mail you a copy immediately. |
8700 + +----------------------------------------------------------------------+
8701 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
8702 + +----------------------------------------------------------------------+
8704 + This software was contributed to PHP by Community Connect Inc. in 2002
8705 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8706 + Future revisions and derivatives of this source code must acknowledge
8707 + Community Connect Inc. as the original contributor of this module by
8708 + leaving this note intact in the source code.
8710 + All other licensing and usage conditions are those of the PHP Group.
8714 +/* $Id: apc_mmap.c 307048 2011-01-03 23:53:17Z kalle $ */
8717 +#include "apc_mmap.h"
8718 +#include "apc_lock.h"
8723 +#include <sys/types.h>
8724 +#include <sys/mman.h>
8727 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
8728 + * tells whatever update daemons might be running to not flush dirty
8729 + * vm pages to disk unless absolutely necessary. My guess is that
8730 + * most systems that don't have this probably default to only synching
8731 + * to disk when absolutely necessary.
8734 +#define MAP_NOSYNC 0
8737 +/* support for systems where MAP_ANONYMOUS is defined but not MAP_ANON, ie: HP-UX bug #14615 */
8738 +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
8739 +# define MAP_ANON MAP_ANONYMOUS
8742 +apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC)
8744 + apc_segment_t segment;
8747 + int flags = MAP_SHARED | MAP_NOSYNC;
8750 + /* If no filename was provided, do an anonymous mmap */
8751 + if(!file_mask || (file_mask && !strlen(file_mask))) {
8752 +#if !defined(MAP_ANON)
8753 + 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);
8756 + flags = MAP_SHARED | MAP_ANON;
8759 + } else if(!strcmp(file_mask,"/dev/zero")) {
8760 + fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
8762 + apc_error("apc_mmap: open on /dev/zero failed:" TSRMLS_CC);
8765 + remap = 0; /* cannot remap */
8766 + } else if(strstr(file_mask,".shm")) {
8768 + * If the filemask contains .shm we try to do a POSIX-compliant shared memory
8769 + * backed mmap which should avoid synchs on some platforms. At least on
8770 + * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
8771 + * a file in a mounted shmfs. For this to work on Linux you need to make sure
8772 + * you actually have shmfs mounted. Also on Linux, make sure the file_mask you
8773 + * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX
8774 + * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
8775 + * path you want here.
8777 + if(!mktemp(file_mask)) {
8778 + apc_error("apc_mmap: mktemp on %s failed:" TSRMLS_CC, file_mask);
8781 + fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
8783 + apc_error("apc_mmap: shm_open on %s failed:" TSRMLS_CC, file_mask);
8786 + if (ftruncate(fd, size) < 0) {
8788 + shm_unlink(file_mask);
8789 + apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
8792 + shm_unlink(file_mask);
8795 + * Otherwise we do a normal filesystem mmap
8797 + fd = mkstemp(file_mask);
8799 + apc_error("apc_mmap: mkstemp on %s failed:" TSRMLS_CC, file_mask);
8802 + if (ftruncate(fd, size) < 0) {
8804 + unlink(file_mask);
8805 + apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
8808 + unlink(file_mask);
8811 + segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
8812 + segment.size = size;
8814 +#ifdef APC_MEMPROTECT
8816 + segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0);
8818 + segment.roaddr = NULL;
8822 + if((long)segment.shmaddr == -1) {
8823 + apc_error("apc_mmap: mmap failed:" TSRMLS_CC);
8826 + if(fd != -1) close(fd);
8832 + segment.shmaddr = (void*)-1;
8834 +#ifdef APC_MEMPROTECT
8835 + segment.roaddr = NULL;
8840 +void apc_unmap(apc_segment_t *segment TSRMLS_DC)
8842 + if (munmap(segment->shmaddr, segment->size) < 0) {
8843 + apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
8846 +#ifdef APC_MEMPROTECT
8847 + if (segment->roaddr && munmap(segment->roaddr, segment->size) < 0) {
8848 + apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
8857 + * Local variables:
8859 + * c-basic-offset: 4
8861 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8862 + * vim<600: expandtab sw=4 ts=4 sts=4
8864 diff -Naur a/ext/apc/apc_mmap.h b/ext/apc/apc_mmap.h
8865 --- a/ext/apc/apc_mmap.h 1970-01-01 01:00:00.000000000 +0100
8866 +++ b/ext/apc/apc_mmap.h 2012-07-20 00:10:35.000000000 +0200
8869 + +----------------------------------------------------------------------+
8871 + +----------------------------------------------------------------------+
8872 + | Copyright (c) 2006-2011 The PHP Group |
8873 + +----------------------------------------------------------------------+
8874 + | This source file is subject to version 3.01 of the PHP license, |
8875 + | that is bundled with this package in the file LICENSE, and is |
8876 + | available through the world-wide-web at the following url: |
8877 + | http://www.php.net/license/3_01.txt |
8878 + | If you did not receive a copy of the PHP license and are unable to |
8879 + | obtain it through the world-wide-web, please send a note to |
8880 + | license@php.net so we can mail you a copy immediately. |
8881 + +----------------------------------------------------------------------+
8882 + | Authors: Gopal V <gopalv@php.net> |
8883 + +----------------------------------------------------------------------+
8885 + This software was contributed to PHP by Community Connect Inc. in 2002
8886 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8887 + Future revisions and derivatives of this source code must acknowledge
8888 + Community Connect Inc. as the original contributor of this module by
8889 + leaving this note intact in the source code.
8891 + All other licensing and usage conditions are those of the PHP Group.
8895 +/* $Id: apc_mmap.h 307048 2011-01-03 23:53:17Z kalle $ */
8900 +#include <limits.h>
8903 +#include "apc_sma.h"
8905 +/* Wrapper functions for shared memory mapped files */
8908 +apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC);
8909 +void apc_unmap(apc_segment_t* segment TSRMLS_DC);
8915 + * Local variables:
8917 + * c-basic-offset: 4
8919 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8920 + * vim<600: expandtab sw=4 ts=4 sts=4
8922 diff -Naur a/ext/apc/apc.php b/ext/apc/apc.php
8923 --- a/ext/apc/apc.php 1970-01-01 01:00:00.000000000 +0100
8924 +++ b/ext/apc/apc.php 2012-07-20 00:10:35.000000000 +0200
8928 + +----------------------------------------------------------------------+
8930 + +----------------------------------------------------------------------+
8931 + | Copyright (c) 2006-2011 The PHP Group |
8932 + +----------------------------------------------------------------------+
8933 + | This source file is subject to version 3.01 of the PHP license, |
8934 + | that is bundled with this package in the file LICENSE, and is |
8935 + | available through the world-wide-web at the following url: |
8936 + | http://www.php.net/license/3_01.txt |
8937 + | If you did not receive a copy of the PHP license and are unable to |
8938 + | obtain it through the world-wide-web, please send a note to |
8939 + | license@php.net so we can mail you a copy immediately. |
8940 + +----------------------------------------------------------------------+
8941 + | Authors: Ralf Becker <beckerr@php.net> |
8942 + | Rasmus Lerdorf <rasmus@php.net> |
8943 + | Ilia Alshanetsky <ilia@prohost.org> |
8944 + +----------------------------------------------------------------------+
8946 + All other licensing and usage conditions are those of the PHP Group.
8950 +$VERSION='$Id: apc.php 325483 2012-05-01 00:34:04Z rasmus $';
8952 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
8953 +if (file_exists("apc.conf.php")) include("apc.conf.php");
8954 +////////////////////////////////////////////////////////
8956 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
8958 +defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if
8959 + // no other authentication is available
8961 + // There will be no further authentication. You
8962 + // will have to handle this by yourself!
8964 + // You need to change ADMIN_PASSWORD to make
8966 +defaults('ADMIN_USERNAME','apc'); // Admin Username
8967 +defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!!
8969 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let
8970 +// users generate a md5 or crypt password in a easy way to fill it in above
8972 +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German
8973 +defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
8975 +defaults('GRAPH_SIZE',200); // Image size
8977 +//defaults('PROXY', 'tcp://127.0.0.1:8080');
8979 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
8982 +// "define if not defined"
8983 +function defaults($d,$v) {
8984 + if (!defined($d)) define($d,$v); // or just @define(...)
8987 +// rewrite $PHP_SELF to block XSS attacks
8989 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';
8991 +$host = php_uname('n');
8992 +if($host) { $host = '('.$host.')'; }
8993 +if (isset($_SERVER['SERVER_ADDR'])) {
8994 + $host .= ' ('.$_SERVER['SERVER_ADDR'].')';
8997 +// operation constants
8998 +define('OB_HOST_STATS',1);
8999 +define('OB_SYS_CACHE',2);
9000 +define('OB_USER_CACHE',3);
9001 +define('OB_SYS_CACHE_DIR',4);
9002 +define('OB_VERSION_CHECK',9);
9004 +// check validity of input variables
9006 + 'OB' => '/^\d+$/', // operational mode switch
9007 + 'CC' => '/^[01]$/', // clear cache requested
9008 + 'DU' => '/^.*$/', // Delete User Key
9009 + 'SH' => '/^[a-z0-9]+$/', // shared object description
9011 + 'IMG' => '/^[123]$/', // image to generate
9012 + 'LO' => '/^1$/', // login requested
9014 + 'COUNT' => '/^\d+$/', // number of line displayed in list
9015 + 'SCOPE' => '/^[AD]$/', // list view scope
9016 + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key
9017 + 'SORT2' => '/^[DA]$/', // second sort key
9018 + 'AGGR' => '/^\d+$/', // aggregation by dir level
9019 + 'SEARCH' => '~^[a-zA-Z0-9/_.-]*$~' // aggregation by dir level
9022 +// default cache mode
9023 +$cache_mode='opcode';
9027 + 'A' => 'cache_list',
9028 + 'D' => 'deleted_list'
9031 +// handle POST and GET requests
9032 +if (empty($_REQUEST)) {
9033 + if (!empty($_GET) && !empty($_POST)) {
9034 + $_REQUEST = array_merge($_GET, $_POST);
9035 + } else if (!empty($_GET)) {
9036 + $_REQUEST = $_GET;
9037 + } else if (!empty($_POST)) {
9038 + $_REQUEST = $_POST;
9040 + $_REQUEST = array();
9044 +// check parameter syntax
9045 +foreach($vardom as $var => $dom) {
9046 + if (!isset($_REQUEST[$var])) {
9047 + $MYREQUEST[$var]=NULL;
9048 + } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
9049 + $MYREQUEST[$var]=$_REQUEST[$var];
9051 + $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
9055 +// check parameter sematics
9056 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
9057 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
9058 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
9059 +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS;
9060 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
9061 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
9065 + "?SCOPE=".$MYREQUEST['SCOPE'].
9066 + "&SORT1=".$MYREQUEST['SORT1'].
9067 + "&SORT2=".$MYREQUEST['SORT2'].
9068 + "&COUNT=".$MYREQUEST['COUNT'];
9071 + "?SCOPE=".$MYREQUEST['SCOPE'].
9072 + "&COUNT=".$MYREQUEST['COUNT'];
9074 +// authentication needed?
9076 +if (!USE_AUTHENTICATION) {
9080 + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
9082 + if (!isset($_SERVER['PHP_AUTH_USER']) ||
9083 + !isset($_SERVER['PHP_AUTH_PW']) ||
9084 + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
9085 + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
9086 + Header("WWW-Authenticate: Basic realm=\"APC Login\"");
9087 + Header("HTTP/1.0 401 Unauthorized");
9091 + <h1>Rejected!</h1>
9092 + <big>Wrong Username or Password!</big><br/> <br/>
9093 + <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
9104 +// select cache mode
9105 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
9106 + $cache_mode='user';
9109 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
9110 + apc_clear_cache($cache_mode);
9113 +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
9114 + apc_delete($MYREQUEST['DU']);
9117 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
9118 + echo "No cache info available. APC does not appear to be running.";
9122 +$cache_user = apc_cache_info('user', 1);
9123 +$mem=apc_sma_info();
9124 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear
9126 +// don't cache this page
9128 +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
9129 +header("Cache-Control: post-check=0, pre-check=0", false);
9130 +header("Pragma: no-cache"); // HTTP/1.0
9132 +function duration($ts) {
9134 + $years = (int)((($time - $ts)/(7*86400))/52.177457);
9135 + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
9136 + $weeks = (int)(($rem)/(7*86400));
9137 + $days = (int)(($rem)/86400) - $weeks*7;
9138 + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
9139 + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
9141 + if($years==1) $str .= "$years year, ";
9142 + if($years>1) $str .= "$years years, ";
9143 + if($weeks==1) $str .= "$weeks week, ";
9144 + if($weeks>1) $str .= "$weeks weeks, ";
9145 + if($days==1) $str .= "$days day,";
9146 + if($days>1) $str .= "$days days,";
9147 + if($hours == 1) $str .= " $hours hour and";
9148 + if($hours>1) $str .= " $hours hours and";
9149 + if($mins == 1) $str .= " 1 minute";
9150 + else $str .= " $mins minutes";
9156 +function graphics_avail() {
9157 + return extension_loaded('gd');
9159 +if (isset($MYREQUEST['IMG']))
9161 + if (!graphics_avail()) {
9165 + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
9167 + $w=deg2rad((360+$start+($end-$start)/2)%360);
9170 + if (function_exists("imagefilledarc")) {
9171 + // exists only if GD 2.0.1 is avaliable
9172 + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
9173 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
9174 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
9176 + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
9177 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
9178 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
9179 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
9180 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
9181 + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
9184 + if ($placeindex>0) {
9185 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
9186 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
9189 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
9194 + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
9196 + $w=deg2rad((360+$start+($end-$start)/2)%360);
9198 + if ($placeindex>0) {
9199 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
9200 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
9203 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
9207 + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
9208 + global $col_black;
9212 + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
9213 + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
9214 + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
9215 + imagerectangle($im, $x, $y1, $x1, $y, $color1);
9217 + if ($placeindex>0) {
9219 + if ($placeindex<16)
9222 + $py=$placeindex*12+6;
9223 + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
9224 + imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
9225 + imagestring($im,2,$px,$py-6,$text,$color1);
9228 + if ($placeindex<31) {
9230 + $py=($placeindex-15)*12+6;
9232 + $px=$x+40*2+100*intval(($placeindex-15)/15);
9233 + $py=($placeindex%15)*12+6;
9235 + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
9236 + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
9237 + imagestring($im,2,$px+2,$py-6,$text,$color1);
9240 + imagestring($im,4,$x+5,$y1-16,$text,$color1);
9246 + $size = GRAPH_SIZE; // image size
9247 + if ($MYREQUEST['IMG']==3)
9248 + $image = imagecreate(2*$size+150, $size+10);
9250 + $image = imagecreate($size+50, $size+10);
9252 + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
9253 + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
9254 + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
9255 + $col_black = imagecolorallocate($image, 0, 0, 0);
9256 + imagecolortransparent($image,$col_white);
9258 + switch ($MYREQUEST['IMG']) {
9261 + $s=$mem['num_seg']*$mem['seg_size'];
9262 + $a=$mem['avail_mem'];
9266 + // This block of code creates the pie chart. It is a lot more complex than you
9267 + // would expect because we try to visualize any memory fragmentation as well.
9269 + $string_placement=array();
9270 + for($i=0; $i<$mem['num_seg']; $i++) {
9272 + $free = $mem['block_lists'][$i];
9273 + uasort($free, 'block_sort');
9274 + foreach($free as $block) {
9275 + if($block['offset']!=$ptr) { // Used block
9276 + $angle_to = $angle_from+($block['offset']-$ptr)/$s;
9277 + if(($angle_to+$fuzz)>1) $angle_to = 1;
9278 + if( ($angle_to*360) - ($angle_from*360) >= 1) {
9279 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
9280 + if (($angle_to-$angle_from)>0.05) {
9281 + array_push($string_placement, array($angle_from,$angle_to));
9284 + $angle_from = $angle_to;
9286 + $angle_to = $angle_from+($block['size'])/$s;
9287 + if(($angle_to+$fuzz)>1) $angle_to = 1;
9288 + if( ($angle_to*360) - ($angle_from*360) >= 1) {
9289 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
9290 + if (($angle_to-$angle_from)>0.05) {
9291 + array_push($string_placement, array($angle_from,$angle_to));
9294 + $angle_from = $angle_to;
9295 + $ptr = $block['offset']+$block['size'];
9297 + if ($ptr < $mem['seg_size']) { // memory at the end
9298 + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
9299 + if(($angle_to+$fuzz)>1) $angle_to = 1;
9300 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
9301 + if (($angle_to-$angle_from)>0.05) {
9302 + array_push($string_placement, array($angle_from,$angle_to));
9306 + foreach ($string_placement as $angle) {
9307 + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
9312 + $s=$cache['num_hits']+$cache['num_misses'];
9313 + $a=$cache['num_hits'];
9315 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
9316 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
9320 + $s=$mem['num_seg']*$mem['seg_size'];
9321 + $a=$mem['avail_mem'];
9326 + // This block of code creates the bar chart. It is a lot more complex than you
9327 + // would expect because we try to visualize any memory fragmentation as well.
9328 + for($i=0; $i<$mem['num_seg']; $i++) {
9330 + $free = $mem['block_lists'][$i];
9331 + uasort($free, 'block_sort');
9332 + foreach($free as $block) {
9333 + if($block['offset']!=$ptr) { // Used block
9334 + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
9337 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
9338 + else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
9342 + $h=(GRAPH_SIZE-5)*($block['size'])/$s;
9345 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
9346 + else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
9349 + $ptr = $block['offset']+$block['size'];
9351 + if ($ptr < $mem['seg_size']) { // memory at the end
9352 + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
9354 + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
9360 + $s=$cache['num_hits']+$cache['num_misses'];
9361 + $a=$cache['num_hits'];
9363 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
9364 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
9368 + header("Content-type: image/png");
9373 +// pretty printer for byte values
9375 +function bsize($s) {
9376 + foreach (array('','K','M','G') as $i => $k) {
9377 + if ($s < 1024) break;
9380 + return sprintf("%5.1f %sBytes",$s,$k);
9383 +// sortable table header in "scripts for this host" view
9384 +function sortheader($key,$name,$extra='') {
9385 + global $MYREQUEST, $MY_SELF_WO_SORT;
9387 + if ($MYREQUEST['SORT1']==$key) {
9388 + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
9390 + return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
9394 +// create menu entry
9395 +function menu_entry($ob,$title) {
9396 + global $MYREQUEST,$MY_SELF;
9397 + if ($MYREQUEST['OB']!=$ob) {
9398 + return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
9399 + } else if (empty($MYREQUEST['SH'])) {
9400 + return "<li><span class=active>$title</span></li>";
9402 + return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";
9406 +function put_login_link($s="Login")
9408 + global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
9409 + // needs ADMIN_PASSWORD to be changed!
9411 + if (!USE_AUTHENTICATION) {
9413 + } else if (ADMIN_PASSWORD=='password')
9416 + <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>
9418 + } else if ($AUTHENTICATED) {
9420 + '{$_SERVER['PHP_AUTH_USER']}' logged in!
9424 + <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
9429 +function block_sort($array1, $array2)
9431 + if ($array1['offset'] > $array2['offset']) {
9440 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
9442 +<head><title>APC INFO <?php echo $host ?></title>
9444 +body { background:white; font-size:100.01%; margin:0; padding:0; }
9445 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
9446 +* html body {font-size:0.8em}
9447 +* html p {font-size:0.8em}
9448 +* html td {font-size:0.8em}
9449 +* html th {font-size:0.8em}
9450 +* html input {font-size:0.8em}
9451 +* html submit {font-size:0.8em}
9452 +td { vertical-align:top }
9453 +a { color:black; font-weight:none; text-decoration:none; }
9454 +a:hover { text-decoration:underline; }
9455 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
9458 +div.head div.login {
9459 + position:absolute;
9465 +div.head div.login a {
9466 + position:absolute;
9468 + background:rgb(119,123,180);
9469 + border:solid rgb(102,102,153) 2px;
9472 + padding:0.1em 0.5em 0.1em 0.5em;
9473 + text-decoration:none;
9475 +div.head div.login a:hover {
9476 + background:rgb(193,193,244);
9479 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
9480 +* html h1.apc { margin-bottom:-7px; }
9481 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
9482 +h1.apc div.logo span.logo {
9483 + background:rgb(119,123,180);
9485 + border-right: solid black 1px;
9486 + border-bottom: solid black 1px;
9487 + font-style:italic;
9489 + padding-left:1.2em;
9490 + padding-right:1.2em;
9493 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
9494 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
9495 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
9498 + border-bottom:solid rgb(102,102,153) 1px;
9499 + border-style:none;
9500 + border-top:solid rgb(102,102,153) 10px;
9507 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
9508 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
9510 + background:rgb(153,153,204);
9511 + border:solid rgb(102,102,153) 2px;
9515 + padding:0.1em 0.5em 0.1em 0.5em;
9516 + text-decoration:none;
9519 +ol.menu a.child_active {
9520 + background:rgb(153,153,204);
9521 + border:solid rgb(102,102,153) 2px;
9525 + padding:0.1em 0.5em 0.1em 0.5em;
9526 + text-decoration:none;
9527 + border-left: solid black 5px;
9530 +ol.menu span.active {
9531 + background:rgb(153,153,204);
9532 + border:solid rgb(102,102,153) 2px;
9536 + padding:0.1em 0.5em 0.1em 0.5em;
9537 + text-decoration:none;
9538 + border-left: solid black 5px;
9540 +ol.menu span.inactive {
9541 + background:rgb(193,193,244);
9542 + border:solid rgb(182,182,233) 2px;
9546 + padding:0.1em 0.5em 0.1em 0.5em;
9547 + text-decoration:none;
9551 + background:rgb(193,193,244);
9552 + text-decoration:none;
9557 + background:rgb(204,204,204);
9558 + border:solid rgb(204,204,204) 1px;
9559 + margin-bottom:1em;
9562 + background:rgb(204,204,204);
9566 + padding:0.1em 1em 0.1em 1em;
9569 + border:solid rgb(204,204,204) 1px;
9573 +div.info table th {
9574 + background:rgb(204,204,204);
9577 + padding:0.1em 1em 0.1em 1em;
9579 +div.info table th a.sortable { color:black; }
9580 +div.info table tr.tr-0 { background:rgb(238,238,238); }
9581 +div.info table tr.tr-1 { background:rgb(221,221,221); }
9582 +div.info table td { padding:0.3em 1em 0.3em 1em; }
9583 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
9584 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
9585 +div.info table td h3 {
9588 + margin-left:-0.3em;
9591 +div.graph { margin-bottom:1em }
9592 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
9593 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
9594 +div.graph table td.td-0 { background:rgb(238,238,238); }
9595 +div.graph table td.td-1 { background:rgb(221,221,221); }
9596 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
9598 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
9599 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
9600 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
9602 +div.sorting { margin:1.5em 0em 1.5em 2em }
9603 +.center { text-align:center }
9604 +.aright { position:absolute;right:1em }
9605 +.right { text-align:right }
9606 +.ok { color:rgb(0,200,0); font-weight:bold}
9607 +.failed { color:rgb(200,0,0); font-weight:bold}
9610 + border: black solid 1px;
9611 + border-right:solid black 2px;
9612 + border-bottom:solid black 2px;
9613 + padding:0 0.5em 0 0.5em;
9616 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
9617 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
9620 + background:rgb(238,238,238);
9621 + border:solid rgb(204,204,204) 1px;
9622 + color:rgb(200,0,0);
9626 + text-align:center;
9630 + background:rgb(153,153,204);
9631 + border:solid rgb(102,102,153) 2px;
9635 + padding:0.1em 0.5em 0.1em 0.5em;
9643 + <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
9644 + <div class="nameinfo">Opcode Cache</div>
9646 + <div class="login">
9647 + <?php put_login_link(); ?>
9654 +// Display main Menu
9657 + <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
9660 + menu_entry(1,'View Host Stats'),
9661 + menu_entry(2,'System Cache Entries');
9662 +if ($AUTHENTICATED) {
9663 + echo menu_entry(4,'Per-Directory Entries');
9666 + menu_entry(3,'User Cache Entries'),
9667 + menu_entry(9,'Version Check');
9669 +if ($AUTHENTICATED) {
9671 + <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>
9681 + <div class=content>
9684 +// MAIN SWITCH STATEMENT
9686 +switch ($MYREQUEST['OB']) {
9692 +// -----------------------------------------------
9694 +// -----------------------------------------------
9695 +case OB_HOST_STATS:
9696 + $mem_size = $mem['num_seg']*$mem['seg_size'];
9697 + $mem_avail= $mem['avail_mem'];
9698 + $mem_used = $mem_size-$mem_avail;
9699 + $seg_size = bsize($mem['seg_size']);
9700 + $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
9701 + $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
9702 + $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
9703 + $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
9704 + $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
9705 + $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
9706 + $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
9707 + $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
9708 + $apcversion = phpversion('apc');
9709 + $phpversion = phpversion();
9710 + $number_files = $cache['num_entries'];
9711 + $size_files = bsize($cache['mem_size']);
9712 + $number_vars = $cache_user['num_entries'];
9713 + $size_vars = bsize($cache_user['mem_size']);
9716 + <div class="info div1"><h2>General Cache Information</h2>
9717 + <table cellspacing=0><tbody>
9718 + <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
9719 + <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
9722 + if(!empty($_SERVER['SERVER_NAME']))
9723 + echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
9724 + if(!empty($_SERVER['SERVER_SOFTWARE']))
9725 + echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
9728 + <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
9729 + <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
9732 + echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
9733 + echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
9734 + echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
9739 + <div class="info div1"><h2>File Cache Information</h2>
9740 + <table cellspacing=0><tbody>
9741 + <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
9742 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
9743 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
9744 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
9745 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
9746 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
9747 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
9748 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
9752 + <div class="info div1"><h2>User Cache Information</h2>
9753 + <table cellspacing=0><tbody>
9754 + <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
9755 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
9756 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
9757 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
9758 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
9759 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
9760 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
9761 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
9766 + <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
9770 + foreach (ini_get_all('apc') as $k => $v) {
9771 + echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
9775 + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
9776 + $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
9778 + $mem_note = "Memory Usage";
9784 + <div class="graph div3"><h2>Host Status Diagrams</h2>
9785 + <table cellspacing=0><tbody>
9787 + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
9790 + <td class=td-0>$mem_note</td>
9791 + <td class=td-1>Hits & Misses</td>
9796 + graphics_avail() ?
9798 + "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
9799 + "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
9802 + '<td class=td-0><span class="green box"> </span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
9803 + '<td class=td-1><span class="green box"> </span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
9806 + '<td class=td-0><span class="red box"> </span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
9807 + '<td class=td-1><span class="red box"> </span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
9813 + <h2>Detailed Memory Usage and Fragmentation</h2>
9814 + <table cellspacing=0><tbody>
9816 + <td class=td-0 colspan=2><br/>
9819 + // Fragementation: (freeseg - 1) / total_seg
9820 + $nseg = $freeseg = $fragsize = $freetotal = 0;
9821 + for($i=0; $i<$mem['num_seg']; $i++) {
9823 + foreach($mem['block_lists'][$i] as $block) {
9824 + if ($block['offset'] != $ptr) {
9827 + $ptr = $block['offset'] + $block['size'];
9828 + /* Only consider blocks <5M for the fragmentation % */
9829 + if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
9830 + $freetotal+=$block['size'];
9832 + $freeseg += count($mem['block_lists'][$i]);
9835 + if ($freeseg > 1) {
9836 + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
9841 + if (graphics_avail()) {
9842 + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
9844 + <img alt="" $size src="$PHP_SELF?IMG=3&$time">
9848 + </br>Fragmentation: $frag
9852 + if(isset($mem['adist'])) {
9853 + foreach($mem['adist'] as $i=>$v) {
9854 + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
9855 + if($i==0) $range = "1";
9856 + else $range = "$cur - $nxt";
9857 + echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
9868 +// -----------------------------------------------
9869 +// User Cache Entries
9870 +// -----------------------------------------------
9871 +case OB_USER_CACHE:
9872 + if (!$AUTHENTICATED) {
9873 + echo '<div class="error">You need to login to see the user values here!<br/> <br/>';
9874 + put_login_link("Login now!");
9878 + $fieldname='info';
9879 + $fieldheading='User Entry Label';
9882 +// -----------------------------------------------
9883 +// System Cache Entries
9884 +// -----------------------------------------------
9886 + if (!isset($fieldname))
9888 + $fieldname='filename';
9889 + $fieldheading='Script Filename';
9890 + if(ini_get("apc.stat")) $fieldkey='inode';
9891 + else $fieldkey='filename';
9893 + if (!empty($MYREQUEST['SH']))
9896 + <div class="info"><table cellspacing=0><tbody>
9897 + <tr><th>Attribute</th><th>Value</th></tr>
9901 + foreach($scope_list as $j => $list) {
9902 + foreach($cache[$list] as $i => $entry) {
9903 + if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
9904 + foreach($entry as $k => $value) {
9905 + if (!$AUTHENTICATED) {
9906 + // hide all path entries if not logged in
9907 + $value=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$value);
9910 + if ($k == "num_hits") {
9911 + $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
9913 + if ($k == 'deletion_time') {
9914 + if(!$entry['deletion_time']) $value = "None";
9917 + "<tr class=tr-$m>",
9918 + "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
9919 + "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),"</td>",
9923 + if($fieldkey=='info') {
9924 + echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
9925 + $output = var_export(apc_fetch($entry[$fieldkey]),true);
9926 + echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
9927 + echo "</pre></td></tr>\n";
9942 + <div class=sorting><form>Scope:
9943 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
9944 + <select name=SCOPE>
9947 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
9948 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
9950 + ", Sorting:<select name=SORT1>",
9951 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
9952 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
9953 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
9954 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
9955 + "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
9956 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
9957 + "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
9958 + if($fieldname=='info') echo
9959 + "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
9962 + '<select name=SORT2>',
9963 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
9964 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
9966 + '<select name=COUNT onChange="form.submit()">',
9967 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
9968 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
9969 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
9970 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
9971 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
9972 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
9973 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
9974 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
9976 + ' Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
9977 + ' <input type=submit value="GO!">',
9980 + if (isset($MYREQUEST['SEARCH'])) {
9981 + // Don't use preg_quote because we want the user to be able to specify a
9982 + // regular expression subpattern.
9983 + $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i';
9984 + if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
9985 + echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
9991 + '<div class="info"><table cellspacing=0><tbody>',
9993 + '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>',
9994 + '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>',
9995 + '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>',
9996 + '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
9997 + '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
9998 + '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>';
10000 + if($fieldname=='info') {
10002 + echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
10004 + echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
10006 + // builds list with alpha numeric sortable keys
10009 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
10010 + switch($MYREQUEST['SORT1']) {
10011 + case 'A': $k=sprintf('%015d-',$entry['access_time']); break;
10012 + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break;
10013 + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break;
10014 + case 'M': $k=sprintf('%015d-',$entry['mtime']); break;
10015 + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
10016 + case 'T': $k=sprintf('%015d-',$entry['ttl']); break;
10017 + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
10018 + case 'S': $k=''; break;
10020 + if (!$AUTHENTICATED) {
10021 + // hide all path entries if not logged in
10022 + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry);
10024 + $list[$k.$entry[$fieldname]]=$entry;
10032 + switch ($MYREQUEST['SORT2']) {
10033 + case "A": krsort($list); break;
10034 + case "D": ksort($list); break;
10039 + foreach($list as $k => $entry) {
10040 + if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {
10041 + $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8');
10043 + '<tr class=tr-',$i%2,'>',
10044 + "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$field_value,'</a></td>',
10045 + '<td class="td-n center">',$entry['num_hits'],'</td>',
10046 + '<td class="td-n right">',$entry['mem_size'],'</td>',
10047 + '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
10048 + '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
10049 + '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
10051 + if($fieldname=='info') {
10052 + if($entry['ttl'])
10053 + echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
10055 + echo '<td class="td-n center">None</td>';
10057 + if ($entry['deletion_time']) {
10059 + echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
10060 + } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
10062 + echo '<td class="td-last center">';
10063 + echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
10066 + echo '<td class="td-last center"> </td>';
10070 + if ($i == $MYREQUEST['COUNT'])
10076 + echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
10082 + if ($list && $i < count($list)) {
10083 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
10092 +// -----------------------------------------------
10093 +// Per-Directory System Cache Entries
10094 +// -----------------------------------------------
10095 +case OB_SYS_CACHE_DIR:
10096 + if (!$AUTHENTICATED) {
10101 + <div class=sorting><form>Scope:
10102 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
10103 + <select name=SCOPE>
10106 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
10107 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
10109 + ", Sorting:<select name=SORT1>",
10110 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
10111 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
10112 + "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
10113 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
10114 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
10115 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
10117 + '<select name=SORT2>',
10118 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
10119 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
10121 + '<select name=COUNT onChange="form.submit()">',
10122 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
10123 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
10124 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
10125 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
10126 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
10127 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
10128 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
10129 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
10131 + ", Group By Dir Level:<select name=AGGR>",
10132 + "<option value='' selected>None</option>";
10133 + for ($i = 1; $i < 10; $i++)
10134 + echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
10135 + echo '</select>',
10136 + ' <input type=submit value="GO!">',
10139 + '<div class="info"><table cellspacing=0><tbody>',
10141 + '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
10142 + '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
10143 + '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>',
10144 + '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>',
10145 + '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>',
10146 + '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>',
10149 + // builds list with alpha numeric sortable keys
10151 + $tmp = $list = array();
10152 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
10153 + $n = dirname($entry['filename']);
10154 + if ($MYREQUEST['AGGR'] > 0) {
10155 + $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
10157 + if (!isset($tmp[$n])) {
10158 + $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
10160 + $tmp[$n]['hits'] += $entry['num_hits'];
10161 + $tmp[$n]['size'] += $entry['mem_size'];
10162 + ++$tmp[$n]['ents'];
10165 + foreach ($tmp as $k => $v) {
10166 + switch($MYREQUEST['SORT1']) {
10167 + case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
10168 + case 'T': $kn=sprintf('%015d-',$v['ents']); break;
10169 + case 'H': $kn=sprintf('%015d-',$v['hits']); break;
10170 + case 'Z': $kn=sprintf('%015d-',$v['size']); break;
10171 + case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
10172 + case 'S': $kn = $k; break;
10174 + $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
10181 + switch ($MYREQUEST['SORT2']) {
10182 + case "A": krsort($list); break;
10183 + case "D": ksort($list); break;
10188 + foreach($list as $entry) {
10190 + '<tr class=tr-',$i%2,'>',
10191 + "<td class=td-0>",$entry[0],'</a></td>',
10192 + '<td class="td-n center">',$entry[1],'</td>',
10193 + '<td class="td-n center">',$entry[2],'</td>',
10194 + '<td class="td-n center">',$entry[3],'</td>',
10195 + '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
10196 + '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
10199 + if (++$i == $MYREQUEST['COUNT']) break;
10203 + echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
10209 + if ($list && $i < count($list)) {
10210 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
10218 +// -----------------------------------------------
10220 +// -----------------------------------------------
10221 +case OB_VERSION_CHECK:
10223 + <div class="info"><h2>APC Version Information</h2>
10224 + <table cellspacing=0><tbody>
10229 + if (defined('PROXY')) {
10230 + $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) );
10231 + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt);
10233 + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
10236 + echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
10238 + $apcversion = phpversion('apc');
10240 + preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
10241 + echo '<tr class="tr-0 center"><td>';
10242 + if (version_compare($apcversion, $match[1], '>=')) {
10243 + echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
10246 + echo '<div class="failed">You are running an older version of APC ('.$apcversion.'),
10247 + newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
10248 + http://pecl.php.net/package/APC/'.$match[1].'</a>
10252 + echo '</td></tr>';
10253 + echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
10255 + preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
10256 + next($match[2]); next($match[2]);
10258 + while (list(,$v) = each($match[2])) {
10259 + list(,$ver) = explode(' ', $v, 2);
10260 + if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
10262 + } else if (!$i--) {
10265 + echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."</a></b><br><blockquote>";
10266 + echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."</blockquote>";
10269 + echo '</td></tr>';
10285 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
10288 diff -Naur a/ext/apc/apc_php.h b/ext/apc/apc_php.h
10289 --- a/ext/apc/apc_php.h 1970-01-01 01:00:00.000000000 +0100
10290 +++ b/ext/apc/apc_php.h 2012-07-20 00:10:35.000000000 +0200
10293 + +----------------------------------------------------------------------+
10295 + +----------------------------------------------------------------------+
10296 + | Copyright (c) 2006-2011 The PHP Group |
10297 + +----------------------------------------------------------------------+
10298 + | This source file is subject to version 3.01 of the PHP license, |
10299 + | that is bundled with this package in the file LICENSE, and is |
10300 + | available through the world-wide-web at the following url: |
10301 + | http://www.php.net/license/3_01.txt |
10302 + | If you did not receive a copy of the PHP license and are unable to |
10303 + | obtain it through the world-wide-web, please send a note to |
10304 + | license@php.net so we can mail you a copy immediately. |
10305 + +----------------------------------------------------------------------+
10306 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10307 + | George Schlossnagle <george@omniti.com> |
10308 + | Rasmus Lerdorf <rasmus@php.net> |
10309 + | Arun C. Murthy <arunc@yahoo-inc.com> |
10310 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
10311 + +----------------------------------------------------------------------+
10313 + This software was contributed to PHP by Community Connect Inc. in 2002
10314 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10315 + Future revisions and derivatives of this source code must acknowledge
10316 + Community Connect Inc. as the original contributor of this module by
10317 + leaving this note intact in the source code.
10319 + All other licensing and usage conditions are those of the PHP Group.
10323 +/* $Id: apc_php.h 313808 2011-07-28 06:17:10Z gopalv $ */
10329 + * The purpose of this header file is to include all PHP and Zend headers that
10330 + * are typically needed elsewhere in APC. This makes it easy to insure that
10331 + * all required headers are available.
10336 +#include "zend_API.h"
10337 +#include "zend_compile.h"
10338 +#include "zend_hash.h"
10339 +#include "zend_extensions.h"
10341 +#if ZEND_MODULE_API_NO >= 20100409
10342 +#define ZEND_ENGINE_2_4
10344 +#if ZEND_MODULE_API_NO > 20060613
10345 +#define ZEND_ENGINE_2_3
10347 +#if ZEND_MODULE_API_NO > 20050922
10348 +#define ZEND_ENGINE_2_2
10350 +#if ZEND_MODULE_API_NO > 20050921
10351 +#define ZEND_ENGINE_2_1
10353 +#ifdef ZEND_ENGINE_2_1
10354 +#include "zend_vm.h"
10357 +#ifndef IS_CONSTANT_TYPE_MASK
10358 +#define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
10361 +#include "rfc1867.h"
10366 + * Local variables:
10368 + * c-basic-offset: 4
10370 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
10371 + * vim<600: expandtab sw=4 ts=4 sts=4
10373 diff -Naur a/ext/apc/apc_php_pcre.h b/ext/apc/apc_php_pcre.h
10374 --- a/ext/apc/apc_php_pcre.h 1970-01-01 01:00:00.000000000 +0100
10375 +++ b/ext/apc/apc_php_pcre.h 2012-07-20 00:10:35.000000000 +0200
10378 + +----------------------------------------------------------------------+
10379 + | APC/PHP Version 5 |
10380 + +----------------------------------------------------------------------+
10381 + | Copyright (c) 1997-2011 The PHP Group |
10382 + +----------------------------------------------------------------------+
10383 + | This source file is subject to version 3.01 of the PHP license, |
10384 + | that is bundled with this package in the file LICENSE, and is |
10385 + | available through the world-wide-web at the following url: |
10386 + | http://www.php.net/license/3_01.txt |
10387 + | If you did not receive a copy of the PHP license and are unable to |
10388 + | obtain it through the world-wide-web, please send a note to |
10389 + | license@php.net so we can mail you a copy immediately. |
10390 + +----------------------------------------------------------------------+
10391 + | Author: Andrei Zmievski <andrei@php.net> |
10392 + +----------------------------------------------------------------------+
10395 +/* $Id: apc_php_pcre.h 307048 2011-01-03 23:53:17Z kalle $ */
10397 +#ifndef PHP_PCRE_H
10398 +#define PHP_PCRE_H
10400 +#if HAVE_PCRE || HAVE_BUNDLED_PCRE
10402 +#if HAVE_BUNDLED_PCRE
10403 +#include "ext/pcre/pcrelib/pcre.h"
10409 +#include <locale.h>
10412 +PHP_FUNCTION(preg_match);
10413 +PHP_FUNCTION(preg_match_all);
10414 +PHP_FUNCTION(preg_replace);
10415 +PHP_FUNCTION(preg_replace_callback);
10416 +PHP_FUNCTION(preg_split);
10417 +PHP_FUNCTION(preg_quote);
10418 +PHP_FUNCTION(preg_grep);
10420 +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);
10421 +PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC);
10422 +PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC);
10424 +extern zend_module_entry pcre_module_entry;
10425 +#define pcre_module_ptr &pcre_module_entry
10429 + pcre_extra *extra;
10430 + int preg_options;
10431 +#if HAVE_SETLOCALE
10433 + unsigned const char *tables;
10435 + int compile_options;
10437 +} pcre_cache_entry;
10439 +PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC);
10441 +PHPAPI void php_pcre_match_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
10442 + zval *subpats, int global, int use_flags, long flags, long start_offset TSRMLS_DC);
10444 +PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
10445 + int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
10447 +PHPAPI void php_pcre_split_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
10448 + long limit_val, long flags TSRMLS_DC);
10450 +PHPAPI void php_pcre_grep_impl( pcre_cache_entry *pce, zval *input, zval *return_value,
10451 + long flags TSRMLS_DC);
10453 +ZEND_BEGIN_MODULE_GLOBALS(pcre)
10454 + HashTable pcre_cache;
10455 + long backtrack_limit;
10456 + long recursion_limit;
10458 +ZEND_END_MODULE_GLOBALS(pcre)
10461 +# define PCRE_G(v) TSRMG(pcre_globals_id, zend_pcre_globals *, v)
10463 +# define PCRE_G(v) (pcre_globals.v)
10468 +#define pcre_module_ptr NULL
10470 +#endif /* HAVE_PCRE || HAVE_BUNDLED_PCRE */
10472 +#define phpext_pcre_ptr pcre_module_ptr
10474 +#endif /* PHP_PCRE_H */
10475 diff -Naur a/ext/apc/apc_pool.c b/ext/apc/apc_pool.c
10476 --- a/ext/apc/apc_pool.c 1970-01-01 01:00:00.000000000 +0100
10477 +++ b/ext/apc/apc_pool.c 2012-07-20 00:10:35.000000000 +0200
10480 + +----------------------------------------------------------------------+
10482 + +----------------------------------------------------------------------+
10483 + | Copyright (c) 2006-2011 The PHP Group |
10484 + +----------------------------------------------------------------------+
10485 + | This source file is subject to version 3.01 of the PHP license, |
10486 + | that is bundled with this package in the file LICENSE, and is |
10487 + | available through the world-wide-web at the following url: |
10488 + | http://www.php.net/license/3_01.txt. |
10489 + | If you did not receive a copy of the PHP license and are unable to |
10490 + | obtain it through the world-wide-web, please send a note to |
10491 + | license@php.net so we can mail you a copy immediately. |
10492 + +----------------------------------------------------------------------+
10493 + | Authors: Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
10494 + +----------------------------------------------------------------------+
10496 + This software was contributed to PHP by Yahoo! Inc. in 2008.
10498 + Future revisions and derivatives of this source code must acknowledge
10499 + Yahoo! Inc. as the original contributor of this module by
10500 + leaving this note intact in the source code.
10502 + All other licensing and usage conditions are those of the PHP Group.
10506 +/* $Id: apc_pool.c 307555 2011-01-18 07:17:21Z gopalv $ */
10509 +#include "apc_pool.h"
10510 +#include <assert.h>
10512 +#ifdef HAVE_VALGRIND_MEMCHECK_H
10513 +#include <valgrind/memcheck.h>
10517 +/* {{{ forward references */
10518 +static apc_pool* apc_unpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC);
10519 +static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC);
10522 +/* {{{ apc_pool_create */
10523 +apc_pool* apc_pool_create(apc_pool_type pool_type,
10524 + apc_malloc_t allocate,
10525 + apc_free_t deallocate,
10526 + apc_protect_t protect,
10527 + apc_unprotect_t unprotect
10530 + if(pool_type == APC_UNPOOL) {
10531 + return apc_unpool_create(pool_type, allocate, deallocate,
10532 + protect, unprotect TSRMLS_CC);
10535 + return apc_realpool_create(pool_type, allocate, deallocate,
10536 + protect, unprotect TSRMLS_CC);
10540 +/* {{{ apc_pool_destroy */
10541 +void apc_pool_destroy(apc_pool *pool TSRMLS_DC)
10543 + apc_free_t deallocate = pool->deallocate;
10544 + apc_pcleanup_t cleanup = pool->cleanup;
10546 + cleanup(pool TSRMLS_CC);
10547 + deallocate(pool TSRMLS_CC);
10551 +/* {{{ apc_unpool implementation */
10553 +typedef struct _apc_unpool apc_unpool;
10555 +struct _apc_unpool {
10557 + /* apc_unpool is a lie! */
10560 +static void* apc_unpool_alloc(apc_pool* pool, size_t size TSRMLS_DC)
10562 + apc_unpool *upool = (apc_unpool*)pool;
10564 + apc_malloc_t allocate = upool->parent.allocate;
10566 + upool->parent.size += size;
10567 + upool->parent.used += size;
10569 + return allocate(size TSRMLS_CC);
10572 +static void apc_unpool_free(apc_pool* pool, void *ptr TSRMLS_DC)
10574 + apc_unpool *upool = (apc_unpool*) pool;
10576 + apc_free_t deallocate = upool->parent.deallocate;
10578 + deallocate(ptr TSRMLS_CC);
10581 +static void apc_unpool_cleanup(apc_pool* pool TSRMLS_DC)
10585 +static apc_pool* apc_unpool_create(apc_pool_type type,
10586 + apc_malloc_t allocate, apc_free_t deallocate,
10587 + apc_protect_t protect, apc_unprotect_t unprotect
10590 + apc_unpool* upool = allocate(sizeof(apc_unpool) TSRMLS_CC);
10596 + upool->parent.type = type;
10597 + upool->parent.allocate = allocate;
10598 + upool->parent.deallocate = deallocate;
10600 + upool->parent.protect = protect;
10601 + upool->parent.unprotect = unprotect;
10603 + upool->parent.palloc = apc_unpool_alloc;
10604 + upool->parent.pfree = apc_unpool_free;
10606 + upool->parent.cleanup = apc_unpool_cleanup;
10608 + upool->parent.used = 0;
10609 + upool->parent.size = 0;
10611 + return &(upool->parent);
10616 +/*{{{ apc_realpool implementation */
10618 +/* {{{ typedefs */
10619 +typedef struct _pool_block
10623 + unsigned char *mark;
10624 + struct _pool_block *next;
10625 + unsigned :0; /* this should align to word */
10626 + /* data comes here */
10630 + parts in ? are optional and turned on for fun, memory loss,
10631 + and for something else that I forgot about ... ah, debugging
10633 + |--------> data[] |<-- non word boundary (too)
10634 + +-------------+--------------+-----------+-------------+-------------->>>
10635 + | pool_block | ?sizeinfo<1> | block<1> | ?redzone<1> | ?sizeinfo<2>
10636 + | | (size_t) | | padded left |
10637 + +-------------+--------------+-----------+-------------+-------------->>>
10640 +typedef struct _apc_realpool apc_realpool;
10642 +struct _apc_realpool
10644 + struct _apc_pool parent;
10649 + unsigned long count;
10651 + pool_block *head;
10652 + pool_block first;
10657 +/* {{{ redzone code */
10658 +static const unsigned char decaff[] = {
10659 + 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
10660 + 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
10661 + 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
10662 + 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad
10665 +/* a redzone is at least 4 (0xde,0xca,0xc0,0xff) bytes */
10666 +#define REDZONE_SIZE(size) \
10667 + ((ALIGNWORD((size)) > ((size) + 4)) ? \
10668 + (ALIGNWORD((size)) - (size)) : /* does not change realsize */\
10669 + ALIGNWORD((size)) - (size) + ALIGNWORD((sizeof(char)))) /* adds 1 word to realsize */
10671 +#define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t))
10673 +#define MARK_REDZONE(block, redsize) do {\
10674 + memcpy(block, decaff, redsize );\
10677 +#define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0)
10681 +#define INIT_POOL_BLOCK(rpool, entry, size) do {\
10682 + (entry)->avail = (entry)->capacity = (size);\
10683 + (entry)->mark = ((unsigned char*)(entry)) + ALIGNWORD(sizeof(pool_block));\
10684 + (entry)->next = (rpool)->head;\
10685 + (rpool)->head = (entry);\
10688 +/* {{{ create_pool_block */
10689 +static pool_block* create_pool_block(apc_realpool *rpool, size_t size TSRMLS_DC)
10691 + apc_malloc_t allocate = rpool->parent.allocate;
10693 + size_t realsize = sizeof(pool_block) + ALIGNWORD(size);
10695 + pool_block* entry = allocate(realsize TSRMLS_CC);
10701 + INIT_POOL_BLOCK(rpool, entry, size);
10703 + rpool->parent.size += realsize;
10711 +/* {{{ apc_realpool_alloc */
10712 +static void* apc_realpool_alloc(apc_pool *pool, size_t size TSRMLS_DC)
10714 + apc_realpool *rpool = (apc_realpool*)pool;
10715 + unsigned char *p = NULL;
10716 + size_t realsize = ALIGNWORD(size);
10718 + unsigned char *redzone = NULL;
10719 + size_t redsize = 0;
10720 + size_t *sizeinfo= NULL;
10721 + pool_block *entry = NULL;
10724 + if(APC_POOL_HAS_REDZONES(pool)) {
10725 + redsize = REDZONE_SIZE(size); /* redsize might be re-using word size padding */
10726 + realsize = size + redsize; /* recalculating realsize */
10728 + redsize = realsize - size; /* use padding space */
10731 + if(APC_POOL_HAS_SIZEINFO(pool)) {
10732 + realsize += ALIGNWORD(sizeof(size_t));
10735 + /* minimize look-back, a value of 8 seems to give similar fill-ratios (+2%)
10736 + * as looping through the entire list. And much faster in allocations. */
10737 + for(entry = rpool->head, i = 0; entry != NULL && (i < 8); entry = entry->next, i++) {
10738 + if(entry->avail >= realsize) {
10743 + /* upgrade the pool type to reduce overhead */
10744 + if(rpool->count > 4 && rpool->dsize < 4096) {
10745 + rpool->dsize = 4096;
10746 + } else if(rpool->count > 8 && rpool->dsize < 8192) {
10747 + rpool->dsize = 8192;
10750 + poolsize = ALIGNSIZE(realsize, rpool->dsize);
10752 + entry = create_pool_block(rpool, poolsize TSRMLS_CC);
10761 + if(APC_POOL_HAS_SIZEINFO(pool)) {
10762 + sizeinfo = (size_t*)p;
10763 + p += SIZEINFO_SIZE;
10764 + *sizeinfo = size;
10767 + redzone = p + size;
10769 + if(APC_POOL_HAS_REDZONES(pool)) {
10770 + MARK_REDZONE(redzone, redsize);
10773 +#ifdef VALGRIND_MAKE_MEM_NOACCESS
10774 + if(redsize != 0) {
10775 + VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
10779 + entry->avail -= realsize;
10780 + entry->mark += realsize;
10781 + pool->used += realsize;
10783 +#ifdef VALGRIND_MAKE_MEM_UNDEFINED
10784 + /* need to write before reading data off this */
10785 + VALGRIND_MAKE_MEM_UNDEFINED(p, size);
10792 +/* {{{ apc_realpool_check_integrity */
10794 + * Checking integrity at runtime, does an
10795 + * overwrite check only when the sizeinfo
10798 + * Marked as used in gcc, so that this function
10799 + * is accessible from gdb, eventhough it is never
10800 + * used in code in non-debug builds.
10802 +static APC_USED int apc_realpool_check_integrity(apc_realpool *rpool)
10804 + apc_pool *pool = &(rpool->parent);
10805 + pool_block *entry;
10806 + size_t *sizeinfo = NULL;
10807 + unsigned char *start;
10809 + unsigned char *redzone;
10812 + for(entry = rpool->head; entry != NULL; entry = entry->next) {
10813 + start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
10814 + if((entry->mark - start) != (entry->capacity - entry->avail)) {
10819 + if(!APC_POOL_HAS_REDZONES(pool) ||
10820 + !APC_POOL_HAS_SIZEINFO(pool)) {
10821 + (void)pool; /* remove unused warning */
10825 + for(entry = rpool->head; entry != NULL; entry = entry->next) {
10826 + start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
10828 + while(start < entry->mark) {
10829 + sizeinfo = (size_t*)start;
10830 + /* redzone starts where real data ends, in a non-word boundary
10831 + * redsize is at least 4 bytes + whatever's needed to make it
10832 + * to another word boundary.
10834 + redzone = start + SIZEINFO_SIZE + (*sizeinfo);
10835 + redsize = REDZONE_SIZE(*sizeinfo);
10836 +#ifdef VALGRIND_MAKE_MEM_DEFINED
10837 + VALGRIND_MAKE_MEM_DEFINED(redzone, redsize);
10839 + if(!CHECK_REDZONE(redzone, redsize))
10842 + fprintf(stderr, "Redzone check failed for %p\n",
10843 + start + ALIGNWORD(sizeof(size_t)));*/
10846 +#ifdef VALGRIND_MAKE_MEM_NOACCESS
10847 + VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
10849 + realsize = SIZEINFO_SIZE + *sizeinfo + redsize;
10850 + start += realsize;
10858 +/* {{{ apc_realpool_free */
10860 + * free does not do anything other than
10861 + * check for redzone values when free'ing
10864 +static void apc_realpool_free(apc_pool *pool, void *p TSRMLS_DC)
10869 +static void apc_realpool_cleanup(apc_pool *pool TSRMLS_DC)
10871 + pool_block *entry;
10873 + apc_realpool *rpool = (apc_realpool*)pool;
10874 + apc_free_t deallocate = pool->deallocate;
10876 + assert(apc_realpool_check_integrity(rpool)!=0);
10878 + entry = rpool->head;
10880 + while(entry->next != NULL) {
10881 + tmp = entry->next;
10882 + deallocate(entry TSRMLS_CC);
10887 +/* {{{ apc_realpool_create */
10888 +static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t allocate, apc_free_t deallocate,
10889 + apc_protect_t protect, apc_unprotect_t unprotect
10893 + size_t dsize = 0;
10894 + apc_realpool *rpool;
10896 + switch(type & APC_POOL_SIZE_MASK) {
10897 + case APC_SMALL_POOL:
10901 + case APC_LARGE_POOL:
10905 + case APC_MEDIUM_POOL:
10913 + rpool = (apc_realpool*)allocate((sizeof(apc_realpool) + ALIGNWORD(dsize)) TSRMLS_CC);
10919 + rpool->parent.type = type;
10921 + rpool->parent.allocate = allocate;
10922 + rpool->parent.deallocate = deallocate;
10924 + rpool->parent.size = sizeof(apc_realpool) + ALIGNWORD(dsize);
10926 + rpool->parent.palloc = apc_realpool_alloc;
10927 + rpool->parent.pfree = apc_realpool_free;
10929 + rpool->parent.protect = protect;
10930 + rpool->parent.unprotect = unprotect;
10932 + rpool->parent.cleanup = apc_realpool_cleanup;
10934 + rpool->dsize = dsize;
10935 + rpool->head = NULL;
10936 + rpool->count = 0;
10938 + INIT_POOL_BLOCK(rpool, &(rpool->first), dsize);
10940 + return &(rpool->parent);
10946 +/* {{{ apc_pool_init */
10947 +void apc_pool_init()
10949 + /* put all ye sanity checks here */
10950 + assert(sizeof(decaff) > REDZONE_SIZE(ALIGNWORD(sizeof(char))));
10951 + assert(sizeof(pool_block) == ALIGNWORD(sizeof(pool_block)));
10952 +#if APC_POOL_DEBUG
10953 + assert((APC_POOL_SIZE_MASK & (APC_POOL_SIZEINFO | APC_POOL_REDZONES)) == 0);
10958 +/* {{{ apc_pstrdup */
10959 +void* APC_ALLOC apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC)
10961 + return s != NULL ? apc_pmemcpy(s, (strlen(s) + 1), pool TSRMLS_CC) : NULL;
10965 +/* {{{ apc_pmemcpy */
10966 +void* APC_ALLOC apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC)
10970 + if (p != NULL && (q = apc_pool_alloc(pool, n)) != NULL) {
10979 + * Local variables:
10981 + * c-basic-offset: 4
10983 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
10984 + * vim<600: expandtab sw=4 ts=4 sts=4
10986 diff -Naur a/ext/apc/apc_pool.h b/ext/apc/apc_pool.h
10987 --- a/ext/apc/apc_pool.h 1970-01-01 01:00:00.000000000 +0100
10988 +++ b/ext/apc/apc_pool.h 2012-07-20 00:10:35.000000000 +0200
10991 + +----------------------------------------------------------------------+
10993 + +----------------------------------------------------------------------+
10994 + | Copyright (c) 2006-2011 The PHP Group |
10995 + +----------------------------------------------------------------------+
10996 + | This source file is subject to version 3.01 of the PHP license, |
10997 + | that is bundled with this package in the file LICENSE, and is |
10998 + | available through the world-wide-web at the following url: |
10999 + | http://www.php.net/license/3_01.txt. |
11000 + | If you did not receive a copy of the PHP license and are unable to |
11001 + | obtain it through the world-wide-web, please send a note to |
11002 + | license@php.net so we can mail you a copy immediately. |
11003 + +----------------------------------------------------------------------+
11004 + | Authors: Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
11005 + +----------------------------------------------------------------------+
11007 + This software was contributed to PHP by Yahoo! Inc. in 2008.
11009 + Future revisions and derivatives of this source code must acknowledge
11010 + Yahoo! Inc. as the original contributor of this module by
11011 + leaving this note intact in the source code.
11013 + All other licensing and usage conditions are those of the PHP Group.
11017 +/* $Id: apc_pool.h 307048 2011-01-03 23:53:17Z kalle $ */
11019 +#ifndef APC_POOL_H
11020 +#define APC_POOL_H
11023 +#include "apc_sma.h"
11025 +/* #define APC_POOL_DEBUG 1 */
11028 + APC_UNPOOL = 0x0,
11029 + APC_SMALL_POOL = 0x1,
11030 + APC_MEDIUM_POOL = 0x2,
11031 + APC_LARGE_POOL = 0x3,
11032 + APC_POOL_SIZE_MASK = 0x7, /* waste a bit */
11033 +#if APC_POOL_DEBUG
11034 + APC_POOL_REDZONES = 0x08,
11035 + APC_POOL_SIZEINFO = 0x10,
11036 + APC_POOL_OPT_MASK = 0x18
11040 +#if APC_POOL_DEBUG
11041 +#define APC_POOL_HAS_SIZEINFO(pool) ((pool->type & APC_POOL_SIZEINFO)!=0)
11042 +#define APC_POOL_HAS_REDZONES(pool) ((pool->type & APC_POOL_REDZONES)!=0)
11044 +/* let gcc optimize away the optional features */
11045 +#define APC_POOL_HAS_SIZEINFO(pool) (0)
11046 +#define APC_POOL_HAS_REDZONES(pool) (0)
11050 +typedef struct _apc_pool apc_pool;
11052 +typedef void (*apc_pcleanup_t)(apc_pool *pool TSRMLS_DC);
11054 +typedef void* (*apc_palloc_t)(apc_pool *pool, size_t size TSRMLS_DC);
11055 +typedef void (*apc_pfree_t) (apc_pool *pool, void* p TSRMLS_DC);
11057 +typedef void* (*apc_protect_t) (void *p);
11058 +typedef void* (*apc_unprotect_t)(void *p);
11060 +struct _apc_pool {
11061 + apc_pool_type type;
11063 + apc_malloc_t allocate;
11064 + apc_free_t deallocate;
11066 + apc_palloc_t palloc;
11067 + apc_pfree_t pfree;
11069 + apc_protect_t protect;
11070 + apc_unprotect_t unprotect;
11072 + apc_pcleanup_t cleanup;
11077 + /* apc_realpool and apc_unpool add more here */
11080 +#define apc_pool_alloc(pool, size) ((void *) pool->palloc(pool, size TSRMLS_CC))
11081 +#define apc_pool_free(pool, ptr) ((void) pool->pfree (pool, ptr TSRMLS_CC))
11083 +#define apc_pool_protect(pool, ptr) (pool->protect ? \
11084 + (pool)->protect((ptr)) : (ptr))
11086 +#define apc_pool_unprotect(pool, ptr) (pool->unprotect ? \
11087 + (pool)->unprotect((ptr)) : (ptr))
11089 +extern void apc_pool_init();
11091 +extern apc_pool* apc_pool_create(apc_pool_type pool_type,
11092 + apc_malloc_t allocate,
11093 + apc_free_t deallocate,
11094 + apc_protect_t protect,
11095 + apc_unprotect_t unprotect
11098 +extern void apc_pool_destroy(apc_pool* pool TSRMLS_DC);
11100 +extern void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC);
11101 +extern void* apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC);
11104 diff -Naur a/ext/apc/apc_pthreadmutex.c b/ext/apc/apc_pthreadmutex.c
11105 --- a/ext/apc/apc_pthreadmutex.c 1970-01-01 01:00:00.000000000 +0100
11106 +++ b/ext/apc/apc_pthreadmutex.c 2012-07-20 00:10:35.000000000 +0200
11109 + +----------------------------------------------------------------------+
11111 + +----------------------------------------------------------------------+
11112 + | Copyright (c) 2006-2011 The PHP Group |
11113 + +----------------------------------------------------------------------+
11114 + | This source file is subject to version 3.01 of the PHP license, |
11115 + | that is bundled with this package in the file LICENSE, and is |
11116 + | available through the world-wide-web at the following url: |
11117 + | http://www.php.net/license/3_01.txt |
11118 + | If you did not receive a copy of the PHP license and are unable to |
11119 + | obtain it through the world-wide-web, please send a note to |
11120 + | license@php.net so we can mail you a copy immediately. |
11121 + +----------------------------------------------------------------------+
11122 + | Authors: Brian Shire <shire@php.net> |
11123 + +----------------------------------------------------------------------+
11127 +/* $Id: apc_pthreadmutex.c 307048 2011-01-03 23:53:17Z kalle $ */
11129 +#include "apc_pthreadmutex.h"
11131 +#ifdef APC_PTHREADMUTEX_LOCKS
11133 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC)
11136 + pthread_mutexattr_t* attr;
11137 + attr = malloc(sizeof(pthread_mutexattr_t));
11139 + result = pthread_mutexattr_init(attr);
11140 + if(result == ENOMEM) {
11141 + apc_error("pthread mutex error: Insufficient memory exists to create the mutex attribute object." TSRMLS_CC);
11142 + } else if(result == EINVAL) {
11143 + apc_error("pthread mutex error: attr does not point to writeable memory." TSRMLS_CC);
11144 + } else if(result == EFAULT) {
11145 + apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC);
11148 +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
11149 + result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
11150 + if (result == EINVAL) {
11151 + apc_error("pthread_mutexattr_settype: unable to set adaptive mutexes" TSRMLS_CC);
11155 + /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
11156 + result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
11157 + if(result == EINVAL) {
11158 + 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);
11159 + } else if(result == EFAULT) {
11160 + apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC);
11161 + } else if(result == ENOTSUP) {
11162 + apc_error("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC);
11165 + if(pthread_mutex_init(lock, attr)) {
11166 + apc_error("unable to initialize pthread lock" TSRMLS_CC);
11171 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
11173 + return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
11176 +void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC)
11179 + result = pthread_mutex_lock(lock);
11180 + if(result == EINVAL) {
11181 + apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC);
11182 + } else if(result == EDEADLK) {
11183 + apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC);
11187 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC)
11189 + if(pthread_mutex_unlock(lock)) {
11190 + apc_error("unable to unlock pthread lock" TSRMLS_CC);
11194 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC)
11197 + rval = pthread_mutex_trylock(lock);
11198 + if(rval == EBUSY) { /* Lock is already held */
11200 + } else if(rval == 0) { /* Obtained lock */
11202 + } else { /* Other error */
11203 + apc_error("unable to obtain pthread trylock" TSRMLS_CC);
11212 + * Local variables:
11214 + * c-basic-offset: 4
11216 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11217 + * vim<600: expandtab sw=4 ts=4 sts=4
11219 diff -Naur a/ext/apc/apc_pthreadmutex.h b/ext/apc/apc_pthreadmutex.h
11220 --- a/ext/apc/apc_pthreadmutex.h 1970-01-01 01:00:00.000000000 +0100
11221 +++ b/ext/apc/apc_pthreadmutex.h 2012-07-20 00:10:35.000000000 +0200
11224 + +----------------------------------------------------------------------+
11226 + +----------------------------------------------------------------------+
11227 + | Copyright (c) 2006-2011 The PHP Group |
11228 + +----------------------------------------------------------------------+
11229 + | This source file is subject to version 3.01 of the PHP license, |
11230 + | that is bundled with this package in the file LICENSE, and is |
11231 + | available through the world-wide-web at the following url: |
11232 + | http://www.php.net/license/3_01.txt |
11233 + | If you did not receive a copy of the PHP license and are unable to |
11234 + | obtain it through the world-wide-web, please send a note to |
11235 + | license@php.net so we can mail you a copy immediately. |
11236 + +----------------------------------------------------------------------+
11237 + | Authors: Brian Shire <shire@php.net> |
11238 + +----------------------------------------------------------------------+
11242 +/* $Id: apc_pthreadmutex.h 307048 2011-01-03 23:53:17Z kalle $ */
11244 +#ifndef APC_PTHREADMUTEX_H
11245 +#define APC_PTHREADMUTEX_H
11249 +#ifdef APC_PTHREADMUTEX_LOCKS
11251 +#include <pthread.h>
11253 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC);
11254 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
11255 +void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC);
11256 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC);
11257 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC);
11264 + * Local variables:
11266 + * c-basic-offset: 4
11268 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11269 + * vim<600: expandtab sw=4 ts=4 sts=4
11271 diff -Naur a/ext/apc/apc_pthreadrwlock.c b/ext/apc/apc_pthreadrwlock.c
11272 --- a/ext/apc/apc_pthreadrwlock.c 1970-01-01 01:00:00.000000000 +0100
11273 +++ b/ext/apc/apc_pthreadrwlock.c 2012-07-20 00:10:35.000000000 +0200
11276 + +----------------------------------------------------------------------+
11278 + +----------------------------------------------------------------------+
11279 + | Copyright (c) 2006-2011 The PHP Group |
11280 + +----------------------------------------------------------------------+
11281 + | This source file is subject to version 3.01 of the PHP license, |
11282 + | that is bundled with this package in the file LICENSE, and is |
11283 + | available through the world-wide-web at the following url: |
11284 + | http://www.php.net/license/3_01.txt |
11285 + | If you did not receive a copy of the PHP license and are unable to |
11286 + | obtain it through the world-wide-web, please send a note to |
11287 + | license@php.net so we can mail you a copy immediately. |
11288 + +----------------------------------------------------------------------+
11289 + | Authors: Gopal V <gopalv@php.net> |
11290 + +----------------------------------------------------------------------+
11296 +#include "apc_pthreadrwlock.h"
11298 +#ifdef APC_PTHREADRW_LOCKS
11300 +pthread_rwlock_t *apc_pthreadrwlock_create(pthread_rwlock_t *lock TSRMLS_DC)
11303 + pthread_rwlockattr_t attr;
11305 + result = pthread_rwlockattr_init(&attr);
11306 + if(result == ENOMEM) {
11307 + apc_error("pthread rwlock error: Insufficient memory exists to create the rwlock attribute object." TSRMLS_CC);
11308 + } else if(result == EINVAL) {
11309 + apc_error("pthread rwlock error: attr does not point to writeable memory." TSRMLS_CC);
11310 + } else if(result == EFAULT) {
11311 + apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC);
11314 +#ifdef __USE_UNIX98
11315 + pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
11318 + result = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
11319 + if(result == EINVAL) {
11320 + apc_error("pthread rwlock error: attr is not an initialized rwlock attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC);
11321 + } else if(result == EFAULT) {
11322 + apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC);
11323 + } else if(result == ENOTSUP) {
11324 + apc_error("pthread rwlock error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC);
11327 + if(pthread_rwlock_init(lock, &attr)) {
11328 + apc_error("unable to initialize pthread rwlock" TSRMLS_CC);
11331 + pthread_rwlockattr_destroy(&attr);
11336 +void apc_pthreadrwlock_destroy(pthread_rwlock_t *lock)
11338 + return; /* we don't actually destroy the rwlock, as it would destroy it for all processes */
11341 +void apc_pthreadrwlock_lock(pthread_rwlock_t *lock TSRMLS_DC)
11344 + result = pthread_rwlock_wrlock(lock);
11345 + if(result == EINVAL) {
11346 + apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC);
11347 + } else if(result == EDEADLK) {
11348 + apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC);
11352 +void apc_pthreadrwlock_rdlock(pthread_rwlock_t *lock TSRMLS_DC)
11355 + result = pthread_rwlock_rdlock(lock);
11356 + if(result == EINVAL) {
11357 + apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC);
11358 + } else if(result == EDEADLK) {
11359 + apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC);
11363 +void apc_pthreadrwlock_unlock(pthread_rwlock_t *lock TSRMLS_DC)
11365 + if(pthread_rwlock_unlock(lock)) {
11366 + apc_error("unable to unlock pthread lock" TSRMLS_CC);
11370 +zend_bool apc_pthreadrwlock_nonblocking_lock(pthread_rwlock_t *lock TSRMLS_DC)
11373 + rval = pthread_rwlock_trywrlock(lock);
11374 + if(rval == EBUSY) { /* Lock is already held */
11376 + } else if(rval == 0) { /* Obtained lock */
11378 + } else { /* Other error */
11379 + apc_error("unable to obtain pthread trylock" TSRMLS_CC);
11388 + * Local variables:
11390 + * c-basic-offset: 4
11392 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11393 + * vim<600: expandtab sw=4 ts=4 sts=4
11395 diff -Naur a/ext/apc/apc_pthreadrwlock.h b/ext/apc/apc_pthreadrwlock.h
11396 --- a/ext/apc/apc_pthreadrwlock.h 1970-01-01 01:00:00.000000000 +0100
11397 +++ b/ext/apc/apc_pthreadrwlock.h 2012-07-20 00:10:35.000000000 +0200
11400 + +----------------------------------------------------------------------+
11402 + +----------------------------------------------------------------------+
11403 + | Copyright (c) 2006-2011 The PHP Group |
11404 + +----------------------------------------------------------------------+
11405 + | This source file is subject to version 3.01 of the PHP license, |
11406 + | that is bundled with this package in the file LICENSE, and is |
11407 + | available through the world-wide-web at the following url: |
11408 + | http://www.php.net/license/3_01.txt |
11409 + | If you did not receive a copy of the PHP license and are unable to |
11410 + | obtain it through the world-wide-web, please send a note to |
11411 + | license@php.net so we can mail you a copy immediately. |
11412 + +----------------------------------------------------------------------+
11413 + | Authors: Gopal V <gopalv@php.net> |
11414 + +----------------------------------------------------------------------+
11418 +/* $Id: apc_pthreadrwlock.h 302175 2010-08-13 06:20:28Z kalle $ */
11420 +#ifndef APC_PTHREADRWLOCK_H
11421 +#define APC_PTHREADRWLOCK_H
11425 +#ifdef APC_PTHREADRW_LOCKS
11427 +#include <pthread.h>
11429 +pthread_rwlock_t *apc_pthreadrwlock_create(pthread_rwlock_t *lock TSRMLS_DC);
11430 +void apc_pthreadrwlock_destroy(pthread_rwlock_t *lock);
11431 +void apc_pthreadrwlock_lock(pthread_rwlock_t *lock TSRMLS_DC);
11432 +void apc_pthreadrwlock_rdlock(pthread_rwlock_t *lock TSRMLS_DC);
11433 +void apc_pthreadrwlock_unlock(pthread_rwlock_t *lock TSRMLS_DC);
11434 +zend_bool apc_pthreadrwlock_nonblocking_lock(pthread_rwlock_t *lock TSRMLS_DC);
11441 + * Local variables:
11443 + * c-basic-offset: 4
11445 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11446 + * vim<600: expandtab sw=4 ts=4 sts=4
11448 diff -Naur a/ext/apc/apc_rfc1867.c b/ext/apc/apc_rfc1867.c
11449 --- a/ext/apc/apc_rfc1867.c 1970-01-01 01:00:00.000000000 +0100
11450 +++ b/ext/apc/apc_rfc1867.c 2012-07-20 00:10:35.000000000 +0200
11453 + +----------------------------------------------------------------------+
11455 + +----------------------------------------------------------------------+
11456 + | Copyright (c) 2006-2011 The PHP Group |
11457 + +----------------------------------------------------------------------+
11458 + | This source file is subject to version 3.01 of the PHP license, |
11459 + | that is bundled with this package in the file LICENSE, and is |
11460 + | available through the world-wide-web at the following url: |
11461 + | http://www.php.net/license/3_01.txt |
11462 + | If you did not receive a copy of the PHP license and are unable to |
11463 + | obtain it through the world-wide-web, please send a note to |
11464 + | license@php.net so we can mail you a copy immediately. |
11465 + +----------------------------------------------------------------------+
11466 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
11467 + +----------------------------------------------------------------------+
11469 + This software was contributed to PHP by Community Connect Inc. in 2002
11470 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11471 + Future revisions and derivatives of this source code must acknowledge
11472 + Community Connect Inc. as the original contributor of this module by
11473 + leaving this note intact in the source code.
11475 + All other licensing and usage conditions are those of the PHP Group.
11479 +/* $Id: apc_rfc1867.c 309694 2011-03-25 18:47:38Z rasmus $*/
11482 +#include "apc_globals.h"
11483 +#include "rfc1867.h"
11486 +#include "win32/time.h"
11489 +#ifdef MULTIPART_EVENT_FORMDATA
11490 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC);
11491 +extern int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC);
11493 +static int update_bytes_processed(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
11494 + int *bytes_ptr = (int*)data;
11495 + zval* val = entry->data.user.val;
11497 + if(Z_TYPE_P(val) == IS_ARRAY) {
11498 + HashTable *ht = val->value.ht;
11499 + Bucket* curr = NULL;
11500 + for (curr = ht->pListHead; curr != NULL; curr = curr->pListNext) {
11501 + if(curr->nKeyLength == 8 &&
11502 + (!memcmp(curr->arKey, "current", curr->nKeyLength))) {
11503 + zval* current = ((zval**)curr->pData)[0];
11504 + current->value.lval = *bytes_ptr;
11513 +static double my_time() {
11514 + struct timeval a;
11516 + gettimeofday(&a, NULL);
11517 + t = a.tv_sec + (a.tv_usec/1000000.00);
11522 +#define RFC1867_DATA(name) \
11523 + ((request_data)->name)
11525 +int apc_rfc1867_progress(uint event, void *event_data, void **extra TSRMLS_DC) {
11526 + apc_rfc1867_data *request_data = &APCG(rfc1867_data);
11527 + zval *track = NULL;
11530 + case MULTIPART_EVENT_START:
11532 + multipart_event_start *data = (multipart_event_start *) event_data;
11534 + RFC1867_DATA(content_length) = data->content_length;
11535 + RFC1867_DATA(tracking_key)[0] = '\0';
11536 + RFC1867_DATA(name)[0] = '\0';
11537 + RFC1867_DATA(cancel_upload) = 0;
11538 + RFC1867_DATA(temp_filename) = NULL;
11539 + RFC1867_DATA(filename)[0] = '\0';
11540 + RFC1867_DATA(key_length) = 0;
11541 + RFC1867_DATA(start_time) = my_time();
11542 + RFC1867_DATA(bytes_processed) = 0;
11543 + RFC1867_DATA(prev_bytes_processed) = 0;
11544 + RFC1867_DATA(rate) = 0;
11545 + RFC1867_DATA(update_freq) = (int) APCG(rfc1867_freq);
11546 + RFC1867_DATA(started) = 0;
11548 + if(RFC1867_DATA(update_freq) < 0) { // frequency is a percentage, not bytes
11549 + RFC1867_DATA(update_freq) = (int) (RFC1867_DATA(content_length) * APCG(rfc1867_freq) / 100);
11554 + case MULTIPART_EVENT_FORMDATA:
11556 + int prefix_len = strlen(APCG(rfc1867_prefix));
11557 + multipart_event_formdata *data = (multipart_event_formdata *) event_data;
11558 + if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name)))
11559 + && data->value && data->length) {
11561 + if(data->length >= sizeof(RFC1867_DATA(tracking_key)) - prefix_len) {
11562 + apc_warning("Key too long for '%s'. Maximum size is '%d' characters." TSRMLS_CC,
11563 + APCG(rfc1867_name),
11564 + sizeof(RFC1867_DATA(tracking_key)) - prefix_len);
11568 + if(RFC1867_DATA(started)) {
11569 + apc_warning("Upload progress key '%s' should be before the file upload entry in the form." TSRMLS_CC,
11570 + APCG(rfc1867_name));
11574 + strlcat(RFC1867_DATA(tracking_key), APCG(rfc1867_prefix), 63);
11575 + strlcat(RFC1867_DATA(tracking_key), *data->value, 63);
11576 + RFC1867_DATA(key_length) = data->length + prefix_len;
11577 + RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
11582 + case MULTIPART_EVENT_FILE_START:
11584 + RFC1867_DATA(started) = 1;
11585 + if(*RFC1867_DATA(tracking_key)) {
11586 + multipart_event_file_start *data = (multipart_event_file_start *) event_data;
11588 + RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
11589 + strlcpy(RFC1867_DATA(filename),*data->filename,128);
11590 + RFC1867_DATA(temp_filename) = NULL;
11591 + strlcpy(RFC1867_DATA(name),data->name,64);
11592 + ALLOC_INIT_ZVAL(track);
11593 + array_init(track);
11594 + add_assoc_long(track, "total", RFC1867_DATA(content_length));
11595 + add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
11596 + add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
11597 + add_assoc_string(track, "name", RFC1867_DATA(name), 1);
11598 + add_assoc_long(track, "done", 0);
11599 + add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
11600 + _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
11601 + zval_ptr_dtor(&track);
11606 + case MULTIPART_EVENT_FILE_DATA:
11607 + if(*RFC1867_DATA(tracking_key)) {
11608 + multipart_event_file_data *data = (multipart_event_file_data *) event_data;
11609 + RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
11610 + if(RFC1867_DATA(bytes_processed) - RFC1867_DATA(prev_bytes_processed) > (uint) RFC1867_DATA(update_freq)) {
11611 + if(!_apc_update(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), update_bytes_processed, &RFC1867_DATA(bytes_processed) TSRMLS_CC)) {
11612 + ALLOC_INIT_ZVAL(track);
11613 + array_init(track);
11614 + add_assoc_long(track, "total", RFC1867_DATA(content_length));
11615 + add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
11616 + add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
11617 + add_assoc_string(track, "name", RFC1867_DATA(name), 1);
11618 + add_assoc_long(track, "done", 0);
11619 + add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
11620 + _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
11621 + zval_ptr_dtor(&track);
11623 + RFC1867_DATA(prev_bytes_processed) = RFC1867_DATA(bytes_processed);
11628 + case MULTIPART_EVENT_FILE_END:
11629 + if(*RFC1867_DATA(tracking_key)) {
11630 + multipart_event_file_end *data = (multipart_event_file_end *) event_data;
11631 + RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
11632 + RFC1867_DATA(cancel_upload) = data->cancel_upload;
11633 + if(data->temp_filename) {
11634 + RFC1867_DATA(temp_filename) = data->temp_filename;
11636 + RFC1867_DATA(temp_filename) = "";
11638 + ALLOC_INIT_ZVAL(track);
11639 + array_init(track);
11640 + add_assoc_long(track, "total", RFC1867_DATA(content_length));
11641 + add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
11642 + add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
11643 + add_assoc_string(track, "name", RFC1867_DATA(name), 1);
11644 + add_assoc_string(track, "temp_filename", RFC1867_DATA(temp_filename), 1);
11645 + add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
11646 + add_assoc_long(track, "done", 0);
11647 + add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
11648 + _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
11649 + zval_ptr_dtor(&track);
11653 + case MULTIPART_EVENT_END:
11654 + if(*RFC1867_DATA(tracking_key)) {
11655 + double now = my_time();
11656 + multipart_event_end *data = (multipart_event_end *) event_data;
11657 + RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
11658 + if(now>RFC1867_DATA(start_time)) RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed)/(now-RFC1867_DATA(start_time));
11659 + else RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed); /* Too quick */
11660 + ALLOC_INIT_ZVAL(track);
11661 + array_init(track);
11662 + add_assoc_long(track, "total", RFC1867_DATA(content_length));
11663 + add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
11664 + add_assoc_double(track, "rate", RFC1867_DATA(rate));
11665 + add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
11666 + add_assoc_string(track, "name", RFC1867_DATA(name), 1);
11667 + add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
11668 + add_assoc_long(track, "done", 1);
11669 + add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
11670 + _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
11671 + zval_ptr_dtor(&track);
11681 + * Local variables:
11683 + * c-basic-offset: 4
11685 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11686 + * vim<600: expandtab sw=4 ts=4 sts=4
11688 diff -Naur a/ext/apc/apc_sem.c b/ext/apc/apc_sem.c
11689 --- a/ext/apc/apc_sem.c 1970-01-01 01:00:00.000000000 +0100
11690 +++ b/ext/apc/apc_sem.c 2012-07-20 00:10:35.000000000 +0200
11693 + +----------------------------------------------------------------------+
11695 + +----------------------------------------------------------------------+
11696 + | Copyright (c) 2006-2011 The PHP Group |
11697 + +----------------------------------------------------------------------+
11698 + | This source file is subject to version 3.01 of the PHP license, |
11699 + | that is bundled with this package in the file LICENSE, and is |
11700 + | available through the world-wide-web at the following url: |
11701 + | http://www.php.net/license/3_01.txt |
11702 + | If you did not receive a copy of the PHP license and are unable to |
11703 + | obtain it through the world-wide-web, please send a note to |
11704 + | license@php.net so we can mail you a copy immediately. |
11705 + +----------------------------------------------------------------------+
11706 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
11707 + +----------------------------------------------------------------------+
11709 + This software was contributed to PHP by Community Connect Inc. in 2002
11710 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11711 + Future revisions and derivatives of this source code must acknowledge
11712 + Community Connect Inc. as the original contributor of this module by
11713 + leaving this note intact in the source code.
11715 + All other licensing and usage conditions are those of the PHP Group.
11719 +/* $Id: apc_sem.c 307048 2011-01-03 23:53:17Z kalle $ */
11723 +#ifdef APC_SEM_LOCKS
11725 +#include "apc_sem.h"
11727 +#include <sys/types.h>
11728 +#include <sys/ipc.h>
11729 +#include <sys/sem.h>
11730 +#include <sys/stat.h>
11731 +#include <unistd.h>
11734 +/* we have semun, no need to define */
11738 + int val; /* value for SETVAL */
11739 + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
11740 + unsigned short *array; /* array for GETALL, SETALL */
11741 + /* Linux specific part: */
11742 + struct seminfo *__buf; /* buffer for IPC_INFO */
11744 +#define HAVE_SEMUN 1
11748 +# define SEM_R 0444
11751 +# define SEM_A 0222
11754 +/* always use SEM_UNDO, otherwise we risk deadlock */
11755 +#define USE_SEM_UNDO
11757 +#ifdef USE_SEM_UNDO
11758 +# define UNDO SEM_UNDO
11763 +int apc_sem_create(int proj, int initval TSRMLS_DC)
11766 + int perms = 0777;
11768 + key_t key = IPC_PRIVATE;
11770 + if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
11771 + /* sempahore created for the first time, initialize now */
11772 + arg.val = initval;
11773 + if (semctl(semid, 0, SETVAL, arg) < 0) {
11774 + apc_error("apc_sem_create: semctl(%d,...) failed:" TSRMLS_CC, semid);
11777 + else if (errno == EEXIST) {
11778 + /* sempahore already exists, don't initialize */
11779 + if ((semid = semget(key, 1, perms)) < 0) {
11780 + apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key);
11782 + /* insert <sleazy way to avoid race condition> here */
11785 + apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key);
11791 +void apc_sem_destroy(int semid)
11793 + /* we expect this call to fail often, so we do not check */
11795 + semctl(semid, 0, IPC_RMID, arg);
11798 +void apc_sem_lock(int semid TSRMLS_DC)
11800 + struct sembuf op;
11804 + op.sem_flg = UNDO;
11806 + if (semop(semid, &op, 1) < 0) {
11807 + if (errno != EINTR) {
11808 + apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid);
11813 +int apc_sem_nonblocking_lock(int semid TSRMLS_DC)
11815 + struct sembuf op;
11819 + op.sem_flg = UNDO | IPC_NOWAIT;
11821 + if (semop(semid, &op, 1) < 0) {
11822 + if (errno == EAGAIN) {
11823 + return 0; /* Lock is already held */
11824 + } else if (errno != EINTR) {
11825 + apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid);
11829 + return 1; /* Lock obtained */
11832 +void apc_sem_unlock(int semid TSRMLS_DC)
11834 + struct sembuf op;
11838 + op.sem_flg = UNDO;
11840 + if (semop(semid, &op, 1) < 0) {
11841 + if (errno != EINTR) {
11842 + apc_error("apc_sem_unlock: semop(%d) failed:" TSRMLS_CC, semid);
11847 +void apc_sem_wait_for_zero(int semid TSRMLS_DC)
11849 + struct sembuf op;
11853 + op.sem_flg = UNDO;
11855 + if (semop(semid, &op, 1) < 0) {
11856 + if (errno != EINTR) {
11857 + apc_error("apc_sem_waitforzero: semop(%d) failed:" TSRMLS_CC, semid);
11862 +int apc_sem_get_value(int semid TSRMLS_DC)
11865 + unsigned short val[1];
11868 + if (semctl(semid, 0, GETALL, arg) < 0) {
11869 + apc_error("apc_sem_getvalue: semctl(%d,...) failed:" TSRMLS_CC, semid);
11874 +#endif /* APC_SEM_LOCKS */
11877 + * Local variables:
11879 + * c-basic-offset: 4
11881 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11882 + * vim<600: expandtab sw=4 ts=4 sts=4
11884 diff -Naur a/ext/apc/apc_sem.h b/ext/apc/apc_sem.h
11885 --- a/ext/apc/apc_sem.h 1970-01-01 01:00:00.000000000 +0100
11886 +++ b/ext/apc/apc_sem.h 2012-07-20 00:10:35.000000000 +0200
11889 + +----------------------------------------------------------------------+
11891 + +----------------------------------------------------------------------+
11892 + | Copyright (c) 2006-2011 The PHP Group |
11893 + +----------------------------------------------------------------------+
11894 + | This source file is subject to version 3.01 of the PHP license, |
11895 + | that is bundled with this package in the file LICENSE, and is |
11896 + | available through the world-wide-web at the following url: |
11897 + | http://www.php.net/license/3_01.txt |
11898 + | If you did not receive a copy of the PHP license and are unable to |
11899 + | obtain it through the world-wide-web, please send a note to |
11900 + | license@php.net so we can mail you a copy immediately. |
11901 + +----------------------------------------------------------------------+
11902 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
11903 + +----------------------------------------------------------------------+
11905 + This software was contributed to PHP by Community Connect Inc. in 2002
11906 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11907 + Future revisions and derivatives of this source code must acknowledge
11908 + Community Connect Inc. as the original contributor of this module by
11909 + leaving this note intact in the source code.
11911 + All other licensing and usage conditions are those of the PHP Group.
11915 +/* $Id: apc_sem.h 307048 2011-01-03 23:53:17Z kalle $ */
11920 +/* Wrapper functions for SysV sempahores */
11922 +extern int apc_sem_create(int proj, int initval TSRMLS_DC);
11923 +extern void apc_sem_destroy(int semid);
11924 +extern void apc_sem_lock(int semid TSRMLS_DC);
11925 +extern int apc_sem_nonblocking_lock(int semid TSRMLS_DC);
11926 +extern void apc_sem_unlock(int semid TSRMLS_DC);
11927 +extern void apc_sem_wait_for_zero(int semid TSRMLS_DC);
11928 +extern int apc_sem_get_value(int semid TSRMLS_DC);
11933 + * Local variables:
11935 + * c-basic-offset: 4
11937 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11938 + * vim<600: expandtab sw=4 ts=4 sts=4
11940 diff -Naur a/ext/apc/apc_serializer.h b/ext/apc/apc_serializer.h
11941 --- a/ext/apc/apc_serializer.h 1970-01-01 01:00:00.000000000 +0100
11942 +++ b/ext/apc/apc_serializer.h 2012-07-20 00:10:35.000000000 +0200
11945 + +----------------------------------------------------------------------+
11947 + +----------------------------------------------------------------------+
11948 + | Copyright (c) 2006-2011 The PHP Group |
11949 + +----------------------------------------------------------------------+
11950 + | This source file is subject to version 3.01 of the PHP license, |
11951 + | that is bundled with this package in the file LICENSE, and is |
11952 + | available through the world-wide-web at the following url: |
11953 + | http://www.php.net/license/3_01.txt. |
11954 + | If you did not receive a copy of the PHP license and are unable to |
11955 + | obtain it through the world-wide-web, please send a note to |
11956 + | license@php.net so we can mail you a copy immediately. |
11957 + +----------------------------------------------------------------------+
11958 + | Authors: Gopal Vijayaraghavan <gopalv@php.net> |
11959 + +----------------------------------------------------------------------+
11965 +#ifndef APC_SERIALIZER_H
11966 +#define APC_SERIALIZER_H
11968 +/* this is a shipped .h file, do not include any other header in this file */
11969 +#define APC_SERIALIZER_NAME(module) module##_apc_serializer
11970 +#define APC_UNSERIALIZER_NAME(module) module##_apc_unserializer
11972 +#define APC_SERIALIZER_ARGS unsigned char **buf, size_t *buf_len, const zval *value, void *config TSRMLS_DC
11973 +#define APC_UNSERIALIZER_ARGS zval **value, unsigned char *buf, size_t buf_len, void *config TSRMLS_DC
11975 +typedef int (*apc_serialize_t)(APC_SERIALIZER_ARGS);
11976 +typedef int (*apc_unserialize_t)(APC_UNSERIALIZER_ARGS);
11978 +typedef int (*apc_register_serializer_t)(const char* name,
11979 + apc_serialize_t serialize,
11980 + apc_unserialize_t unserialize,
11981 + void *config TSRMLS_DC);
11984 + * ABI version for constant hooks. Increment this any time you make any changes
11985 + * to any function in this file.
11987 +#define APC_SERIALIZER_ABI "0"
11988 +#define APC_SERIALIZER_CONSTANT "\000apc_register_serializer-" APC_SERIALIZER_ABI
11990 +#if !defined(APC_UNUSED)
11991 +# if defined(__GNUC__)
11992 +# define APC_UNUSED __attribute__((unused))
11994 +# define APC_UNUSED
11998 +static APC_UNUSED int apc_register_serializer(const char* name,
11999 + apc_serialize_t serialize,
12000 + apc_unserialize_t unserialize,
12001 + void *config TSRMLS_DC)
12003 + zval apc_magic_constant;
12006 + /* zend_get_constant will return 1 on success, otherwise apc_magic_constant wouldn't be touched at all */
12007 + if (zend_get_constant(APC_SERIALIZER_CONSTANT, sizeof(APC_SERIALIZER_CONSTANT)-1, &apc_magic_constant TSRMLS_CC)) {
12008 + apc_register_serializer_t register_func = (apc_register_serializer_t)(Z_LVAL(apc_magic_constant));
12009 + if(register_func) {
12010 + retval = register_func(name, serialize, unserialize, NULL TSRMLS_CC);
12012 + zval_dtor(&apc_magic_constant);
12021 + * Local variables:
12023 + * c-basic-offset: 4
12025 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12026 + * vim<600: expandtab sw=4 ts=4 sts=4
12028 diff -Naur a/ext/apc/apc_shm.c b/ext/apc/apc_shm.c
12029 --- a/ext/apc/apc_shm.c 1970-01-01 01:00:00.000000000 +0100
12030 +++ b/ext/apc/apc_shm.c 2012-07-20 00:10:35.000000000 +0200
12033 + +----------------------------------------------------------------------+
12035 + +----------------------------------------------------------------------+
12036 + | Copyright (c) 2006-2011 The PHP Group |
12037 + +----------------------------------------------------------------------+
12038 + | This source file is subject to version 3.01 of the PHP license, |
12039 + | that is bundled with this package in the file LICENSE, and is |
12040 + | available through the world-wide-web at the following url: |
12041 + | http://www.php.net/license/3_01.txt |
12042 + | If you did not receive a copy of the PHP license and are unable to |
12043 + | obtain it through the world-wide-web, please send a note to |
12044 + | license@php.net so we can mail you a copy immediately. |
12045 + +----------------------------------------------------------------------+
12046 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
12047 + | Rasmus Lerdorf <rasmus@php.net> |
12048 + +----------------------------------------------------------------------+
12050 + This software was contributed to PHP by Community Connect Inc. in 2002
12051 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12052 + Future revisions and derivatives of this source code must acknowledge
12053 + Community Connect Inc. as the original contributor of this module by
12054 + leaving this note intact in the source code.
12056 + All other licensing and usage conditions are those of the PHP Group.
12060 +/* $Id: apc_shm.c 307259 2011-01-08 12:05:24Z gopalv $ */
12062 +#include "apc_shm.h"
12065 +/* shm functions are available in TSRM */
12066 +#include <tsrm/tsrm_win32.h>
12067 +#define key_t long
12069 +#include <sys/ipc.h>
12070 +#include <sys/shm.h>
12071 +#include <sys/stat.h>
12075 +# define SHM_R 0444 /* read permission */
12078 +# define SHM_A 0222 /* write permission */
12081 +int apc_shm_create(int proj, size_t size TSRMLS_DC)
12083 + int shmid; /* shared memory id */
12084 + int oflag; /* permissions on shm */
12085 + key_t key = IPC_PRIVATE; /* shm key */
12087 + oflag = IPC_CREAT | SHM_R | SHM_A;
12088 + if ((shmid = shmget(key, size, oflag)) < 0) {
12089 + 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));
12095 +void apc_shm_destroy(int shmid)
12097 + /* we expect this call to fail often, so we do not check */
12098 + shmctl(shmid, IPC_RMID, 0);
12101 +apc_segment_t apc_shm_attach(int shmid, size_t size TSRMLS_DC)
12103 + apc_segment_t segment; /* shm segment */
12105 + if ((long)(segment.shmaddr = shmat(shmid, 0, 0)) == -1) {
12106 + apc_error("apc_shm_attach: shmat failed:" TSRMLS_CC);
12109 +#ifdef APC_MEMPROTECT
12111 + if ((long)(segment.roaddr = shmat(shmid, 0, SHM_RDONLY)) == -1) {
12112 + segment.roaddr = NULL;
12117 + segment.size = size;
12120 + * We set the shmid for removal immediately after attaching to it. The
12121 + * segment won't disappear until all processes have detached from it.
12123 + apc_shm_destroy(shmid);
12127 +void apc_shm_detach(apc_segment_t* segment TSRMLS_DC)
12129 + if (shmdt(segment->shmaddr) < 0) {
12130 + apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
12133 +#ifdef APC_MEMPROTECT
12134 + if (segment->roaddr && shmdt(segment->roaddr) < 0) {
12135 + apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
12141 + * Local variables:
12143 + * c-basic-offset: 4
12145 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12146 + * vim<600: expandtab sw=4 ts=4 sts=4
12148 diff -Naur a/ext/apc/apc_shm.h b/ext/apc/apc_shm.h
12149 --- a/ext/apc/apc_shm.h 1970-01-01 01:00:00.000000000 +0100
12150 +++ b/ext/apc/apc_shm.h 2012-07-20 00:10:35.000000000 +0200
12153 + +----------------------------------------------------------------------+
12155 + +----------------------------------------------------------------------+
12156 + | Copyright (c) 2006-2011 The PHP Group |
12157 + +----------------------------------------------------------------------+
12158 + | This source file is subject to version 3.01 of the PHP license, |
12159 + | that is bundled with this package in the file LICENSE, and is |
12160 + | available through the world-wide-web at the following url: |
12161 + | http://www.php.net/license/3_01.txt |
12162 + | If you did not receive a copy of the PHP license and are unable to |
12163 + | obtain it through the world-wide-web, please send a note to |
12164 + | license@php.net so we can mail you a copy immediately. |
12165 + +----------------------------------------------------------------------+
12166 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
12167 + +----------------------------------------------------------------------+
12169 + This software was contributed to PHP by Community Connect Inc. in 2002
12170 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12171 + Future revisions and derivatives of this source code must acknowledge
12172 + Community Connect Inc. as the original contributor of this module by
12173 + leaving this note intact in the source code.
12175 + All other licensing and usage conditions are those of the PHP Group.
12179 +/* $Id: apc_shm.h 307259 2011-01-08 12:05:24Z gopalv $ */
12184 +#include <sys/types.h>
12189 +#include "apc_sma.h"
12191 +/* Wrapper functions for unix shared memory */
12193 +extern int apc_shm_create(int proj, size_t size TSRMLS_DC);
12194 +extern void apc_shm_destroy(int shmid);
12195 +extern apc_segment_t apc_shm_attach(int shmid, size_t size TSRMLS_DC);
12196 +extern void apc_shm_detach(apc_segment_t* segment TSRMLS_DC);
12201 + * Local variables:
12203 + * c-basic-offset: 4
12205 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12206 + * vim<600: expandtab sw=4 ts=4 sts=4
12208 diff -Naur a/ext/apc/apc_signal.c b/ext/apc/apc_signal.c
12209 --- a/ext/apc/apc_signal.c 1970-01-01 01:00:00.000000000 +0100
12210 +++ b/ext/apc/apc_signal.c 2012-07-20 00:10:35.000000000 +0200
12213 + +----------------------------------------------------------------------+
12215 + +----------------------------------------------------------------------+
12216 + | Copyright (c) 2006-2011 The PHP Group |
12217 + +----------------------------------------------------------------------+
12218 + | This source file is subject to version 3.01 of the PHP license, |
12219 + | that is bundled with this package in the file LICENSE, and is |
12220 + | available through the world-wide-web at the following url: |
12221 + | http://www.php.net/license/3_01.txt |
12222 + | If you did not receive a copy of the PHP license and are unable to |
12223 + | obtain it through the world-wide-web, please send a note to |
12224 + | license@php.net so we can mail you a copy immediately. |
12225 + +----------------------------------------------------------------------+
12226 + | Authors: Lucas Nealan <lucas@php.net> |
12227 + +----------------------------------------------------------------------+
12229 + This software was contributed to PHP by Facebook Inc. in 2007.
12231 + Future revisions and derivatives of this source code must acknowledge
12232 + Facebook Inc. as the original contributor of this module by leaving
12233 + this note intact in the source code.
12235 + All other licensing and usage conditions are those of the PHP Group.
12238 + /* $Id: apc_signal.c 307048 2011-01-03 23:53:17Z kalle $ */
12240 + /* Allows apc to install signal handlers and maintain signalling
12241 + to already registered handlers. Registers all signals that
12242 + coredump by default and unmaps the shared memory segment
12243 + before the coredump. Note: PHP module init is called before
12244 + signals are set by Apache and thus apc_set_signals should
12245 + be called in request init (RINIT)
12250 +#if HAVE_SIGACTION
12251 +#include <signal.h>
12252 +#include "apc_globals.h"
12253 +#include "apc_sma.h"
12254 +#include "apc_signal.h"
12256 +static apc_signal_info_t apc_signal_info = {0};
12258 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC);
12259 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
12260 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
12262 +/* {{{ apc_core_unmap
12263 + * Coredump signal handler, unmaps shm and calls previously installed handlers
12265 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context)
12269 + apc_sma_cleanup(TSRMLS_C);
12270 + apc_rehandle_signal(signo, siginfo, context);
12272 +#if !defined(WIN32) && !defined(NETWARE)
12273 + kill(getpid(), signo);
12279 +/* {{{ apc_rehandle_signal
12280 + * Call the previously registered handler for a signal
12282 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
12285 + apc_signal_entry_t p_sig = {0};
12287 + for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) {
12288 + p_sig = *apc_signal_info.prev[i];
12289 + if (p_sig.signo == signo) {
12290 + if (p_sig.siginfo) {
12291 + (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
12293 + (*(void (*)(int))p_sig.handler)(signo);
12300 +/* {{{ apc_register_signal
12301 + * Set a handler for a previously installed signal and save so we can
12302 + * callback when handled
12304 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC)
12306 + struct sigaction sa = {{0}};
12307 + apc_signal_entry_t p_sig = {0};
12309 + if (sigaction(signo, NULL, &sa) == 0) {
12310 + if ((void*)sa.sa_handler == (void*)handler) {
12314 + if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
12315 + p_sig.signo = signo;
12316 + p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
12317 + p_sig.handler = (void *)sa.sa_handler;
12319 + 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);
12320 + apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t) TSRMLS_CC);
12321 + *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
12323 + /* inherit flags and mask if already set */
12324 + sigemptyset(&sa.sa_mask);
12326 + sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
12327 +#if defined(SA_ONESHOT)
12328 + sa.sa_flags = SA_ONESHOT;
12329 +#elif defined(SA_RESETHAND)
12330 + sa.sa_flags = SA_RESETHAND;
12333 + sa.sa_handler = (void*)handler;
12335 + if (sigaction(signo, &sa, NULL) < 0) {
12336 + apc_warning("Error installing apc signal handler for %d" TSRMLS_CC, signo);
12344 +/* {{{ apc_set_signals
12345 + * Install our signal handlers */
12346 +void apc_set_signals(TSRMLS_D)
12348 + if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
12349 + /* ISO C standard signals that coredump */
12350 + apc_register_signal(SIGSEGV, apc_core_unmap TSRMLS_CC);
12351 + apc_register_signal(SIGABRT, apc_core_unmap TSRMLS_CC);
12352 + apc_register_signal(SIGFPE, apc_core_unmap TSRMLS_CC);
12353 + apc_register_signal(SIGILL, apc_core_unmap TSRMLS_CC);
12354 + /* extended signals that coredump */
12356 + apc_register_signal(SIGBUS, apc_core_unmap TSRMLS_CC);
12359 + apc_register_signal(SIGABORT, apc_core_unmap TSRMLS_CC);
12362 + apc_register_signal(SIGEMT, apc_core_unmap TSRMLS_CC);
12365 + apc_register_signal(SIGIOT, apc_core_unmap TSRMLS_CC);
12368 + apc_register_signal(SIGQUIT, apc_core_unmap TSRMLS_CC);
12371 + apc_register_signal(SIGSYS, apc_core_unmap TSRMLS_CC);
12374 + apc_register_signal(SIGTRAP, apc_core_unmap TSRMLS_CC);
12377 + apc_register_signal(SIGXCPU, apc_core_unmap TSRMLS_CC);
12380 + apc_register_signal(SIGXFSZ, apc_core_unmap TSRMLS_CC);
12385 +/* {{{ apc_set_signals
12386 + * cleanup signals for shutdown */
12387 +void apc_shutdown_signals(TSRMLS_D)
12390 + if (apc_signal_info.installed > 0) {
12391 + for (i=0; (i < apc_signal_info.installed); i++) {
12392 + apc_efree(apc_signal_info.prev[i] TSRMLS_CC);
12394 + apc_efree(apc_signal_info.prev TSRMLS_CC);
12395 + apc_signal_info.installed = 0; /* just in case */
12399 +#endif /* HAVE_SIGACTION */
12402 + * Local variables:
12404 + * c-basic-offset: 4
12406 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12407 + * vim<600: expandtab sw=4 ts=4 sts=4
12409 diff -Naur a/ext/apc/apc_signal.h b/ext/apc/apc_signal.h
12410 --- a/ext/apc/apc_signal.h 1970-01-01 01:00:00.000000000 +0100
12411 +++ b/ext/apc/apc_signal.h 2012-07-20 00:10:35.000000000 +0200
12414 + +----------------------------------------------------------------------+
12416 + +----------------------------------------------------------------------+
12417 + | Copyright (c) 2006-2011 The PHP Group |
12418 + +----------------------------------------------------------------------+
12419 + | This source file is subject to version 3.01 of the PHP license, |
12420 + | that is bundled with this package in the file LICENSE, and is |
12421 + | available through the world-wide-web at the following url: |
12422 + | http://www.php.net/license/3_01.txt |
12423 + | If you did not receive a copy of the PHP license and are unable to |
12424 + | obtain it through the world-wide-web, please send a note to |
12425 + | license@php.net so we can mail you a copy immediately. |
12426 + +----------------------------------------------------------------------+
12427 + | Authors: Lucas Nealan <lucas@php.net> |
12428 + +----------------------------------------------------------------------+
12432 +/* $Id: apc_signal.h 307048 2011-01-03 23:53:17Z kalle $ */
12434 +#ifndef APC_SIGNAL_H
12435 +#define APC_SIGNAL_H
12438 +#include "apc_php.h"
12440 +typedef struct apc_signal_entry_t {
12441 + int signo; /* signal number */
12442 + int siginfo; /* siginfo style handler calling */
12443 + void* handler; /* signal handler */
12444 +} apc_signal_entry_t;
12446 +typedef struct apc_signal_info_t {
12447 + int installed; /* How many signals we've installed handles for */
12448 + apc_signal_entry_t **prev; /* Previous signal handlers */
12449 +} apc_signal_info_t;
12451 +void apc_set_signals(TSRMLS_D);
12452 +void apc_shutdown_signals(TSRMLS_D);
12457 + * Local variables:
12459 + * c-basic-offset: 4
12461 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12462 + * vim<600: expandtab sw=4 ts=4 sts=4
12464 diff -Naur a/ext/apc/apc_sma.c b/ext/apc/apc_sma.c
12465 --- a/ext/apc/apc_sma.c 1970-01-01 01:00:00.000000000 +0100
12466 +++ b/ext/apc/apc_sma.c 2012-07-20 00:10:35.000000000 +0200
12469 + +----------------------------------------------------------------------+
12471 + +----------------------------------------------------------------------+
12472 + | Copyright (c) 2006-2011 The PHP Group |
12473 + +----------------------------------------------------------------------+
12474 + | This source file is subject to version 3.01 of the PHP license, |
12475 + | that is bundled with this package in the file LICENSE, and is |
12476 + | available through the world-wide-web at the following url: |
12477 + | http://www.php.net/license/3_01.txt |
12478 + | If you did not receive a copy of the PHP license and are unable to |
12479 + | obtain it through the world-wide-web, please send a note to |
12480 + | license@php.net so we can mail you a copy immediately. |
12481 + +----------------------------------------------------------------------+
12482 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
12483 + | Rasmus Lerdorf <rasmus@php.net> |
12484 + +----------------------------------------------------------------------+
12486 + This software was contributed to PHP by Community Connect Inc. in 2002
12487 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12488 + Future revisions and derivatives of this source code must acknowledge
12489 + Community Connect Inc. as the original contributor of this module by
12490 + leaving this note intact in the source code.
12492 + All other licensing and usage conditions are those of the PHP Group.
12496 +/* $Id: apc_sma.c 309489 2011-03-21 00:00:54Z pajoye $ */
12498 +#include "apc_sma.h"
12500 +#include "apc_globals.h"
12501 +#include "apc_lock.h"
12502 +#include "apc_shm.h"
12503 +#include "apc_cache.h"
12505 +#include <limits.h>
12506 +#include "apc_mmap.h"
12508 +#ifdef HAVE_VALGRIND_MEMCHECK_H
12509 +#include <valgrind/memcheck.h>
12512 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
12514 +static int sma_initialized = 0; /* true if the sma has been initialized */
12515 +static uint sma_numseg; /* number of shm segments to allow */
12516 +static size_t sma_segsize; /* size of each shm segment */
12517 +static apc_segment_t* sma_segments; /* array of shm segments */
12518 +static int sma_lastseg = 0; /* index of MRU segment */
12520 +typedef struct sma_header_t sma_header_t;
12521 +struct sma_header_t {
12522 + apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */
12523 + size_t segsize; /* size of entire segment */
12524 + size_t avail; /* bytes available (not necessarily contiguous) */
12525 +#if ALLOC_DISTRIBUTION
12526 + size_t adist[30];
12530 +#define SMA_HDR(i) ((sma_header_t*)((sma_segments[i]).shmaddr))
12531 +#define SMA_ADDR(i) ((char*)(SMA_HDR(i)))
12532 +#define SMA_RO(i) ((char*)(sma_segments[i]).roaddr)
12533 +#define SMA_LCK(i) ((SMA_HDR(i))->sma_lock)
12536 +/* do not enable for threaded http servers */
12537 +/* #define __APC_SMA_DEBUG__ 1 */
12539 +#ifdef __APC_SMA_DEBUG__
12540 +/* global counter for identifying blocks
12541 + * Technically it is possible to do the same
12542 + * using offsets, but double allocations of the
12543 + * same offset can happen. */
12544 +static volatile size_t block_id = 0;
12547 +#define APC_SMA_CANARIES 1
12549 +typedef struct block_t block_t;
12551 + size_t size; /* size of this block */
12552 + size_t prev_size; /* size of sequentially previous block, 0 if prev is allocated */
12553 + size_t fnext; /* offset in segment of next free block */
12554 + size_t fprev; /* offset in segment of prev free block */
12555 +#ifdef APC_SMA_CANARIES
12556 + size_t canary; /* canary to check for memory overwrites */
12558 +#ifdef __APC_SMA_DEBUG__
12559 + size_t id; /* identifier for the memory block */
12563 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
12564 + * module. Both assume the presence of a variable shmaddr that points to the
12565 + * beginning of the shared memory segment in question. */
12567 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
12568 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
12570 +/* macros for getting the next or previous sequential block */
12571 +#define NEXT_SBLOCK(block) ((block_t*)((char*)block + block->size))
12572 +#define PREV_SBLOCK(block) (block->prev_size ? ((block_t*)((char*)block - block->prev_size)) : NULL)
12574 +/* Canary macros for setting, checking and resetting memory canaries */
12575 +#ifdef APC_SMA_CANARIES
12576 + #define SET_CANARY(v) (v)->canary = 0x42424242
12577 + #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
12578 + #define RESET_CANARY(v) (v)->canary = -42
12580 + #define SET_CANARY(v)
12581 + #define CHECK_CANARY(v)
12582 + #define RESET_CANARY(v)
12586 +/* {{{ MINBLOCKSIZE */
12587 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
12591 +/* {{{ sma_debug_state(apc_sma_segment_t *segment, int canary_check, int verbose)
12592 + * useful for debuging state of memory blocks and free list, and sanity checking
12594 +static void sma_debug_state(void* shmaddr, int canary_check, int verbose TSRMLS_DC) {
12595 + sma_header_t *header = (sma_header_t*)shmaddr;
12596 + block_t *cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12597 + block_t *prv = NULL;
12600 + /* Verify free list */
12601 + if (verbose) apc_warning("Free List: " TSRMLS_CC);
12603 + if (verbose) apc_warning(" 0x%x[%d] (s%d)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
12604 + if (canary_check) CHECK_CANARY(cur);
12605 + if (!cur->fnext) break;
12606 + cur = BLOCKAT(cur->fnext);
12607 + avail += cur->size;
12608 + if (prv == cur) {
12609 + apc_warning("Circular list detected!" TSRMLS_CC);
12612 + if (prv && cur->fprev != OFFSET(prv)) {
12613 + apc_warning("Previous pointer does not point to previous!" TSRMLS_CC);
12618 + assert(avail == header->avail);
12620 + /* Verify each block */
12621 + if (verbose) apc_warning("Block List: " TSRMLS_CC);
12622 + cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12624 + if(!cur->fnext) {
12625 + if (verbose) apc_warning(" 0x%x[%d] (s%d) (u)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
12627 + if (verbose) apc_warning(" 0x%x[%d] (s%d) (f)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
12629 + if (canary_check) CHECK_CANARY(cur);
12630 + if (!cur->size && !cur->fnext) break;
12631 + if (!cur->size) {
12632 + cur = BLOCKAT(OFFSET(cur) + ALIGNWORD(sizeof(block_t)));
12634 + cur = NEXT_SBLOCK(cur);
12636 + if (prv == cur) {
12637 + apc_warning("Circular list detected!" TSRMLS_CC);
12646 +/* {{{ sma_allocate: tries to allocate at least size bytes in a segment */
12647 +static APC_HOTSPOT size_t sma_allocate(sma_header_t* header, size_t size, size_t fragment, size_t *allocated)
12649 + void* shmaddr; /* header of shared memory segment */
12650 + block_t* prv; /* block prior to working block */
12651 + block_t* cur; /* working block in list */
12652 + block_t* prvnextfit; /* block before next fit */
12653 + size_t realsize; /* actual size of block needed, including header */
12654 + const size_t block_size = ALIGNWORD(sizeof(struct block_t));
12656 + realsize = ALIGNWORD(size + block_size);
12659 + * First, insure that the segment contains at least realsize free bytes,
12660 + * even if they are not contiguous.
12662 + shmaddr = header;
12664 + if (header->avail < realsize) {
12668 + prvnextfit = 0; /* initially null (no fit) */
12669 + prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12670 + CHECK_CANARY(prv);
12672 + while (prv->fnext != 0) {
12673 + cur = BLOCKAT(prv->fnext);
12674 +#ifdef __APC_SMA_DEBUG__
12675 + CHECK_CANARY(cur);
12677 + /* If it can fit realsize bytes in cur block, stop searching */
12678 + if (cur->size >= realsize) {
12679 + prvnextfit = prv;
12685 + if (prvnextfit == 0) {
12689 + prv = prvnextfit;
12690 + cur = BLOCKAT(prv->fnext);
12692 + CHECK_CANARY(prv);
12693 + CHECK_CANARY(cur);
12695 + if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE + fragment)))) {
12696 + /* cur is big enough for realsize, but too small to split - unlink it */
12697 + *(allocated) = cur->size - block_size;
12698 + prv->fnext = cur->fnext;
12699 + BLOCKAT(cur->fnext)->fprev = OFFSET(prv);
12700 + NEXT_SBLOCK(cur)->prev_size = 0; /* block is alloc'd */
12702 + /* nextfit is too big; split it into two smaller blocks */
12703 + block_t* nxt; /* the new block (chopped part of cur) */
12704 + size_t oldsize; /* size of cur before split */
12706 + oldsize = cur->size;
12707 + cur->size = realsize;
12708 + *(allocated) = cur->size - block_size;
12709 + nxt = NEXT_SBLOCK(cur);
12710 + nxt->prev_size = 0; /* block is alloc'd */
12711 + nxt->size = oldsize - realsize; /* and fix the size */
12712 + NEXT_SBLOCK(nxt)->prev_size = nxt->size; /* adjust size */
12715 + /* replace cur with next in free list */
12716 + nxt->fnext = cur->fnext;
12717 + nxt->fprev = cur->fprev;
12718 + BLOCKAT(nxt->fnext)->fprev = OFFSET(nxt);
12719 + BLOCKAT(nxt->fprev)->fnext = OFFSET(nxt);
12720 +#ifdef __APC_SMA_DEBUG__
12727 + /* update the block header */
12728 + header->avail -= cur->size;
12729 +#if ALLOC_DISTRIBUTION
12730 + header->adist[(int)(log(size)/log(2))]++;
12734 +#ifdef __APC_SMA_DEBUG__
12735 + cur->id = ++block_id;
12736 + fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
12739 + return OFFSET(cur) + block_size;
12743 +/* {{{ sma_deallocate: deallocates the block at the given offset */
12744 +static APC_HOTSPOT size_t sma_deallocate(void* shmaddr, size_t offset)
12746 + sma_header_t* header; /* header of shared memory segment */
12747 + block_t* cur; /* the new block to insert */
12748 + block_t* prv; /* the block before cur */
12749 + block_t* nxt; /* the block after cur */
12750 + size_t size; /* size of deallocated block */
12752 + offset -= ALIGNWORD(sizeof(struct block_t));
12753 + assert(offset >= 0);
12755 + /* find position of new block in free list */
12756 + cur = BLOCKAT(offset);
12758 + /* update the block header */
12759 + header = (sma_header_t*) shmaddr;
12760 + header->avail += cur->size;
12761 + size = cur->size;
12763 + if (cur->prev_size != 0) {
12764 + /* remove prv from list */
12765 + prv = PREV_SBLOCK(cur);
12766 + BLOCKAT(prv->fnext)->fprev = prv->fprev;
12767 + BLOCKAT(prv->fprev)->fnext = prv->fnext;
12768 + /* cur and prv share an edge, combine them */
12769 + prv->size +=cur->size;
12770 + RESET_CANARY(cur);
12774 + nxt = NEXT_SBLOCK(cur);
12775 + if (nxt->fnext != 0) {
12776 + assert(NEXT_SBLOCK(NEXT_SBLOCK(cur))->prev_size == nxt->size);
12777 + /* cur and nxt shared an edge, combine them */
12778 + BLOCKAT(nxt->fnext)->fprev = nxt->fprev;
12779 + BLOCKAT(nxt->fprev)->fnext = nxt->fnext;
12780 + cur->size += nxt->size;
12781 +#ifdef __APC_SMA_DEBUG__
12782 + CHECK_CANARY(nxt);
12783 + nxt->id = -1; /* assert this or set it ? */
12785 + RESET_CANARY(nxt);
12788 + NEXT_SBLOCK(cur)->prev_size = cur->size;
12790 + /* insert new block after prv */
12791 + prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12792 + cur->fnext = prv->fnext;
12793 + prv->fnext = OFFSET(cur);
12794 + cur->fprev = OFFSET(prv);
12795 + BLOCKAT(cur->fnext)->fprev = OFFSET(cur);
12801 +/* {{{ apc_sma_init */
12803 +void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC)
12807 + if (sma_initialized) {
12810 + sma_initialized = 1;
12814 + * I don't think multiple anonymous mmaps makes any sense
12815 + * so force sma_numseg to 1 in this case
12817 + if(!mmap_file_mask ||
12818 + (mmap_file_mask && !strlen(mmap_file_mask)) ||
12819 + (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
12822 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
12825 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
12828 + sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
12830 + sma_segments = (apc_segment_t*) apc_emalloc((sma_numseg * sizeof(apc_segment_t)) TSRMLS_CC);
12832 + for (i = 0; i < sma_numseg; i++) {
12833 + sma_header_t* header;
12834 + block_t *first, *empty, *last;
12838 + sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize TSRMLS_CC);
12839 + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
12841 + sma_segments[i] = apc_shm_attach(apc_shm_create(i, sma_segsize TSRMLS_CC), sma_segsize TSRMLS_CC);
12844 + sma_segments[i].size = sma_segsize;
12846 + shmaddr = sma_segments[i].shmaddr;
12848 + header = (sma_header_t*) shmaddr;
12849 + apc_lck_create(NULL, 0, 1, header->sma_lock);
12850 + header->segsize = sma_segsize;
12851 + header->avail = sma_segsize - ALIGNWORD(sizeof(sma_header_t)) - ALIGNWORD(sizeof(block_t)) - ALIGNWORD(sizeof(block_t));
12852 +#if ALLOC_DISTRIBUTION
12855 + for(j=0; j<30; j++) header->adist[j] = 0;
12858 + first = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12860 + first->fnext = ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t));
12861 + first->fprev = 0;
12862 + first->prev_size = 0;
12863 + SET_CANARY(first);
12864 +#ifdef __APC_SMA_DEBUG__
12867 + empty = BLOCKAT(first->fnext);
12868 + empty->size = header->avail - ALIGNWORD(sizeof(block_t));
12869 + empty->fnext = OFFSET(empty) + empty->size;
12870 + empty->fprev = ALIGNWORD(sizeof(sma_header_t));
12871 + empty->prev_size = 0;
12872 + SET_CANARY(empty);
12873 +#ifdef __APC_SMA_DEBUG__
12876 + last = BLOCKAT(empty->fnext);
12879 + last->fprev = OFFSET(empty);
12880 + last->prev_size = empty->size;
12881 + SET_CANARY(last);
12882 +#ifdef __APC_SMA_DEBUG__
12889 +/* {{{ apc_sma_cleanup */
12890 +void apc_sma_cleanup(TSRMLS_D)
12894 + assert(sma_initialized);
12896 + for (i = 0; i < sma_numseg; i++) {
12897 + apc_lck_destroy(SMA_LCK(i));
12899 + apc_unmap(&sma_segments[i] TSRMLS_CC);
12901 + apc_shm_detach(&sma_segments[i] TSRMLS_CC);
12904 + sma_initialized = 0;
12905 + apc_efree(sma_segments TSRMLS_CC);
12909 +/* {{{ apc_sma_malloc_ex */
12910 +void* apc_sma_malloc_ex(size_t n, size_t fragment, size_t* allocated TSRMLS_DC)
12917 + assert(sma_initialized);
12918 + LOCK(SMA_LCK(sma_lastseg));
12920 + off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
12922 + if(off == -1 && APCG(current_cache)) {
12923 + /* retry failed allocation after we expunge */
12924 + UNLOCK(SMA_LCK(sma_lastseg));
12925 + APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC);
12926 + LOCK(SMA_LCK(sma_lastseg));
12927 + off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
12931 + void* p = (void *)(SMA_ADDR(sma_lastseg) + off);
12932 + UNLOCK(SMA_LCK(sma_lastseg));
12933 +#ifdef VALGRIND_MALLOCLIKE_BLOCK
12934 + VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
12939 + UNLOCK(SMA_LCK(sma_lastseg));
12941 + for (i = 0; i < sma_numseg; i++) {
12942 + if (i == sma_lastseg) {
12945 + LOCK(SMA_LCK(i));
12946 + off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
12947 + if(off == -1 && APCG(current_cache)) {
12948 + /* retry failed allocation after we expunge */
12949 + UNLOCK(SMA_LCK(i));
12950 + APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC);
12951 + LOCK(SMA_LCK(i));
12952 + off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
12955 + void* p = (void *)(SMA_ADDR(i) + off);
12956 + UNLOCK(SMA_LCK(i));
12958 +#ifdef VALGRIND_MALLOCLIKE_BLOCK
12959 + VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
12963 + UNLOCK(SMA_LCK(i));
12966 + /* I've tried being nice, but now you're just asking for it */
12968 + apc_cache->expunge_cb(apc_cache, (n+fragment) TSRMLS_CC);
12969 + apc_user_cache->expunge_cb(apc_user_cache, (n+fragment) TSRMLS_CC);
12974 + /* now, I've truly and well given up */
12980 +/* {{{ apc_sma_malloc */
12981 +void* apc_sma_malloc(size_t n TSRMLS_DC)
12983 + size_t allocated;
12984 + void *p = apc_sma_malloc_ex(n, MINBLOCKSIZE, &allocated TSRMLS_CC);
12990 +/* {{{ apc_sma_realloc */
12991 +void* apc_sma_realloc(void *p, size_t n TSRMLS_DC)
12993 + apc_sma_free(p TSRMLS_CC);
12994 + return apc_sma_malloc(n TSRMLS_CC);
12998 +/* {{{ apc_sma_strdup */
12999 +char* apc_sma_strdup(const char* s TSRMLS_DC)
13004 + if(!s) return NULL;
13006 + len = strlen(s)+1;
13007 + q = apc_sma_malloc(len TSRMLS_CC);
13008 + if(!q) return NULL;
13009 + memcpy(q, s, len);
13014 +/* {{{ apc_sma_free */
13015 +void apc_sma_free(void* p TSRMLS_DC)
13025 + assert(sma_initialized);
13028 + for (i = 0; i < sma_numseg; i++) {
13029 + offset = (size_t)((char *)p - SMA_ADDR(i));
13030 + if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
13031 + LOCK(SMA_LCK(i));
13032 + d_size = sma_deallocate(SMA_HDR(i), offset);
13033 + UNLOCK(SMA_LCK(i));
13034 +#ifdef VALGRIND_FREELIKE_BLOCK
13035 + VALGRIND_FREELIKE_BLOCK(p, 0);
13041 + apc_error("apc_sma_free: could not locate address %p" TSRMLS_CC, p);
13045 +#ifdef APC_MEMPROTECT
13047 +void* apc_sma_protect(void *p)
13049 + unsigned int i = 0;
13056 + if(SMA_RO(sma_lastseg) == NULL) return p;
13058 + offset = (size_t)((char *)p - SMA_ADDR(sma_lastseg));
13060 + if(p >= (void*)SMA_ADDR(sma_lastseg) && offset < sma_segsize) {
13061 + return SMA_RO(sma_lastseg) + offset;
13064 + for (i = 0; i < sma_numseg; i++) {
13065 + offset = (size_t)((char *)p - SMA_ADDR(i));
13066 + if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
13067 + return SMA_RO(i) + offset;
13076 +void* apc_sma_unprotect(void *p)
13078 + unsigned int i = 0;
13085 + if(SMA_RO(sma_lastseg) == NULL) return p;
13087 + offset = (size_t)((char *)p - SMA_RO(sma_lastseg));
13089 + if(p >= (void*)SMA_RO(sma_lastseg) && offset < sma_segsize) {
13090 + return SMA_ADDR(sma_lastseg) + offset;
13093 + for (i = 0; i < sma_numseg; i++) {
13094 + offset = (size_t)((char *)p - SMA_RO(i));
13095 + if (p >= (void*)SMA_RO(i) && offset < sma_segsize) {
13096 + return SMA_ADDR(i) + offset;
13105 +void* apc_sma_protect(void *p) { return p; }
13106 +void* apc_sma_unprotect(void *p) { return p; }
13110 +/* {{{ apc_sma_info */
13111 +apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC)
13113 + apc_sma_info_t* info;
13114 + apc_sma_link_t** link;
13119 + if (!sma_initialized) {
13123 + info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t) TSRMLS_CC);
13124 + info->num_seg = sma_numseg;
13125 + info->seg_size = sma_segsize - (ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t)) + ALIGNWORD(sizeof(block_t)));
13127 + info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*) TSRMLS_CC);
13128 + for (i = 0; i < sma_numseg; i++) {
13129 + info->list[i] = NULL;
13132 + if(limited) return info;
13134 + /* For each segment */
13135 + for (i = 0; i < sma_numseg; i++) {
13136 + RDLOCK(SMA_LCK(i));
13137 + shmaddr = SMA_ADDR(i);
13138 + prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
13140 + link = &info->list[i];
13142 + /* For each block in this segment */
13143 + while (BLOCKAT(prv->fnext)->fnext != 0) {
13144 + block_t* cur = BLOCKAT(prv->fnext);
13145 +#ifdef __APC_SMA_DEBUG__
13146 + CHECK_CANARY(cur);
13149 + *link = apc_emalloc(sizeof(apc_sma_link_t) TSRMLS_CC);
13150 + (*link)->size = cur->size;
13151 + (*link)->offset = prv->fnext;
13152 + (*link)->next = NULL;
13153 + link = &(*link)->next;
13157 +#if ALLOC_DISTRIBUTION
13158 + sma_header_t* header = (sma_header_t*) segment->shmaddr;
13159 + memcpy(info->seginfo[i].adist, header->adist, sizeof(size_t) * 30);
13163 + RDUNLOCK(SMA_LCK(i));
13170 +/* {{{ apc_sma_free_info */
13171 +void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC)
13175 + for (i = 0; i < info->num_seg; i++) {
13176 + apc_sma_link_t* p = info->list[i];
13178 + apc_sma_link_t* q = p;
13180 + apc_efree(q TSRMLS_CC);
13183 + apc_efree(info->list TSRMLS_CC);
13184 + apc_efree(info TSRMLS_CC);
13188 +/* {{{ apc_sma_get_avail_mem */
13189 +size_t apc_sma_get_avail_mem()
13191 + size_t avail_mem = 0;
13194 + for (i = 0; i < sma_numseg; i++) {
13195 + sma_header_t* header = SMA_HDR(i);
13196 + avail_mem += header->avail;
13198 + return avail_mem;
13202 +/* {{{ apc_sma_get_avail_size */
13203 +zend_bool apc_sma_get_avail_size(size_t size)
13207 + for (i = 0; i < sma_numseg; i++) {
13208 + sma_header_t* header = SMA_HDR(i);
13209 + if (header->avail > size) {
13218 +#if ALLOC_DISTRIBUTION
13219 +size_t *apc_sma_get_alloc_distribution(void) {
13220 + sma_header_t* header = (sma_header_t*) segment->sma_shmaddr;
13221 + return header->adist;
13226 + * Local variables:
13228 + * c-basic-offset: 4
13230 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13231 + * vim<600: expandtab sw=4 ts=4 sts=4
13233 diff -Naur a/ext/apc/apc_sma.h b/ext/apc/apc_sma.h
13234 --- a/ext/apc/apc_sma.h 1970-01-01 01:00:00.000000000 +0100
13235 +++ b/ext/apc/apc_sma.h 2012-07-20 00:10:35.000000000 +0200
13238 + +----------------------------------------------------------------------+
13240 + +----------------------------------------------------------------------+
13241 + | Copyright (c) 2006-2011 The PHP Group |
13242 + +----------------------------------------------------------------------+
13243 + | This source file is subject to version 3.01 of the PHP license, |
13244 + | that is bundled with this package in the file LICENSE, and is |
13245 + | available through the world-wide-web at the following url: |
13246 + | http://www.php.net/license/3_01.txt |
13247 + | If you did not receive a copy of the PHP license and are unable to |
13248 + | obtain it through the world-wide-web, please send a note to |
13249 + | license@php.net so we can mail you a copy immediately. |
13250 + +----------------------------------------------------------------------+
13251 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13252 + +----------------------------------------------------------------------+
13254 + This software was contributed to PHP by Community Connect Inc. in 2002
13255 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13256 + Future revisions and derivatives of this source code must acknowledge
13257 + Community Connect Inc. as the original contributor of this module by
13258 + leaving this note intact in the source code.
13260 + All other licensing and usage conditions are those of the PHP Group.
13264 +/* $Id: apc_sma.h 307048 2011-01-03 23:53:17Z kalle $ */
13269 +#define ALLOC_DISTRIBUTION 0
13273 +/* Simple shared memory allocator */
13275 +typedef struct _apc_segment_t apc_segment_t;
13277 +struct _apc_segment_t {
13280 +#ifdef APC_MEMPROTECT
13285 +extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC);
13286 +extern void apc_sma_cleanup(TSRMLS_D);
13287 +extern void* apc_sma_malloc(size_t size TSRMLS_DC);
13288 +extern void* apc_sma_malloc_ex(size_t size, size_t fragment, size_t* allocated TSRMLS_DC);
13289 +extern void* apc_sma_realloc(void* p, size_t size TSRMLS_DC);
13290 +extern char* apc_sma_strdup(const char *s TSRMLS_DC);
13291 +extern void apc_sma_free(void* p TSRMLS_DC);
13292 +#if ALLOC_DISTRIBUTION
13293 +extern size_t *apc_sma_get_alloc_distribution();
13296 +extern void* apc_sma_protect(void *p);
13297 +extern void* apc_sma_unprotect(void *p);
13299 +/* {{{ struct definition: apc_sma_link_t */
13300 +typedef struct apc_sma_link_t apc_sma_link_t;
13301 +struct apc_sma_link_t {
13302 + long size; /* size of this free block */
13303 + long offset; /* offset in segment of this block */
13304 + apc_sma_link_t* next; /* link to next free block */
13308 +/* {{{ struct definition: apc_sma_info_t */
13309 +typedef struct apc_sma_info_t apc_sma_info_t;
13310 +struct apc_sma_info_t {
13311 + int num_seg; /* number of shared memory segments */
13312 + size_t seg_size; /* size of each shared memory segment */
13313 + apc_sma_link_t** list; /* there is one list per segment */
13317 +extern apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC);
13318 +extern void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC);
13320 +extern size_t apc_sma_get_avail_mem();
13321 +extern zend_bool apc_sma_get_avail_size(size_t size);
13322 +extern void apc_sma_check_integrity();
13324 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
13325 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
13326 +#define ALIGNSIZE(x, size) ((size) * (1 + (((x)-1)/(size))))
13327 +#define ALIGNWORD(x) ALIGNSIZE(x, sizeof(apc_word_t))
13333 + * Local variables:
13335 + * c-basic-offset: 4
13337 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13338 + * vim<600: expandtab sw=4 ts=4 sts=4
13340 diff -Naur a/ext/apc/apc_spin.c b/ext/apc/apc_spin.c
13341 --- a/ext/apc/apc_spin.c 1970-01-01 01:00:00.000000000 +0100
13342 +++ b/ext/apc/apc_spin.c 2012-07-20 00:10:35.000000000 +0200
13345 + +----------------------------------------------------------------------+
13347 + +----------------------------------------------------------------------+
13348 + | Copyright (c) 2006-2011 The PHP Group |
13349 + +----------------------------------------------------------------------+
13350 + | This source file is subject to version 3.01 of the PHP license, |
13351 + | that is bundled with this package in the file LICENSE, and is |
13352 + | available through the world-wide-web at the following url: |
13353 + | http://www.php.net/license/3_01.txt |
13354 + | If you did not receive a copy of the PHP license and are unable to |
13355 + | obtain it through the world-wide-web, please send a note to |
13356 + | license@php.net so we can mail you a copy immediately. |
13357 + +----------------------------------------------------------------------+
13358 + | Authors: Brian Shire <shire@php.net> |
13359 + +----------------------------------------------------------------------+
13363 +/* $Id: apc_spin.c 307048 2011-01-03 23:53:17Z kalle $ */
13365 +#include "apc_spin.h"
13367 +#ifdef APC_SPIN_LOCKS
13369 +slock_t *apc_slock_create(slock_t *lock)
13371 + S_INIT_LOCK(lock);
13375 +void apc_slock_destroy(slock_t *lock)
13380 +void apc_slock_lock(slock_t *lock TSRMLS_DC)
13385 +void apc_slock_unlock(slock_t *lock)
13390 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
13392 + /* Technically we aren't supposed to call this directly, but the original
13393 + * code provides no method for absolute non-blocking locks, so we'll call into
13394 + * the TAS (test and set) functionality directly
13396 + return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */
13403 + * Local variables:
13405 + * c-basic-offset: 4
13407 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13408 + * vim<600: expandtab sw=4 ts=4 sts=4
13410 diff -Naur a/ext/apc/apc_spin.h b/ext/apc/apc_spin.h
13411 --- a/ext/apc/apc_spin.h 1970-01-01 01:00:00.000000000 +0100
13412 +++ b/ext/apc/apc_spin.h 2012-07-20 00:10:35.000000000 +0200
13415 + +----------------------------------------------------------------------+
13417 + +----------------------------------------------------------------------+
13418 + | Copyright (c) 2006-2011 The PHP Group |
13419 + +----------------------------------------------------------------------+
13420 + | This source file is subject to version 3.01 of the PHP license, |
13421 + | that is bundled with this package in the file LICENSE, and is |
13422 + | available through the world-wide-web at the following url: |
13423 + | http://www.php.net/license/3_01.txt |
13424 + | If you did not receive a copy of the PHP license and are unable to |
13425 + | obtain it through the world-wide-web, please send a note to |
13426 + | license@php.net so we can mail you a copy immediately. |
13427 + +----------------------------------------------------------------------+
13428 + | Authors: Brian Shire <shire@php.net> |
13429 + +----------------------------------------------------------------------+
13433 +/* $Id: apc_spin.h 307048 2011-01-03 23:53:17Z kalle $ */
13435 +#ifndef APC_SPIN_H
13436 +#define APC_SPIN_H
13440 +#ifdef APC_SPIN_LOCKS
13442 +#include "pgsql_s_lock.h"
13444 +slock_t *apc_slock_create(slock_t *lock);
13445 +void apc_slock_destroy(slock_t *lock);
13446 +void apc_slock_lock(slock_t *lock TSRMLS_DC);
13447 +zend_bool apc_slock_nonblocking_lock(slock_t *lock);
13448 +void apc_slock_unlock(slock_t *lock);
13455 + * Local variables:
13457 + * c-basic-offset: 4
13459 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13460 + * vim<600: expandtab sw=4 ts=4 sts=4
13462 diff -Naur a/ext/apc/apc_stack.c b/ext/apc/apc_stack.c
13463 --- a/ext/apc/apc_stack.c 1970-01-01 01:00:00.000000000 +0100
13464 +++ b/ext/apc/apc_stack.c 2012-07-20 00:10:35.000000000 +0200
13467 + +----------------------------------------------------------------------+
13469 + +----------------------------------------------------------------------+
13470 + | Copyright (c) 2006-2011 The PHP Group |
13471 + +----------------------------------------------------------------------+
13472 + | This source file is subject to version 3.01 of the PHP license, |
13473 + | that is bundled with this package in the file LICENSE, and is |
13474 + | available through the world-wide-web at the following url: |
13475 + | http://www.php.net/license/3_01.txt |
13476 + | If you did not receive a copy of the PHP license and are unable to |
13477 + | obtain it through the world-wide-web, please send a note to |
13478 + | license@php.net so we can mail you a copy immediately. |
13479 + +----------------------------------------------------------------------+
13480 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13481 + +----------------------------------------------------------------------+
13483 + This software was contributed to PHP by Community Connect Inc. in 2002
13484 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13485 + Future revisions and derivatives of this source code must acknowledge
13486 + Community Connect Inc. as the original contributor of this module by
13487 + leaving this note intact in the source code.
13489 + All other licensing and usage conditions are those of the PHP Group.
13493 +/* $Id: apc_stack.c 307048 2011-01-03 23:53:17Z kalle $ */
13496 +#include "apc_stack.h"
13498 +struct apc_stack_t {
13504 +apc_stack_t* apc_stack_create(int size_hint TSRMLS_DC)
13506 + apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t) TSRMLS_CC);
13508 + stack->capacity = (size_hint > 0) ? size_hint : 10;
13510 + stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity TSRMLS_CC);
13515 +void apc_stack_destroy(apc_stack_t* stack TSRMLS_DC)
13517 + if (stack != NULL) {
13518 + apc_efree(stack->data TSRMLS_CC);
13519 + apc_efree(stack TSRMLS_CC);
13523 +void apc_stack_clear(apc_stack_t* stack)
13525 + assert(stack != NULL);
13529 +void apc_stack_push(apc_stack_t* stack, void* item TSRMLS_DC)
13531 + assert(stack != NULL);
13532 + if (stack->size == stack->capacity) {
13533 + stack->capacity *= 2;
13534 + stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity TSRMLS_CC);
13536 + stack->data[stack->size++] = item;
13539 +void* apc_stack_pop(apc_stack_t* stack)
13541 + assert(stack != NULL && stack->size > 0);
13542 + return stack->data[--stack->size];
13545 +void* apc_stack_top(apc_stack_t* stack)
13547 + assert(stack != NULL && stack->size > 0);
13548 + return stack->data[stack->size-1];
13551 +void* apc_stack_get(apc_stack_t* stack, int n)
13553 + assert(stack != NULL && stack->size > n);
13554 + return stack->data[n];
13557 +int apc_stack_size(apc_stack_t* stack)
13559 + assert(stack != NULL);
13560 + return stack->size;
13565 + * Local variables:
13567 + * c-basic-offset: 4
13569 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13570 + * vim<600: expandtab sw=4 ts=4 sts=4
13572 diff -Naur a/ext/apc/apc_stack.h b/ext/apc/apc_stack.h
13573 --- a/ext/apc/apc_stack.h 1970-01-01 01:00:00.000000000 +0100
13574 +++ b/ext/apc/apc_stack.h 2012-07-20 00:10:35.000000000 +0200
13577 + +----------------------------------------------------------------------+
13579 + +----------------------------------------------------------------------+
13580 + | Copyright (c) 2006-2011 The PHP Group |
13581 + +----------------------------------------------------------------------+
13582 + | This source file is subject to version 3.01 of the PHP license, |
13583 + | that is bundled with this package in the file LICENSE, and is |
13584 + | available through the world-wide-web at the following url: |
13585 + | http://www.php.net/license/3_01.txt |
13586 + | If you did not receive a copy of the PHP license and are unable to |
13587 + | obtain it through the world-wide-web, please send a note to |
13588 + | license@php.net so we can mail you a copy immediately. |
13589 + +----------------------------------------------------------------------+
13590 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13591 + | George Schlossnagle <george@omniti.com> |
13592 + +----------------------------------------------------------------------+
13594 + This software was contributed to PHP by Community Connect Inc. in 2002
13595 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13596 + Future revisions and derivatives of this source code must acknowledge
13597 + Community Connect Inc. as the original contributor of this module by
13598 + leaving this note intact in the source code.
13600 + All other licensing and usage conditions are those of the PHP Group.
13604 +/* $Id: apc_stack.h 307048 2011-01-03 23:53:17Z kalle $ */
13606 +#ifndef APC_STACK_H
13607 +#define APC_STACK_H
13609 +/* Basic stack datatype */
13611 +#define T apc_stack_t*
13612 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
13614 +extern T apc_stack_create(int size_hint TSRMLS_DC);
13615 +extern void apc_stack_destroy(T stack TSRMLS_DC);
13616 +extern void apc_stack_clear(T stack);
13617 +extern void apc_stack_push(T stack, void* item TSRMLS_DC);
13618 +extern void* apc_stack_pop(T stack);
13619 +extern void* apc_stack_top(T stack);
13620 +extern void* apc_stack_get(T stack, int n);
13621 +extern int apc_stack_size(T stack);
13627 + * Local variables:
13629 + * c-basic-offset: 4
13631 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13632 + * vim<600: expandtab sw=4 ts=4 sts=4
13634 diff -Naur a/ext/apc/apc_string.c b/ext/apc/apc_string.c
13635 --- a/ext/apc/apc_string.c 1970-01-01 01:00:00.000000000 +0100
13636 +++ b/ext/apc/apc_string.c 2012-07-20 00:10:35.000000000 +0200
13639 + +----------------------------------------------------------------------+
13641 + +----------------------------------------------------------------------+
13642 + | Copyright (c) 2006-2011 The PHP Group |
13643 + +----------------------------------------------------------------------+
13644 + | This source file is subject to version 3.01 of the PHP license, |
13645 + | that is bundled with this package in the file LICENSE, and is |
13646 + | available through the world-wide-web at the following url: |
13647 + | http://www.php.net/license/3_01.txt |
13648 + | If you did not receive a copy of the PHP license and are unable to |
13649 + | obtain it through the world-wide-web, please send a note to |
13650 + | license@php.net so we can mail you a copy immediately. |
13651 + +----------------------------------------------------------------------+
13652 + | Authors: Dmitry Stogov <dmitry@zend.com> |
13653 + +----------------------------------------------------------------------+
13655 + This software was contributed to PHP by Community Connect Inc. in 2002
13656 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13657 + Future revisions and derivatives of this source code must acknowledge
13658 + Community Connect Inc. as the original contributor of this module by
13659 + leaving this note intact in the source code.
13661 + All other licensing and usage conditions are those of the PHP Group.
13665 +/* $Id: apc_string.c 326089 2012-06-11 04:29:57Z rasmus $ */
13668 +#include "apc_globals.h"
13669 +#include "apc_php.h"
13670 +#include "apc_lock.h"
13672 +#ifdef ZEND_ENGINE_2_4
13675 +typedef struct _apc_interned_strings_data_t {
13676 + char *interned_strings_start;
13677 + char *interned_strings_end;
13678 + char *interned_strings_top;
13680 + HashTable interned_strings;
13681 +} apc_interned_strings_data_t;
13683 +apc_interned_strings_data_t *apc_interned_strings_data = NULL;
13685 +#define APCSG(v) (apc_interned_strings_data->v)
13687 +static char *old_interned_strings_start;
13688 +static char *old_interned_strings_end;
13689 +static const char *(*old_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
13690 +static void (*old_interned_strings_snapshot)(TSRMLS_D);
13691 +static void (*old_interned_strings_restore)(TSRMLS_D);
13693 +static const char *apc_dummy_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC)
13698 +static void apc_dummy_interned_strings_snapshot_for_php(TSRMLS_D)
13702 +static void apc_dummy_interned_strings_restore_for_php(TSRMLS_D)
13707 +const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC)
13714 + if (arKey >= APCSG(interned_strings_start) && arKey < APCSG(interned_strings_end)) {
13718 + h = zend_inline_hash_func(arKey, nKeyLength);
13719 + nIndex = h & APCSG(interned_strings).nTableMask;
13721 + p = APCSG(interned_strings).arBuckets[nIndex];
13722 + while (p != NULL) {
13723 + if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
13724 + if (!memcmp(p->arKey, arKey, nKeyLength)) {
13731 + if (APCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1) >=
13732 + APCSG(interned_strings_end)) {
13737 + p = (Bucket *) APCSG(interned_strings_top);
13738 + APCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1);
13740 + p->arKey = (char*)(p+1);
13741 + memcpy(p->arKey, arKey, nKeyLength);
13742 + ((char *)p->arKey)[nKeyLength] = '\0';
13743 + p->nKeyLength = nKeyLength;
13745 + p->pData = &p->pDataPtr;
13748 + p->pNext = APCSG(interned_strings).arBuckets[nIndex];
13751 + p->pNext->pLast = p;
13753 + APCSG(interned_strings).arBuckets[nIndex] = p;
13755 + p->pListLast = APCSG(interned_strings).pListTail;
13756 + APCSG(interned_strings).pListTail = p;
13757 + p->pListNext = NULL;
13758 + if (p->pListLast != NULL) {
13759 + p->pListLast->pListNext = p;
13761 + if (!APCSG(interned_strings).pListHead) {
13762 + APCSG(interned_strings).pListHead = p;
13765 + APCSG(interned_strings).nNumOfElements++;
13769 + return zend_new_interned_string(arKey, nKeyLength, 0 TSRMLS_CC);
13774 +static void apc_copy_internal_strings(TSRMLS_D)
13778 + p = CG(function_table)->pListHead;
13780 + if (p->nKeyLength) {
13781 + p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13783 + p = p->pListNext;
13786 + p = CG(class_table)->pListHead;
13788 + zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr);
13790 + if (p->nKeyLength) {
13791 + p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13795 + ce->name = apc_new_interned_string(ce->name, ce->name_length+1 TSRMLS_CC);
13798 + q = ce->properties_info.pListHead;
13800 + zend_property_info *info = (zend_property_info*)(q->pData);
13802 + if (q->nKeyLength) {
13803 + q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13806 + if (info->name) {
13807 + info->name = apc_new_interned_string(info->name, info->name_length+1 TSRMLS_CC);
13810 + q = q->pListNext;
13813 + q = ce->function_table.pListHead;
13815 + if (q->nKeyLength) {
13816 + q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13818 + q = q->pListNext;
13821 + q = ce->constants_table.pListHead;
13823 + if (q->nKeyLength) {
13824 + q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13826 + q = q->pListNext;
13829 + p = p->pListNext;
13832 + p = EG(zend_constants)->pListHead;
13834 + if (p->nKeyLength) {
13835 + p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13837 + p = p->pListNext;
13841 +void apc_interned_strings_init(TSRMLS_D)
13843 + int count = APCG(shm_strings_buffer) / (sizeof(Bucket) + sizeof(Bucket*) * 2);
13845 + apc_interned_strings_data = (apc_interned_strings_data_t*) apc_sma_malloc(APCG(shm_strings_buffer) TSRMLS_CC);
13846 + memset((void *)apc_interned_strings_data, 0, APCG(shm_strings_buffer));
13848 + CREATE_LOCK(APCSG(lock));
13850 + zend_hash_init(&APCSG(interned_strings), count, NULL, NULL, 1);
13851 + APCSG(interned_strings).nTableMask = APCSG(interned_strings).nTableSize - 1;
13852 + APCSG(interned_strings).arBuckets = (Bucket**)((char*)apc_interned_strings_data + sizeof(apc_interned_strings_data_t));
13854 + APCSG(interned_strings_start) = (char*)APCSG(interned_strings).arBuckets + APCSG(interned_strings).nTableSize * sizeof(Bucket *);
13855 + APCSG(interned_strings_end) = (char*)apc_interned_strings_data + APCG(shm_strings_buffer);
13856 + APCSG(interned_strings_top) = APCSG(interned_strings_start);
13858 + old_interned_strings_start = CG(interned_strings_start);
13859 + old_interned_strings_end = CG(interned_strings_end);
13860 + old_new_interned_string = zend_new_interned_string;
13861 + old_interned_strings_snapshot = zend_interned_strings_snapshot;
13862 + old_interned_strings_restore = zend_interned_strings_restore;
13864 + CG(interned_strings_start) = APCSG(interned_strings_start);
13865 + CG(interned_strings_end) = APCSG(interned_strings_end);
13866 + zend_new_interned_string = apc_dummy_new_interned_string_for_php;
13867 + zend_interned_strings_snapshot = apc_dummy_interned_strings_snapshot_for_php;
13868 + zend_interned_strings_restore = apc_dummy_interned_strings_restore_for_php;
13870 + apc_copy_internal_strings(TSRMLS_C);
13873 +void apc_interned_strings_shutdown(TSRMLS_D)
13875 + zend_hash_clean(CG(function_table));
13876 + zend_hash_clean(CG(class_table));
13877 + zend_hash_clean(EG(zend_constants));
13879 + CG(interned_strings_start) = old_interned_strings_start;
13880 + CG(interned_strings_end) = old_interned_strings_end;
13881 + zend_new_interned_string = old_new_interned_string;
13882 + zend_interned_strings_snapshot = old_interned_strings_snapshot;
13883 + zend_interned_strings_restore = old_interned_strings_restore;
13885 + DESTROY_LOCK(APCSG(lock));
13892 + * Local variables:
13894 + * c-basic-offset: 4
13896 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13897 + * vim<600: expandtab sw=4 ts=4 sts=4
13899 diff -Naur a/ext/apc/apc_string.h b/ext/apc/apc_string.h
13900 --- a/ext/apc/apc_string.h 1970-01-01 01:00:00.000000000 +0100
13901 +++ b/ext/apc/apc_string.h 2012-07-20 00:10:35.000000000 +0200
13904 + +----------------------------------------------------------------------+
13906 + +----------------------------------------------------------------------+
13907 + | Copyright (c) 2006-2011 The PHP Group |
13908 + +----------------------------------------------------------------------+
13909 + | This source file is subject to version 3.01 of the PHP license, |
13910 + | that is bundled with this package in the file LICENSE, and is |
13911 + | available through the world-wide-web at the following url: |
13912 + | http://www.php.net/license/3_01.txt |
13913 + | If you did not receive a copy of the PHP license and are unable to |
13914 + | obtain it through the world-wide-web, please send a note to |
13915 + | license@php.net so we can mail you a copy immediately. |
13916 + +----------------------------------------------------------------------+
13917 + | Authors: Dmitry Stogov <dmitry@zend.com> |
13918 + +----------------------------------------------------------------------+
13920 + This software was contributed to PHP by Community Connect Inc. in 2002
13921 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13922 + Future revisions and derivatives of this source code must acknowledge
13923 + Community Connect Inc. as the original contributor of this module by
13924 + leaving this note intact in the source code.
13926 + All other licensing and usage conditions are those of the PHP Group.
13930 +/* $Id: apc_string.h 324145 2012-03-12 11:38:28Z pajoye $ */
13932 +#ifndef APC_STRING
13933 +#define APC_STRING
13938 +void apc_interned_strings_init(TSRMLS_D);
13939 +void apc_interned_strings_shutdown(TSRMLS_D);
13942 +const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC);
13947 + * Local variables:
13949 + * c-basic-offset: 4
13951 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13952 + * vim<600: expandtab sw=4 ts=4 sts=4
13954 diff -Naur a/ext/apc/apc_windows_srwlock_kernel.c b/ext/apc/apc_windows_srwlock_kernel.c
13955 --- a/ext/apc/apc_windows_srwlock_kernel.c 1970-01-01 01:00:00.000000000 +0100
13956 +++ b/ext/apc/apc_windows_srwlock_kernel.c 2012-07-20 00:10:35.000000000 +0200
13959 + +----------------------------------------------------------------------+
13961 + +----------------------------------------------------------------------+
13962 + | Copyright (c) 2006-2011 The PHP Group |
13963 + +----------------------------------------------------------------------+
13964 + | This source file is subject to version 3.01 of the PHP license, |
13965 + | that is bundled with this package in the file LICENSE, and is |
13966 + | available through the world-wide-web at the following url: |
13967 + | http://www.php.net/license/3_01.txt |
13968 + | If you did not receive a copy of the PHP license and are unable to |
13969 + | obtain it through the world-wide-web, please send a note to |
13970 + | license@php.net so we can mail you a copy immediately. |
13971 + +----------------------------------------------------------------------+
13972 + | Authors: Pierre Joye <pierre@php.net> |
13973 + +----------------------------------------------------------------------+
13977 + These APIs are not actually exposed nor documented. But should work fine
13978 + from a binary as available since XP without signature changes.
13982 +non blocking could be possible using the fWait argument (to 0). However
13983 +I'm not sure whether the wait handlers is actually implemented in all
13984 +supported platforms (xp+). could be enabled later once really tested.
13990 +#ifdef APC_SRWLOCK_KERNEL
13991 +#include "apc_windows_srwlock_kernel.h"
13995 +void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl);
13996 +void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl);
13997 +BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait);
13998 +BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait);
13999 +void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl);
14001 +typedef void (WINAPI *tRtlInitializeResource)(LPRTL_RWLOCK rwl);
14002 +typedef void (WINAPI *tRtlDeleteResource)(LPRTL_RWLOCK rwl);
14003 +typedef BYTE (WINAPI *tRtlAcquireResourceExclusive)(LPRTL_RWLOCK rwl, BYTE fWait);
14004 +typedef BYTE (WINAPI *tRtlAcquireResourceShared)(LPRTL_RWLOCK rwl, BYTE fWait);
14005 +typedef void (WINAPI *tRtlReleaseResource)(LPRTL_RWLOCK rwl);
14006 +typedef void (WINAPI *tRtlDumpResource)(LPRTL_RWLOCK rwl);
14008 +tRtlInitializeResource pRtlInitializeResource = 0;
14009 +tRtlDeleteResource pRtlDeleteResource = 0;
14010 +tRtlAcquireResourceExclusive pRtlAcquireResourceExclusive = 0;
14011 +tRtlAcquireResourceShared pRtlAcquireResourceShared = 0;
14012 +tRtlReleaseResource pRtlReleaseResource = 0;
14013 +tRtlDumpResource pRtlDumpResource = 0;
14017 +void apc_windows_cs_status(apc_windows_cs_rwlock_t *lock );
14018 +apc_windows_cs_rwlock_t *apc_windows_cs_create(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14020 + ntdll = LoadLibrary("ntdll.dll");
14021 + if (ntdll == 0) {
14025 + pRtlInitializeResource = (tRtlInitializeResource) GetProcAddress(ntdll, "RtlInitializeResource");
14026 + pRtlDeleteResource = (tRtlDeleteResource) GetProcAddress(ntdll, "RtlDeleteResource");
14027 + pRtlAcquireResourceExclusive = (tRtlAcquireResourceExclusive) GetProcAddress(ntdll, "RtlAcquireResourceExclusive");
14028 + pRtlAcquireResourceShared = (tRtlAcquireResourceShared) GetProcAddress(ntdll, "RtlAcquireResourceShared");
14029 + pRtlReleaseResource = (tRtlReleaseResource) GetProcAddress(ntdll, "RtlReleaseResource");
14030 + pRtlDumpResource = (tRtlReleaseResource) GetProcAddress(ntdll, "RtlDumpResource");
14031 + if (pRtlInitializeResource == 0 || pRtlDeleteResource == 0 || pRtlAcquireResourceExclusive == 0 ||
14032 + pRtlAcquireResourceShared == 0 || pRtlReleaseResource == 0 || pRtlDumpResource == 0) {
14035 + pRtlInitializeResource(lock);
14039 +void apc_windows_cs_destroy(apc_windows_cs_rwlock_t *lock)
14043 + pRtlDeleteResource(lock);
14045 + __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
14046 + EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
14048 + /* Ignore exception (resource was freed during shutdown of another thread) */
14050 + FreeLibrary(ntdll);
14054 +void apc_windows_cs_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14056 + pRtlAcquireResourceExclusive(lock, 1);
14059 +void apc_windows_cs_rdlock(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14061 + pRtlAcquireResourceShared(lock, 1);
14064 +void apc_windows_cs_unlock_rd(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14066 + pRtlReleaseResource(lock);
14069 +void apc_windows_cs_unlock_wr(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14071 + pRtlReleaseResource(lock);
14074 +/* debugging purposes, output using trace msgs */
14075 +void apc_windows_cs_status(apc_windows_cs_rwlock_t *lock)
14077 + pRtlDumpResource(lock);
14084 + * Local variables:
14086 + * c-basic-offset: 4
14088 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14089 + * vim<600: expandtab sw=4 ts=4 sts=4
14091 diff -Naur a/ext/apc/apc_windows_srwlock_kernel.h b/ext/apc/apc_windows_srwlock_kernel.h
14092 --- a/ext/apc/apc_windows_srwlock_kernel.h 1970-01-01 01:00:00.000000000 +0100
14093 +++ b/ext/apc/apc_windows_srwlock_kernel.h 2012-07-20 00:10:35.000000000 +0200
14096 + +----------------------------------------------------------------------+
14098 + +----------------------------------------------------------------------+
14099 + | Copyright (c) 2006-2011 The PHP Group |
14100 + +----------------------------------------------------------------------+
14101 + | This source file is subject to version 3.01 of the PHP license, |
14102 + | that is bundled with this package in the file LICENSE, and is |
14103 + | available through the world-wide-web at the following url: |
14104 + | http://www.php.net/license/3_01.txt |
14105 + | If you did not receive a copy of the PHP license and are unable to |
14106 + | obtain it through the world-wide-web, please send a note to |
14107 + | license@php.net so we can mail you a copy immediately. |
14108 + +----------------------------------------------------------------------+
14109 + | Authors: Pierre Joye <pierre@php.net> |
14110 + +----------------------------------------------------------------------+
14114 +#ifndef APC_WINDOWS_CS_RWLOCK_H
14115 +#define APC_WINDOWS_CS_RWLOCK_H
14119 +#ifdef APC_SRWLOCK_KERNEL
14121 +typedef struct _RTL_RWLOCK {
14122 + RTL_CRITICAL_SECTION rtlCS;
14124 + HANDLE hSharedReleaseSemaphore;
14125 + UINT uSharedWaiters;
14127 + HANDLE hExclusiveReleaseSemaphore;
14128 + UINT uExclusiveWaiters;
14130 + INT iNumberActive;
14131 + HANDLE hOwningThreadId;
14132 + DWORD dwTimeoutBoost;
14133 + PVOID pDebugInfo;
14134 +} RTL_RWLOCK, *LPRTL_RWLOCK;
14136 +#define apc_windows_cs_rwlock_t RTL_RWLOCK
14138 +struct apc_windows_cs_rwlock_t {
14139 + CRITICAL_SECTION cs;
14140 + LONG writers_waiting_count;
14141 + LONG readers_waiting_count;
14142 + DWORD active_writers_readers_flag;
14143 + HANDLE ready_to_read;
14144 + HANDLE ready_to_write;
14145 + DWORD reader_races_lost;
14148 +apc_windows_cs_rwlock_t *apc_windows_cs_create(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14149 +void apc_windows_cs_destroy(apc_windows_cs_rwlock_t *lock);
14150 +void apc_windows_cs_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14151 +void apc_windows_cs_rdlock(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14152 +void apc_windows_cs_unlock_rd(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14153 +void apc_windows_cs_unlock_wr(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14154 +# if NONBLOCKING_LOCK_AVAILABLE==1 /* Only in win7/2008 */
14155 +zend_bool apc_pthreadrwlock_nonblocking_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC);
14162 + * Local variables:
14164 + * c-basic-offset: 4
14166 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14167 + * vim<600: expandtab sw=4 ts=4 sts=4
14169 diff -Naur a/ext/apc/apc_zend.c b/ext/apc/apc_zend.c
14170 --- a/ext/apc/apc_zend.c 1970-01-01 01:00:00.000000000 +0100
14171 +++ b/ext/apc/apc_zend.c 2012-07-20 00:10:35.000000000 +0200
14174 + +----------------------------------------------------------------------+
14176 + +----------------------------------------------------------------------+
14177 + | Copyright (c) 2006-2011 The PHP Group |
14178 + +----------------------------------------------------------------------+
14179 + | This source file is subject to version 3.01 of the PHP license, |
14180 + | that is bundled with this package in the file LICENSE, and is |
14181 + | available through the world-wide-web at the following url: |
14182 + | http://www.php.net/license/3_01.txt |
14183 + | If you did not receive a copy of the PHP license and are unable to |
14184 + | obtain it through the world-wide-web, please send a note to |
14185 + | license@php.net so we can mail you a copy immediately. |
14186 + +----------------------------------------------------------------------+
14187 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
14188 + +----------------------------------------------------------------------+
14190 + This software was contributed to PHP by Community Connect Inc. in 2002
14191 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
14192 + Future revisions and derivatives of this source code must acknowledge
14193 + Community Connect Inc. as the original contributor of this module by
14194 + leaving this note intact in the source code.
14196 + All other licensing and usage conditions are those of the PHP Group.
14200 +/* $Id: apc_zend.c 307048 2011-01-03 23:53:17Z kalle $ */
14202 +#include "apc_zend.h"
14203 +#include "apc_globals.h"
14206 +int apc_reserved_offset;
14208 +void* apc_php_malloc(size_t n TSRMLS_DC)
14210 + return emalloc(n);
14213 +void apc_php_free(void* p TSRMLS_DC)
14218 +#ifdef APC_OPCODE_OVERRIDE
14220 +static opcode_handler_t *apc_original_opcode_handlers;
14221 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
14223 +#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
14225 +#ifdef ZEND_ENGINE_2_4
14226 +static zval *apc_get_zval_ptr(zend_uchar op_type, znode_op *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
14230 + switch (op_type) {
14234 + return APC_EX_T(node->var).var.ptr;
14236 + return (*freeval = &APC_EX_T(node->var).tmp_var);
14239 + zval ***ret = &execute_data->CVs[node->var];
14242 + zend_compiled_variable *cv = &EG(active_op_array)->vars[node->var];
14244 + if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
14245 + apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name);
14246 + return &EG(uninitialized_zval);
14257 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
14261 + switch (node->op_type) {
14263 + return &(node->u.constant);
14265 + return APC_EX_T(node->u.var).var.ptr;
14267 + return (*freeval = &APC_EX_T(node->u.var).tmp_var);
14268 +#ifdef ZEND_ENGINE_2_1
14271 + zval ***ret = &execute_data->CVs[node->u.var];
14274 + zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
14276 + if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
14277 + apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name);
14278 + return &EG(uninitialized_zval);
14291 +static int ZEND_FASTCALL apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
14294 + zval *freeop1 = NULL;
14295 + zval *inc_filename = NULL, tmp_inc_filename;
14296 + char realpath[MAXPATHLEN];
14297 + php_stream_wrapper *wrapper;
14298 + char *path_for_open;
14299 + char *full_path = NULL;
14301 + apc_opflags_t* flags = NULL;
14303 +#ifdef ZEND_ENGINE_2_4
14304 + if (opline->extended_value != ZEND_INCLUDE_ONCE &&
14305 + opline->extended_value != ZEND_REQUIRE_ONCE) {
14306 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14309 + inc_filename = apc_get_zval_ptr(opline->op1_type, &opline->op1, &freeop1, execute_data TSRMLS_CC);
14311 + if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
14312 + Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
14313 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14316 + inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
14319 + if (Z_TYPE_P(inc_filename) != IS_STRING) {
14320 + tmp_inc_filename = *inc_filename;
14321 + zval_copy_ctor(&tmp_inc_filename);
14322 + convert_to_string(&tmp_inc_filename);
14323 + inc_filename = &tmp_inc_filename;
14326 + wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
14328 + 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)))) {
14329 + /* Fallback to original handler */
14330 + if (inc_filename == &tmp_inc_filename) {
14331 + zval_dtor(&tmp_inc_filename);
14333 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14336 + if (!full_path) {
14337 + full_path = path_for_open;
14339 + if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
14340 +#ifdef ZEND_ENGINE_2_4
14341 + if (!(opline->result_type & EXT_TYPE_UNUSED)) {
14342 + ALLOC_INIT_ZVAL(APC_EX_T(opline->result.var).var.ptr);
14343 + ZVAL_TRUE(APC_EX_T(opline->result.var).var.ptr);
14346 + if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
14347 + ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
14348 + ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
14351 + if (inc_filename == &tmp_inc_filename) {
14352 + zval_dtor(&tmp_inc_filename);
14355 + zval_dtor(freeop1);
14357 + execute_data->opline++;
14361 + if (inc_filename == &tmp_inc_filename) {
14362 + zval_dtor(&tmp_inc_filename);
14365 + if(apc_reserved_offset != -1) {
14366 + /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
14367 + flags = (apc_opflags_t*) & (execute_data->op_array->reserved[apc_reserved_offset]);
14370 + if(flags && flags->deep_copy == 1) {
14371 + /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily
14372 + * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
14374 +#ifdef ZEND_ENGINE_2_4
14375 + opline->extended_value = (opline->extended_value == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
14376 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14377 + opline->extended_value = (opline->extended_value == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
14379 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
14380 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14381 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
14384 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14390 +void apc_zend_init(TSRMLS_D)
14392 + zend_extension dummy_ext;
14393 + apc_reserved_offset = zend_get_resource_handle(&dummy_ext);
14394 + assert(apc_reserved_offset == dummy_ext.resource_number);
14395 + assert(apc_reserved_offset != -1);
14396 + assert(sizeof(apc_opflags_t) <= sizeof(void*));
14397 + if (!APCG(include_once)) {
14398 + /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
14402 + memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
14404 + /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
14405 +#ifdef ZEND_ENGINE_2_1
14406 + apc_original_opcode_handlers = zend_opcode_handlers;
14407 + zend_opcode_handlers = apc_opcode_handlers;
14409 + apc_original_opcode_handlers = apc_opcode_handlers;
14412 + APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
14415 +void apc_zend_shutdown(TSRMLS_D)
14417 + if (!APCG(include_once)) {
14418 + /* Nothing changed, nothing to restore */
14422 +#ifdef ZEND_ENGINE_2_1
14423 + zend_opcode_handlers = apc_original_opcode_handlers;
14425 + memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
14429 +#else /* Opcode Overrides unavailable */
14431 +void apc_zend_init(TSRMLS_D) { }
14432 +void apc_zend_shutdown(TSRMLS_D) { }
14434 +#endif /* APC_OPCODE_OVERRIDE */
14437 + * Local variables:
14439 + * c-basic-offset: 4
14441 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14442 + * vim<600: expandtab sw=4 ts=4 sts=4
14444 diff -Naur a/ext/apc/apc_zend.h b/ext/apc/apc_zend.h
14445 --- a/ext/apc/apc_zend.h 1970-01-01 01:00:00.000000000 +0100
14446 +++ b/ext/apc/apc_zend.h 2012-07-20 00:10:35.000000000 +0200
14449 + +----------------------------------------------------------------------+
14451 + +----------------------------------------------------------------------+
14452 + | Copyright (c) 2006-2011 The PHP Group |
14453 + +----------------------------------------------------------------------+
14454 + | This source file is subject to version 3.01 of the PHP license, |
14455 + | that is bundled with this package in the file LICENSE, and is |
14456 + | available through the world-wide-web at the following url: |
14457 + | http://www.php.net/license/3_01.txt |
14458 + | If you did not receive a copy of the PHP license and are unable to |
14459 + | obtain it through the world-wide-web, please send a note to |
14460 + | license@php.net so we can mail you a copy immediately. |
14461 + +----------------------------------------------------------------------+
14462 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
14463 + +----------------------------------------------------------------------+
14465 + This software was contributed to PHP by Community Connect Inc. in 2002
14466 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
14467 + Future revisions and derivatives of this source code must acknowledge
14468 + Community Connect Inc. as the original contributor of this module by
14469 + leaving this note intact in the source code.
14471 + All other licensing and usage conditions are those of the PHP Group.
14475 +/* $Id: apc_zend.h 326712 2012-07-19 21:33:27Z rasmus $ */
14477 +#ifndef APC_ZEND_H
14478 +#define APC_ZEND_H
14480 +/* Utilities for interfacing with the zend engine */
14483 +#include "apc_php.h"
14485 +#ifndef Z_REFCOUNT_P
14486 +#define Z_REFCOUNT_P(pz) (pz)->refcount
14487 +#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
14490 +#ifndef Z_SET_REFCOUNT_P
14491 +#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc
14492 +#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc)
14495 +#ifndef Z_ADDREF_P
14496 +#define Z_ADDREF_P(pz) (pz)->refcount++
14497 +#define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz))
14500 +#ifndef Z_DELREF_P
14501 +#define Z_DELREF_P(pz) (pz)->refcount--
14502 +#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz))
14506 +#define Z_ISREF_P(pz) (pz)->is_ref
14507 +#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
14510 +#ifndef Z_SET_ISREF_P
14511 +#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1
14512 +#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
14515 +#ifndef Z_UNSET_ISREF_P
14516 +#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0
14517 +#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
14520 +#ifndef Z_SET_ISREF_TO_P
14521 +#define Z_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = isref
14522 +#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
14526 +extern void* apc_php_malloc(size_t n TSRMLS_DC);
14527 +extern void apc_php_free(void* p TSRMLS_DC);
14529 +extern void apc_zend_init(TSRMLS_D);
14530 +extern void apc_zend_shutdown(TSRMLS_D);
14533 +/* offset for apc info in op_array->reserved */
14534 +extern int apc_reserved_offset;
14536 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
14537 +# define ZEND_VM_KIND_CALL 1
14540 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
14541 +# define ZEND_VM_KIND ZEND_VM_KIND_CALL
14544 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
14545 +# define APC_OPCODE_OVERRIDE
14548 +#ifdef APC_OPCODE_OVERRIDE
14550 +#ifdef ZEND_ENGINE_2_1
14551 +/* Taken from Zend/zend_vm_execute.h */
14552 +#define _CONST_CODE 0
14553 +#define _TMP_CODE 1
14554 +#define _VAR_CODE 2
14555 +#define _UNUSED_CODE 3
14556 +#define _CV_CODE 4
14557 +static inline int _apc_opcode_handler_decode(zend_op *opline)
14559 + static const int apc_vm_decode[] = {
14560 + _UNUSED_CODE, /* 0 */
14561 + _CONST_CODE, /* 1 = IS_CONST */
14562 + _TMP_CODE, /* 2 = IS_TMP_VAR */
14563 + _UNUSED_CODE, /* 3 */
14564 + _VAR_CODE, /* 4 = IS_VAR */
14565 + _UNUSED_CODE, /* 5 */
14566 + _UNUSED_CODE, /* 6 */
14567 + _UNUSED_CODE, /* 7 */
14568 + _UNUSED_CODE, /* 8 = IS_UNUSED */
14569 + _UNUSED_CODE, /* 9 */
14570 + _UNUSED_CODE, /* 10 */
14571 + _UNUSED_CODE, /* 11 */
14572 + _UNUSED_CODE, /* 12 */
14573 + _UNUSED_CODE, /* 13 */
14574 + _UNUSED_CODE, /* 14 */
14575 + _UNUSED_CODE, /* 15 */
14576 + _CV_CODE /* 16 = IS_CV */
14578 +#ifdef ZEND_ENGINE_2_4
14579 + return (opline->opcode * 25) + (apc_vm_decode[opline->op1_type] * 5) + apc_vm_decode[opline->op2_type];
14581 + return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
14585 +# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline;
14586 +# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline)
14587 +# if PHP_MAJOR_VERSION >= 6
14588 +# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1)
14589 +# elif defined(ZEND_ENGINE_2_4)
14590 +# define APC_OPCODE_HANDLER_COUNT ((25 * 159) + 1) /* 5 new opcodes in 5.4 - qm_assign_var, jmp_set_var, separate, bind_trais, add_trait */
14591 +# elif PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3
14592 +# define APC_OPCODE_HANDLER_COUNT ((25 * 154) + 1) /* 3 new opcodes in 5.3 - unused, lambda, jmp_set */
14594 +# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1)
14596 +# 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; }
14599 +# define APC_ZEND_ONLINE
14600 +# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode)
14601 +# define APC_OPCODE_HANDLER_COUNT 512
14602 +# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname;
14605 +#ifndef ZEND_FASTCALL /* Added in ZE2.3.0 */
14606 +#define ZEND_FASTCALL
14609 +/* Added in ZE2.3.0 */
14610 +#ifndef zend_parse_parameters_none
14611 +# define zend_parse_parameters_none() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
14615 +#endif /* APC_OPCODE_OVERRIDE */
14617 +#ifdef ZEND_ENGINE_2_4
14618 +# define ZEND_CE_FILENAME(ce) (ce)->info.user.filename
14619 +# define ZEND_CE_DOC_COMMENT(ce) (ce)->info.user.doc_comment
14620 +# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->info.user.doc_comment_len
14621 +# define ZEND_CE_BUILTIN_FUNCTIONS(ce) (ce)->info.internal.builtin_functions
14623 +# define ZEND_CE_FILENAME(ce) (ce)->filename
14624 +# define ZEND_CE_DOC_COMMENT(ce) (ce)->doc_comment
14625 +# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->doc_comment_len
14626 +# define ZEND_CE_BUILTIN_FUNCTIONS(ce) (ce)->builtin_functions
14629 +#endif /* APC_ZEND_H */
14632 + * Local variables:
14634 + * c-basic-offset: 4
14636 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14637 + * vim<600: expandtab sw=4 ts=4 sts=4
14639 diff -Naur a/ext/apc/CHANGELOG b/ext/apc/CHANGELOG
14640 --- a/ext/apc/CHANGELOG 1970-01-01 01:00:00.000000000 +0100
14641 +++ b/ext/apc/CHANGELOG 2012-07-20 00:10:35.000000000 +0200
14644 +3.1.2 : 2008-12-12
14646 +- pecl package.xml/build fixes (bjori)
14648 +3.1.1 : 2008-12-12
14650 +- PHP4 compatibilty break
14651 +- apc_pool allocator (Gopal)
14652 +- doubly-linked sma allocator (Shire)
14653 +- php 5.3 gc compatibility (Gopal)
14654 +- APCIterator for easy access (Shire)
14655 +- apc_delete_file (Shire)
14656 +- apc_inc/apc_dec/apc_cas functions (Shire)
14657 +- apc.canonicalize (Gopal)
14658 +- apc.preload_path (Gopal)
14659 +- apc.rfc1867_ttl (Shire)
14660 +- apc.file_md5 (Shire)
14661 +- consolidate locking macros (Shire)
14662 +- remove futex/TSRM locks (Shire)
14663 +- non-blocking semaphore locks (Shire)
14664 +- zval* object rework (Gopal)
14666 +3.0.19: 2008-05-14
14667 +- Safe-mode and fast-cgi fixes
14668 +- Fix double-free of builtin_functions
14671 +3.0.18: 2008-03-29
14672 +- Revert apc_expunge_cb bug-fix
14675 +3.0.17: 2008-03-26
14677 +- Fix apc_add() cache expunge bug (Rasmus)
14678 +- Added parameter to apc_fetch to determine success/failure when fetching booleans (shire)
14679 +- Fix misc. memleaks (shire)
14681 +3.0.16: 2007-12-26
14682 +- Fix for longstanding cache-full crash (Christian Seiler)
14683 + http://news.php.net/php.pecl.dev/4951 for the details
14684 +- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
14685 +- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
14686 +- Minor cleanups (Lucas Nealan)
14687 +- Added configure option to enable apc_cache_info('filehits') (Shire)
14689 +3.0.15: 2007-10-18
14690 +- Eliminate a per-request time() syscall (Rasmus)
14691 +- Added rfc1867 prefix, name, and freq ini options (Shire)
14692 +- Allow deletion of individual user cache entries via apc.php (Sara)
14693 +- Fix overzealous cleanup during RSHUTDOWN (Gopal)
14694 +- Fix memory alignment and locking issues (Gopal)
14695 +- Make apc_compile insert/replace entries (Shire)
14696 +- Make mixed inheritance recompile & cache afresh (Gopal)
14697 +- Make nostat mode search include_path for canonicalization (Gopal)
14698 +- ZTS & other compile fixes (Gopal, Edin, Shire)
14700 +3.0.14: 2007-03-21
14701 +- Build fix (Shire)
14702 +- Don't hook the upload hook if APC is disabled (Rasmus)
14703 +- Local shadow cache support (Gopal)
14704 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
14705 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
14706 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
14707 +- Allocator fixes to reduce fragmentation (Gopal)
14709 +3.0.13: 2007-02-24
14710 +- File upload progress (Rasmus)
14711 +- Pthread mutex and spin locks (Shire)
14712 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
14713 +- apc.stat_ctime flag for ctime checks (Rasmus)
14714 +- Multiple key fetches with apc_fetch (Shire)
14715 +- Canary checks for shm memory deallocation (Gopal)
14716 +- Add hooks for external optimizer (Shire)
14717 +- Obsolete and remove apc optimizer (Gopal)
14718 +- APC info changes - cache insert rate, hit and miss rates (Shire)
14719 +- Fix apc_load_constants (Gopal)
14720 +- Rewrite dump opcode code to use vld (Gopal)
14721 +- Use apc_[ewn]print functions for error reporting (Shire)
14722 +- Auto global fixes and refactoring (Gopal, Shire)
14723 +- Fix memory leaks in object serialization (Ilia)
14724 +- Memory cleanup code for destructor order (Gopal)
14725 +- Win32 build fixes (Ilia, Wez)
14726 +- ZTS and Php 4 build fixes (Bjori)
14727 +- Add apc_add() function (Rasmus)
14728 +- Add optional limited flag to apc_sma_info() (Rasmus)
14730 +3.0.12p2: 2006-09-05
14731 +- Package version up
14733 +3.0,12p1: 2006-09-05
14734 +- PHP4 build fixes
14736 +3.0.12: 2006-09-05
14737 +- PHP 5.2 compatibility (Gopal)
14738 +- TSRM fixes (Gopal)
14739 +- Add extra flags to op_array->reserved to improve op array
14740 + processing code (Gopal)
14741 +- Fix crashes in optimizer and cli mode (Ilia)
14742 +- Optimizer fixes for PHP5 (Ilia, Gopal)
14743 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
14744 +- Php 4 function table and properties fixes (Gopal)
14745 +- Fix memory leaks in apc_cache_info (Gopal)
14747 +3.0.11: 2006-08-16
14748 +- Made --enable-apc-mmap the default compile option (for real this time)
14749 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
14750 + only fetch header information to make it useful when you have tens of
14751 + thousands of entries. (Brian Shire)
14752 +- 64-bit fixes (George)
14753 +- Don't mix Full Path and Inode keys (George)
14754 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
14755 + require_once() and include_once() statements. (Sara)
14756 +- Add a non-blocking write_lock for cache inserts. This is a better approach
14757 + to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
14758 +- A bit of work on the optimizer. (Sara)
14759 +- Various memory issues resolved. (Gopal)
14761 +3.0.10: 2006-03-11
14762 +- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
14763 + includes will not be stat'ed for any changes. You will have to restart the server if you
14764 + change anything. This mode increases performance quite a bit, especially if you have a
14767 +- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
14768 + than it solves. I'll need to revisit locking and signal handling at some point soon.
14771 +- Eliminate rand() call when slam_defense is not set (Rasmus)
14772 +- Fix for __isset problem (Gopal)
14773 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
14774 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
14775 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
14776 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
14777 +- Add automatic serialization of objects in apc_store() (Marcus)
14778 +- 64-bit .ini flag fix (Rasmus)
14779 +- Static members fix (Gopal)
14780 +- sma_cleanup() mem leak fix (Rasmus)
14781 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
14782 +- Fix autoglobals JIT bug (Gopal)
14783 +- Fix instance bug (Gopal)
14784 +- Add a lock cleanup safety net to request shutdown (Rasmus)
14785 +- Fix apc.slam_defense edge-case bug (Rasmus)
14786 +- User entry memory usage tracking support (Ilia)
14787 +- 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)
14790 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
14791 +Cache corruption fix in cache-full cleanup code (Gopal)
14794 +- Fix to apc.php to show final segment in frag chart. (Ilia)
14795 +- A couple of win32 fixes. (Frank)
14796 +- Add apc.enable_cli ini directive. (Rasmus)
14797 +- Add test cases. (Marcus)
14798 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
14799 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
14800 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
14801 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
14804 +- Added apc.php to package.xml file.
14805 +- Track per-entry memory usage. (Val)
14806 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
14807 +- fcntl locking robustness fixes. (Rasmus)
14808 +- Shared read-locks where possible. (Rasmus)
14809 +- Added file_update_protection configuration parameter. (Rasmus)
14810 +- Windows ZTS fixes (Frank)
14813 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
14814 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
14815 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
14816 +- Segfault in cache cleanup code (Ilia, Rasmus)
14819 +- Add win32 support (Edin )
14820 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
14821 +- A couple of other minor fixes
14824 +- Fix compile problem against PHP 5.0.x
14827 +- Better shm error message
14833 +- PHP 5.1 support (Arun, Gopal, Rasmus)
14834 +- Major Inheritance bug fix (Arun, Gopal)
14837 +- ground-up rewrite sharing none of the original source code (djc)
14840 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
14841 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
14842 + this parameter to your php.ini file to activate apc shm or mmap caching
14843 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
14845 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
14846 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
14847 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
14848 +- fixed regex support [gws 2001-05-16]
14849 +- enhanced reader-writer lock support [rg 2001-05-07]
14852 +- fixed (?) memory alignment bug on 64 bit archiecures
14853 +- added many cache visibiliy functions
14854 +- added opional fcntl locks under shm version
14855 +- numerous bug fixes
14858 +- added ability to detect and decompile compiled files placed as 'source'
14859 + [gws,dw 2001-01-30]
14860 +- fixed apc_rstat bug [gws 2001-01-29]
14861 +- added hack to support included urls [gws 2001-01-30]
14862 +- fixed apc_cache_index [mb 2001-01-31]
14863 +- added multiple regex support [gs 2001-02-03]
14864 +- added apc_cache_info [mb,gs 2001-02-03]
14867 +- partially fixed for Solaris [gws 2001-01-29]
14868 +- fixed mtime support for relative includes [gws 2001-01-29]
14869 +- code cleanup [yg,ta,gws 2001-01-29]
14872 +- support for mtime in mmap [yg,gws 2001-01-27]
14873 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
14876 +- support for relative include paths [djc,gws 2001-01-19]
14877 +- class member array support fixed [djc 2001-01-18]
14878 +- added apc_cache_index [gws 2001-01-18]
14881 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
14884 +- fixed support for class inheritance [djc 2001-01-16]
14887 +- support for inherited classes [gws 2001-01-15]
14888 +- support for intialization of class variables and objects [gws 2001-01-13]
14891 +- added optional file modification time check [djc 2001-01-12]
14892 diff -Naur a/ext/apc/config.m4 b/ext/apc/config.m4
14893 --- a/ext/apc/config.m4 1970-01-01 01:00:00.000000000 +0100
14894 +++ b/ext/apc/config.m4 2012-07-20 00:10:35.000000000 +0200
14897 +dnl $Id: config.m4 326700 2012-07-19 11:56:57Z ab $
14900 +PHP_ARG_ENABLE(apc, whether to enable APC support,
14901 +[ --enable-apc Enable APC support])
14903 +AC_ARG_ENABLE(apc-debug,
14904 +[ --enable-apc-debug Enable APC debugging],
14906 + PHP_APC_DEBUG=$enableval
14912 +AC_MSG_CHECKING(whether we should enable cache request file info)
14913 +AC_ARG_ENABLE(apc-filehits,
14914 +[ --enable-apc-filehits Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
14916 + PHP_APC_FILEHITS=$enableval
14917 + AC_MSG_RESULT($enableval)
14920 + PHP_APC_FILEHITS=no
14921 + AC_MSG_RESULT(no)
14924 +AC_MSG_CHECKING(whether we should use mmap)
14925 +AC_ARG_ENABLE(apc-mmap,
14926 +[ --disable-apc-mmap
14927 + Disable mmap support and use IPC shm instead],
14929 + PHP_APC_MMAP=$enableval
14930 + AC_MSG_RESULT($enableval)
14933 + AC_MSG_RESULT(yes)
14936 +AC_MSG_CHECKING(whether we should use semaphore locking instead of fcntl)
14937 +AC_ARG_ENABLE(apc-sem,
14938 +[ --enable-apc-sem
14939 + Enable semaphore locks instead of fcntl],
14941 + PHP_APC_SEM=$enableval
14942 + AC_MSG_RESULT($enableval)
14945 + AC_MSG_RESULT(no)
14948 +AC_MSG_CHECKING(whether we should use pthread mutex locking)
14949 +AC_ARG_ENABLE(apc-pthreadmutex,
14950 +[ --disable-apc-pthreadmutex
14951 + Disable pthread mutex locking ],
14953 + PHP_APC_PTHREADMUTEX=$enableval
14954 + AC_MSG_RESULT($enableval)
14957 + PHP_APC_PTHREADMUTEX=yes
14958 + AC_MSG_RESULT(yes)
14961 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
14962 + orig_LIBS="$LIBS"
14963 + LIBS="$LIBS -lpthread"
14966 + #include <sys/types.h>
14967 + #include <pthread.h>
14969 + pthread_mutex_t mutex;
14970 + pthread_mutexattr_t attr;
14972 + if(pthread_mutexattr_init(&attr)) {
14973 + puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
14976 + if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
14977 + puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
14980 + if(pthread_mutex_init(&mutex, &attr)) {
14981 + puts("Unable to initialize the mutex (pthread_mutex_init).");
14984 + if(pthread_mutexattr_destroy(&attr)) {
14985 + puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
14988 + if(pthread_mutex_destroy(&mutex)) {
14989 + puts("Unable to destroy mutex (pthread_mutex_destroy).");
14993 + puts("pthread mutexs are supported!");
14998 + PHP_ADD_LIBRARY(pthread)
15001 + AC_MSG_WARN([It doesn't appear that pthread mutexes are supported on your system])
15002 + PHP_APC_PTHREADMUTEX=no
15005 + PHP_ADD_LIBRARY(pthread)
15008 + LIBS="$orig_LIBS"
15011 +AC_MSG_CHECKING(whether we should use pthread read/write locking)
15012 +AC_ARG_ENABLE(apc-pthreadrwlocks,
15013 +[ --enable-apc-pthreadrwlocks
15014 + Enable pthread read/write locking ],
15016 + PHP_APC_PTHREADRWLOCK=$enableval
15017 + AC_MSG_RESULT($enableval)
15020 + PHP_APC_PTHREADRWLOCK=no
15021 + AC_MSG_RESULT(no)
15024 +if test "$PHP_APC_PTHREADRWLOCK" != "no"; then
15025 + orig_LIBS="$LIBS"
15026 + LIBS="$LIBS -lpthread"
15029 + #include <sys/types.h>
15030 + #include <pthread.h>
15032 + pthread_rwlock_t rwlock;
15033 + pthread_rwlockattr_t attr;
15035 + if(pthread_rwlockattr_init(&attr)) {
15036 + puts("Unable to initialize pthread attributes (pthread_rwlockattr_init).");
15039 + if(pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
15040 + puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_rwlockattr_setpshared), your system may not support shared rwlock's.");
15043 + if(pthread_rwlock_init(&rwlock, &attr)) {
15044 + puts("Unable to initialize the rwlock (pthread_rwlock_init).");
15047 + if(pthread_rwlockattr_destroy(&attr)) {
15048 + puts("Unable to destroy rwlock attributes (pthread_rwlockattr_destroy).");
15051 + if(pthread_rwlock_destroy(&rwlock)) {
15052 + puts("Unable to destroy rwlock (pthread_rwlock_destroy).");
15056 + puts("pthread rwlocks are supported!");
15061 + PHP_ADD_LIBRARY(pthread)
15062 + APC_CFLAGS="-D_GNU_SOURCE"
15065 + AC_MSG_WARN([It doesn't appear that pthread rwlocks are supported on your system])
15066 + PHP_APC_PTHREADRWLOCK=no
15069 + PHP_ADD_LIBRARY(pthread)
15072 + LIBS="$orig_LIBS"
15075 + AC_CACHE_CHECK([whether the target compiler supports builtin atomics], PHP_cv_APC_GCC_ATOMICS, [
15079 + __sync_fetch_and_add(&foo, 1);
15080 + __sync_bool_compare_and_swap(&foo, 0, 1);
15081 + return __sync_fetch_and_add(&foo, 1);
15083 + [PHP_cv_APC_GCC_ATOMICS=yes],
15084 + [PHP_cv_APC_GCC_ATOMICS=no])
15087 + if test "x${PHP_cv_APC_GCC_ATOMICS}" != "xno"; then
15088 + AC_DEFINE(HAVE_ATOMIC_OPERATIONS, 1,
15089 + [Define this if your target compiler supports builtin atomics])
15091 + if test "$PHP_APC_PTHREADRWLOCK" != "no"; then
15092 + AC_MSG_WARN([Disabling pthread rwlocks, because of missing atomic operations])
15093 + dnl - fall back would most likely be pthread mutexes
15094 + PHP_APC_PTHREADRWLOCK=no
15098 +AC_MSG_CHECKING(whether we should use spin locks)
15099 +AC_ARG_ENABLE(apc-spinlocks,
15100 +[ --enable-apc-spinlocks
15101 + Enable spin locks EXPERIMENTAL ],
15103 + PHP_APC_SPINLOCKS=$enableval
15104 + AC_MSG_RESULT($enableval)
15107 + PHP_APC_SPINLOCKS=no
15108 + AC_MSG_RESULT(no)
15112 +AC_MSG_CHECKING(whether we should enable memory protection)
15113 +AC_ARG_ENABLE(apc-memprotect,
15114 +[ --enable-apc-memprotect
15115 + Enable mmap/shm memory protection],
15117 + PHP_APC_MEMPROTECT=$enableval
15118 + AC_MSG_RESULT($enableval)
15120 + PHP_APC_MEMPROTECT=no
15121 + AC_MSG_RESULT(no)
15124 +if test "$PHP_APC" != "no"; then
15125 + test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
15126 + test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
15128 + if test "$PHP_APC_DEBUG" != "no"; then
15129 + AC_DEFINE(__DEBUG_APC__, 1, [ ])
15132 + if test "$PHP_APC_SEM" != "no"; then
15133 + AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
15134 + elif test "$PHP_APC_SPINLOCKS" != "no"; then
15135 + AC_DEFINE(APC_SPIN_LOCKS, 1, [ ])
15136 + elif test "$PHP_APC_PTHREADRWLOCK" != "no"; then
15137 + AC_DEFINE(APC_PTHREADRW_LOCKS, 1, [ ])
15138 + elif test "$PHP_APC_PTHREADMUTEX" != "no"; then
15139 + AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
15141 + AC_DEFINE(APC_FCNTL_LOCKS, 1, [ ])
15144 + if test "$PHP_APC_MEMPROTECT" != "no"; then
15145 + AC_DEFINE(APC_MEMPROTECT, 1, [ shm/mmap memory protection ])
15148 + AC_CACHE_CHECK(for zend_set_lookup_function_hook, php_cv_zend_set_lookup_function_hook,
15150 + orig_cflags=$CFLAGS
15151 + CFLAGS="$INCLUDES $EXTRA_INCLUDES"
15153 +#include "main/php.h"
15154 +#include "Zend/zend_API.h"
15155 + ], [#ifndef zend_set_lookup_function_hook
15156 + (void) zend_set_lookup_function_hook;
15158 + php_cv_zend_set_lookup_function_hook=yes
15160 + php_cv_zend_set_lookup_function_hook=no
15162 + CFLAGS=$orig_cflags
15164 + if test "$php_cv_zend_set_lookup_function_hook" = "yes"; then
15165 + AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 1, [ ])
15167 + AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 0, [ ])
15170 + AC_CHECK_FUNCS(sigaction)
15171 + AC_CACHE_CHECK(for union semun, php_cv_semun,
15174 +#include <sys/types.h>
15175 +#include <sys/ipc.h>
15176 +#include <sys/sem.h>
15177 + ], [union semun x; x.val=1], [
15183 + if test "$php_cv_semun" = "yes"; then
15184 + AC_DEFINE(HAVE_SEMUN, 1, [ ])
15186 + AC_DEFINE(HAVE_SEMUN, 0, [ ])
15189 + AC_MSG_CHECKING(whether we should enable valgrind support)
15190 + AC_ARG_ENABLE(valgrind-checks,
15191 + [ --disable-valgrind-checks
15192 + Disable valgrind based memory checks],
15194 + PHP_APC_VALGRIND=$enableval
15195 + AC_MSG_RESULT($enableval)
15197 + PHP_APC_VALGRIND=yes
15198 + AC_MSG_RESULT(yes)
15199 + AC_CHECK_HEADER(valgrind/memcheck.h,
15200 + [AC_DEFINE([HAVE_VALGRIND_MEMCHECK_H],1, [enable valgrind memchecks])])
15203 + apc_sources="apc.c php_apc.c \
15212 + apc_pthreadmutex.c \
15213 + apc_pthreadrwlock.c \
15226 + PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
15227 + PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
15228 + PHP_SUBST(APC_SHARED_LIBADD)
15229 + PHP_SUBST(APC_CFLAGS)
15230 + PHP_INSTALL_HEADERS(ext/apc, [apc_serializer.h])
15231 + AC_DEFINE(HAVE_APC, 1, [ ])
15234 +PHP_ARG_ENABLE(coverage, whether to include code coverage symbols,
15235 +[ --enable-coverage DEVELOPERS ONLY!!], no, no)
15237 +if test "$PHP_COVERAGE" = "yes"; then
15239 + if test "$GCC" != "yes"; then
15240 + AC_MSG_ERROR([GCC is required for --enable-coverage])
15243 + dnl Check if ccache is being used
15244 + case `$php_shtool path $CC` in
15245 + *ccache*[)] gcc_ccache=yes;;
15246 + *[)] gcc_ccache=no;;
15249 + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
15250 + AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
15253 + lcov_version_list="1.5 1.6 1.7 1.9"
15255 + AC_CHECK_PROG(LCOV, lcov, lcov)
15256 + AC_CHECK_PROG(GENHTML, genhtml, genhtml)
15258 + PHP_SUBST(GENHTML)
15260 + if test "$LCOV"; then
15261 + AC_CACHE_CHECK([for lcov version], php_cv_lcov_version, [
15262 + php_cv_lcov_version=invalid
15263 + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` #'
15264 + for lcov_check_version in $lcov_version_list; do
15265 + if test "$lcov_version" = "$lcov_check_version"; then
15266 + php_cv_lcov_version="$lcov_check_version (ok)"
15271 + lcov_msg="To enable code coverage reporting you must have one of the following LCOV versions installed: $lcov_version_list"
15272 + AC_MSG_ERROR([$lcov_msg])
15275 + case $php_cv_lcov_version in
15277 + lcov_msg="You must have one of the following versions of LCOV: $lcov_version_list (found: $lcov_version)."
15278 + AC_MSG_ERROR([$lcov_msg])
15283 + if test -z "$GENHTML"; then
15284 + AC_MSG_ERROR([Could not find genhtml from the LCOV package])
15287 + PHP_ADD_MAKEFILE_FRAGMENT
15289 + dnl Remove all optimization flags from CFLAGS
15291 + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'`
15292 + CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'`
15295 + dnl Add the special gcc flags
15296 + CFLAGS="$CFLAGS -O0 -ggdb -fprofile-arcs -ftest-coverage"
15297 + CXXFLAGS="$CXXFLAGS -ggdb -O0 -fprofile-arcs -ftest-coverage"
15300 diff -Naur a/ext/apc/config.w32 b/ext/apc/config.w32
15301 --- a/ext/apc/config.w32 1970-01-01 01:00:00.000000000 +0100
15302 +++ b/ext/apc/config.w32 2012-07-20 00:10:35.000000000 +0200
15304 +// $Id: config.w32 309203 2011-03-14 06:47:16Z pajoye $
15305 +// vim:ft=javascript
15307 +ARG_ENABLE('apc', 'Whether to enable APC support', 'no');
15308 +ARG_ENABLE('apc-debug', 'Whether to enable APC debugging', 'no');
15309 +ARG_ENABLE('apc-filehits', 'Whether to enable cache request file info', 'no');
15310 +ARG_ENABLE('apc-spinlocks', 'Whether to use spin locks (experimental)', 'no');
15311 +ARG_ENABLE('apc-memprotect', 'Whether to enable memory protection (experimental)', 'no');
15312 +ARG_ENABLE('apc-srwlock-native', 'Whether to use SRWLOCK locks native (win7/2008 only)', 'no');
15313 +ARG_ENABLE('apc-srwlock-kernel', 'Whether to use SRWLOCK locks (loaded at runtime)', 'no');
15315 +if(PHP_APC != 'no')
15317 + var apc_sources = 'apc.c php_apc.c apc_cache.c apc_compile.c apc_debug.c ' +
15318 + 'apc_fcntl_win32.c apc_iterator.c apc_main.c apc_shm.c ' +
15319 + 'apc_sma.c apc_stack.c apc_rfc1867.c apc_zend.c apc_pool.c ' +
15320 + 'apc_bin.c apc_string.c';
15322 + if(PHP_APC_DEBUG != 'no')
15324 + ADD_FLAG('CFLAGS_APC', '/D __DEBUG_APC__=1');
15327 + if(PHP_APC_FILEHITS != 'no')
15329 + AC_DEFINE('APC_FILEHITS', 1);
15332 + if(PHP_APC_MEMPROTECT != 'no')
15334 + AC_DEFINE('APC_MEMPROTECT', 1);
15337 + if(PHP_APC_SRWLOCK_NATIVE != 'no') {
15338 + AC_DEFINE('APC_SRWLOCK_NATIVE', 1);
15340 + if(PHP_APC_SRWLOCK_KERNEL != 'no') {
15341 + AC_DEFINE('APC_SRWLOCK_KERNEL', 1);
15342 + ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1');
15344 + apc_sources += ' apc_windows_srwlock_kernel.c';
15346 + if(PHP_APC_SPINLOCKS != 'no') {
15347 + AC_DEFINE('APC_SPIN_LOCKS', 1);
15348 + ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1');
15350 + apc_sources += ' apc_spin.c pgsql_s_lock.c';
15352 + AC_DEFINE('APC_FCNTL_LOCKS', 1);
15357 + AC_DEFINE('HAVE_APC', 1);
15358 + AC_DEFINE('HAVE_ATOMIC_OPERATIONS', 1);
15360 + PHP_INSTALL_HEADERS("ext/apc", "apc_serializer.h");
15362 + EXTENSION('apc', apc_sources);
15364 diff -Naur a/ext/apc/INSTALL b/ext/apc/INSTALL
15365 --- a/ext/apc/INSTALL 1970-01-01 01:00:00.000000000 +0100
15366 +++ b/ext/apc/INSTALL 2012-07-20 00:10:35.000000000 +0200
15368 +Installation Instructions for APC
15369 +---------------------------------
15371 +This version of APC should work on PHP 4.3.0 - 4.4.x and
15372 +5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer
15373 +supported. Upgrade to PHP 5.1.x or 5.2.x and you will
15374 +notice all sorts of performance increases.
15378 +Building from CVS can be done like this:
15380 + svn co http://svn.php.net/repository/pecl/apc/trunk apc
15383 + ./configure --with-php-config=/usr/local/php/bin/php-config
15385 + export TEST_PHP_ARGS='-n'
15389 +Suggested Configuration (in your php.ini file)
15390 +----------------------------------------------
15393 + apc.shm_size=128M
15395 + apc.user_ttl=7200
15398 +These are fully described at the bottom of this file.
15400 ++---------------------+
15401 +| QUICK INSTALL (DSO) |
15402 ++---------------------+
15404 +These instructions assume your PHP installation is located in /usr/local/php and you
15405 +want Apache optimizations (--with-apxs).
15407 +$ gunzip -c apc_x.y.tar.gz | tar xf -
15409 +$ /usr/local/php/bin/phpize
15410 +$ ./configure --with-php-config=/usr/local/php/bin/php-config
15414 +You will probably need to run the final command (make install) as root.
15416 +The above sequence of commands will install a .so file in your PHP
15417 +installation extension directory. The output of make install should display
15418 +that path to the screen.
15420 +Next you must edit your php.ini file, which is normally located in
15421 +/usr/local/php/lib/php.ini, and add the following line:
15423 + extension="apc.so"
15425 +Replace "/path/to/php/extensions" with whatever path was displayed when you
15426 +ran make install above.
15428 +Then restart your web server and consult the output of phpinfo(). If there is
15429 +an informational section for APC, the installation was successful.
15431 ++------------------------+
15432 +| QUICK INSTALL (Static) |
15433 ++------------------------+
15435 +APC will not successfully compile on all systems as a DSO. If you run into
15436 +problems using the DSO quick install, you can try to compile it statically
15437 +into PHP. (The DSO install is recommended, though.)
15439 +These instructions assume the current directory is the root of the PHP source
15440 +tree, and that you have already configured PHP by running its bundled
15444 +$ gunzip -c apc_x.y.tar.gz | tar xf -
15451 +Once this is complete, simply restart your web server. You do not need to
15452 +modify your php.ini file to enable APC.
15454 ++-----------------+
15455 +| VERBOSE INSTALL |
15456 ++-----------------+
15458 +These instructions assume your PHP installation is located in /usr/local/php.
15460 +1. Unpack your distribution file.
15462 + You will have downloaded a file named something like apc_x.y.tar.gz.
15463 + Unzip this file with a command like
15465 + gunzip apc_x.y.tar.gz
15467 + Next you have to untar it with
15469 + tar xvf apc_x.y.tar
15471 + This will create an apc_x.y directory. cd into this new directory:
15477 + phpize is a script that should have been installed with PHP, and is
15478 + normally located in /usr/local/php/bin assuming you installed PHP in
15479 + /usr/local/php. (If you do not have the phpize script, you must reinstall
15480 + PHP and be sure not to disable PEAR.)
15482 + Run the phpize command:
15484 + /usr/local/php/bin/phpize
15486 + Its output should resemble this:
15488 + autoheader: `config.h.in' is created
15489 + You should update your `aclocal.m4' by running aclocal.
15491 + PHP Api Version: 20020918
15492 + Zend Module Api No: 20020429
15493 + Zend Extension Api No: 20021010
15495 + phpize should create a configure script in the current directory. If you
15496 + get errors instead, you might be missing some required development tools,
15497 + such as autoconf or libtool. You can try downloading the latest versions
15498 + of those tools and running phpize again.
15500 +3. Run the configure script.
15502 + phpize creates a configure script. The only option you need to specify is
15503 + the location of your php-config script:
15505 + ./configure --enable-apc
15507 + php-config should be located in the same directory as phpize.
15509 + If you prefer to use mmap instead of the default IPC shared memory support,
15510 + add --enable-apc-mmap to your configure line.
15512 + If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
15513 + --enable-sem to your configure line. If you don't have a problem
15514 + with your server segaulting, or any other unnatural accumulation of
15515 + semaphores on your system, the semaphore based locking is slightly faster.
15517 +4. Compile and install the files. Simply type: make install
15519 + (You may need to be root in order to install)
15521 + If you encounter errors from libtool or gcc during this step, please
15522 + contact the project maintainer (dcowgill@php.net).
15524 +5. Edit your php.ini
15526 + make install should have printed a line resembling the following:
15528 + Installing shared extensions: /path/to/extension/
15530 + Copy the path /path/to/extension/ and add the following line to your
15531 + php.ini file (normally located in /usr/local/php/lib/php.ini):
15533 + extension="apc.so"
15535 + If you don't have a php.ini file in that location, you can create it now.
15537 +6. Restart the web server and test the installation.
15539 + Restart your web server now (for apache, it's apachectl restart) and
15540 + create a small test PHP file in your document root. The file should
15541 + contain just the following line:
15543 + <?php phpinfo() ?>
15545 + Request that file in a web browser. If there is an entry for APC in the
15546 + list of installed modules, the installation was successful.
15548 + If APC is not listed, consult your web server error log. If it contains an
15549 + error message saying that it can't load the APC extension, your system
15550 + might not be able to load shared libraries created with PHP's build
15551 + system. One alternative would be to compile APC statically into PHP. See
15552 + the Quick Install (Static) instructions above.
15554 + You should consult your error log anyway to see if APC generated any
15555 + errors. On BSD-based platforms, it is typical for APC to be unable to
15556 + allocate the default-sized shared memory segment. See below for hints on
15557 + raising your system's shared memory limitations.
15559 ++-----------------+
15560 +| CONFIGURING APC |
15561 ++-----------------+
15563 +Although the default APC settings are fine for many installations, serious
15564 +users should consider tuning the following parameters:
15566 + OPTION DESCRIPTION
15567 + ------------------ --------------------------------------------------
15568 + apc.enabled This can be set to 0 to disable APC. This is
15569 + primarily useful when APC is statically compiled
15570 + into PHP, since there is no other way to disable
15571 + it (when compiled as a DSO, the zend_extension
15572 + line can just be commented-out).
15575 + apc.shm_segments The number of shared memory segments to allocate
15576 + for the compiler cache. If APC is running out of
15577 + shared memory but you have already set
15578 + apc.shm_size as high as your system allows, you
15579 + can try raising this value. Setting this to a
15580 + value other than 1 has no effect in mmap mode
15581 + since mmap'ed shm segments don't have size limits.
15584 + apc.shm_size The size of each shared memory segment in MB.
15585 + By default, some systems (including most BSD
15586 + variants) have very low limits on the size of a
15587 + shared memory segment. M/G suffixes must be used.
15591 + apc.optimization This option has been deprecated.
15594 + apc.num_files_hint A "hint" about the number of distinct source files
15595 + that will be included or requested on your web
15596 + server. Set to zero or omit if you're not sure;
15597 + this setting is mainly useful for sites that have
15598 + many thousands of source files.
15601 + apc.user_entries_hint Just like num_files_hint, a "hint" about the number
15602 + of distinct user cache variables to store.
15603 + Set to zero or omit if you're not sure;
15606 + apc.ttl The number of seconds a cache entry is allowed to
15607 + idle in a slot in case this cache entry slot is
15608 + needed by another entry. Leaving this at zero
15609 + means that your cache could potentially fill up
15610 + with stale entries while newer entries won't be
15614 + apc.user_ttl The number of seconds a user cache entry is allowed
15615 + to idle in a slot in case this cache entry slot is
15616 + needed by another entry. Leaving this at zero
15617 + means that your cache could potentially fill up
15618 + with stale entries while newer entries won't be
15623 + apc.gc_ttl The number of seconds that a cache entry may
15624 + remain on the garbage-collection list. This value
15625 + provides a failsafe in the event that a server
15626 + process dies while executing a cached source file;
15627 + if that source file is modified, the memory
15628 + allocated for the old version will not be
15629 + reclaimed until this TTL reached. Set to zero to
15630 + disable this feature.
15633 + apc.cache_by_default On by default, but can be set to off and used in
15634 + conjunction with positive apc.filters so that files
15635 + are only cached if matched by a positive filter.
15638 + apc.filters A comma-separated list of POSIX extended regular
15639 + expressions. If any pattern matches the source
15640 + filename, the file will not be cached. Note that
15641 + the filename used for matching is the one passed
15642 + to include/require, not the absolute path. If the
15643 + first character of the expression is a + then the
15644 + expression will be additive in the sense that any
15645 + files matched by the expression will be cached, and
15646 + if the first character is a - then anything matched
15647 + will not be cached. The - case is the default, so
15648 + it can be left off.
15651 + apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap
15652 + this is the mktemp-style file_mask to pass to the
15653 + mmap module for determing whether your mmap'ed memory
15654 + region is going to be file-backed or shared memory
15655 + backed. For straight file-backed mmap, set it to
15656 + something like /tmp/apc.XXXXXX (exactly 6 X's).
15657 + To use POSIX-style shm_open/mmap put a ".shm"
15658 + somewhere in your mask. eg. "/apc.shm.XXXXXX"
15659 + You can also set it to "/dev/zero" to use your
15660 + kernel's /dev/zero interface to anonymous mmap'ed
15661 + memory. Leaving it undefined will force an
15665 + apc.slam_defense ** DEPRECATED - Use apc.write_lock instead **
15666 + On very busy servers whenever you start the server or
15667 + modify files you can create a race of many processes
15668 + all trying to cache the same file at the same time.
15669 + This option sets the percentage of processes that will
15670 + skip trying to cache an uncached file. Or think of it
15671 + as the probability of a single process to skip caching.
15672 + For example, setting this to 75 would mean that there is
15673 + a 75% chance that the process will not cache an uncached
15674 + file. So the higher the setting the greater the defense
15675 + against cache slams. Setting this to 0 disables this
15679 + apc.file_update_protection
15680 + When you modify a file on a live web server you really
15681 + should do so in an atomic manner. That is, write to a
15682 + temporary file and rename (mv) the file into its permanent
15683 + position when it is ready. Many text editors, cp, tar and
15684 + other such programs don't do this. This means that there
15685 + is a chance that a file is accessed (and cached) while it
15686 + is still being written to. This file_update_protection
15687 + setting puts a delay on caching brand new files. The
15688 + default is 2 seconds which means that if the modification
15689 + timestamp (mtime) on a file shows that it is less than 2
15690 + seconds old when it is accessed, it will not be cached.
15691 + The unfortunate person who accessed this half-written file
15692 + will still see weirdness, but at least it won't persist.
15693 + If you are certain you always atomically update your files
15694 + by using something like rsync which does this correctly, you
15695 + can turn this protection off by setting it to 0. If you
15696 + have a system that is flooded with io causing some update
15697 + procedure to take longer than 2 seconds, you may want to
15698 + increase this a bit.
15701 + apc.enable_cli Mostly for testing and debugging. Setting this enables APC
15702 + for the CLI version of PHP. Normally you wouldn't want to
15703 + create, populate and tear down the APC cache on every CLI
15704 + request, but for various test scenarios it is handy to be
15705 + able to enable APC for the CLI version of APC easily.
15708 + apc.max_file_size Prevents large files from being cached.
15711 + apc.stat Whether to stat the main script file and the fullpath
15712 + includes. If you turn this off you will need to restart
15713 + your server in order to update scripts.
15716 + apc.canonicalize Whether to canonicalize paths in stat=0 mode or
15717 + fall back to stat behaviour if set to 0
15720 + apc.write_lock On busy servers when you first start up the server, or when
15721 + many files are modified, you can end up with all your processes
15722 + trying to compile and cache the same files. With write_lock
15723 + enabled, only one process at a time will try to compile an
15724 + uncached script while the other processes will run uncached
15725 + instead of sitting around waiting on a lock.
15728 + apc.report_autofilter Logs any scripts that were automatically excluded from being
15729 + cached due to early/late binding issues.
15732 + apc.rfc1867 RFC1867 File Upload Progress hook handler is only available
15733 + if you compiled APC against PHP 5.2.0 or later. When enabled
15734 + any file uploads which includes a field called
15735 + APC_UPLOAD_PROGRESS before the file field in an upload form
15736 + will cause APC to automatically create an upload_<key>
15737 + user cache entry where <key> is the value of the
15738 + APC_UPLOAD_PROGRESS form entry.
15740 + Note that the file upload tracking is not threadsafe at this
15741 + point, so new uploads that happen while a previous one is
15742 + still going will disable the tracking for the previous.
15745 + apc.rfc1867_prefix Key prefix to use for the user cache entry generated by
15746 + rfc1867 upload progress functionality.
15747 + (Default: "upload_")
15749 + apc.rfc1867_name Specify the hidden form entry name that activates APC upload
15750 + progress and specifies the user cache key suffix.
15751 + (Default: "APC_UPLOAD_PROGRESS")
15753 + apc.rfc1867_freq The frequency that updates should be made to the user cache
15754 + entry for upload progress. This can take the form of a
15755 + percentage of the total file size or a size in bytes
15756 + optionally suffixed with 'k', 'm', or 'g' for kilobytes,
15757 + megabytes, or gigabytes respectively (case insensitive).
15758 + A setting of 0 updates as often as possible, which may cause
15762 + apc.localcache ** REMOVED
15763 + apc.localcache.size ** REMOVED
15765 + apc.include_once_override
15766 + Optimize include_once and require_once calls and avoid the
15767 + expensive system calls used.
15771 + Defines which serializer should be used. Default is the
15772 + standard PHP serializer. Other can be used without having
15773 + to re compile apc, like igbinary for example.
15774 + (apc.serializer=igbinary)
15775 diff -Naur a/ext/apc/LICENSE b/ext/apc/LICENSE
15776 --- a/ext/apc/LICENSE 1970-01-01 01:00:00.000000000 +0100
15777 +++ b/ext/apc/LICENSE 2012-07-20 00:10:35.000000000 +0200
15779 +--------------------------------------------------------------------
15780 + The PHP License, version 3.01
15781 +Copyright (c) 1999 - 2011 The PHP Group. All rights reserved.
15782 +--------------------------------------------------------------------
15784 +Redistribution and use in source and binary forms, with or without
15785 +modification, is permitted provided that the following conditions
15788 + 1. Redistributions of source code must retain the above copyright
15789 + notice, this list of conditions and the following disclaimer.
15791 + 2. Redistributions in binary form must reproduce the above copyright
15792 + notice, this list of conditions and the following disclaimer in
15793 + the documentation and/or other materials provided with the
15796 + 3. The name "PHP" must not be used to endorse or promote products
15797 + derived from this software without prior written permission. For
15798 + written permission, please contact group@php.net.
15800 + 4. Products derived from this software may not be called "PHP", nor
15801 + may "PHP" appear in their name, without prior written permission
15802 + from group@php.net. You may indicate that your software works in
15803 + conjunction with PHP by saying "Foo for PHP" instead of calling
15804 + it "PHP Foo" or "phpfoo"
15806 + 5. The PHP Group may publish revised and/or new versions of the
15807 + license from time to time. Each version will be given a
15808 + distinguishing version number.
15809 + Once covered code has been published under a particular version
15810 + of the license, you may always continue to use it under the terms
15811 + of that version. You may also choose to use such covered code
15812 + under the terms of any subsequent version of the license
15813 + published by the PHP Group. No one other than the PHP Group has
15814 + the right to modify the terms applicable to covered code created
15815 + under this License.
15817 + 6. Redistributions of any form whatsoever must retain the following
15819 + "This product includes PHP software, freely available from
15820 + <http://www.php.net/software/>".
15822 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
15823 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15824 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15825 +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
15826 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15827 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15828 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
15829 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15830 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
15831 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15832 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
15833 +OF THE POSSIBILITY OF SUCH DAMAGE.
15835 +--------------------------------------------------------------------
15837 +This software consists of voluntary contributions made by many
15838 +individuals on behalf of the PHP Group.
15840 +The PHP Group can be contacted via Email at group@php.net.
15842 +For more information on the PHP Group and the PHP project,
15843 +please see <http://www.php.net>.
15845 +PHP includes the Zend Engine, freely available at
15846 +<http://www.zend.com>.
15847 diff -Naur a/ext/apc/NOTICE b/ext/apc/NOTICE
15848 --- a/ext/apc/NOTICE 1970-01-01 01:00:00.000000000 +0100
15849 +++ b/ext/apc/NOTICE 2012-07-20 00:10:35.000000000 +0200
15851 +This is the NOTICE file that holds acknowledgements and stuff.
15853 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
15854 +This extension is being released under the PHP License for complete compliance
15855 +with PHP and to encourage wide-spread use. It is our intention that this
15856 +project be kept open source and that all commercial spin-offs contribute their
15857 +modifications back into the public source-tree.
15861 + George Schlossnagle
15863 +PHP5 support and major features by:
15865 + Gopal Vijayaraghavan
15868 +This software was contributed to PHP by Community Connect Inc. in 2002
15869 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
15870 +Future revisions and derivatives of this source code must acknowledge
15871 +Community Connect Inc. as the original contributor of this module by
15872 +leaving this note intact in the source code.
15874 +All other licensing and usage conditions are those of the PHP Group.
15876 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting
15877 +this project and providing a challenging and stimulating environment in
15878 +which exciting projects can happen.
15881 + Mike Bretz bug fixes, GUI, and lots of work
15882 + Ricardo Galli changed read-write locks to prefer readers
15883 + Yann Grossel bug fixes
15884 + Thies Arntzen bug fixes
15885 + Sara Golemon optimizer work
15888 + Florian Baumert help debugging phplib problems
15889 + Thomas Duffey help debugging inheritance issues
15890 + Vibol Hou help debugging phplib problems
15891 + Angel Li diffs for ANSI comment compliance
15892 + Christian Rishøj help debugging phplib problems
15893 + Sascha Schumann memory error bug fix
15894 diff -Naur a/ext/apc/pgsql_s_lock.c b/ext/apc/pgsql_s_lock.c
15895 --- a/ext/apc/pgsql_s_lock.c 1970-01-01 01:00:00.000000000 +0100
15896 +++ b/ext/apc/pgsql_s_lock.c 2012-07-20 00:10:35.000000000 +0200
15899 + +----------------------------------------------------------------------+
15901 + +----------------------------------------------------------------------+
15902 + | Copyright (c) 2006-2011 The PHP Group |
15903 + +----------------------------------------------------------------------+
15904 + | This source file is subject to version 3.01 of the PHP license, |
15905 + | that is bundled with this package in the file LICENSE, and is |
15906 + | available through the world-wide-web at the following url: |
15907 + | http://www.php.net/license/3_01.txt |
15908 + | If you did not receive a copy of the PHP license and are unable to |
15909 + | obtain it through the world-wide-web, please send a note to |
15910 + | license@php.net so we can mail you a copy immediately. |
15911 + +----------------------------------------------------------------------+
15912 + | The following code was ported from the PostgreSQL project, please |
15913 + | see appropriate copyright notices that follow. |
15914 + | Initial conversion by Brian Shire <shire@php.net> |
15915 + +----------------------------------------------------------------------+
15919 +/* $Id: pgsql_s_lock.c 307048 2011-01-03 23:53:17Z kalle $ */
15921 +/*-------------------------------------------------------------------------
15924 + * Hardware-dependent implementation of spinlocks.
15927 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
15928 + * Portions Copyright (c) 1994, Regents of the University of California
15932 + * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
15934 + *-------------------------------------------------------------------------
15936 +/* #include "postgres.h" -- Removed for APC */
15938 +/* -- Added for APC -- */
15940 +#ifdef APC_SPIN_LOCKS
15942 +#ifdef S_LOCK_TEST
15943 +#include <stdio.h>
15946 +#include <sys/select.h>
15952 +#include "win32/unistd.h"
15954 +#include <unistd.h>
15957 +/* #include "storage/s_lock.h" -- Removed for APC */
15958 +#include "pgsql_s_lock.h"
15960 +static int spins_per_delay = DEFAULT_SPINS_PER_DELAY;
15963 +/* -- APC specific additions ------------------------------*/
15964 +/* The following dependencies have been copied from
15965 + * other pgsql source files. The original locations
15966 + * have been noted.
15969 +/* -- from include/c.h -- */
15978 +/* -- from include/pg_config_manual.h -- */
15979 +#define MAX_RANDOM_VALUE (0x7FFFFFFF)
15983 + * Return the maximum of two numbers.
15985 +#define Max(x, y) ((x) > (y) ? (x) : (y))
15987 +/* -- from include/c.h -- */
15990 + * Return the minimum of two numbers.
15992 +#define Min(x, y) ((x) < (y) ? (x) : (y))
15995 +/* -- from backend/port/win32/signal.c -- */
15997 + * pg_usleep --- delay the specified number of microseconds.
15999 + * NOTE: although the delay is specified in microseconds, the effective
16000 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
16001 + * the requested delay to be rounded up to the next resolution boundary.
16003 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
16006 +pg_usleep(long microsec)
16008 + if (microsec > 0)
16011 + struct timeval delay;
16013 + delay.tv_sec = microsec / 1000000L;
16014 + delay.tv_usec = microsec % 1000000L;
16015 + (void) select(0, NULL, NULL, NULL, &delay);
16017 + SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
16022 +/* -- End APC specific additions ------------------------------*/
16026 + * s_lock_stuck() - complain about a stuck spinlock
16029 +s_lock_stuck(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
16031 +#if defined(S_LOCK_TEST)
16033 + "\nStuck spinlock (%p) detected at %s:%d.\n",
16034 + lock, file, line);
16037 + /* -- Removed for APC
16038 + elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
16039 + lock, file, line);
16041 + apc_error("Stuck spinlock (%p) detected" TSRMLS_CC, lock);
16047 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
16050 +s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
16053 + * We loop tightly for awhile, then delay using pg_usleep() and try again.
16054 + * Preferably, "awhile" should be a small multiple of the maximum time we
16055 + * expect a spinlock to be held. 100 iterations seems about right as an
16056 + * initial guess. However, on a uniprocessor the loop is a waste of
16057 + * cycles, while in a multi-CPU scenario it's usually better to spin a bit
16058 + * longer than to call the kernel, so we try to adapt the spin loop count
16059 + * depending on whether we seem to be in a uniprocessor or multiprocessor.
16061 + * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
16062 + * be wrong; there are platforms where that can result in a "stuck
16063 + * spinlock" failure. This has been seen particularly on Alphas; it seems
16064 + * that the first TAS after returning from kernel space will always fail
16065 + * on that hardware.
16067 + * Once we do decide to block, we use randomly increasing pg_usleep()
16068 + * delays. The first delay is 1 msec, then the delay randomly increases to
16069 + * about one second, after which we reset to 1 msec and start again. The
16070 + * idea here is that in the presence of heavy contention we need to
16071 + * increase the delay, else the spinlock holder may never get to run and
16072 + * release the lock. (Consider situation where spinlock holder has been
16073 + * nice'd down in priority by the scheduler --- it will not get scheduled
16074 + * until all would-be acquirers are sleeping, so if we always use a 1-msec
16075 + * sleep, there is a real possibility of starvation.) But we can't just
16076 + * clamp the delay to an upper bound, else it would take a long time to
16077 + * make a reasonable number of tries.
16079 + * We time out and declare error after NUM_DELAYS delays (thus, exactly
16080 + * that many tries). With the given settings, this will usually take 2 or
16081 + * so minutes. It seems better to fix the total number of tries (and thus
16082 + * the probability of unintended failure) than to fix the total time
16085 + * The pg_usleep() delays are measured in milliseconds because 1 msec is a
16086 + * common resolution limit at the OS level for newer platforms. On older
16087 + * platforms the resolution limit is usually 10 msec, in which case the
16088 + * total delay before timeout will be a bit more.
16090 +#define MIN_SPINS_PER_DELAY 10
16091 +#define MAX_SPINS_PER_DELAY 1000
16092 +#define NUM_DELAYS 1000
16093 +#define MIN_DELAY_MSEC 1
16094 +#define MAX_DELAY_MSEC 1000
16098 + int cur_delay = 0;
16100 + while (TAS(lock))
16102 + /* CPU-specific delay each time through the loop */
16105 + /* Block the process every spins_per_delay tries */
16106 + if (++spins >= spins_per_delay)
16108 + if (++delays > NUM_DELAYS)
16109 + s_lock_stuck(lock, file, line TSRMLS_CC);
16111 + if (cur_delay == 0) /* first time to delay? */
16112 + cur_delay = MIN_DELAY_MSEC;
16114 + pg_usleep(cur_delay * 1000L);
16116 +#if defined(S_LOCK_TEST)
16117 + fprintf(stdout, "*");
16121 + /* increase delay by a random fraction between 1X and 2X */
16122 + cur_delay += (int) (cur_delay *
16123 + ((double) rand() / (double) MAX_RANDOM_VALUE) + 0.5);
16124 + /* wrap back to minimum delay when max is exceeded */
16125 + if (cur_delay > MAX_DELAY_MSEC)
16126 + cur_delay = MIN_DELAY_MSEC;
16133 + * If we were able to acquire the lock without delaying, it's a good
16134 + * indication we are in a multiprocessor. If we had to delay, it's a sign
16135 + * (but not a sure thing) that we are in a uniprocessor. Hence, we
16136 + * decrement spins_per_delay slowly when we had to delay, and increase it
16137 + * rapidly when we didn't. It's expected that spins_per_delay will
16138 + * converge to the minimum value on a uniprocessor and to the maximum
16139 + * value on a multiprocessor.
16141 + * Note: spins_per_delay is local within our current process. We want to
16142 + * average these observations across multiple backends, since it's
16143 + * relatively rare for this function to even get entered, and so a single
16144 + * backend might not live long enough to converge on a good value. That
16145 + * is handled by the two routines below.
16147 + if (cur_delay == 0)
16149 + /* we never had to delay */
16150 + if (spins_per_delay < MAX_SPINS_PER_DELAY)
16151 + spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
16155 + if (spins_per_delay > MIN_SPINS_PER_DELAY)
16156 + spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
16161 +#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
16163 + * Set local copy of spins_per_delay during backend startup.
16165 + * NB: this has to be pretty fast as it is called while holding a spinlock
16168 +set_spins_per_delay(int shared_spins_per_delay)
16170 + spins_per_delay = shared_spins_per_delay;
16174 + * Update shared estimate of spins_per_delay during backend exit.
16176 + * NB: this has to be pretty fast as it is called while holding a spinlock
16179 +update_spins_per_delay(int shared_spins_per_delay)
16182 + * We use an exponential moving average with a relatively slow adaption
16183 + * rate, so that noise in any one backend's result won't affect the shared
16184 + * value too much. As long as both inputs are within the allowed range,
16185 + * the result must be too, so we need not worry about clamping the result.
16187 + * We deliberately truncate rather than rounding; this is so that single
16188 + * adjustments inside a backend can affect the shared estimate (see the
16189 + * asymmetric adjustment rules above).
16191 + return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
16196 + * Various TAS implementations that cannot live in s_lock.h as no inline
16197 + * definition exists (yet).
16198 + * In the future, get rid of tas.[cso] and fold it into this file.
16200 + * If you change something here, you will likely need to modify s_lock.h too,
16201 + * because the definitions for these are split between this file and s_lock.h.
16205 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
16208 +#if defined(__GNUC__)
16211 + * All the gcc flavors that are not inlined
16216 + * Note: all the if-tests here probably ought to be testing gcc version
16217 + * rather than platform, but I don't have adequate info to know what to
16218 + * write. Ideally we'd flush all this in favor of the inline version.
16220 +#if defined(__m68k__) && !defined(__linux__)
16221 +/* really means: extern int tas(slock_t* **lock); */
16225 + __asm__ __volatile__(
16226 +#if defined(__NetBSD__) && defined(__ELF__)
16227 +/* no underscore for label and % for registers */
16231 + movel %sp@(0x4),%a0 \n\
16234 + moveq #-128,%d0 \n\
16243 + movel sp@(0x4),a0 \n\
16246 + moveq #-128,d0 \n\
16251 +#endif /* __NetBSD__ && __ELF__ */
16254 +#endif /* __m68k__ && !__linux__ */
16255 +#else /* not __GNUC__ */
16264 +tas_dummy() /* really means: extern int tas(slock_t
16270 + asm("|#PROC# 04");
16271 + asm(" .globl _tas");
16273 + asm("|#PROLOGUE# 1");
16274 + asm(" movel sp@(0x4),a0");
16276 + asm(" beq LLA1");
16277 + asm(" moveq #-128,d0");
16280 + asm(" moveq #0,d0");
16285 +#endif /* not __GNUC__ */
16286 +#endif /* HAVE_SPINLOCKS */
16288 +#endif /* APC_SPIN_LOCKS */
16289 diff -Naur a/ext/apc/pgsql_s_lock.h b/ext/apc/pgsql_s_lock.h
16290 --- a/ext/apc/pgsql_s_lock.h 1970-01-01 01:00:00.000000000 +0100
16291 +++ b/ext/apc/pgsql_s_lock.h 2012-07-20 00:10:35.000000000 +0200
16294 + +----------------------------------------------------------------------+
16296 + +----------------------------------------------------------------------+
16297 + | Copyright (c) 2006-2011 The PHP Group |
16298 + +----------------------------------------------------------------------+
16299 + | This source file is subject to version 3.01 of the PHP license, |
16300 + | that is bundled with this package in the file LICENSE, and is |
16301 + | available through the world-wide-web at the following url: |
16302 + | http://www.php.net/license/3_01.txt |
16303 + | If you did not receive a copy of the PHP license and are unable to |
16304 + | obtain it through the world-wide-web, please send a note to |
16305 + | license@php.net so we can mail you a copy immediately. |
16306 + +----------------------------------------------------------------------+
16307 + | The following code was ported from the PostgreSQL project, please |
16308 + | see appropriate copyright notices that follow. |
16309 + | Initial conversion by Brian Shire <shire@php.net> |
16310 + +----------------------------------------------------------------------+
16314 +/* $Id: pgsql_s_lock.h 307048 2011-01-03 23:53:17Z kalle $ */
16316 +/*-------------------------------------------------------------------------
16319 + * Hardware-dependent implementation of spinlocks.
16321 + * NOTE: none of the macros in this file are intended to be called directly.
16322 + * Call them through the hardware-independent macros in spin.h.
16324 + * The following hardware-dependent macros must be provided for each
16325 + * supported platform:
16327 + * void S_INIT_LOCK(slock_t *lock)
16328 + * Initialize a spinlock (to the unlocked state).
16330 + * void S_LOCK(slock_t *lock)
16331 + * Acquire a spinlock, waiting if necessary.
16332 + * Time out and abort() if unable to acquire the lock in a
16333 + * "reasonable" amount of time --- typically ~ 1 minute.
16335 + * void S_UNLOCK(slock_t *lock)
16336 + * Unlock a previously acquired lock.
16338 + * bool S_LOCK_FREE(slock_t *lock)
16339 + * Tests if the lock is free. Returns TRUE if free, FALSE if locked.
16340 + * This does *not* change the state of the lock.
16342 + * void SPIN_DELAY(void)
16343 + * Delay operation to occur inside spinlock wait loop.
16345 + * Note to implementors: there are default implementations for all these
16346 + * macros at the bottom of the file. Check if your platform can use
16347 + * these or needs to override them.
16349 + * Usually, S_LOCK() is implemented in terms of an even lower-level macro
16352 + * int TAS(slock_t *lock)
16353 + * Atomic test-and-set instruction. Attempt to acquire the lock,
16354 + * but do *not* wait. Returns 0 if successful, nonzero if unable
16355 + * to acquire the lock.
16357 + * TAS() is NOT part of the API, and should never be called directly.
16359 + * CAUTION: on some platforms TAS() may sometimes report failure to acquire
16360 + * a lock even when the lock is not locked. For example, on Alpha TAS()
16361 + * will "fail" if interrupted. Therefore TAS() should always be invoked
16362 + * in a retry loop, even if you are certain the lock is free.
16364 + * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
16365 + * points, ie, loads and stores of other values must not be moved across
16366 + * a lock or unlock. In most cases it suffices to make the operation be
16367 + * done through a "volatile" pointer.
16369 + * On most supported platforms, TAS() uses a tas() function written
16370 + * in assembly language to execute a hardware atomic-test-and-set
16371 + * instruction. Equivalent OS-supplied mutex routines could be used too.
16373 + * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
16374 + * defined), then we fall back on an emulation that uses SysV semaphores
16375 + * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
16376 + * implementation, because of the cost of a kernel call per lock or unlock.
16377 + * An old report is that Postgres spends around 40% of its time in semop(2)
16378 + * when using the SysV semaphore code.
16381 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
16382 + * Portions Copyright (c) 1994, Regents of the University of California
16384 + * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
16386 + *-------------------------------------------------------------------------
16391 +/** APC namespace protection ************************************************/
16392 +/* hack to protect against any possible runtime namespace collisions...*/
16393 +#define pg_usleep apc_spin_pg_usleep
16394 +#define s_lock apc_spin_s_lock
16395 +#define spins_per_delay apc_spin_spins_per_delay
16396 +/****************************************************************************/
16399 +/* #include "storage/pg_sema.h" -- Removed for APC */
16401 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
16403 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
16406 +#if defined(__GNUC__) || defined(__ICC)
16407 +/*************************************************************************
16408 + * All the gcc inlines
16409 + * Gcc consistently defines the CPU as __cpu__.
16410 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
16414 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
16416 + __asm__ __volatile__(
16417 + " instruction \n"
16418 + " instruction \n"
16419 + " instruction \n"
16420 +: "=r"(_res), "+m"(*lock) // return register, in/out lock value
16421 +: "r"(lock) // lock pointer, in input register
16422 +: "memory", "cc"); // show clobbered registers here
16424 + * The output-operands list (after first colon) should always include
16425 + * "+m"(*lock), whether or not the asm code actually refers to this
16426 + * operand directly. This ensures that gcc believes the value in the
16427 + * lock variable is used and set by the asm code. Also, the clobbers
16428 + * list (after third colon) should always include "memory"; this prevents
16429 + * gcc from thinking it can cache the values of shared-memory fields
16430 + * across the asm code. Add "cc" if your asm code changes the condition
16431 + * code register, and also list any temp registers the code uses.
16436 +#ifdef __i386__ /* 32-bit i386 */
16437 +#define HAS_TEST_AND_SET
16439 +typedef unsigned char slock_t;
16441 +#define TAS(lock) tas(lock)
16443 +static __inline__ int
16444 +tas(volatile slock_t *lock)
16446 + register slock_t _res = 1;
16449 + * Use a non-locking test before asserting the bus lock. Note that the
16450 + * extra test appears to be a small loss on some x86 platforms and a small
16451 + * win on others; it's by no means clear that we should keep it.
16453 + __asm__ __volatile__(
16457 + " xchgb %0,%1 \n"
16459 +: "+q"(_res), "+m"(*lock)
16461 +: "memory", "cc");
16462 + return (int) _res;
16465 +#define SPIN_DELAY() spin_delay()
16467 +static __inline__ void
16471 + * This sequence is equivalent to the PAUSE instruction ("rep" is
16472 + * ignored by old IA32 processors if the following instruction is
16473 + * not a string operation); the IA-32 Architecture Software
16474 + * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
16475 + * PAUSE in the inner loop of a spin lock is necessary for good
16478 + * The PAUSE instruction improves the performance of IA-32
16479 + * processors supporting Hyper-Threading Technology when
16480 + * executing spin-wait loops and other routines where one
16481 + * thread is accessing a shared lock or semaphore in a tight
16482 + * polling loop. When executing a spin-wait loop, the
16483 + * processor can suffer a severe performance penalty when
16484 + * exiting the loop because it detects a possible memory order
16485 + * violation and flushes the core processor's pipeline. The
16486 + * PAUSE instruction provides a hint to the processor that the
16487 + * code sequence is a spin-wait loop. The processor uses this
16488 + * hint to avoid the memory order violation and prevent the
16489 + * pipeline flush. In addition, the PAUSE instruction
16490 + * de-pipelines the spin-wait loop to prevent it from
16491 + * consuming execution resources excessively.
16493 + __asm__ __volatile__(
16497 +#endif /* __i386__ */
16500 +#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
16501 +#define HAS_TEST_AND_SET
16503 +typedef unsigned char slock_t;
16505 +#define TAS(lock) tas(lock)
16507 +static __inline__ int
16508 +tas(volatile slock_t *lock)
16510 + register slock_t _res = 1;
16513 + * On Opteron, using a non-locking test before the locking instruction
16514 + * is a huge loss. On EM64T, it appears to be a wash or small loss,
16515 + * so we needn't bother to try to distinguish the sub-architectures.
16517 + __asm__ __volatile__(
16519 + " xchgb %0,%1 \n"
16520 +: "+q"(_res), "+m"(*lock)
16522 +: "memory", "cc");
16523 + return (int) _res;
16526 +#define SPIN_DELAY() spin_delay()
16528 +static __inline__ void
16532 + * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
16533 + * Opteron, but it may be of some use on EM64T, so we keep it.
16535 + __asm__ __volatile__(
16539 +#endif /* __x86_64__ */
16542 +#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */
16543 +#define HAS_TEST_AND_SET
16545 +typedef unsigned int slock_t;
16547 +#define TAS(lock) tas(lock)
16549 +#ifndef __INTEL_COMPILER
16551 +static __inline__ int
16552 +tas(volatile slock_t *lock)
16556 + __asm__ __volatile__(
16557 + " xchg4 %0=%1,%2 \n"
16558 +: "=r"(ret), "+m"(*lock)
16561 + return (int) ret;
16564 +#else /* __INTEL_COMPILER */
16566 +static __inline__ int
16567 +tas(volatile slock_t *lock)
16571 + ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
16576 +#endif /* __INTEL_COMPILER */
16577 +#endif /* __ia64__ || __ia64 */
16580 +#if defined(__arm__) || defined(__arm)
16581 +#define HAS_TEST_AND_SET
16583 +typedef unsigned char slock_t;
16585 +#define TAS(lock) tas(lock)
16587 +static __inline__ int
16588 +tas(volatile slock_t *lock)
16590 + register slock_t _res = 1;
16592 + __asm__ __volatile__(
16593 + " swpb %0, %0, [%2] \n"
16594 +: "+r"(_res), "+m"(*lock)
16597 + return (int) _res;
16600 +#endif /* __arm__ */
16603 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
16604 +#if defined(__s390__) || defined(__s390x__)
16605 +#define HAS_TEST_AND_SET
16607 +typedef unsigned int slock_t;
16609 +#define TAS(lock) tas(lock)
16611 +static __inline__ int
16612 +tas(volatile slock_t *lock)
16616 + __asm__ __volatile__(
16617 + " cs %0,%3,0(%2) \n"
16618 +: "+d"(_res), "+m"(*lock)
16619 +: "a"(lock), "d"(1)
16620 +: "memory", "cc");
16624 +#endif /* __s390__ || __s390x__ */
16627 +#if defined(__sparc__) /* Sparc */
16628 +#define HAS_TEST_AND_SET
16630 +typedef unsigned char slock_t;
16632 +#define TAS(lock) tas(lock)
16634 +static __inline__ int
16635 +tas(volatile slock_t *lock)
16637 + register slock_t _res;
16640 + * See comment in /pg/backend/port/tas/solaris_sparc.s for why this
16641 + * uses "ldstub", and that file uses "cas". gcc currently generates
16642 + * sparcv7-targeted binaries, so "cas" use isn't possible.
16644 + __asm__ __volatile__(
16645 + " ldstub [%2], %0 \n"
16646 +: "=r"(_res), "+m"(*lock)
16649 + return (int) _res;
16652 +#endif /* __sparc__ */
16656 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
16657 +#define HAS_TEST_AND_SET
16659 +#if defined(__ppc64__) || defined(__powerpc64__)
16660 +typedef unsigned long slock_t;
16662 +typedef unsigned int slock_t;
16665 +#define TAS(lock) tas(lock)
16667 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
16668 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
16670 +static __inline__ int
16671 +tas(volatile slock_t *lock)
16676 + __asm__ __volatile__(
16677 +" lwarx %0,0,%3 \n"
16680 +" addi %0,%0,1 \n"
16681 +" stwcx. %0,0,%3 \n"
16690 +: "=&r"(_t), "=r"(_res), "+m"(*lock)
16692 +: "memory", "cc");
16696 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
16697 +#define S_UNLOCK(lock) \
16700 + __asm__ __volatile__ (" sync \n"); \
16701 + *((volatile slock_t *) (lock)) = 0; \
16704 +#endif /* powerpc */
16707 +/* Linux Motorola 68k */
16708 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
16709 +#define HAS_TEST_AND_SET
16711 +typedef unsigned char slock_t;
16713 +#define TAS(lock) tas(lock)
16715 +static __inline__ int
16716 +tas(volatile slock_t *lock)
16720 + __asm__ __volatile__(
16724 +: "=d"(rv), "+m"(*lock)
16726 +: "memory", "cc");
16730 +#endif /* (__mc68000__ || __m68k__) && __linux__ */
16734 + * VAXen -- even multiprocessor ones
16735 + * (thanks to Tom Ivar Helbekkmo)
16737 +#if defined(__vax__)
16738 +#define HAS_TEST_AND_SET
16740 +typedef unsigned char slock_t;
16742 +#define TAS(lock) tas(lock)
16744 +static __inline__ int
16745 +tas(volatile slock_t *lock)
16747 + register int _res;
16749 + __asm__ __volatile__(
16750 + " movl $1, %0 \n"
16751 + " bbssi $0, (%2), 1f \n"
16754 +: "=&r"(_res), "+m"(*lock)
16760 +#endif /* __vax__ */
16763 +#if defined(__ns32k__) /* National Semiconductor 32K */
16764 +#define HAS_TEST_AND_SET
16766 +typedef unsigned char slock_t;
16768 +#define TAS(lock) tas(lock)
16770 +static __inline__ int
16771 +tas(volatile slock_t *lock)
16773 + register int _res;
16775 + __asm__ __volatile__(
16776 + " sbitb 0, %1 \n"
16778 +: "=r"(_res), "+m"(*lock)
16784 +#endif /* __ns32k__ */
16787 +#if defined(__alpha) || defined(__alpha__) /* Alpha */
16789 + * Correct multi-processor locking methods are explained in section 5.5.3
16790 + * of the Alpha AXP Architecture Handbook, which at this writing can be
16791 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
16792 + * For gcc we implement the handbook's code directly with inline assembler.
16794 +#define HAS_TEST_AND_SET
16796 +typedef unsigned long slock_t;
16798 +#define TAS(lock) tas(lock)
16800 +static __inline__ int
16801 +tas(volatile slock_t *lock)
16803 + register slock_t _res;
16805 + __asm__ __volatile__(
16808 + " ldq_l %0, %1 \n"
16811 + " stq_c $0, %1 \n"
16815 + "2: mov 1, %0 \n"
16817 +: "=&r"(_res), "+m"(*lock)
16820 + return (int) _res;
16823 +#define S_UNLOCK(lock) \
16826 + __asm__ __volatile__ (" mb \n"); \
16827 + *((volatile slock_t *) (lock)) = 0; \
16830 +#endif /* __alpha || __alpha__ */
16833 +#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
16834 +/* Note: on SGI we use the OS' mutex ABI, see below */
16835 +/* Note: R10000 processors require a separate SYNC */
16836 +#define HAS_TEST_AND_SET
16838 +typedef unsigned int slock_t;
16840 +#define TAS(lock) tas(lock)
16842 +static __inline__ int
16843 +tas(volatile slock_t *lock)
16845 + register volatile slock_t *_l = lock;
16846 + register int _res;
16847 + register int _tmp;
16849 + __asm__ __volatile__(
16852 + " .set noreorder \n"
16853 + " .set nomacro \n"
16855 + " or %1, %0, 1 \n"
16858 + " or %0, %0, %1 \n"
16861 +: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
16867 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
16868 +#define S_UNLOCK(lock) \
16871 + __asm__ __volatile__( \
16872 + " .set push \n" \
16873 + " .set mips2 \n" \
16874 + " .set noreorder \n" \
16875 + " .set nomacro \n" \
16878 + *((volatile slock_t *) (lock)) = 0; \
16881 +#endif /* __mips__ && !__sgi */
16884 +/* These live in s_lock.c, but only for gcc */
16887 +#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
16888 +#define HAS_TEST_AND_SET
16890 +typedef unsigned char slock_t;
16894 +#endif /* __GNUC__ */
16899 + * ---------------------------------------------------------------------
16900 + * Platforms that use non-gcc inline assembly:
16901 + * ---------------------------------------------------------------------
16904 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
16907 +#if defined(USE_UNIVEL_CC) /* Unixware compiler */
16908 +#define HAS_TEST_AND_SET
16910 +typedef unsigned char slock_t;
16912 +#define TAS(lock) tas(lock)
16915 +tas(volatile slock_t *s_lock)
16917 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
16920 + movl s_lock, %ebx
16923 + xchgb %al, (%ebx)
16927 +#endif /* defined(USE_UNIVEL_CC) */
16930 +#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */
16932 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
16933 + * have some builtin functions that accomplish much the same results.
16934 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
16935 + * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only
16936 + * operate on an int (ie, longword), but that's OK as long as we define
16937 + * S_INIT_LOCK to zero out the whole quadword.
16939 +#define HAS_TEST_AND_SET
16941 +typedef unsigned long slock_t;
16943 +#include <alpha/builtins.h>
16944 +#define S_INIT_LOCK(lock) (*(lock) = 0)
16945 +#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
16946 +#define S_UNLOCK(lock) __UNLOCK_LONG(lock)
16948 +#endif /* __alpha || __alpha__ */
16951 +#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
16955 + * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
16956 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
16957 + * struct. The active word in the struct is whichever has the aligned address;
16958 + * the other three words just sit at -1.
16960 + * When using gcc, we can inline the required assembly code.
16962 +#define HAS_TEST_AND_SET
16969 +#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
16971 +#if defined(__GNUC__)
16973 +static __inline__ int
16974 +tas(volatile slock_t *lock)
16976 + volatile int *lockword = TAS_ACTIVE_WORD(lock);
16977 + register int lockval;
16979 + __asm__ __volatile__(
16980 + " ldcwx 0(0,%2),%0 \n"
16981 +: "=r"(lockval), "+m"(*lockword)
16984 + return (lockval == 0);
16987 +#endif /* __GNUC__ */
16989 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
16991 +#define S_INIT_LOCK(lock) \
16993 + volatile slock_t *lock_ = (lock); \
16994 + lock_->sema[0] = -1; \
16995 + lock_->sema[1] = -1; \
16996 + lock_->sema[2] = -1; \
16997 + lock_->sema[3] = -1; \
17000 +#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
17002 +#endif /* __hppa || __hppa__ */
17005 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
17007 +#define HAS_TEST_AND_SET
17009 +typedef unsigned int slock_t;
17011 +#include <ia64/sys/inline.h>
17012 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
17014 +#endif /* HPUX on IA64, non gcc */
17017 +#if defined(__sgi) /* SGI compiler */
17020 + * slock_t is defined as a unsigned long. We use the standard SGI
17023 + * The following comment is left for historical reasons, but is probably
17024 + * not a good idea since the mutex ABI is supported.
17026 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
17027 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
17028 + * for the R3000 chips out there.
17030 +#define HAS_TEST_AND_SET
17032 +typedef unsigned long slock_t;
17034 +#include "mutex.h"
17035 +#define TAS(lock) (test_and_set(lock,1))
17036 +#define S_UNLOCK(lock) (test_then_and(lock,0))
17037 +#define S_INIT_LOCK(lock) (test_then_and(lock,0))
17038 +#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
17039 +#endif /* __sgi */
17042 +#if defined(sinix) /* Sinix */
17044 + * SINIX / Reliant UNIX
17045 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
17046 + * member. (Basically same as SGI)
17048 +#define HAS_TEST_AND_SET
17050 +#include "abi_mutex.h"
17051 +typedef abilock_t slock_t;
17053 +#define TAS(lock) (!acquire_lock(lock))
17054 +#define S_UNLOCK(lock) release_lock(lock)
17055 +#define S_INIT_LOCK(lock) init_lock(lock)
17056 +#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
17057 +#endif /* sinix */
17060 +#if defined(_AIX) /* AIX */
17064 +#define HAS_TEST_AND_SET
17066 +typedef unsigned int slock_t;
17068 +#define TAS(lock) _check_lock(lock, 0, 1)
17069 +#define S_UNLOCK(lock) _clear_lock(lock, 0)
17073 +#if defined (nextstep) /* Nextstep */
17074 +#define HAS_TEST_AND_SET
17076 +typedef struct mutex slock_t;
17078 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */
17080 +#define S_LOCK(lock) mutex_lock(lock)
17081 +#define S_UNLOCK(lock) mutex_unlock(lock)
17082 +#define S_INIT_LOCK(lock) mutex_init(lock)
17083 +/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
17084 +#define S_LOCK_FREE(alock) ((alock)->lock == 0)
17085 +#endif /* nextstep */
17088 +/* These are in s_lock.c */
17091 +#if defined(sun3) /* Sun3 */
17092 +#define HAS_TEST_AND_SET
17094 +typedef unsigned char slock_t;
17098 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
17099 +#define HAS_TEST_AND_SET
17101 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
17102 +typedef unsigned int slock_t;
17104 +typedef unsigned char slock_t;
17107 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
17110 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
17114 +#ifdef WIN32_ONLY_COMPILER
17115 +typedef LONG slock_t;
17117 +#define HAS_TEST_AND_SET
17118 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
17120 +#define SPIN_DELAY() spin_delay()
17122 +static __forceinline void
17125 + /* See comment for gcc code. Same code, MASM syntax */
17132 +#endif /* !defined(HAS_TEST_AND_SET) */
17135 +/* Blow up if we didn't have any way to do spinlocks */
17136 +#ifndef HAS_TEST_AND_SET
17137 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
17138 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
17139 +/* #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. */
17143 +#else /* !HAVE_SPINLOCKS */
17147 + * Fake spinlock implementation using semaphores --- slow and prone
17148 + * to fall foul of kernel limits on number of semaphores, so don't use this
17149 + * unless you must! The subroutines appear in spin.c.
17152 +/* -- Removed for APC
17153 +typedef PGSemaphoreData slock_t;
17155 +extern bool s_lock_free_sema(volatile slock_t *lock);
17156 +extern void s_unlock_sema(volatile slock_t *lock);
17157 +extern void s_init_lock_sema(volatile slock_t *lock);
17158 +extern int tas_sema(volatile slock_t *lock);
17160 +#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
17161 +#define S_UNLOCK(lock) s_unlock_sema(lock)
17162 +#define S_INIT_LOCK(lock) s_init_lock_sema(lock)
17163 +#define TAS(lock) tas_sema(lock)
17166 +#endif /* HAVE_SPINLOCKS */
17170 + * Default Definitions - override these above as needed.
17173 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
17175 +#if !defined(S_LOCK)
17176 +#define S_LOCK(lock) \
17179 + s_lock((lock), __FILE__, __LINE__ TSRMLS_CC); \
17181 +#endif /* S_LOCK */
17183 +#if !defined(S_LOCK_FREE)
17184 +#define S_LOCK_FREE(lock) (*(lock) == 0)
17185 +#endif /* S_LOCK_FREE */
17187 +#if !defined(S_UNLOCK)
17188 +#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
17189 +#endif /* S_UNLOCK */
17191 +#if !defined(S_INIT_LOCK)
17192 +#define S_INIT_LOCK(lock) S_UNLOCK(lock)
17193 +#endif /* S_INIT_LOCK */
17195 +#if !defined(SPIN_DELAY)
17196 +#define SPIN_DELAY() ((void) 0)
17197 +#endif /* SPIN_DELAY */
17200 +extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
17203 +#define TAS(lock) tas(lock)
17208 + * Platform-independent out-of-line support routines
17210 +extern void s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC);
17212 +/* Support for dynamic adjustment of spins_per_delay */
17213 +#define DEFAULT_SPINS_PER_DELAY 100
17215 +#if 0 /* -- Removed from APC use -- */
17216 +extern void set_spins_per_delay(int shared_spins_per_delay);
17217 +extern int update_spins_per_delay(int shared_spins_per_delay);
17220 +#endif /* S_LOCK_H */
17221 diff -Naur a/ext/apc/php_apc.c b/ext/apc/php_apc.c
17222 --- a/ext/apc/php_apc.c 1970-01-01 01:00:00.000000000 +0100
17223 +++ b/ext/apc/php_apc.c 2012-07-20 00:10:35.000000000 +0200
17226 + +----------------------------------------------------------------------+
17228 + +----------------------------------------------------------------------+
17229 + | Copyright (c) 2006-2011 The PHP Group |
17230 + +----------------------------------------------------------------------+
17231 + | This source file is subject to version 3.01 of the PHP license, |
17232 + | that is bundled with this package in the file LICENSE, and is |
17233 + | available through the world-wide-web at the following url: |
17234 + | http://www.php.net/license/3_01.txt |
17235 + | If you did not receive a copy of the PHP license and are unable to |
17236 + | obtain it through the world-wide-web, please send a note to |
17237 + | license@php.net so we can mail you a copy immediately. |
17238 + +----------------------------------------------------------------------+
17239 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
17240 + | Rasmus Lerdorf <rasmus@php.net> |
17241 + +----------------------------------------------------------------------+
17243 + This software was contributed to PHP by Community Connect Inc. in 2002
17244 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
17245 + Future revisions and derivatives of this source code must acknowledge
17246 + Community Connect Inc. as the original contributor of this module by
17247 + leaving this note intact in the source code.
17249 + All other licensing and usage conditions are those of the PHP Group.
17253 +/* $Id: php_apc.c 325875 2012-05-27 17:15:26Z felipe $ */
17255 +#include "apc_zend.h"
17256 +#include "apc_cache.h"
17257 +#include "apc_iterator.h"
17258 +#include "apc_main.h"
17259 +#include "apc_sma.h"
17260 +#include "apc_lock.h"
17261 +#include "apc_bin.h"
17262 +#include "php_globals.h"
17263 +#include "php_ini.h"
17264 +#include "ext/standard/info.h"
17265 +#include "ext/standard/file.h"
17266 +#include "ext/standard/flock_compat.h"
17267 +#ifdef HAVE_SYS_FILE_H
17268 +#include <sys/file.h>
17271 +#include "rfc1867.h"
17272 +#include "php_apc.h"
17273 +#include "ext/standard/md5.h"
17275 +#if HAVE_SIGACTION
17276 +#include "apc_signal.h"
17279 +/* {{{ PHP_FUNCTION declarations */
17280 +PHP_FUNCTION(apc_cache_info);
17281 +PHP_FUNCTION(apc_clear_cache);
17282 +PHP_FUNCTION(apc_sma_info);
17283 +PHP_FUNCTION(apc_store);
17284 +PHP_FUNCTION(apc_fetch);
17285 +PHP_FUNCTION(apc_delete);
17286 +PHP_FUNCTION(apc_delete_file);
17287 +PHP_FUNCTION(apc_compile_file);
17288 +PHP_FUNCTION(apc_define_constants);
17289 +PHP_FUNCTION(apc_load_constants);
17290 +PHP_FUNCTION(apc_add);
17291 +PHP_FUNCTION(apc_inc);
17292 +PHP_FUNCTION(apc_dec);
17293 +PHP_FUNCTION(apc_cas);
17294 +PHP_FUNCTION(apc_bin_dump);
17295 +PHP_FUNCTION(apc_bin_load);
17296 +PHP_FUNCTION(apc_bin_dumpfile);
17297 +PHP_FUNCTION(apc_bin_loadfile);
17298 +PHP_FUNCTION(apc_exists);
17301 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
17302 +ZEND_DECLARE_MODULE_GLOBALS(apc)
17304 +/* True globals */
17305 +apc_cache_t* apc_cache = NULL;
17306 +apc_cache_t* apc_user_cache = NULL;
17308 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
17310 + apc_globals->filters = NULL;
17311 + apc_globals->compiled_filters = NULL;
17312 + apc_globals->initialized = 0;
17313 + apc_globals->cache_stack = apc_stack_create(0 TSRMLS_CC);
17314 + apc_globals->cache_by_default = 1;
17315 + apc_globals->fpstat = 1;
17316 + apc_globals->canonicalize = 1;
17317 + apc_globals->stat_ctime = 0;
17318 + apc_globals->write_lock = 1;
17319 + apc_globals->slam_defense = 1;
17320 + apc_globals->report_autofilter = 0;
17321 + apc_globals->include_once = 0;
17322 + apc_globals->apc_optimize_function = NULL;
17323 +#ifdef MULTIPART_EVENT_FORMDATA
17324 + apc_globals->rfc1867 = 0;
17325 + memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data));
17327 + memset(&apc_globals->copied_zvals, 0, sizeof(HashTable));
17328 + apc_globals->force_file_update = 0;
17329 + apc_globals->coredump_unmap = 0;
17330 + apc_globals->preload_path = NULL;
17331 + apc_globals->use_request_time = 1;
17332 + apc_globals->lazy_class_table = NULL;
17333 + apc_globals->lazy_function_table = NULL;
17334 + apc_globals->serializer_name = NULL;
17335 + apc_globals->serializer = NULL;
17338 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
17340 + /* deallocate the ignore patterns */
17341 + if (apc_globals->filters != NULL) {
17343 + for (i=0; apc_globals->filters[i] != NULL; i++) {
17344 + apc_efree(apc_globals->filters[i] TSRMLS_CC);
17346 + apc_efree(apc_globals->filters TSRMLS_CC);
17349 + /* the stack should be empty */
17350 + assert(apc_stack_size(apc_globals->cache_stack) == 0);
17352 + /* apc cleanup */
17353 + apc_stack_destroy(apc_globals->cache_stack TSRMLS_CC);
17355 + /* the rest of the globals are cleaned up in apc_module_shutdown() */
17358 +static long apc_atol(const char *str, int str_len)
17360 +#if PHP_MAJOR_VERSION >= 6 || PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
17361 + return zend_atol(str, str_len);
17363 + /* Re-implement zend_atol() for 5.2.x */
17367 + str_len = strlen(str);
17370 + retval = strtol(str, NULL, 0);
17372 + if (str_len > 0) {
17373 + switch (str[str_len - 1]) {
17377 + /* break intentionally missing */
17381 + /* break intentionally missing */
17397 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
17399 + APCG(filters) = apc_tokenize(new_value, ',' TSRMLS_CC);
17404 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
17407 + if(zend_atoi(new_value, new_value_length)!=1) {
17408 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
17410 + APCG(shm_segments) = 1;
17412 + APCG(shm_segments) = zend_atoi(new_value, new_value_length);
17418 +static PHP_INI_MH(OnUpdateShmSize) /* {{{ */
17420 + long s = apc_atol(new_value, new_value_length);
17426 + if(s < 1048576L) {
17427 + /* if it's less than 1Mb, they are probably using the old syntax */
17428 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_size now uses M/G suffixes, please update your ini files");
17429 + s = s * 1048576L;
17432 + APCG(shm_size) = s;
17438 +#ifdef MULTIPART_EVENT_FORMDATA
17439 +static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
17442 + tmp = zend_atoi(new_value, new_value_length);
17444 + apc_error("rfc1867_freq must be greater than or equal to zero." TSRMLS_CC);
17447 + if(new_value[new_value_length-1] == '%') {
17449 + apc_error("rfc1867_freq cannot be over 100%%" TSRMLS_CC);
17452 + APCG(rfc1867_freq) = tmp / 100.0;
17454 + APCG(rfc1867_freq) = tmp;
17462 +STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
17463 +STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
17464 +STD_PHP_INI_ENTRY("apc.shm_size", "32M", PHP_INI_SYSTEM, OnUpdateShmSize, shm_size, zend_apc_globals, apc_globals)
17465 +#ifdef ZEND_ENGINE_2_4
17466 +STD_PHP_INI_ENTRY("apc.shm_strings_buffer", "4M", PHP_INI_SYSTEM, OnUpdateLong, shm_strings_buffer, zend_apc_globals, apc_globals)
17468 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
17469 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateLong, num_files_hint, zend_apc_globals, apc_globals)
17470 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateLong, user_entries_hint, zend_apc_globals, apc_globals)
17471 +STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateLong, gc_ttl, zend_apc_globals, apc_globals)
17472 +STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateLong, ttl, zend_apc_globals, apc_globals)
17473 +STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateLong, user_ttl, zend_apc_globals, apc_globals)
17475 +STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
17477 +PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
17478 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
17479 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateLong,file_update_protection, zend_apc_globals, apc_globals)
17480 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
17481 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateLong, max_file_size, zend_apc_globals, apc_globals)
17482 +STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
17483 +STD_PHP_INI_BOOLEAN("apc.canonicalize", "1", PHP_INI_SYSTEM, OnUpdateBool, canonicalize, zend_apc_globals, apc_globals)
17484 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
17485 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
17486 +STD_PHP_INI_BOOLEAN("apc.slam_defense", "1", PHP_INI_SYSTEM, OnUpdateBool, slam_defense, zend_apc_globals, apc_globals)
17487 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
17488 +#ifdef MULTIPART_EVENT_FORMDATA
17489 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
17490 +STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
17491 +STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
17492 +STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
17493 +STD_PHP_INI_ENTRY("apc.rfc1867_ttl", "3600", PHP_INI_SYSTEM, OnUpdateLong, rfc1867_ttl, zend_apc_globals, apc_globals)
17495 +STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
17496 +STD_PHP_INI_ENTRY("apc.preload_path", (char*)NULL, PHP_INI_SYSTEM, OnUpdateString, preload_path, zend_apc_globals, apc_globals)
17497 +STD_PHP_INI_BOOLEAN("apc.file_md5", "0", PHP_INI_SYSTEM, OnUpdateBool, file_md5, zend_apc_globals, apc_globals)
17498 +STD_PHP_INI_BOOLEAN("apc.use_request_time", "1", PHP_INI_ALL, OnUpdateBool, use_request_time, zend_apc_globals, apc_globals)
17499 +STD_PHP_INI_BOOLEAN("apc.lazy_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_functions, zend_apc_globals, apc_globals)
17500 +STD_PHP_INI_BOOLEAN("apc.lazy_classes", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_classes, zend_apc_globals, apc_globals)
17501 +STD_PHP_INI_ENTRY("apc.serializer", "default", PHP_INI_SYSTEM, OnUpdateStringUnempty, serializer_name, zend_apc_globals, apc_globals)
17506 +/* {{{ PHP_MINFO_FUNCTION(apc) */
17507 +static PHP_MINFO_FUNCTION(apc)
17509 + apc_serializer_t *serializer = NULL;
17510 + smart_str names = {0,};
17513 + php_info_print_table_start();
17514 + php_info_print_table_header(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
17515 + php_info_print_table_row(2, "Version", PHP_APC_VERSION);
17516 +#ifdef __DEBUG_APC__
17517 + php_info_print_table_row(2, "APC Debugging", "Enabled");
17519 + php_info_print_table_row(2, "APC Debugging", "Disabled");
17522 + php_info_print_table_row(2, "MMAP Support", "Enabled");
17523 + php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
17525 + php_info_print_table_row(2, "MMAP Support", "Disabled");
17527 + php_info_print_table_row(2, "Locking type", APC_LOCK_TYPE);
17529 + for( i = 0, serializer = apc_get_serializers(TSRMLS_C);
17530 + serializer->name != NULL;
17531 + serializer++, i++) {
17532 + if(i != 0) smart_str_appends(&names, ", ");
17533 + smart_str_appends(&names, serializer->name);
17537 + smart_str_0(&names);
17538 + php_info_print_table_row(2, "Serialization Support", names.c);
17539 + smart_str_free(&names);
17541 + php_info_print_table_row(2, "Serialization Support", "broken");
17544 + php_info_print_table_row(2, "Revision", "$Revision: 325875 $");
17545 + php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
17546 + php_info_print_table_end();
17547 + DISPLAY_INI_ENTRIES();
17551 +#ifdef MULTIPART_EVENT_FORMDATA
17552 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
17555 +/* {{{ PHP_MINIT_FUNCTION(apc) */
17556 +static PHP_MINIT_FUNCTION(apc)
17558 + ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
17560 + REGISTER_INI_ENTRIES();
17562 + /* Disable APC in cli mode unless overridden by apc.enable_cli */
17563 + if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
17564 + APCG(enabled) = 0;
17567 + if (APCG(enabled)) {
17568 + if(APCG(initialized)) {
17569 + apc_process_init(module_number TSRMLS_CC);
17571 + apc_module_init(module_number TSRMLS_CC);
17572 + apc_zend_init(TSRMLS_C);
17573 + apc_process_init(module_number TSRMLS_CC);
17574 +#ifdef MULTIPART_EVENT_FORMDATA
17575 + /* File upload progress tracking */
17576 + if(APCG(rfc1867)) {
17577 + php_rfc1867_callback = apc_rfc1867_progress;
17580 + apc_iterator_init(module_number TSRMLS_CC);
17583 + 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);
17584 + 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);
17591 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
17592 +static PHP_MSHUTDOWN_FUNCTION(apc)
17594 + if(APCG(enabled)) {
17595 + apc_process_shutdown(TSRMLS_C);
17596 + apc_zend_shutdown(TSRMLS_C);
17597 + apc_module_shutdown(TSRMLS_C);
17599 + php_apc_shutdown_globals(&apc_globals);
17601 +#if HAVE_SIGACTION
17602 + apc_shutdown_signals(TSRMLS_C);
17606 + ts_free_id(apc_globals_id);
17608 + UNREGISTER_INI_ENTRIES();
17613 +/* {{{ PHP_RINIT_FUNCTION(apc) */
17614 +static PHP_RINIT_FUNCTION(apc)
17616 + if(APCG(enabled)) {
17617 + apc_request_init(TSRMLS_C);
17619 +#if HAVE_SIGACTION
17620 + apc_set_signals(TSRMLS_C);
17627 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
17628 +static PHP_RSHUTDOWN_FUNCTION(apc)
17630 + if(APCG(enabled)) {
17631 + apc_request_shutdown(TSRMLS_C);
17637 +/* {{{ proto array apc_cache_info([string type [, bool limited]]) */
17638 +PHP_FUNCTION(apc_cache_info)
17641 + char *cache_type;
17643 + zend_bool limited = 0;
17645 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
17649 + if(ZEND_NUM_ARGS()) {
17650 + if(!strcasecmp(cache_type,"user")) {
17651 + info = apc_cache_info(apc_user_cache, limited TSRMLS_CC);
17652 + } else if(!strcasecmp(cache_type,"filehits")) {
17653 +#ifdef APC_FILEHITS
17654 + RETVAL_ZVAL(APCG(filehits), 1, 0);
17660 + info = apc_cache_info(apc_cache, limited TSRMLS_CC);
17663 + info = apc_cache_info(apc_cache, limited TSRMLS_CC);
17667 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
17671 + RETURN_ZVAL(info, 0, 1);
17676 +/* {{{ proto void apc_clear_cache([string cache]) */
17677 +PHP_FUNCTION(apc_clear_cache)
17679 + char *cache_type;
17682 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
17687 + if(!strcasecmp(cache_type, "user")) {
17688 + apc_cache_clear(apc_user_cache TSRMLS_CC);
17692 + apc_cache_clear(apc_cache TSRMLS_CC);
17697 +/* {{{ proto array apc_sma_info([bool limited]) */
17698 +PHP_FUNCTION(apc_sma_info)
17700 + apc_sma_info_t* info;
17701 + zval* block_lists;
17703 + zend_bool limited = 0;
17705 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
17709 + info = apc_sma_info(limited TSRMLS_CC);
17712 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
17716 + array_init(return_value);
17717 + add_assoc_long(return_value, "num_seg", info->num_seg);
17718 + add_assoc_double(return_value, "seg_size", (double)info->seg_size);
17719 + add_assoc_double(return_value, "avail_mem", (double)apc_sma_get_avail_mem());
17722 + apc_sma_free_info(info TSRMLS_CC);
17726 +#if ALLOC_DISTRIBUTION
17728 + size_t *adist = apc_sma_get_alloc_distribution();
17730 + ALLOC_INIT_ZVAL(list);
17731 + array_init(list);
17732 + for(i=0; i<30; i++) {
17733 + add_next_index_long(list, adist[i]);
17735 + add_assoc_zval(return_value, "adist", list);
17738 + ALLOC_INIT_ZVAL(block_lists);
17739 + array_init(block_lists);
17741 + for (i = 0; i < info->num_seg; i++) {
17742 + apc_sma_link_t* p;
17745 + ALLOC_INIT_ZVAL(list);
17746 + array_init(list);
17748 + for (p = info->list[i]; p != NULL; p = p->next) {
17751 + ALLOC_INIT_ZVAL(link);
17752 + array_init(link);
17754 + add_assoc_long(link, "size", p->size);
17755 + add_assoc_long(link, "offset", p->offset);
17756 + add_next_index_zval(list, link);
17758 + add_next_index_zval(block_lists, list);
17760 + add_assoc_zval(return_value, "block_lists", block_lists);
17761 + apc_sma_free_info(info TSRMLS_CC);
17766 +int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC)
17768 + if(!APCG(enabled)) {
17772 + if (!APCG(serializer) && APCG(serializer_name)) {
17773 + /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */
17774 + APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC);
17777 + HANDLE_BLOCK_INTERRUPTIONS();
17778 + APCG(current_cache) = apc_user_cache;
17780 + if (!_apc_cache_user_update(apc_user_cache, strkey, strkey_len + 1, updater, data TSRMLS_CC)) {
17781 + HANDLE_UNBLOCK_INTERRUPTIONS();
17785 + APCG(current_cache) = NULL;
17786 + HANDLE_UNBLOCK_INTERRUPTIONS();
17792 +/* {{{ _apc_store */
17793 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
17794 + apc_cache_entry_t *entry;
17795 + apc_cache_key_t key;
17797 + apc_context_t ctxt={0,};
17802 + if(!APCG(enabled)) return 0;
17804 + if (!APCG(serializer) && APCG(serializer_name)) {
17805 + /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */
17806 + APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC);
17809 + HANDLE_BLOCK_INTERRUPTIONS();
17811 + APCG(current_cache) = apc_user_cache;
17813 + ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
17814 + if (!ctxt.pool) {
17815 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
17818 + ctxt.copy = APC_COPY_IN_USER;
17819 + ctxt.force_update = 0;
17826 + if (!apc_cache_make_user_key(&key, strkey, strkey_len, t)) {
17830 + if (apc_cache_is_last_key(apc_user_cache, &key, t TSRMLS_CC)) {
17834 + if (!(entry = apc_cache_make_user_entry(strkey, strkey_len, val, &ctxt, ttl TSRMLS_CC))) {
17838 + if (!apc_cache_user_insert(apc_user_cache, key, entry, &ctxt, t, exclusive TSRMLS_CC)) {
17840 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
17846 + APCG(current_cache) = NULL;
17848 + HANDLE_UNBLOCK_INTERRUPTIONS();
17854 +/* {{{ apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
17856 +static void apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
17858 + zval *key = NULL;
17859 + zval *val = NULL;
17862 + HashPosition hpos;
17868 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &key, &val, &ttl) == FAILURE) {
17872 + if (!key) RETURN_FALSE;
17874 + if (Z_TYPE_P(key) == IS_ARRAY) {
17875 + hash = Z_ARRVAL_P(key);
17876 + array_init(return_value);
17877 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
17878 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
17879 + zend_hash_get_current_key_ex(hash, &hkey, &hkey_len, &hkey_idx, 0, &hpos);
17881 + if(!_apc_store(hkey, hkey_len, *hentry, (unsigned int)ttl, exclusive TSRMLS_CC)) {
17882 + add_assoc_long_ex(return_value, hkey, hkey_len, -1); /* -1: insertion error */
17886 + add_index_long(return_value, hkey_idx, -1); /* -1: insertion error */
17888 + zend_hash_move_forward_ex(hash, &hpos);
17891 + } else if (Z_TYPE_P(key) == IS_STRING) {
17892 + if (!val) RETURN_FALSE;
17893 + if(_apc_store(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, val, (unsigned int)ttl, exclusive TSRMLS_CC))
17896 + apc_warning("apc_store expects key parameter to be a string or an array of key/value pairs." TSRMLS_CC);
17903 +/* {{{ proto int apc_store(mixed key, mixed var [, long ttl ])
17905 +PHP_FUNCTION(apc_store) {
17906 + apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
17910 +/* {{{ proto int apc_add(mixed key, mixed var [, long ttl ])
17912 +PHP_FUNCTION(apc_add) {
17913 + apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
17917 +/* {{{ inc_updater */
17919 +struct _inc_update_args {
17924 +static int inc_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
17926 + struct _inc_update_args *args = (struct _inc_update_args*) data;
17928 + zval* val = entry->data.user.val;
17930 + if(Z_TYPE_P(val) == IS_LONG) {
17931 + Z_LVAL_P(val) += args->step;
17932 + args->lval = Z_LVAL_P(val);
17940 +/* {{{ proto long apc_inc(string key [, long step [, bool& success]])
17942 +PHP_FUNCTION(apc_inc) {
17945 + struct _inc_update_args args = {1L, -1};
17946 + zval *success = NULL;
17948 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
17953 + zval_dtor(success);
17956 + if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
17957 + if(success) ZVAL_TRUE(success);
17958 + RETURN_LONG(args.lval);
17961 + if(success) ZVAL_FALSE(success);
17967 +/* {{{ proto long apc_dec(string key [, long step [, bool &success]])
17969 +PHP_FUNCTION(apc_dec) {
17972 + struct _inc_update_args args = {1L, -1};
17973 + zval *success = NULL;
17975 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
17980 + zval_dtor(success);
17983 + args.step = args.step * -1;
17985 + if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
17986 + if(success) ZVAL_TRUE(success);
17987 + RETURN_LONG(args.lval);
17990 + if(success) ZVAL_FALSE(success);
17996 +/* {{{ cas_updater */
17997 +static int cas_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
17998 + long* vals = ((long*)data);
17999 + long old = vals[0];
18000 + long new = vals[1];
18001 + zval* val = entry->data.user.val;
18003 + if(Z_TYPE_P(val) == IS_LONG) {
18004 + if(Z_LVAL_P(val) == old) {
18005 + Z_LVAL_P(val) = new;
18014 +/* {{{ proto int apc_cas(string key, int old, int new)
18016 +PHP_FUNCTION(apc_cas) {
18021 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &strkey, &strkey_len, &vals[0], &vals[1]) == FAILURE) {
18025 + if(_apc_update(strkey, strkey_len, cas_updater, &vals TSRMLS_CC)) RETURN_TRUE;
18030 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
18031 + return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
18034 +/* {{{ proto mixed apc_fetch(mixed key[, bool &success])
18036 +PHP_FUNCTION(apc_fetch) {
18038 + zval *success = NULL;
18040 + HashPosition hpos;
18043 + zval *result_entry;
18046 + apc_cache_entry_t* entry;
18048 + apc_context_t ctxt = {0,};
18050 + if(!APCG(enabled)) RETURN_FALSE;
18052 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == FAILURE) {
18059 + ZVAL_BOOL(success, 0);
18062 + ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC);
18063 + if (!ctxt.pool) {
18064 + apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
18067 + ctxt.copy = APC_COPY_OUT_USER;
18068 + ctxt.force_update = 0;
18070 + if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
18071 + convert_to_string(key);
18074 + if(Z_TYPE_P(key) == IS_STRING) {
18075 + strkey = Z_STRVAL_P(key);
18076 + strkey_len = Z_STRLEN_P(key);
18077 + if(!strkey_len) RETURN_FALSE;
18078 + entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC);
18080 + /* deep-copy returned shm zval to emalloc'ed return_value */
18081 + apc_cache_fetch_zval(return_value, entry->data.user.val, &ctxt TSRMLS_CC);
18082 + apc_cache_release(apc_user_cache, entry TSRMLS_CC);
18086 + } else if(Z_TYPE_P(key) == IS_ARRAY) {
18087 + hash = Z_ARRVAL_P(key);
18088 + MAKE_STD_ZVAL(result);
18089 + array_init(result);
18090 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
18091 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
18092 + if(Z_TYPE_PP(hentry) != IS_STRING) {
18093 + apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC);
18096 + entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1), t TSRMLS_CC);
18098 + /* deep-copy returned shm zval to emalloc'ed return_value */
18099 + MAKE_STD_ZVAL(result_entry);
18100 + apc_cache_fetch_zval(result_entry, entry->data.user.val, &ctxt TSRMLS_CC);
18101 + apc_cache_release(apc_user_cache, entry TSRMLS_CC);
18102 + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
18103 + } /* don't set values we didn't find */
18104 + zend_hash_move_forward_ex(hash, &hpos);
18106 + RETVAL_ZVAL(result, 0, 1);
18108 + apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC);
18110 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
18115 + ZVAL_BOOL(success, 1);
18118 + apc_pool_destroy(ctxt.pool TSRMLS_CC);
18123 +/* {{{ proto mixed apc_exists(mixed key)
18125 +PHP_FUNCTION(apc_exists) {
18128 + HashPosition hpos;
18132 + apc_cache_entry_t* entry;
18134 + zval *result_entry;
18137 + if(!APCG(enabled)) RETURN_FALSE;
18139 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
18145 + if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
18146 + convert_to_string(key);
18149 + if(Z_TYPE_P(key) == IS_STRING) {
18150 + strkey = Z_STRVAL_P(key);
18151 + strkey_len = Z_STRLEN_P(key);
18152 + if(!strkey_len) RETURN_FALSE;
18153 + entry = apc_cache_user_exists(apc_user_cache, strkey, strkey_len + 1, t TSRMLS_CC);
18157 + } else if(Z_TYPE_P(key) == IS_ARRAY) {
18158 + hash = Z_ARRVAL_P(key);
18159 + MAKE_STD_ZVAL(result);
18160 + array_init(result);
18161 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
18162 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
18163 + if(Z_TYPE_PP(hentry) != IS_STRING) {
18164 + apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC);
18168 + entry = apc_cache_user_exists(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t TSRMLS_CC);
18170 + MAKE_STD_ZVAL(result_entry);
18171 + ZVAL_BOOL(result_entry, 1);
18172 + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
18173 + } /* don't set values we didn't find */
18174 + zend_hash_move_forward_ex(hash, &hpos);
18176 + RETURN_ZVAL(result, 0, 1);
18178 + apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC);
18186 +/* {{{ proto mixed apc_delete(mixed keys)
18188 +PHP_FUNCTION(apc_delete) {
18191 + if(!APCG(enabled)) RETURN_FALSE;
18193 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
18197 + if (Z_TYPE_P(keys) == IS_STRING) {
18198 + if (!Z_STRLEN_P(keys)) RETURN_FALSE;
18199 + if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_P(keys), (Z_STRLEN_P(keys) + 1) TSRMLS_CC)) {
18204 + } else if (Z_TYPE_P(keys) == IS_ARRAY) {
18205 + HashTable *hash = Z_ARRVAL_P(keys);
18206 + HashPosition hpos;
18208 + array_init(return_value);
18209 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
18210 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
18211 + if(Z_TYPE_PP(hentry) != IS_STRING) {
18212 + apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18213 + add_next_index_zval(return_value, *hentry);
18214 + Z_ADDREF_PP(hentry);
18215 + } else if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1) TSRMLS_CC) != 1) {
18216 + add_next_index_zval(return_value, *hentry);
18217 + Z_ADDREF_PP(hentry);
18219 + zend_hash_move_forward_ex(hash, &hpos);
18222 + } else if (Z_TYPE_P(keys) == IS_OBJECT) {
18223 + if (apc_iterator_delete(keys TSRMLS_CC)) {
18229 + apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18234 +/* {{{ proto mixed apc_delete_file(mixed keys)
18235 + * Deletes the given files from the opcode cache.
18236 + * Accepts a string, array of strings, or APCIterator object.
18237 + * Returns True/False, or for an Array an Array of failed files.
18239 +PHP_FUNCTION(apc_delete_file) {
18242 + if(!APCG(enabled)) RETURN_FALSE;
18244 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
18248 + if (Z_TYPE_P(keys) == IS_STRING) {
18249 + if (!Z_STRLEN_P(keys)) RETURN_FALSE;
18250 + if(apc_cache_delete(apc_cache, Z_STRVAL_P(keys), Z_STRLEN_P(keys) + 1 TSRMLS_CC) != 1) {
18255 + } else if (Z_TYPE_P(keys) == IS_ARRAY) {
18256 + HashTable *hash = Z_ARRVAL_P(keys);
18257 + HashPosition hpos;
18259 + array_init(return_value);
18260 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
18261 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
18262 + if(Z_TYPE_PP(hentry) != IS_STRING) {
18263 + apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18264 + add_next_index_zval(return_value, *hentry);
18265 + Z_ADDREF_PP(hentry);
18266 + } else if(apc_cache_delete(apc_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1 TSRMLS_CC) != 1) {
18267 + add_next_index_zval(return_value, *hentry);
18268 + Z_ADDREF_PP(hentry);
18270 + zend_hash_move_forward_ex(hash, &hpos);
18273 + } else if (Z_TYPE_P(keys) == IS_OBJECT) {
18274 + if (apc_iterator_delete(keys TSRMLS_CC)) {
18280 + apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18285 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
18287 + unsigned int const_key_len;
18289 + HashPosition pos;
18291 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
18292 + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
18297 + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
18298 + if(key_type != HASH_KEY_IS_STRING) {
18299 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
18302 + switch(Z_TYPE_PP(entry)) {
18307 + case IS_RESOURCE:
18311 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
18314 + c.value = **entry;
18315 + zval_copy_ctor(&c.value);
18316 + c.flags = case_sensitive;
18317 + c.name = zend_strndup(const_key, const_key_len);
18318 + c.name_len = const_key_len;
18319 + c.module_number = PHP_USER_CONSTANT;
18320 + zend_register_constant(&c TSRMLS_CC);
18322 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
18326 +/* {{{ proto mixed apc_define_constants(string key, array constants [, bool case_sensitive])
18328 +PHP_FUNCTION(apc_define_constants) {
18331 + zval *constants = NULL;
18332 + zend_bool case_sensitive = 1;
18333 + int argc = ZEND_NUM_ARGS();
18335 + if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
18339 + if(!strkey_len) RETURN_FALSE;
18341 + _apc_define_constants(constants, case_sensitive TSRMLS_CC);
18342 + if(_apc_store(strkey, strkey_len + 1, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
18346 +/* {{{ proto mixed apc_load_constants(string key [, bool case_sensitive])
18348 +PHP_FUNCTION(apc_load_constants) {
18351 + apc_cache_entry_t* entry;
18353 + zend_bool case_sensitive = 1;
18355 + if(!APCG(enabled)) RETURN_FALSE;
18356 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
18360 + if(!strkey_len) RETURN_FALSE;
18364 + entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC);
18367 + _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
18368 + apc_cache_release(apc_user_cache, entry TSRMLS_CC);
18376 +/* {{{ proto mixed apc_compile_file(mixed filenames [, bool atomic])
18378 +PHP_FUNCTION(apc_compile_file) {
18380 + zend_file_handle file_handle;
18381 + zend_op_array *op_array;
18382 + char** filters = NULL;
18383 + zend_bool cache_by_default = 1;
18384 + HashTable cg_function_table, cg_class_table;
18385 + HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
18386 + apc_cache_entry_t** cache_entries;
18387 + apc_cache_key_t* keys;
18388 + zend_op_array **op_arrays;
18391 + HashPosition hpos;
18395 + zend_bool atomic=1;
18396 + apc_context_t ctxt = {0,};
18397 + zend_execute_data *orig_current_execute_data;
18400 + if(!APCG(enabled)) RETURN_FALSE;
18402 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &file, &atomic) == FAILURE) {
18406 + if (Z_TYPE_P(file) != IS_ARRAY && Z_TYPE_P(file) != IS_STRING) {
18407 + apc_warning("apc_compile_file argument must be a string or an array of strings" TSRMLS_CC);
18411 + HANDLE_BLOCK_INTERRUPTIONS();
18412 + APCG(current_cache) = apc_cache;
18414 + /* reset filters and cache_by_default */
18415 + filters = APCG(filters);
18416 + APCG(filters) = NULL;
18418 + cache_by_default = APCG(cache_by_default);
18419 + APCG(cache_by_default) = 1;
18421 + /* Replace function/class tables to avoid namespace conflicts */
18422 + zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
18423 + cg_orig_function_table = CG(function_table);
18424 + CG(function_table) = &cg_function_table;
18425 + zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
18426 + cg_orig_class_table = CG(class_table);
18427 + CG(class_table) = &cg_class_table;
18428 + eg_orig_function_table = EG(function_table);
18429 + EG(function_table) = CG(function_table);
18430 + eg_orig_class_table = EG(class_table);
18431 + EG(class_table) = CG(class_table);
18432 + APCG(force_file_update) = 1;
18434 + /* Compile the file(s), loading it into the cache */
18435 + if (Z_TYPE_P(file) == IS_STRING) {
18436 + file_handle.type = ZEND_HANDLE_FILENAME;
18437 + file_handle.filename = Z_STRVAL_P(file);
18438 + file_handle.free_filename = 0;
18439 + file_handle.opened_path = NULL;
18441 + orig_current_execute_data = EG(current_execute_data);
18443 + op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
18445 + EG(current_execute_data) = orig_current_execute_data;
18446 + EG(in_execution) = 1;
18447 + CG(unclean_shutdown) = 0;
18448 + apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
18450 + } zend_end_try();
18451 + if(op_array != NULL) {
18452 + /* Free up everything */
18453 + destroy_op_array(op_array TSRMLS_CC);
18459 + zend_destroy_file_handle(&file_handle TSRMLS_CC);
18461 + } else { /* IS_ARRAY */
18463 + array_init(return_value);
18467 + op_arrays = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(zend_op_array*));
18468 + cache_entries = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_entry_t*));
18469 + keys = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_key_t));
18470 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
18471 + while(zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos) == SUCCESS) {
18472 + if (Z_TYPE_PP(hentry) != IS_STRING) {
18473 + apc_warning("apc_compile_file array values must be strings, aborting." TSRMLS_CC);
18476 + file_handle.type = ZEND_HANDLE_FILENAME;
18477 + file_handle.filename = Z_STRVAL_PP(hentry);
18478 + file_handle.free_filename = 0;
18479 + file_handle.opened_path = NULL;
18481 + if (!apc_cache_make_file_key(&(keys[i]), file_handle.filename, PG(include_path), t TSRMLS_CC)) {
18482 + add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1); /* -1: compilation error */
18483 + apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
18487 + if (keys[i].type == APC_CACHE_KEY_FPFILE) {
18488 + keys[i].data.fpfile.fullpath = estrndup(keys[i].data.fpfile.fullpath, keys[i].data.fpfile.fullpath_len);
18489 + } else if (keys[i].type == APC_CACHE_KEY_USER) {
18490 + keys[i].data.user.identifier = estrndup(keys[i].data.user.identifier, keys[i].data.user.identifier_len);
18493 + orig_current_execute_data = EG(current_execute_data);
18495 + if (apc_compile_cache_entry(&keys[i], &file_handle, ZEND_INCLUDE, t, &op_arrays[i], &cache_entries[i] TSRMLS_CC) != SUCCESS) {
18496 + op_arrays[i] = NULL;
18497 + cache_entries[i] = NULL;
18498 + add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2); /* -2: input or cache insertion error */
18499 + apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
18502 + EG(current_execute_data) = orig_current_execute_data;
18503 + EG(in_execution) = 1;
18504 + CG(unclean_shutdown) = 0;
18505 + op_arrays[i] = NULL;
18506 + cache_entries[i] = NULL;
18507 + add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1); /* -1: compilation error */
18508 + apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename);
18509 + } zend_end_try();
18511 + zend_destroy_file_handle(&file_handle TSRMLS_CC);
18512 + if(op_arrays[i] != NULL) {
18516 + /* clean out the function/class tables */
18517 + zend_hash_clean(&cg_function_table);
18518 + zend_hash_clean(&cg_class_table);
18520 + zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
18524 + /* atomically update the cache if no errors or not atomic */
18525 + ctxt.copy = APC_COPY_IN_OPCODE;
18526 + ctxt.force_update = 1;
18527 + if (count == i || !atomic) {
18528 + rval = apc_cache_insert_mult(apc_cache, keys, cache_entries, &ctxt, t, i TSRMLS_CC);
18534 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
18535 + for(c=0; c < i; c++) {
18536 + zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos);
18537 + if (rval && rval[c] != 1) {
18538 + add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2); /* -2: input or cache insertion error */
18539 + if (cache_entries[c]) {
18540 + apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC);
18543 + if (op_arrays[c]) {
18544 + destroy_op_array(op_arrays[c] TSRMLS_CC);
18545 + efree(op_arrays[c]);
18547 + if (atomic_fail && cache_entries[c]) {
18548 + apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC);
18550 + if (keys[c].type == APC_CACHE_KEY_FPFILE) {
18551 + efree((void*)keys[c].data.fpfile.fullpath);
18552 + } else if (keys[c].type == APC_CACHE_KEY_USER) {
18553 + efree((void*)keys[c].data.user.identifier);
18555 + zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
18557 + efree(op_arrays);
18559 + efree(cache_entries);
18566 + /* Return class/function tables to previous states, destroy temp tables */
18567 + APCG(force_file_update) = 0;
18568 + CG(function_table) = cg_orig_function_table;
18569 + zend_hash_destroy(&cg_function_table);
18570 + CG(class_table) = cg_orig_class_table;
18571 + zend_hash_destroy(&cg_class_table);
18572 + EG(function_table) = eg_orig_function_table;
18573 + EG(class_table) = eg_orig_class_table;
18575 + /* Restore global settings */
18576 + APCG(filters) = filters;
18577 + APCG(cache_by_default) = cache_by_default;
18579 + APCG(current_cache) = NULL;
18580 + HANDLE_UNBLOCK_INTERRUPTIONS();
18585 +/* {{{ proto mixed apc_bin_dump([array files [, array user_vars]])
18586 + Returns a binary dump of the given files and user variables from the APC cache.
18587 + A NULL for files or user_vars signals a dump of every entry, while array() will dump nothing.
18589 +PHP_FUNCTION(apc_bin_dump) {
18591 + zval *z_files = NULL, *z_user_vars = NULL;
18592 + HashTable *h_files, *h_user_vars;
18595 + if(!APCG(enabled)) {
18596 + apc_warning("APC is not enabled, apc_bin_dump not available." TSRMLS_CC);
18600 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &z_files, &z_user_vars) == FAILURE) {
18604 + h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
18605 + h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
18606 + bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
18608 + RETVAL_STRINGL((char*)bd, bd->size-1, 0);
18610 + apc_error("Unknown error encountered during apc_bin_dump." TSRMLS_CC);
18617 +/* {{{ proto mixed apc_bin_dumpfile(array files, array user_vars, string filename, [int flags [, resource context]])
18618 + Output a binary dump of the given files and user variables from the APC cache to the named file.
18620 +PHP_FUNCTION(apc_bin_dumpfile) {
18622 + zval *z_files = NULL, *z_user_vars = NULL;
18623 + HashTable *h_files, *h_user_vars;
18624 + char *filename = NULL;
18625 + int filename_len;
18627 + zval *zcontext = NULL;
18628 + php_stream_context *context = NULL;
18629 + php_stream *stream;
18630 + int numbytes = 0;
18633 + if(!APCG(enabled)) {
18634 + apc_warning("APC is not enabled, apc_bin_dumpfile not available." TSRMLS_CC);
18639 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!s|lr!", &z_files, &z_user_vars, &filename, &filename_len, &flags, &zcontext) == FAILURE) {
18643 + if(!filename_len) {
18644 + apc_error("apc_bin_dumpfile filename argument must be a valid filename." TSRMLS_CC);
18648 + h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
18649 + h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
18650 + bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
18652 + apc_error("Unknown error encountered during apc_bin_dumpfile." TSRMLS_CC);
18657 + /* Most of the following has been taken from the file_get/put_contents functions */
18659 + context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
18660 + stream = php_stream_open_wrapper_ex(filename, (flags & PHP_FILE_APPEND) ? "ab" : "wb",
18661 + ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
18662 + if (stream == NULL) {
18664 + apc_error("Unable to write to file in apc_bin_dumpfile." TSRMLS_CC);
18668 + if (flags & LOCK_EX && php_stream_lock(stream, LOCK_EX)) {
18669 + php_stream_close(stream);
18671 + apc_error("Unable to get a lock on file in apc_bin_dumpfile." TSRMLS_CC);
18675 + numbytes = php_stream_write(stream, (char*)bd, bd->size);
18676 + if(numbytes != bd->size) {
18680 + php_stream_close(stream);
18683 + if(numbytes < 0) {
18684 + apc_error("Only %d of %d bytes written, possibly out of free disk space" TSRMLS_CC, numbytes, bd->size);
18688 + RETURN_LONG(numbytes);
18691 +/* {{{ proto mixed apc_bin_load(string data, [int flags])
18692 + Load the given binary dump into the APC file/user cache.
18694 +PHP_FUNCTION(apc_bin_load) {
18700 + if(!APCG(enabled)) {
18701 + apc_warning("APC is not enabled, apc_bin_load not available." TSRMLS_CC);
18705 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags) == FAILURE) {
18709 + if(!data_len || data_len != ((apc_bd_t*)data)->size -1) {
18710 + 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);
18714 + apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
18719 +/* {{{ proto mixed apc_bin_loadfile(string filename, [resource context, [int flags]])
18720 + Load the given binary dump from the named file into the APC file/user cache.
18722 +PHP_FUNCTION(apc_bin_loadfile) {
18725 + int filename_len;
18726 + zval *zcontext = NULL;
18728 + php_stream_context *context = NULL;
18729 + php_stream *stream;
18733 + if(!APCG(enabled)) {
18734 + apc_warning("APC is not enabled, apc_bin_loadfile not available." TSRMLS_CC);
18738 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!l", &filename, &filename_len, &zcontext, &flags) == FAILURE) {
18742 + if(!filename_len) {
18743 + apc_error("apc_bin_loadfile filename argument must be a valid filename." TSRMLS_CC);
18747 + context = php_stream_context_from_zval(zcontext, 0);
18748 + stream = php_stream_open_wrapper_ex(filename, "rb",
18749 + ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
18751 + apc_error("Unable to read from file in apc_bin_loadfile." TSRMLS_CC);
18755 + len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0);
18757 + apc_warning("File passed to apc_bin_loadfile was empty: %s." TSRMLS_CC, filename);
18759 + } else if(len < 0) {
18760 + apc_warning("Error reading file passed to apc_bin_loadfile: %s." TSRMLS_CC, filename);
18762 + } else if(len != ((apc_bd_t*)data)->size) {
18763 + 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);
18766 + php_stream_close(stream);
18768 + apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
18776 +#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
18777 +# define PHP_APC_ARGINFO
18779 +# define PHP_APC_ARGINFO static
18783 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_store, 0, 0, 2)
18784 + ZEND_ARG_INFO(0, key)
18785 + ZEND_ARG_INFO(0, var)
18786 + ZEND_ARG_INFO(0, ttl)
18787 +ZEND_END_ARG_INFO()
18790 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_clear_cache, 0, 0, 0)
18791 + ZEND_ARG_INFO(0, info)
18792 +ZEND_END_ARG_INFO()
18795 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_sma_info, 0, 0, 0)
18796 + ZEND_ARG_INFO(0, limited)
18797 +ZEND_END_ARG_INFO()
18800 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_cache_info, 0, 0, 0)
18801 + ZEND_ARG_INFO(0, type)
18802 + ZEND_ARG_INFO(0, limited)
18803 +ZEND_END_ARG_INFO()
18806 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_define_constants, 0, 0, 2)
18807 + ZEND_ARG_INFO(0, key)
18808 + ZEND_ARG_INFO(0, constants)
18809 + ZEND_ARG_INFO(0, case_sensitive)
18810 +ZEND_END_ARG_INFO()
18813 +ZEND_BEGIN_ARG_INFO(arginfo_apc_delete_file, 0)
18814 + ZEND_ARG_INFO(0, keys)
18815 +ZEND_END_ARG_INFO()
18818 +ZEND_BEGIN_ARG_INFO(arginfo_apc_delete, 0)
18819 + ZEND_ARG_INFO(0, keys)
18820 +ZEND_END_ARG_INFO()
18823 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_fetch, 0, 0, 1)
18824 + ZEND_ARG_INFO(0, key)
18825 + ZEND_ARG_INFO(1, success)
18826 +ZEND_END_ARG_INFO()
18829 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_inc, 0, 0, 1)
18830 + ZEND_ARG_INFO(0, key)
18831 + ZEND_ARG_INFO(0, step)
18832 + ZEND_ARG_INFO(1, success)
18833 +ZEND_END_ARG_INFO()
18836 +ZEND_BEGIN_ARG_INFO(arginfo_apc_cas, 0)
18837 + ZEND_ARG_INFO(0, key)
18838 + ZEND_ARG_INFO(0, old)
18839 + ZEND_ARG_INFO(0, new)
18840 +ZEND_END_ARG_INFO()
18843 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_load_constants, 0, 0, 1)
18844 + ZEND_ARG_INFO(0, key)
18845 + ZEND_ARG_INFO(0, case_sensitive)
18846 +ZEND_END_ARG_INFO()
18849 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_compile_file, 0, 0, 1)
18850 + ZEND_ARG_INFO(0, filenames)
18851 + ZEND_ARG_INFO(0, atomic)
18852 +ZEND_END_ARG_INFO()
18855 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dump, 0, 0, 0)
18856 + ZEND_ARG_INFO(0, files)
18857 + ZEND_ARG_INFO(0, user_vars)
18858 +ZEND_END_ARG_INFO()
18861 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dumpfile, 0, 0, 3)
18862 + ZEND_ARG_INFO(0, files)
18863 + ZEND_ARG_INFO(0, user_vars)
18864 + ZEND_ARG_INFO(0, filename)
18865 + ZEND_ARG_INFO(0, flags)
18866 + ZEND_ARG_INFO(0, context)
18867 +ZEND_END_ARG_INFO()
18870 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_load, 0, 0, 1)
18871 + ZEND_ARG_INFO(0, data)
18872 + ZEND_ARG_INFO(0, flags)
18873 +ZEND_END_ARG_INFO()
18876 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_loadfile, 0, 0, 1)
18877 + ZEND_ARG_INFO(0, filename)
18878 + ZEND_ARG_INFO(0, context)
18879 + ZEND_ARG_INFO(0, flags)
18880 +ZEND_END_ARG_INFO()
18883 +ZEND_BEGIN_ARG_INFO(arginfo_apc_exists, 0)
18884 + ZEND_ARG_INFO(0, keys)
18885 +ZEND_END_ARG_INFO()
18888 +/* {{{ apc_functions[] */
18889 +zend_function_entry apc_functions[] = {
18890 + PHP_FE(apc_cache_info, arginfo_apc_cache_info)
18891 + PHP_FE(apc_clear_cache, arginfo_apc_clear_cache)
18892 + PHP_FE(apc_sma_info, arginfo_apc_sma_info)
18893 + PHP_FE(apc_store, arginfo_apc_store)
18894 + PHP_FE(apc_fetch, arginfo_apc_fetch)
18895 + PHP_FE(apc_delete, arginfo_apc_delete)
18896 + PHP_FE(apc_delete_file, arginfo_apc_delete_file)
18897 + PHP_FE(apc_define_constants, arginfo_apc_define_constants)
18898 + PHP_FE(apc_load_constants, arginfo_apc_load_constants)
18899 + PHP_FE(apc_compile_file, arginfo_apc_compile_file)
18900 + PHP_FE(apc_add, arginfo_apc_store)
18901 + PHP_FE(apc_inc, arginfo_apc_inc)
18902 + PHP_FE(apc_dec, arginfo_apc_inc)
18903 + PHP_FE(apc_cas, arginfo_apc_cas)
18904 + PHP_FE(apc_bin_dump, arginfo_apc_bin_dump)
18905 + PHP_FE(apc_bin_load, arginfo_apc_bin_load)
18906 + PHP_FE(apc_bin_dumpfile, arginfo_apc_bin_dumpfile)
18907 + PHP_FE(apc_bin_loadfile, arginfo_apc_bin_loadfile)
18908 + PHP_FE(apc_exists, arginfo_apc_exists)
18909 + {NULL, NULL, NULL}
18913 +/* {{{ module definition structure */
18915 +zend_module_entry apc_module_entry = {
18916 + STANDARD_MODULE_HEADER,
18920 + PHP_MSHUTDOWN(apc),
18922 + PHP_RSHUTDOWN(apc),
18925 + STANDARD_MODULE_PROPERTIES
18928 +#ifdef COMPILE_DL_APC
18929 +ZEND_GET_MODULE(apc)
18934 + * Local variables:
18936 + * c-basic-offset: 4
18938 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
18939 + * vim<600: expandtab sw=4 ts=4 sts=4
18941 diff -Naur a/ext/apc/php_apc.h b/ext/apc/php_apc.h
18942 --- a/ext/apc/php_apc.h 1970-01-01 01:00:00.000000000 +0100
18943 +++ b/ext/apc/php_apc.h 2012-07-20 00:10:35.000000000 +0200
18946 + +----------------------------------------------------------------------+
18948 + +----------------------------------------------------------------------+
18949 + | Copyright (c) 2006-2011 The PHP Group |
18950 + +----------------------------------------------------------------------+
18951 + | This source file is subject to version 3.01 of the PHP license, |
18952 + | that is bundled with this package in the file LICENSE, and is |
18953 + | available through the world-wide-web at the following url: |
18954 + | http://www.php.net/license/3_01.txt |
18955 + | If you did not receive a copy of the PHP license and are unable to |
18956 + | obtain it through the world-wide-web, please send a note to |
18957 + | license@php.net so we can mail you a copy immediately. |
18958 + +----------------------------------------------------------------------+
18959 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
18960 + | George Schlossnagle <george@omniti.com> |
18961 + | Rasmus Lerdorf <rasmus@php.net> |
18962 + +----------------------------------------------------------------------+
18964 + This software was contributed to PHP by Community Connect Inc. in 2002
18965 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
18966 + Future revisions and derivatives of this source code must acknowledge
18967 + Community Connect Inc. as the original contributor of this module by
18968 + leaving this note intact in the source code.
18970 + All other licensing and usage conditions are those of the PHP Group.
18974 +/* $Id: php_apc.h 326713 2012-07-19 22:07:31Z rasmus $ */
18979 +#include "apc_php.h"
18980 +#include "apc_globals.h"
18982 +#define PHP_APC_VERSION "3.1.11"
18984 +extern zend_module_entry apc_module_entry;
18985 +#define apc_module_ptr &apc_module_entry
18987 +#define phpext_apc_ptr apc_module_ptr
18989 +#endif /* PHP_APC_H */
18992 + * Local variables:
18994 + * c-basic-offset: 4
18996 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
18997 + * vim<600: expandtab sw=4 ts=4 sts=4
18999 diff -Naur a/ext/apc/TECHNOTES.txt b/ext/apc/TECHNOTES.txt
19000 --- a/ext/apc/TECHNOTES.txt 1970-01-01 01:00:00.000000000 +0100
19001 +++ b/ext/apc/TECHNOTES.txt 2012-07-20 00:10:35.000000000 +0200
19003 +APC Quick-Start Braindump
19005 +This is a rapidly written braindump of how APC currently works in the
19006 +form of a quick-start guide to start hacking on APC.
19008 +1. Install and use APC a bit so you know what it does from the end-user's
19010 + user-space functions are all explained here:
19012 +2. Grab the current APC code from CVS:
19014 + cvs -d:pserver:cvsread@cvs.php.net:/repository login
19016 + cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
19018 + apc/php_apc.c has most of the code for the user-visible stuff. It is
19019 + also a regular PHP extension in the sense that there are MINIT, MINFO,
19020 + MSHUTDOWN, RSHUTDOWN, etc. functions.
19026 + ./configure --enable-apc --enable-mmap
19028 + cp modules/apc.so /usr/local/lib/php
19029 + apachectl restart
19031 +4. Debugging Hints
19034 + gdb /usr/bin/httpd
19038 + Grab the .gdbinit from the PHP source tree and have a look at the macros.
19040 +5. Look through apc/apc_sma.c
19041 + It is a pretty standard memory allocator.
19043 + apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
19044 + caller just like malloc, realloc, strdup and free
19046 + On server startup the MINIT hook in php_apc.c calls apc_module_init() in
19047 + apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into
19048 + apc_mmap.c to mmap the specified sized segment (I tend to just use a single
19049 + segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and
19050 + then unlinks that file right after the mmap to provide automatic shared memory
19051 + cleanup in case the process dies.
19053 + Once the region has been initialized we stick a header_t at the beginning
19054 + of the region. It contains the total size in header->segsize and the number
19055 + of bytes available in header->avail.
19057 + After the header comes a bit of a hack. A zero-sized block is inserted just
19058 + to make things easier later on. And then a huge block that is basically
19059 + the size of the entire segment minus the two (for the 0-sized block, and this one)
19062 + The code for this is:
19064 + header = (header_t*) shmaddr;
19065 + header->segsize = sma_segsize;
19066 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
19067 + memset(&header->lock,0,sizeof(header->lock));
19068 + sma_lock = &header->lock;
19069 + block = BLOCKAT(sizeof(header_t));
19071 + block->next = sizeof(header_t) + sizeof(block_t);
19072 + block = BLOCKAT(block->next);
19073 + block->size = header->avail;
19076 + So the shared memory looks like this:
19078 + +--------+-------+---------------------------------+
19079 + | header | block | block |
19080 + +--------+-------+---------------------------------+
19082 + sma_shmaddrs[0] gives you the address of header
19084 + The blocks are just a simple offset-based linked list (so no pointers):
19086 + typedef struct block_t block_t;
19088 + size_t size; /* size of this block */
19089 + size_t next; /* offset in segment of next free block */
19090 + size_t canary; /* canary to check for memory overwrites */
19091 +#ifdef __APC_SMA_DEBUG__
19092 + int id; /* identifier for the memory block */
19096 + The BLOCKAT macro turns an offset into an actual address for you:
19098 + #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
19100 + where shmaddr = sma_shaddrs[0]
19102 + And the OFFSET macro goes the other way:
19104 + #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
19106 + Allocating a block with a call to apc_sma_allocate() walks through the
19107 + linked list of blocks until it finds one that is >= to the requested size.
19108 + The first call to apc_sma_allocate() will hit the second block. We then
19109 + chop up that block so it looks like this:
19111 + +--------+-------+-------+-------------------------+
19112 + | header | block | block | block |
19113 + +--------+-------+-------+-------------------------+
19115 + Then we unlink that block from the linked list so it won't show up
19116 + as an available block on the next allocate. So we actually have:
19118 + +--------+-------+ +-------------------------+
19119 + | header | block |------>| block |
19120 + +--------+-------+ +-------------------------+
19122 + And header->avail along with block->size of the remaining large
19123 + block are updated accordingly. The arrow there representing the
19124 + link which now points to a block with an offset further along in
19127 + When the block is freed using apc_sma_deallocate() the steps are
19128 + basically just reversed. The block is put back and then the deallocate
19129 + code looks at the block before and after to see if the block immediately
19130 + before and after are free and if so the blocks are combined. So you never
19131 + have 2 free blocks next to each other, apart from at the front with that
19132 + 0-sized dummy block. This mostly prevents fragmentation. I have been
19133 + toying with the idea of always allocating block at 2^n boundaries to make
19134 + it more likely that they will be re-used to cut down on fragmentation further.
19135 + That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
19137 + Of course, anytime we fiddle with our shared memory segment we lock using
19138 + the locking macros, LOCK() and UNLOCK().
19140 + That should mostly take care of the low-level shared memory handling.
19142 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
19145 + The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
19146 + and apc_cache.c for actual cache manipulation.
19148 + After the shared memory segment is created and the caches are initialized,
19149 + apc_module_init() installs the my_compile_file() function overriding Zend's
19150 + version. I'll talk about my_compile_file() and the rest of apc_compile.c
19151 + in the next section. For now I will stick with apc_main.c and apc_cache.c
19152 + and talk about the actual caches. A cache consists of a block of shared
19153 + memory returned by apc_sma_allocate() via apc_sma_malloc(). You will
19154 + notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper
19155 + around PHP's own emalloc() function which allocates per-process memory from
19156 + PHP's pool-based memory allocator. Don't confuse apc_emalloc() and
19157 + apc_sma_malloc() as the first is per-process and the second is shared memory.
19159 + The cache is stored in/described by this struct allocated locally using
19162 + struct apc_cache_t {
19163 + void* shmaddr; /* process (local) address of shared cache */
19164 + header_t* header; /* cache header (stored in SHM) */
19165 + slot_t** slots; /* array of cache slots (stored in SHM) */
19166 + int num_slots; /* number of slots in cache */
19167 + int gc_ttl; /* maximum time on GC list for a slot */
19168 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
19171 + Whenever you see functions that take a 'cache' argument, this is what they
19172 + take. And apc_cache_create() returns a pointer to this populated struct.
19174 + At the beginning of the cache we have a header. Remember, we are down a level now
19175 + from the sma stuff. The sma stuff is the low-level shared-memory allocator which
19176 + has its own header which is completely separate and invisible to apc_cache.c.
19177 + As far as apc_cache.c is concerned the block of memory it is working with could
19178 + have come from a call to malloc().
19180 + The header looks like this:
19182 + typedef struct header_t header_t;
19183 + struct header_t {
19184 + int num_hits; /* total successful hits in cache */
19185 + int num_misses; /* total unsuccessful hits in cache */
19186 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
19189 + Since this is at the start of the shared memory segment, these values are accessible
19190 + across all the apache processes and hence access to them has to be locked.
19192 + After the header we have an array of slots. The number of slots is user-defined
19193 + through the apc.num_slots ini hint. Each slot is described by:
19195 + typedef struct slot_t slot_t;
19197 + apc_cache_key_t key; /* slot key */
19198 + apc_cache_entry_t* value; /* slot value */
19199 + slot_t* next; /* next slot in linked list */
19200 + int num_hits; /* number of hits to this bucket */
19201 + time_t creation_time; /* time slot was initialized */
19202 + time_t deletion_time; /* time slot was removed from cache */
19203 + time_t access_time; /* time slot was last accessed */
19206 + The slot_t *next there is a linked list to other slots that happened to hash to the
19207 + same array position.
19209 + apc_cache_insert() shows what happens on a new cache insert.
19211 + slot = &cache->slots[hash(key) % cache->num_slots];
19213 + cache->slots is our array of slots in the segment. hash() is simply:
19215 + static unsigned int hash(apc_cache_key_t key)
19217 + return key.data.file.device + key.data.file.inode;
19220 + That is, we use the file's device and inode to uniquely identify it. Initially
19221 + we had used the file's full path, but getting that requires a realpath() call which
19222 + is amazingly expensive since it has to stat each component of the path to resolve
19223 + symlinks and get rid of relative path components. By using the device+inode we
19224 + can uniquely identify a file with a single stat.
19226 + So, on an insert we find the array position in the slots array by hashing the device+inode.
19227 + If there are currently no other slots there, we just create the slot and stick it into
19230 + *slot = make_slot(key, value, *slot, t)
19232 + If there are other slots already at this position we walk the link list to get to
19233 + the end. Here is the loop:
19236 + if (key_equals((*slot)->key.data.file, key.data.file)) {
19237 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
19238 + if ((*slot)->key.mtime != key.mtime) {
19239 + remove_slot(cache, slot);
19244 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
19245 + remove_slot(cache, slot);
19248 + slot = &(*slot)->next;
19251 + That first key_equals() check sees if we have an exact match meaning the file
19252 + is already in the cache. Since we try to find the file in the cache before doing
19253 + an insert, this will generally only happen if another process managed to beat us
19254 + to inserting it. If we have a newer version of the file at this point we remove
19255 + it an insert the new version. If our version is not newer we just return without
19258 + While walking the linked list we also check to see if the cache has a TTL defined.
19259 + If while walking the linked list we see a slot that has expired, we remove it
19260 + since we are right there looking at it. This is the only place we remove stale
19261 + entries unless the shared memory segment fills up and we force a full expunge via
19262 + apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks
19263 + down every linked list removing stale slots to free up room. This is obviously
19264 + slow and thus only happens when we have run out of room.
19266 + apc_cache_find() simply hashes and returns the entry if it is there. If it is there
19267 + but older than the mtime in the entry we are looking for, we delete the one that is
19268 + there and return indicating we didn't find it.
19270 + Next we need to understand what an actual cache entry looks like. Have a look at
19271 + apc_cache.h for the structs. I sort of glossed over the key part earlier saying
19272 + that we just used the device+inode to find a hash slot. It is actually a bit more
19273 + complex than that because we have two kinds of caches. We have the standard file
19274 + cache containing opcode arrays, but we also have a user-controlled cache that the
19275 + user can insert whatever they want into via apc_store(). For the user cache we
19276 + obviously don't have a device+inode. The actual identifier is provided by the user
19277 + as a char *. So the key is actually a union that looks like this:
19279 + typedef union _apc_cache_key_data_t {
19281 + int device; /* the filesystem device */
19282 + int inode; /* the filesystem inode */
19285 + char *identifier;
19287 + } apc_cache_key_data_t;
19289 + struct apc_cache_key_t {
19290 + apc_cache_key_data_t data;
19291 + int mtime; /* the mtime of this cached entry */
19294 + And we have two sets of functions to do inserts and finds. apc_cache_user_find()
19295 + and apc_cache_user_insert() operate on the user cache.
19297 + Ok, on to the actual cache entry. Again, because we have two kinds of caches, we
19298 + also have the corresponding two kinds of cache entries described by this union:
19300 + typedef union _apc_cache_entry_value_t {
19302 + char *filename; /* absolute path to source file */
19303 + zend_op_array* op_array; /* op_array allocated in shared memory */
19304 + apc_function_t* functions; /* array of apc_function_t's */
19305 + apc_class_t* classes; /* array of apc_class_t's */
19310 + unsigned int ttl;
19312 + } apc_cache_entry_value_t;
19314 + And then the actual cache entry:
19316 + struct apc_cache_entry_t {
19317 + apc_cache_entry_value_t data;
19318 + unsigned char type;
19322 + The user entry is pretty simple and not all that important for now. I will
19323 + concentrate on the file entries since that is what holds the actual compiled
19324 + opcode arrays along with the functions and classes required by the executor.
19326 + apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
19327 + The main thing to understand here is that we need more than just the opcode
19328 + array, we also need the functions and classes created by the compiler when it
19329 + created the opcode array. As far as the executor is concerned, it doesn't know
19330 + that it isn't operating in normal mode being called right after the parse/compile
19331 + phase, so we need to recreate everything so it looks exactly like it would at
19334 +7. my_compile_file() and apc_compile.c
19336 + my_compile_file() in apc_main.c controls where we get the opcodes from. If
19337 + the user-specified filters exclude the file from being cached, then we just
19338 + call the original compile function and return. Otherwise we fetch the request
19339 + time from Apache to avoid an extra syscall, create the key so we can look up
19340 + the file in the cache. If we find it we stick it on a local stack which we
19341 + use at cleanup time to make sure we return everything back to normal after a
19342 + request and call cached_compile() which installs the functions and classes
19343 + associated with the op_array in this entry and then copy the op_array down
19344 + into our memory space for execution.
19346 + If we didn't find the file in the cache, we need to compile it and insert it.
19347 + To compile it we simply call the original compile function:
19349 + op_array = old_compile_file(h, type TSRMLS_CC);
19351 + To do the insert we need to copy the functions, classes and the opcode array
19352 + the compile phase created into shared memory. This all happens in apc_compile.c
19353 + in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
19354 + functions. Then we make the file entry and do the insert. Both of these
19355 + operations were described in the previous section.
19359 + The optimizer has been deprecated.
19361 +If you made it to the end of this, you should have a pretty good idea of where things are in
19362 +the code. I skimmed over a lot of things, so plan on spending some time reading through the code.
19364 diff -Naur a/ext/apc/tests/apc_001.phpt b/ext/apc/tests/apc_001.phpt
19365 --- a/ext/apc/tests/apc_001.phpt 1970-01-01 01:00:00.000000000 +0100
19366 +++ b/ext/apc/tests/apc_001.phpt 2012-07-20 00:10:35.000000000 +0200
19369 +APC: apc_store/fetch with strings
19371 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19375 +apc.file_update_protection=0
19379 +$foo = 'hello world';
19381 +apc_store('foo',$foo);
19382 +$bar = apc_fetch('foo');
19387 +apc_store('foo\x00bar', $foo);
19388 +$bar = apc_fetch('foo\x00bar');
19395 +string(11) "hello world"
19396 +string(11) "hello world"
19398 +string(11) "hello world"
19400 diff -Naur a/ext/apc/tests/apc_002.phpt b/ext/apc/tests/apc_002.phpt
19401 --- a/ext/apc/tests/apc_002.phpt 1970-01-01 01:00:00.000000000 +0100
19402 +++ b/ext/apc/tests/apc_002.phpt 2012-07-20 00:10:35.000000000 +0200
19405 +APC: apc_store/fetch with objects
19407 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19411 +apc.file_update_protection=0
19418 +apc_store('foo',$foo);
19420 +$bar = apc_fetch('foo');
19429 +object(foo)#%d (0) {
19431 +object(foo)#%d (0) {
19433 +object(foo)#%d (1) {
19438 diff -Naur a/ext/apc/tests/apc_003b.phpt b/ext/apc/tests/apc_003b.phpt
19439 --- a/ext/apc/tests/apc_003b.phpt 1970-01-01 01:00:00.000000000 +0100
19440 +++ b/ext/apc/tests/apc_003b.phpt 2012-07-20 00:10:35.000000000 +0200
19443 +APC: apc_store/fetch with objects (php 5.3)
19446 + require_once(dirname(__FILE__) . '/skipif.inc');
19447 + if(version_compare(zend_version(), '2.3.0') < 0) {
19454 +apc.file_update_protection=0
19461 +apc_store('foo',$foo);
19463 +$bar = apc_fetch('foo');
19468 +class bar extends foo
19470 + public $pub = 'bar';
19471 + protected $pro = 'bar';
19472 + private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
19474 + function __construct()
19476 + $this->bar = true;
19479 + function change()
19481 + $this->pri = 'mod';
19485 +class baz extends bar
19487 + private $pri = 'baz';
19489 + function __construct()
19491 + parent::__construct();
19492 + $this->baz = true;
19500 +apc_store('baz', $baz);
19502 +var_dump(apc_fetch('baz'));
19508 +object(foo)#%d (0) {
19510 +object(foo)#%d (0) {
19512 +object(foo)#%d (1) {
19516 +object(baz)#%d (6) {
19517 + ["pri":"baz":private]=>
19521 + ["pro":protected]=>
19523 + ["pri":"bar":private]=>
19530 +object(baz)#%d (6) {
19531 + ["pri":"baz":private]=>
19535 + ["pro":protected]=>
19537 + ["pri":"bar":private]=>
19544 +object(baz)#%d (6) {
19545 + ["pri":"baz":private]=>
19549 + ["pro":protected]=>
19551 + ["pri":"bar":private]=>
19559 diff -Naur a/ext/apc/tests/apc_003.phpt b/ext/apc/tests/apc_003.phpt
19560 --- a/ext/apc/tests/apc_003.phpt 1970-01-01 01:00:00.000000000 +0100
19561 +++ b/ext/apc/tests/apc_003.phpt 2012-07-20 00:10:35.000000000 +0200
19564 +APC: apc_store/fetch with objects (php pre-5.3)
19567 + require_once(dirname(__FILE__) . '/skipif.inc');
19568 + if(version_compare(zend_version(), '2.3.0') >= 0) {
19575 +apc.file_update_protection=0
19582 +apc_store('foo',$foo);
19584 +$bar = apc_fetch('foo');
19589 +class bar extends foo
19591 + public $pub = 'bar';
19592 + protected $pro = 'bar';
19593 + private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
19595 + function __construct()
19597 + $this->bar = true;
19600 + function change()
19602 + $this->pri = 'mod';
19606 +class baz extends bar
19608 + private $pri = 'baz';
19610 + function __construct()
19612 + parent::__construct();
19613 + $this->baz = true;
19621 +apc_store('baz', $baz);
19623 +var_dump(apc_fetch('baz'));
19629 +object(foo)#%d (0) {
19631 +object(foo)#%d (0) {
19633 +object(foo)#%d (1) {
19637 +object(baz)#%d (6) {
19638 + ["pri:private"]=>
19642 + ["pro:protected"]=>
19644 + ["pri:private"]=>
19651 +object(baz)#%d (6) {
19652 + ["pri:private"]=>
19656 + ["pro:protected"]=>
19658 + ["pri:private"]=>
19665 +object(baz)#%d (6) {
19666 + ["pri:private"]=>
19670 + ["pro:protected"]=>
19672 + ["pri:private"]=>
19680 diff -Naur a/ext/apc/tests/apc_004.phpt b/ext/apc/tests/apc_004.phpt
19681 --- a/ext/apc/tests/apc_004.phpt 1970-01-01 01:00:00.000000000 +0100
19682 +++ b/ext/apc/tests/apc_004.phpt 2012-07-20 00:10:35.000000000 +0200
19685 +APC: apc_store/fetch with bools
19687 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19691 +apc.file_update_protection=0
19696 +var_dump($foo); /* false */
19697 +apc_store('foo',$foo);
19698 +//$success = "some string";
19700 +$bar = apc_fetch('foo', $success);
19701 +var_dump($foo); /* false */
19702 +var_dump($bar); /* false */
19703 +var_dump($success); /* true */
19705 +$bar = apc_fetch('not foo', $success);
19706 +var_dump($foo); /* false */
19707 +var_dump($bar); /* false */
19708 +var_dump($success); /* false */
19722 diff -Naur a/ext/apc/tests/apc_005.phpt b/ext/apc/tests/apc_005.phpt
19723 --- a/ext/apc/tests/apc_005.phpt 1970-01-01 01:00:00.000000000 +0100
19724 +++ b/ext/apc/tests/apc_005.phpt 2012-07-20 00:10:35.000000000 +0200
19727 +APC: apc_store/fetch with arrays of objects
19729 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19733 +apc.file_update_protection=0
19737 +$foo = array(new stdclass(), new stdclass());
19741 +apc_store('foo',$foo);
19743 +$bar = apc_fetch('foo');
19753 + object(stdClass)#1 (0) {
19756 + object(stdClass)#2 (0) {
19761 + object(stdClass)#1 (0) {
19764 + object(stdClass)#2 (0) {
19769 + object(stdClass)#3 (0) {
19772 + object(stdClass)#4 (0) {
19776 diff -Naur a/ext/apc/tests/apc_006.phpt b/ext/apc/tests/apc_006.phpt
19777 --- a/ext/apc/tests/apc_006.phpt 1970-01-01 01:00:00.000000000 +0100
19778 +++ b/ext/apc/tests/apc_006.phpt 2012-07-20 00:10:35.000000000 +0200
19781 +APC: apc_store/fetch reference test
19783 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19787 +apc.file_update_protection=0
19788 +apc.serializer=default
19808 +apc_store('test', $b);
19809 +$x = apc_fetch('test');
19810 +debug_zval_dump($x);
19816 +array(9) refcount(2){
19818 + string(1) "a" refcount(1)
19820 + &array(1) refcount(2){
19822 + string(1) "c" refcount(1)
19825 + &array(1) refcount(2){
19827 + string(1) "c" refcount(1)
19830 + &string(1) "d" refcount(3)
19832 + &string(1) "d" refcount(3)
19834 + &string(1) "d" refcount(3)
19836 + string(1) "e" refcount(2)
19838 + string(1) "e" refcount(2)
19840 + &array(2) refcount(2){
19842 + string(1) "f" refcount(1)
19844 + &array(2) refcount(2){
19846 + string(1) "f" refcount(1)
19853 diff -Naur a/ext/apc/tests/apc_007.phpt b/ext/apc/tests/apc_007.phpt
19854 --- a/ext/apc/tests/apc_007.phpt 1970-01-01 01:00:00.000000000 +0100
19855 +++ b/ext/apc/tests/apc_007.phpt 2012-07-20 00:10:35.000000000 +0200
19858 +APC: apc_inc/apc_dec test
19860 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19864 +apc.file_update_protection=0
19867 +apc_store('foobar',2);
19868 +echo "\$foobar = 2 \n";
19869 +echo "\$foobar += 1 = ".apc_inc('foobar')."\n";
19870 +echo "\$foobar += 10 = ".apc_inc('foobar', 10)."\n";
19872 +echo "\$foobar -= 1 = ".apc_dec('foobar')."\n";
19873 +echo "\$foobar -= 10 = ".apc_dec('foobar',10)."\n";
19875 +echo "\$f__bar += 1 = ".(apc_inc('f__bar')?"ok":"fail")."\n";
19877 +apc_store('perfection', "xyz");
19878 +echo "\$perfection -= 1 = ".(apc_inc('perfection')?"ok":"epic fail")."\n";
19882 +echo "\$foobar += 1 = ".apc_inc('foobar', 1, $success)."\n";
19883 +echo "pass by ref success ". $success . "\n";
19884 +echo "\$foobar -= 1 = ".apc_dec('foobar', 1, $success)."\n";
19885 +echo "pass by ref success ". $success . "\n";
19893 +$foobar += 10 = 13
19896 +$f__bar += 1 = fail
19897 +$perfection -= 1 = epic fail
19899 +pass by ref success 1
19901 +pass by ref success 1
19903 diff -Naur a/ext/apc/tests/apc_008.phpt b/ext/apc/tests/apc_008.phpt
19904 --- a/ext/apc/tests/apc_008.phpt 1970-01-01 01:00:00.000000000 +0100
19905 +++ b/ext/apc/tests/apc_008.phpt 2012-07-20 00:10:35.000000000 +0200
19910 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19914 +apc.file_update_protection=0
19917 +apc_store('foobar',2);
19918 +echo "\$foobar = 2\n";
19919 +echo "\$foobar == 1 ? 2 : 1 = ".(apc_cas('foobar', 1, 2)?"ok":"fail")."\n";
19920 +echo "\$foobar == 2 ? 1 : 2 = ".(apc_cas('foobar', 2, 1)?"ok":"fail")."\n";
19921 +echo "\$foobar = ".apc_fetch("foobar")."\n";
19923 +echo "\$f__bar == 1 ? 2 : 1 = ".(apc_cas('f__bar', 1, 2)?"ok":"fail")."\n";
19925 +apc_store('perfection', "xyz");
19926 +echo "\$perfection == 2 ? 1 : 2 = ".(apc_cas('perfection', 2, 1)?"ok":"epic fail")."\n";
19928 +echo "\$foobar = ".apc_fetch("foobar")."\n";
19934 +$foobar == 1 ? 2 : 1 = fail
19935 +$foobar == 2 ? 1 : 2 = ok
19937 +$f__bar == 1 ? 2 : 1 = fail
19938 +$perfection == 2 ? 1 : 2 = epic fail
19941 diff -Naur a/ext/apc/tests/apc_009.phpt b/ext/apc/tests/apc_009.phpt
19942 --- a/ext/apc/tests/apc_009.phpt 1970-01-01 01:00:00.000000000 +0100
19943 +++ b/ext/apc/tests/apc_009.phpt 2012-07-20 00:10:35.000000000 +0200
19946 +APC: apc_delete_file test
19948 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19952 +apc.file_update_protection=0
19958 +$files = array( 'apc_009.php',
19964 +file_put_contents(dirname(__FILE__).'/apc_009-1.php', '<?php echo "test file";');
19965 +file_put_contents(dirname(__FILE__).'/apc_009-2.php', '<?php syntaxerrorhere!');
19967 +apc_compile_file($files[0]);
19968 +check_file($files[0]);
19969 +apc_delete_file($files[0]);
19970 +check_file($files[0]);
19972 +apc_compile_file($files[0]);
19973 +apc_delete_file(array($files[0]));
19974 +check_file($files[0]);
19976 +apc_compile_file($files[0]);
19977 +$it = new APCIterator('file');
19978 +apc_delete_file($it);
19979 +check_file($files[0]);
19981 +var_dump(apc_compile_file(array($files[0], $files[1])));
19982 +check_file(array($files[0], $files[1]));
19984 +var_dump(apc_compile_file($files));
19985 +check_file($files);
19987 +function check_file($files) {
19989 + if (!is_array($files)) {
19990 + $files = array($files);
19993 + $info = apc_cache_info('file');
19995 + foreach ($files as $file) {
19997 + foreach($info['cache_list'] as $cached_file) {
19998 + if (stristr($cached_file['filename'], $file)) $match = 1;
20001 + echo "$file Found File\n";
20003 + echo "$file Not Found\n";
20013 +unlink('apc_009-1.php');
20014 +unlink('apc_009-2.php');
20017 +apc_009.php Found File
20018 +apc_009.php Not Found
20019 +apc_009.php Not Found
20020 +apc_009.php Not Found
20023 +apc_009.php Found File
20024 +apc_009-1.php Found File
20026 +Parse error: syntax error, unexpected '!' in %s/apc_009-2.php on line 1
20028 +Warning: apc_compile_file(): Error compiling apc_009-2.php in apc_compile_file. in %s/apc_009.php on line 29
20030 +Warning: apc_compile_file(): Error compiling nofile.php in apc_compile_file. in %s/apc_009.php on line 29
20032 + ["apc_009-2.php"]=>
20037 +apc_009.php Found File
20038 +apc_009-1.php Found File
20039 +apc_009-2.php Not Found
20040 +nofile.php Not Found
20042 diff -Naur a/ext/apc/tests/apc_010.phpt b/ext/apc/tests/apc_010.phpt
20043 --- a/ext/apc/tests/apc_010.phpt 1970-01-01 01:00:00.000000000 +0100
20044 +++ b/ext/apc/tests/apc_010.phpt 2012-07-20 00:10:35.000000000 +0200
20047 +APC: apc_store/fetch/add with array of key/value pairs.
20049 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20053 +apc.file_update_protection=0
20057 +$entries = array();
20058 +$entries['key1'] = 'value1';
20059 +$entries['key2'] = 'value2';
20060 +$entries['key3'] = array('value3a','value3b');
20061 +$entries['key4'] = 4;
20063 +var_dump(apc_store($entries));
20064 +$cached_values = apc_fetch(array_keys($entries));
20065 +var_dump($cached_values);
20067 +apc_delete('key2');
20068 +apc_delete('key4');
20069 +$cached_values = apc_fetch(array_keys($entries));
20070 +var_dump($cached_values);
20071 +var_dump(apc_add($entries));
20072 +$cached_values = apc_fetch(array_keys($entries));
20073 +var_dump($cached_values);
20083 + string(6) "value1"
20085 + string(6) "value2"
20089 + string(7) "value3a"
20091 + string(7) "value3b"
20098 + string(6) "value1"
20102 + string(7) "value3a"
20104 + string(7) "value3b"
20115 + string(6) "value1"
20117 + string(6) "value2"
20121 + string(7) "value3a"
20123 + string(7) "value3b"
20129 diff -Naur a/ext/apc/tests/apc53_001.phpt b/ext/apc/tests/apc53_001.phpt
20130 --- a/ext/apc/tests/apc53_001.phpt 1970-01-01 01:00:00.000000000 +0100
20131 +++ b/ext/apc/tests/apc53_001.phpt 2012-07-20 00:10:35.000000000 +0200
20134 +APC: classes with namespaces (php 5.3)
20137 + require_once(dirname(__FILE__) . '/skipif.inc');
20138 + if(version_compare(zend_version(), '2.3.0') < 0) {
20145 +apc.file_update_protection=0
20149 +require_once(dirname(__FILE__) . '/php_5_3_ns.inc');
20151 +$a = new Foo\Bar\Baz();
20157 +object(Foo\Bar\Baz)#1 (3) {
20160 + ["f":protected]=>
20162 + ["s":"Foo\Bar\Baz":private]=>
20163 + string(11) "hello world"
20166 diff -Naur a/ext/apc/tests/apc53_002.phpt b/ext/apc/tests/apc53_002.phpt
20167 --- a/ext/apc/tests/apc53_002.phpt 1970-01-01 01:00:00.000000000 +0100
20168 +++ b/ext/apc/tests/apc53_002.phpt 2012-07-20 00:10:35.000000000 +0200
20171 +APC: global spaces (php 5.3)
20174 + require_once(dirname(__FILE__) . '/skipif.inc');
20175 + if(version_compare(zend_version(), '2.3.0') < 0) {
20182 +apc.file_update_protection=0
20186 +require_once(dirname(__FILE__) . '/php_5_3_ns.inc');
20188 +$a = new Foo\Bar\Baz();
20190 +var_dump(Foo\Bar\sort());
20215 +string(8) "IT WORKS"
20217 diff -Naur a/ext/apc/tests/apc53_003.phpt b/ext/apc/tests/apc53_003.phpt
20218 --- a/ext/apc/tests/apc53_003.phpt 1970-01-01 01:00:00.000000000 +0100
20219 +++ b/ext/apc/tests/apc53_003.phpt 2012-07-20 00:10:35.000000000 +0200
20222 +APC: anonymous functions (php 5.3)
20225 + require_once(dirname(__FILE__) . '/skipif.inc');
20226 + if(version_compare(zend_version(), '2.3.0') < 0) {
20233 +apc.file_update_protection=0
20237 +$greet = function($name)
20239 + printf("Hello %s\r\n", $name);
20252 diff -Naur a/ext/apc/tests/apc53_004.phpt b/ext/apc/tests/apc53_004.phpt
20253 --- a/ext/apc/tests/apc53_004.phpt 1970-01-01 01:00:00.000000000 +0100
20254 +++ b/ext/apc/tests/apc53_004.phpt 2012-07-20 00:10:35.000000000 +0200
20257 +APC: closures (php 5.3)
20260 + require_once(dirname(__FILE__) . '/skipif.inc');
20261 + if(version_compare(zend_version(), '2.3.0') < 0) {
20268 +apc.file_update_protection=0
20271 +function multiplier($n) {
20272 + return function($i) use ($n) {
20277 +$doubler = multiplier(2);
20278 +$tripler = multiplier(3);
20280 +echo "double of 9 is ".$doubler(9)."\n";
20281 +echo "triple of 4 is ".$tripler(4)."\n";
20289 diff -Naur a/ext/apc/tests/apc53_005.phpt b/ext/apc/tests/apc53_005.phpt
20290 --- a/ext/apc/tests/apc53_005.phpt 1970-01-01 01:00:00.000000000 +0100
20291 +++ b/ext/apc/tests/apc53_005.phpt 2012-07-20 00:10:35.000000000 +0200
20294 +APC: goto (php 5.3)
20297 + require_once(dirname(__FILE__) . '/skipif.inc');
20298 + if(version_compare(zend_version(), '2.3.0') < 0) {
20305 +apc.file_update_protection=0
20312 +if($i % 3 == 0) goto b;
20315 +if($i < 10) goto a;
20328 diff -Naur a/ext/apc/tests/apc_bin_001.phpt b/ext/apc/tests/apc_bin_001.phpt
20329 --- a/ext/apc/tests/apc_bin_001.phpt 1970-01-01 01:00:00.000000000 +0100
20330 +++ b/ext/apc/tests/apc_bin_001.phpt 2012-07-20 00:10:35.000000000 +0200
20333 +APC: bindump user cache
20335 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20341 +apc_clear_cache('file');
20342 +apc_store('testkey','testvalue');
20344 +$dump = apc_bin_dump(array(), NULL);
20345 +apc_clear_cache('user');
20346 +var_dump(apc_fetch('testkey'));
20347 +apc_bin_load($dump, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
20348 +var_dump(apc_fetch('testkey'));
20354 +string(9) "testvalue"
20356 diff -Naur a/ext/apc/tests/apc_bin_002-1.inc b/ext/apc/tests/apc_bin_002-1.inc
20357 --- a/ext/apc/tests/apc_bin_002-1.inc 1970-01-01 01:00:00.000000000 +0100
20358 +++ b/ext/apc/tests/apc_bin_002-1.inc 2012-07-20 00:10:35.000000000 +0200
20362 +$my_class = New my_class();
20363 +$my_i_class = New my_i_class();
20365 +echo "apc bindump 002 test\n";
20367 +echo "global scope execution: Success\n";
20369 +echo "function execution: ".my_function()."\n";
20372 +echo "class static method: ".my_class::my_static_method()."\n";
20373 +echo "class dynamic method: ".$my_class->my_method()."\n";
20374 +echo "class static property: ".my_class::$my_static_property."\n";
20375 +echo "class dynamic property: ".$my_class->my_property."\n";
20376 +echo "class constant: ".my_class::my_constant."\n";
20378 +echo "inherited class static method: ".my_i_class::my_static_method()."\n";
20379 +echo "inherited class dynamic method: ".$my_i_class->my_method()."\n";
20380 +echo "inherited class static property: ".my_i_class::$my_static_property."\n";
20381 +echo "inherited class dynamic property: ".$my_i_class->my_property."\n";
20382 +echo "inherited class constant: ".my_i_class::my_constant."\n";
20387 +function my_function() { return "Success"; }
20391 + static $my_static_property = "Success";
20392 + var $my_property = "Success";
20393 + const my_constant = "Success";
20394 + static function my_static_method() { return "Success"; }
20395 + function my_method() { return "Success"; }
20398 +class my_i_class extends my_class {
20399 + function dummy() { return 1; }
20402 diff -Naur a/ext/apc/tests/apc_bin_002-2.inc b/ext/apc/tests/apc_bin_002-2.inc
20403 --- a/ext/apc/tests/apc_bin_002-2.inc 1970-01-01 01:00:00.000000000 +0100
20404 +++ b/ext/apc/tests/apc_bin_002-2.inc 2012-07-20 00:10:35.000000000 +0200
20408 +echo "Failed to use cached version!\n";
20411 diff -Naur a/ext/apc/tests/apc_bin_002.phpt b/ext/apc/tests/apc_bin_002.phpt
20412 --- a/ext/apc/tests/apc_bin_002.phpt 1970-01-01 01:00:00.000000000 +0100
20413 +++ b/ext/apc/tests/apc_bin_002.phpt 2012-07-20 00:10:35.000000000 +0200
20416 +APC: bindump file cache part 1
20418 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20423 +apc.cache_by_default=1
20425 +report_memleaks = Off
20429 +define('filename',dirname(__FILE__).'/apc_bin_002.inc');
20430 +define('filename1',dirname(__FILE__).'/apc_bin_002-1.inc');
20431 +define('filename2',dirname(__FILE__).'/apc_bin_002-2.inc');
20433 +copy(filename1, filename);
20434 +apc_compile_file(filename);
20435 +$data = apc_bin_dump(NULL, NULL);
20437 +apc_clear_cache();
20439 +copy(filename2, filename);
20440 +apc_bin_load($data, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
20441 +include(filename);
20447 +<? php exit(0); ?>
20449 +apc bindump 002 test
20451 +global scope execution: Success
20453 +function execution: Success
20455 +class static method: Success
20456 +class dynamic method: Success
20457 +class static property: Success
20458 +class dynamic property: Success
20459 +class constant: Success
20461 +inherited class static method: Success
20462 +inherited class dynamic method: Success
20463 +inherited class static property: Success
20464 +inherited class dynamic property: Success
20465 +inherited class constant: Success
20468 diff -Naur a/ext/apc/tests/iterator_001.phpt b/ext/apc/tests/iterator_001.phpt
20469 --- a/ext/apc/tests/iterator_001.phpt 1970-01-01 01:00:00.000000000 +0100
20470 +++ b/ext/apc/tests/iterator_001.phpt 2012-07-20 00:10:35.000000000 +0200
20473 +APC: APCIterator general
20475 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20479 +apc.file_update_protection=0
20483 +$it = new APCIterator('user');
20484 +for($i = 0; $i < 41; $i++) {
20485 + apc_store("key$i", "value$i");
20487 +foreach($it as $key=>$value) {
20488 + $vals[$key] = $value['key'];
20503 + string(5) "key10"
20505 + string(5) "key11"
20507 + string(5) "key12"
20509 + string(5) "key13"
20511 + string(5) "key14"
20513 + string(5) "key15"
20515 + string(5) "key16"
20517 + string(5) "key17"
20519 + string(5) "key18"
20521 + string(5) "key19"
20525 + string(5) "key20"
20527 + string(5) "key21"
20529 + string(5) "key22"
20531 + string(5) "key23"
20533 + string(5) "key24"
20535 + string(5) "key25"
20537 + string(5) "key26"
20539 + string(5) "key27"
20541 + string(5) "key28"
20543 + string(5) "key29"
20547 + string(5) "key30"
20549 + string(5) "key31"
20551 + string(5) "key32"
20553 + string(5) "key33"
20555 + string(5) "key34"
20557 + string(5) "key35"
20559 + string(5) "key36"
20561 + string(5) "key37"
20563 + string(5) "key38"
20565 + string(5) "key39"
20569 + string(5) "key40"
20582 diff -Naur a/ext/apc/tests/iterator_002.phpt b/ext/apc/tests/iterator_002.phpt
20583 --- a/ext/apc/tests/iterator_002.phpt 1970-01-01 01:00:00.000000000 +0100
20584 +++ b/ext/apc/tests/iterator_002.phpt 2012-07-20 00:10:35.000000000 +0200
20587 +APC: APCIterator regex
20589 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20593 +apc.file_update_protection=0
20597 +$it = new APCIterator('user', '/key[0-9]0/');
20598 +for($i = 0; $i < 41; $i++) {
20599 + apc_store("key$i", "value$i");
20601 +foreach($it as $key=>$value) {
20602 + $vals[$key] = $value['key'];
20613 + string(5) "key10"
20615 + string(5) "key20"
20617 + string(5) "key30"
20619 + string(5) "key40"
20622 diff -Naur a/ext/apc/tests/iterator_003.phpt b/ext/apc/tests/iterator_003.phpt
20623 --- a/ext/apc/tests/iterator_003.phpt 1970-01-01 01:00:00.000000000 +0100
20624 +++ b/ext/apc/tests/iterator_003.phpt 2012-07-20 00:10:35.000000000 +0200
20627 +APC: APCIterator chunk size
20629 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20633 +apc.file_update_protection=0
20637 +$it = new APCIterator('user', NULL, APC_ITER_ALL, 10);
20638 +for($i = 0; $i < 41; $i++) {
20639 + apc_store("key$i", "value$i");
20641 +foreach($it as $key=>$value) {
20642 + $vals[$key] = $value['key'];
20657 + string(5) "key10"
20659 + string(5) "key11"
20661 + string(5) "key12"
20663 + string(5) "key13"
20665 + string(5) "key14"
20667 + string(5) "key15"
20669 + string(5) "key16"
20671 + string(5) "key17"
20673 + string(5) "key18"
20675 + string(5) "key19"
20679 + string(5) "key20"
20681 + string(5) "key21"
20683 + string(5) "key22"
20685 + string(5) "key23"
20687 + string(5) "key24"
20689 + string(5) "key25"
20691 + string(5) "key26"
20693 + string(5) "key27"
20695 + string(5) "key28"
20697 + string(5) "key29"
20701 + string(5) "key30"
20703 + string(5) "key31"
20705 + string(5) "key32"
20707 + string(5) "key33"
20709 + string(5) "key34"
20711 + string(5) "key35"
20713 + string(5) "key36"
20715 + string(5) "key37"
20717 + string(5) "key38"
20719 + string(5) "key39"
20723 + string(5) "key40"
20736 diff -Naur a/ext/apc/tests/iterator_004.phpt b/ext/apc/tests/iterator_004.phpt
20737 --- a/ext/apc/tests/iterator_004.phpt 1970-01-01 01:00:00.000000000 +0100
20738 +++ b/ext/apc/tests/iterator_004.phpt 2012-07-20 00:10:35.000000000 +0200
20741 +APC: APCIterator regex & chunk size & list
20743 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20747 +apc.file_update_protection=0
20751 +$it = new APCIterator('user', '/key[0-9]0/', APC_ITER_ALL, 1, APC_LIST_ACTIVE);
20752 +for($i = 0; $i < 41; $i++) {
20753 + apc_store("key$i", "value$i");
20755 +foreach($it as $key=>$value) {
20756 + $vals[$key] = $value['key'];
20767 + string(5) "key10"
20769 + string(5) "key20"
20771 + string(5) "key30"
20773 + string(5) "key40"
20776 diff -Naur a/ext/apc/tests/iterator_005.phpt b/ext/apc/tests/iterator_005.phpt
20777 --- a/ext/apc/tests/iterator_005.phpt 1970-01-01 01:00:00.000000000 +0100
20778 +++ b/ext/apc/tests/iterator_005.phpt 2012-07-20 00:10:35.000000000 +0200
20781 +APC: APCIterator delete
20783 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20787 +apc.file_update_protection=0
20793 +$it = new APCIterator('user', '/key[0-9]0/');
20794 +for($i = 0; $i < 41; $i++) {
20795 + apc_store("key$i", "value$i");
20798 +$it2 = new APCIterator('user');
20799 +foreach($it as $key=>$value) {
20800 + $vals[$key] = $value['key'];
20802 +foreach($it2 as $key=>$value) {
20803 + $vals2[$key] = $value['key'];
20821 + string(5) "key11"
20823 + string(5) "key12"
20825 + string(5) "key13"
20827 + string(5) "key14"
20829 + string(5) "key15"
20831 + string(5) "key16"
20833 + string(5) "key17"
20835 + string(5) "key18"
20837 + string(5) "key19"
20841 + string(5) "key21"
20843 + string(5) "key22"
20845 + string(5) "key23"
20847 + string(5) "key24"
20849 + string(5) "key25"
20851 + string(5) "key26"
20853 + string(5) "key27"
20855 + string(5) "key28"
20857 + string(5) "key29"
20861 + string(5) "key31"
20863 + string(5) "key32"
20865 + string(5) "key33"
20867 + string(5) "key34"
20869 + string(5) "key35"
20871 + string(5) "key36"
20873 + string(5) "key37"
20875 + string(5) "key38"
20877 + string(5) "key39"
20892 diff -Naur a/ext/apc/tests/iterator_006.phpt b/ext/apc/tests/iterator_006.phpt
20893 --- a/ext/apc/tests/iterator_006.phpt 1970-01-01 01:00:00.000000000 +0100
20894 +++ b/ext/apc/tests/iterator_006.phpt 2012-07-20 00:10:35.000000000 +0200
20897 +APC: APCIterator formats
20899 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20903 +apc.file_update_protection=0
20904 +apc.user_entries_hint=4096
20911 + APC_ITER_FILENAME,
20916 + APC_ITER_NUM_HITS,
20921 + APC_ITER_REFCOUNT,
20922 + APC_ITER_MEM_SIZE,
20926 + APC_ITER_ALL & ~APC_ITER_TTL,
20927 + APC_ITER_KEY | APC_ITER_NUM_HITS | APC_ITER_MEM_SIZE,
20930 +$it_array = array();
20932 +foreach ($formats as $idx => $format) {
20933 + $it_array[$idx] = new APCIterator('user', NULL, $format);
20936 +for($i = 0; $i < 11; $i++) {
20937 + apc_store("key$i", "value$i");
20940 +foreach ($it_array as $idx => $it) {
20941 + print_it($it, $idx);
20944 +function print_it($it, $idx) {
20945 + echo "IT #$idx\n";
20946 + echo "============================\n";
20947 + foreach ($it as $key=>$value) {
20949 + var_dump($value);
20951 + echo "============================\n\n";
20959 +============================
21015 +============================
21018 +============================
21022 + string(5) "key10"
21074 +============================
21077 +============================
21111 +============================
21114 +============================
21148 +============================
21151 +============================
21185 +============================
21188 +============================
21192 + string(7) "value10"
21197 + string(6) "value0"
21202 + string(6) "value1"
21207 + string(6) "value2"
21212 + string(6) "value3"
21217 + string(6) "value4"
21222 + string(6) "value5"
21227 + string(6) "value6"
21232 + string(6) "value7"
21237 + string(6) "value8"
21242 + string(6) "value9"
21244 +============================
21247 +============================
21281 +============================
21284 +============================
21340 +============================
21343 +============================
21399 +============================
21402 +============================
21405 + ["creation_time"]=>
21410 + ["creation_time"]=>
21415 + ["creation_time"]=>
21420 + ["creation_time"]=>
21425 + ["creation_time"]=>
21430 + ["creation_time"]=>
21435 + ["creation_time"]=>
21440 + ["creation_time"]=>
21445 + ["creation_time"]=>
21450 + ["creation_time"]=>
21455 + ["creation_time"]=>
21458 +============================
21461 +============================
21464 + ["deletion_time"]=>
21469 + ["deletion_time"]=>
21474 + ["deletion_time"]=>
21479 + ["deletion_time"]=>
21484 + ["deletion_time"]=>
21489 + ["deletion_time"]=>
21494 + ["deletion_time"]=>
21499 + ["deletion_time"]=>
21504 + ["deletion_time"]=>
21509 + ["deletion_time"]=>
21514 + ["deletion_time"]=>
21517 +============================
21520 +============================
21523 + ["access_time"]=>
21528 + ["access_time"]=>
21533 + ["access_time"]=>
21538 + ["access_time"]=>
21543 + ["access_time"]=>
21548 + ["access_time"]=>
21553 + ["access_time"]=>
21558 + ["access_time"]=>
21563 + ["access_time"]=>
21568 + ["access_time"]=>
21573 + ["access_time"]=>
21576 +============================
21579 +============================
21635 +============================
21638 +============================
21694 +============================
21697 +============================
21753 +============================
21756 +============================
21790 +============================
21793 +============================
21799 + string(5) "key10"
21801 + string(7) "value10"
21806 + ["creation_time"]=>
21808 + ["deletion_time"]=>
21810 + ["access_time"]=>
21826 + string(6) "value0"
21831 + ["creation_time"]=>
21833 + ["deletion_time"]=>
21835 + ["access_time"]=>
21851 + string(6) "value1"
21856 + ["creation_time"]=>
21858 + ["deletion_time"]=>
21860 + ["access_time"]=>
21876 + string(6) "value2"
21881 + ["creation_time"]=>
21883 + ["deletion_time"]=>
21885 + ["access_time"]=>
21901 + string(6) "value3"
21906 + ["creation_time"]=>
21908 + ["deletion_time"]=>
21910 + ["access_time"]=>
21926 + string(6) "value4"
21931 + ["creation_time"]=>
21933 + ["deletion_time"]=>
21935 + ["access_time"]=>
21951 + string(6) "value5"
21956 + ["creation_time"]=>
21958 + ["deletion_time"]=>
21960 + ["access_time"]=>
21976 + string(6) "value6"
21981 + ["creation_time"]=>
21983 + ["deletion_time"]=>
21985 + ["access_time"]=>
22001 + string(6) "value7"
22006 + ["creation_time"]=>
22008 + ["deletion_time"]=>
22010 + ["access_time"]=>
22026 + string(6) "value8"
22031 + ["creation_time"]=>
22033 + ["deletion_time"]=>
22035 + ["access_time"]=>
22051 + string(6) "value9"
22056 + ["creation_time"]=>
22058 + ["deletion_time"]=>
22060 + ["access_time"]=>
22069 +============================
22072 +============================
22078 + string(5) "key10"
22080 + string(7) "value10"
22085 + ["creation_time"]=>
22087 + ["deletion_time"]=>
22089 + ["access_time"]=>
22103 + string(6) "value0"
22108 + ["creation_time"]=>
22110 + ["deletion_time"]=>
22112 + ["access_time"]=>
22126 + string(6) "value1"
22131 + ["creation_time"]=>
22133 + ["deletion_time"]=>
22135 + ["access_time"]=>
22149 + string(6) "value2"
22154 + ["creation_time"]=>
22156 + ["deletion_time"]=>
22158 + ["access_time"]=>
22172 + string(6) "value3"
22177 + ["creation_time"]=>
22179 + ["deletion_time"]=>
22181 + ["access_time"]=>
22195 + string(6) "value4"
22200 + ["creation_time"]=>
22202 + ["deletion_time"]=>
22204 + ["access_time"]=>
22218 + string(6) "value5"
22223 + ["creation_time"]=>
22225 + ["deletion_time"]=>
22227 + ["access_time"]=>
22241 + string(6) "value6"
22246 + ["creation_time"]=>
22248 + ["deletion_time"]=>
22250 + ["access_time"]=>
22264 + string(6) "value7"
22269 + ["creation_time"]=>
22271 + ["deletion_time"]=>
22273 + ["access_time"]=>
22287 + string(6) "value8"
22292 + ["creation_time"]=>
22294 + ["deletion_time"]=>
22296 + ["access_time"]=>
22310 + string(6) "value9"
22315 + ["creation_time"]=>
22317 + ["deletion_time"]=>
22319 + ["access_time"]=>
22326 +============================
22329 +============================
22333 + string(5) "key10"
22429 +============================
22432 diff -Naur a/ext/apc/tests/iterator_007.phpt b/ext/apc/tests/iterator_007.phpt
22433 --- a/ext/apc/tests/iterator_007.phpt 1970-01-01 01:00:00.000000000 +0100
22434 +++ b/ext/apc/tests/iterator_007.phpt 2012-07-20 00:10:35.000000000 +0200
22437 +APC: APCIterator Overwriting the ctor
22439 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
22445 +class foobar extends APCIterator {
22446 + public function __construct() {}
22448 +$obj = new foobar;
22455 + $obj->getTotalHits(),
22456 + $obj->getTotalSize(),
22457 + $obj->getTotalCount(),
22472 diff -Naur a/ext/apc/tests/php_5_3_ns.inc b/ext/apc/tests/php_5_3_ns.inc
22473 --- a/ext/apc/tests/php_5_3_ns.inc 1970-01-01 01:00:00.000000000 +0100
22474 +++ b/ext/apc/tests/php_5_3_ns.inc 2012-07-20 00:10:35.000000000 +0200
22477 +namespace Foo\Bar;
22480 + $a = array(3,2,1,4);
22481 + \sort($a); // global scoping
22483 + return "IT WORKS";
22487 + protected $f = 3.14;
22488 + private $s = "hello world";
22490 + public function foo() {
22494 diff -Naur a/ext/apc/tests/skipif.inc b/ext/apc/tests/skipif.inc
22495 --- a/ext/apc/tests/skipif.inc 1970-01-01 01:00:00.000000000 +0100
22496 +++ b/ext/apc/tests/skipif.inc 2012-07-20 00:10:35.000000000 +0200
22500 +if (!extension_loaded("apc")) die("skip");
22501 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
22504 diff -Naur a/ext/apc/TODO b/ext/apc/TODO
22505 --- a/ext/apc/TODO 1970-01-01 01:00:00.000000000 +0100
22506 +++ b/ext/apc/TODO 2012-07-20 00:10:35.000000000 +0200
22510 +1. Gallery2 doesn't work with PHP5+APC. There is something wrong
22511 + with the way methods are restored in some edge case I haven't
22512 + been able to figure out yet.
22513 + To reproduce install gallery2 and click down to an individual photo.
22515 +2. apc_store() probably needs some checks to skip trying to store
22516 + internal classes. Something along the lines of:
22518 + if(Z_TYPE_P(val) == IS_OBJECT) {
22519 + zend_class_entry *ce = Z_OBJCE_P(val);
22520 + if(ce->type == ZEND_INTERNAL_CLASS) {
22521 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
22526 + in the apc_store() function in php_apc.c but I am wondering if it needs to do more
22531 +1. The following configurations (build arguments) have not been implemented yet
22533 + (*) --enable-apc-mmap Memory mapping support
22534 + (*) --enable-apc-sem Semaphore locking support (FCNTL replacement)
22535 + (*) --enable-apc-phreadmutex Thread mutexes, while implemented we should probably rename the internals to thread
22536 + (*) --enable-apc-pthreadrwlocks Thread mutexes, read/write locking
22538 +2. Non-blocking locks is not supported either
22540 +3. Update fileinfo to support stat info in a more portable way (see PECL #17903)
22542 +4. Check whether the signal handling needs to be enabled, and if it makes sense on Windows
22543 \ Kein Zeilenumbruch am Dateiende.