[packages] new package uboot-env-mmc: hacked in support for reading/writing an uboot...
[packages.git] / lang / php5 / patches / 005-APC.patch
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
4 @@ -0,0 +1,987 @@
5 +/*
6 +  +----------------------------------------------------------------------+
7 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
21 +
22 + */
23 +
24 +/* $Id: apc_bin.c 324017 2012-03-08 09:46:22Z pajoye $ */
25 +
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.
30 + */
31 +
32 +#include "apc_globals.h"
33 +#include "apc_bin.h"
34 +#include "apc_zend.h"
35 +#include "apc_php.h"
36 +#include "apc_sma.h"
37 +#include "apc_pool.h"
38 +#include "ext/standard/md5.h"
39 +#include "ext/standard/crc32.h"
40 +
41 +extern apc_cache_t* apc_cache;
42 +extern apc_cache_t* apc_user_cache;
43 +
44 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); /* this is hacky */
45 +
46 +#define APC_BINDUMP_DEBUG 0
47 +
48 +
49 +#if APC_BINDUMP_DEBUG
50 +
51 +#define SWIZZLE(bd, ptr)  \
52 +    do { \
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__); \
59 +            return; \
60 +        } \
61 +        printf("\n"); \
62 +    } while(0);
63 +
64 +#define UNSWIZZLE(bd, ptr)  \
65 +    do { \
66 +      printf("UNSWIZZLE: %x -> ", ptr); \
67 +      ptr = (void*)((long)(ptr) + (long)(bd)); \
68 +      printf("%x in %s on line %d \n", ptr, __FILE__, __LINE__); \
69 +    } while(0);
70 +
71 +#else    /* !APC_BINDUMP_DEBUG */
72 +
73 +#define SWIZZLE(bd, ptr) \
74 +    do { \
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__); \
79 +            return NULL; \
80 +        } \
81 +    } while(0);
82 +
83 +#define UNSWIZZLE(bd, ptr) \
84 +    do { \
85 +      ptr = (void*)((long)(ptr) + (long)(bd)); \
86 +    } while(0);
87 +
88 +#endif
89 +
90 +
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);
94 +
95 +typedef void (*apc_swizzle_cb_t)(apc_bd_t *bd, zend_llist *ll, void *ptr TSRMLS_DC);
96 +
97 +#if APC_BINDUMP_DEBUG
98 +#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, __FILE__, __LINE__ TSRMLS_CC)
99 +#else
100 +#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, NULL, 0 TSRMLS_CC)
101 +#endif
102 +
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);
112 +
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);
115 +
116 +
117 +/* {{{ apc_bd_alloc
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);
121 +} /* }}} */
122 +
123 +
124 +/* {{{ apc_bd_free
125 + *  callback for copy_* functions */
126 +static void apc_bd_free(void *ptr TSRMLS_DC) {
127 +    size_t *size;
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);
130 +        return;
131 +    }
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);
134 +} /* }}} */
135 +
136 +
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.
142 + */
143 +static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC) {
144 +    void *rval;
145 +
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);
154 +#endif
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));
157 +          return NULL;
158 +      }
159 +      zend_hash_index_update(&APCG(apc_bd_alloc_list), (ulong)rval, &size, sizeof(size_t), NULL);
160 +    }
161 +
162 +    return rval;
163 +} /* }}} */
164 +
165 +
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) {
168 +    if(*ptr) {
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);
174 +#endif
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); \
177 +            return;
178 +        }
179 +    }
180 +} /* }}} */
181 +
182 +
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) {
185 +    uint i;
186 +
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);
190 +#else
191 +    if (op_array->arg_types) {
192 +        apc_swizzle_ptr(bd, ll, &op_array->arg_types);
193 +    }
194 +#endif
195 +
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);
199 +
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);
205 +        }
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);
208 +        }
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);
211 +        }
212 +#endif
213 +        switch (op_array->opcodes[i].opcode) {
214 +            case ZEND_JMP:
215 +#ifdef ZEND_ENGINE_2_4
216 +                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.jmp_addr);
217 +#else
218 +                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.u.jmp_addr);
219 +#endif
220 +            case ZEND_JMPZ:
221 +            case ZEND_JMPNZ:
222 +            case ZEND_JMPZ_EX:
223 +            case ZEND_JMPNZ_EX:
224 +#ifdef ZEND_ENGINE_2_4
225 +                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.jmp_addr);
226 +#else
227 +                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.u.jmp_addr);
228 +#endif
229 +        }
230 +    }
231 +    apc_swizzle_ptr(bd, ll, &op_array->opcodes);
232 +
233 +    /* break-continue array ptr */
234 +    if(op_array->brk_cont_array) {
235 +        apc_swizzle_ptr(bd, ll, &op_array->brk_cont_array);
236 +    }
237 +
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);
242 +    }
243 +
244 +#ifdef ZEND_ENGINE_2
245 +    /* try-catch */
246 +    if(op_array->try_catch_array) {
247 +        apc_swizzle_ptr(bd, ll, &op_array->try_catch_array);
248 +    }
249 +#endif
250 +
251 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
252 +    /* vars */
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);
256 +        }
257 +        apc_swizzle_ptr(bd, ll, &op_array->vars);
258 +    }
259 +#endif
260 +
261 +#ifdef ZEND_ENGINE_2
262 +    /* doc comment */
263 +    if(op_array->doc_comment) {
264 +        apc_swizzle_ptr(bd, ll, &op_array->doc_comment);
265 +    }
266 +#endif
267 +
268 +} /* }}} */
269 +
270 +
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);
277 +    }
278 +#endif
279 +} /* }}} */
280 +
281 +
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) {
284 +
285 +    uint i;
286 +
287 +    if(ce->name) {
288 +        apc_swizzle_ptr(bd, ll, &ce->name);
289 +    }
290 +
291 +    if (ce->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(ce)) {
292 +        apc_swizzle_ptr(bd, ll, &ZEND_CE_DOC_COMMENT(ce));
293 +    }
294 +
295 +#ifndef ZEND_ENGINE_2
296 +    apc_swizzle_ptr(bd, ll, &ce->refcount);
297 +#endif
298 +
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);
306 +            }
307 +        }
308 +    }
309 +#else
310 +    apc_swizzle_hashtable(bd, ll, &ce->default_properties, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
311 +#endif
312 +
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);
315 +#endif
316 +
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);
323 +            }
324 +        }
325 +    }
326 +    ce->static_members_table = ce->default_static_members_table;
327 +#else
328 +    apc_swizzle_hashtable(bd, ll, &ce->default_static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
329 +
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);
332 +    } else {
333 +        apc_swizzle_ptr(bd, ll, &ce->static_members);
334 +    }
335 +#endif
336 +
337 +    apc_swizzle_hashtable(bd, ll, &ce->constants_table, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
338 +
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);
342 +        }
343 +    }
344 +
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);
355 +
356 +#ifdef ZEND_ENGINE_2_2
357 +    apc_swizzle_ptr(bd, ll, &ce->__tostring);
358 +#endif
359 +
360 +    if (ce->type == ZEND_USER_CLASS) {
361 +        apc_swizzle_ptr(bd, ll, &ZEND_CE_FILENAME(ce));
362 +    }
363 +} /* }}} */
364 +
365 +
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);
370 +
371 +#ifdef ZEND_ENGINE_2_2
372 +    apc_swizzle_ptr(bd, ll, &pi->ce);
373 +#endif
374 +} /* }}} */
375 +
376 +
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);
382 +} /* }}} */
383 +
384 +
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) {
388 +        uint i;
389 +
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);
393 +        }
394 +    }
395 +
396 +} /* }}} */
397 +
398 +
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) {
401 +    uint i;
402 +    Bucket **bp, **bp_prev;
403 +
404 +    bp = &ht->pListHead;
405 +    while(*bp) {
406 +        bp_prev = bp;
407 +        bp = &(*bp)->pListNext;
408 +        if(is_ptr) {
409 +            swizzle_cb(bd, ll, *(void**)(*bp_prev)->pData TSRMLS_CC);
410 +            apc_swizzle_ptr(bd, ll, (*bp_prev)->pData);
411 +        } else {
412 +            swizzle_cb(bd, ll, (void**)(*bp_prev)->pData TSRMLS_CC);
413 +        }
414 +        apc_swizzle_ptr(bd, ll, &(*bp_prev)->pData);
415 +        if((*bp_prev)->pDataPtr) {
416 +            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pDataPtr);
417 +        }
418 +        if((*bp_prev)->pListLast) {
419 +            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pListLast);
420 +        }
421 +        if((*bp_prev)->pNext) {
422 +            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pNext);
423 +        }
424 +        if((*bp_prev)->pLast) {
425 +            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pLast);
426 +        }
427 +        apc_swizzle_ptr(bd, ll, bp_prev);
428 +    }
429 +    for(i=0; i < ht->nTableSize; i++) {
430 +        if(ht->arBuckets[i]) {
431 +            apc_swizzle_ptr(bd, ll, &ht->arBuckets[i]);
432 +        }
433 +    }
434 +    apc_swizzle_ptr(bd, ll, &ht->pListTail);
435 +
436 +    apc_swizzle_ptr(bd, ll, &ht->arBuckets);
437 +} /* }}} */
438 +
439 +
440 +/* {{{ apc_swizzle_zval */
441 +static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC) {
442 +
443 +    if(APCG(copied_zvals).nTableSize) {
444 +        if(zend_hash_index_exists(&APCG(copied_zvals), (ulong)zv)) {
445 +          return;
446 +        }
447 +        zend_hash_index_update(&APCG(copied_zvals), (ulong)zv, (void**)&zv, sizeof(zval*), NULL);
448 +    }
449 +
450 +    switch(zv->type & IS_CONSTANT_TYPE_MASK) {
451 +        case IS_NULL:
452 +        case IS_LONG:
453 +        case IS_DOUBLE:
454 +        case IS_BOOL:
455 +        case IS_RESOURCE:
456 +            /* nothing to do */
457 +            break;
458 +        case IS_CONSTANT:
459 +        case IS_STRING:
460 +            apc_swizzle_ptr(bd, ll, &zv->value.str.val);
461 +            break;
462 +        case IS_ARRAY:
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);
466 +            break;
467 +        case IS_OBJECT:
468 +            break;
469 +        default:
470 +            assert(0); /* shouldn't happen */
471 +    }
472 +} /* }}} */
473 +
474 +
475 +/* {{{ apc_swizzle_bd */
476 +static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC) {
477 +    int count, i;
478 +    PHP_MD5_CTX context;
479 +    unsigned char digest[16];
480 +    register php_uint32 crc;
481 +    php_uint32 crcinit = 0;
482 +    char *crc_p;
483 +    void ***ptr;
484 +    void ***ptr_list;
485 +
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);
492 +#endif
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("[------] ");
497 +#endif
498 +            SWIZZLE(bd, *ptr);  /* swizzle ptr list */
499 +            ptr_list[i] = *ptr;
500 +        }
501 +        ptr = zend_llist_get_next(ll);
502 +    }
503 +    SWIZZLE(bd, bd->entries);
504 +
505 +    if(count > 0) {
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);
512 +    } else {
513 +        bd->num_swizzled_ptrs = 0;
514 +        bd->swizzled_ptrs = NULL;
515 +    }
516 +    ((char*)bd)[bd->size-1] = 0;  /* silence null termination for zval strings */
517 +    efree(ptr_list);
518 +    bd->swizzled = 1;
519 +
520 +    /* Generate MD5/CRC32 checksum */
521 +    for(i=0; i<16; i++) { bd->md5[i] = 0; }
522 +    bd->crc=0;
523 +    PHP_MD5Init(&context);
524 +    PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
525 +    PHP_MD5Final(digest, &context);
526 +    crc = crcinit^0xFFFFFFFF;
527 +    crc_p = (char*)bd;
528 +    for(i=bd->size; i--; ++crc_p) {
529 +      crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
530 +    }
531 +    memcpy(bd->md5, digest, 16);
532 +    bd->crc = crc;
533 +
534 +    return bd;
535 +} /* }}} */
536 +
537 +
538 +/* {{{ apc_unswizzle_bd */
539 +static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC) {
540 +    int i;
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;
547 +    char *crc_p;
548 +
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;
553 +    bd->crc=0;
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);
560 +            return -1;
561 +        }
562 +    }
563 +    if(flags & APC_BIN_VERIFY_CRC32) {
564 +        crc = crcinit^0xFFFFFFFF;
565 +        crc_p = (char*)bd;
566 +        for(i=bd->size; i--; ++crc_p) {
567 +          crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
568 +        }
569 +        if(crc_orig != crc) {
570 +            apc_error("CRC32 checksum of binary dump failed." TSRMLS_CC);
571 +            return -1;
572 +        }
573 +    }
574 +    memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
575 +    bd->crc = crc_orig;
576 +
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]);
584 +            }
585 +        }
586 +    }
587 +
588 +    bd->swizzled=0;
589 +
590 +    return 0;
591 +} /* }}} */
592 +
593 +
594 +/* {{{ apc_bin_checkfilter */
595 +static int apc_bin_checkfilter(HashTable *filter, const char *key, uint key_len) {
596 +    zval **zptr;
597 +
598 +    if(filter == NULL) {
599 +        return 1;
600 +    }
601 +
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) {
604 +            return 0;
605 +        }
606 +    } else {
607 +        return 0;
608 +    }
609 +
610 +
611 +    return 1;
612 +} /* }}} */
613 +
614 +/* {{{ apc_bin_fixup_op_array */
615 +static inline void apc_bin_fixup_op_array(zend_op_array *op_array) {
616 +    ulong i;
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])];
619 +    }
620 +}
621 +/* }}} */
622 +
623 +/* {{{ apc_bin_fixup_class_entry */
624 +static inline void apc_bin_fixup_class_entry(zend_class_entry *ce) {
625 +    zend_function *fe;
626 +    HashPosition hpos;
627 +
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);
633 +    }
634 +
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;
639 +#endif
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;
645 +    }
646 +#endif
647 +    ce->constants_table.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
648 +}
649 +/* }}} */
650 +
651 +/* {{{ apc_bin_dump */
652 +apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC) {
653 +
654 +    int i;
655 +    uint fcount;
656 +    slot_t *sp;
657 +    apc_bd_entry_t *ep;
658 +    int count=0;
659 +    apc_bd_t *bd;
660 +    zend_llist ll;
661 +    zend_function *efp, *sfp;
662 +    long size=0;
663 +    apc_context_t ctxt;
664 +    void *pool_ptr;
665 +
666 +    zend_llist_init(&ll, sizeof(void*), NULL, 0);
667 +    zend_hash_init(&APCG(apc_bd_alloc_list), 0, NULL, NULL, 0);
668 +
669 +    /* flip the hash for faster filter checking */
670 +    files = apc_flip_hash(files);
671 +    user_vars = apc_flip_hash(user_vars);
672 +
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));
680 +                count++;
681 +            }
682 +        }
683 +    }
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));
691 +                    count++;
692 +                }
693 +            } else {
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);
696 +            }
697 +        }
698 +    }
699 +
700 +    size += sizeof(apc_bd_t) +1;  /* +1 for null termination */
701 +    bd = emalloc(size);
702 +    bd->size = 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);
708 +        return NULL;
709 +    }
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);
714 +
715 +    /* User entries */
716 +    zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
717 +    count = 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;
729 +
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);
735 +
736 +                count++;
737 +            }
738 +        }
739 +    }
740 +    zend_hash_destroy(&APCG(copied_zvals));
741 +    APCG(copied_zvals).nTableSize=0;
742 +
743 +    /* File entries */
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);
753 +
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;
767 +                                break;
768 +                            case ZEND_USER_FUNCTION:
769 +                            case ZEND_EVAL_CODE:
770 +                                apc_copy_op_array(&efp->op_array, &sfp->op_array, &ctxt TSRMLS_CC);
771 +                                break;
772 +                            default:
773 +                                assert(0);
774 +                        }
775 +#ifdef ZEND_ENGINE_2
776 +                        efp->common.prototype = NULL;
777 +                        efp->common.fn_flags = sfp->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
778 +#endif
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);
782 +                    }
783 +
784 +
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);
792 +
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);
797 +                    }
798 +
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);
804 +
805 +                    count++;
806 +                } else {
807 +                    /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load */
808 +                }
809 +            }
810 +        }
811 +    }
812 +
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));
817 +
818 +    if(files) {
819 +        zend_hash_destroy(files);
820 +        efree(files);
821 +    }
822 +    if(user_vars) {
823 +        zend_hash_destroy(user_vars);
824 +        efree(user_vars);
825 +    }
826 +
827 +    efree(pool_ptr);
828 +
829 +    return bd;
830 +} /* }}} */
831 +
832 +
833 +/* {{{ apc_bin_load */
834 +int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC) {
835 +
836 +    apc_bd_entry_t *ep;
837 +    uint i, i2;
838 +    int ret;
839 +    time_t t;
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;
846 +
847 +    if (bd->swizzled) {
848 +        if(apc_unswizzle_bd(bd, flags TSRMLS_CC) < 0) {
849 +            return -1;
850 +        }
851 +    }
852 +
853 +    t = apc_time();
854 +
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);
859 +            goto failure;
860 +        }
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?) */
865 +                break;
866 +            case APC_CACHE_KEY_FPFILE:
867 +                ctxt.copy = APC_COPY_IN_OPCODE;
868 +
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();
874 +                        return -1;
875 +                    }
876 +                }
877 +#endif
878 +                if(! (alloc_op_array = apc_copy_op_array(NULL, ep->val.file.op_array, &ctxt TSRMLS_CC))) {
879 +                    goto failure;
880 +                }
881 +                apc_bin_fixup_op_array(alloc_op_array);
882 +
883 +                if(! (alloc_functions = apc_sma_malloc(sizeof(apc_function_t) * (ep->num_functions + 1) TSRMLS_CC))) {
884 +                    goto failure;
885 +                }
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))) {
888 +                        goto failure;
889 +                    }
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))) {
892 +                        goto failure;
893 +                    }
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;
898 +                            break;
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)) {
902 +                                goto failure;
903 +                            }
904 +                            apc_bin_fixup_op_array(&alloc_functions[i2].function->op_array);
905 +                            break;
906 +                        default:
907 +                            assert(0);
908 +                    }
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);
912 +#endif
913 +                }
914 +                alloc_functions[i2].name = NULL;
915 +                alloc_functions[i2].function = NULL;
916 +
917 +                if(! (alloc_classes = apc_sma_malloc(sizeof(apc_class_t) * (ep->num_classes + 1) TSRMLS_CC))) {
918 +                    goto failure;
919 +                }
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))) {
922 +                        goto failure;
923 +                    }
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))) {
926 +                        goto failure;
927 +                    }
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) {
931 +                            goto failure;
932 +                        }
933 +                    }
934 +                }
935 +                alloc_classes[i2].name = NULL;
936 +                alloc_classes[i2].class_entry = NULL;
937 +
938 +                if(!(cache_entry = apc_cache_make_file_entry(ep->val.file.filename, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
939 +                    goto failure;
940 +                }
941 +
942 +                if (!apc_cache_make_file_key(&cache_key, ep->val.file.filename, PG(include_path), t TSRMLS_CC)) {
943 +                    goto failure;
944 +                }
945 +
946 +                if ((ret = apc_cache_insert(apc_cache, cache_key, cache_entry, &ctxt, t TSRMLS_CC)) != 1) {
947 +                    if(ret==-1) {
948 +                        goto failure;
949 +                    }
950 +                }
951 +
952 +#if NONBLOCKING_LOCK_AVAILABLE
953 +                if(APCG(write_lock)) {
954 +                    apc_cache_write_unlock(apc_cache TSRMLS_CC);
955 +                }
956 +#endif
957 +                HANDLE_UNBLOCK_INTERRUPTIONS();
958 +
959 +                break;
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);
963 +                break;
964 +            default:
965 +                break;
966 +       }
967 +    }
968 +
969 +    return 0;
970 +
971 +failure:
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);
977 +    }
978 +#endif
979 +    HANDLE_UNBLOCK_INTERRUPTIONS();
980 +    return -1;
981 +} /* }}} */
982 +
983 +
984 +/*
985 + * Local variables:
986 + * tab-width: 4
987 + * c-basic-offset: 4
988 + * End:
989 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
990 + * vim<600: expandtab sw=4 ts=4 sts=4
991 + */
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
995 @@ -0,0 +1,63 @@
996 +/*
997 +  +----------------------------------------------------------------------+
998 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
1012 +
1013 + */
1014 +
1015 +/* $Id: apc_bin.h 307048 2011-01-03 23:53:17Z kalle $ */
1016 +
1017 +#ifndef APC_BINDUMP_H
1018 +#define APC_BINDUMP_H
1019 +
1020 +#include "apc.h"
1021 +#include "apc_php.h"
1022 +#include "ext/standard/basic_functions.h"
1023 +
1024 +/* APC binload flags */
1025 +#define APC_BIN_VERIFY_MD5    1 << 0
1026 +#define APC_BIN_VERIFY_CRC32  1 << 1
1027 +
1028 +typedef struct _apc_bd_entry_t {
1029 +    unsigned char type;
1030 +    uint num_functions;
1031 +    uint num_classes;
1032 +    apc_cache_entry_value_t val;
1033 +} apc_bd_entry_t;
1034 +
1035 +typedef struct _apc_bd_t {
1036 +    unsigned int size;
1037 +    int swizzled;
1038 +    unsigned char md5[16];
1039 +    php_uint32 crc;
1040 +    unsigned int num_entries;
1041 +    apc_bd_entry_t *entries;
1042 +    int num_swizzled_ptrs;
1043 +    void ***swizzled_ptrs;
1044 +} apc_bd_t;
1045 +
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);
1048 +
1049 +#endif
1050 +
1051 +/*
1052 + * Local variables:
1053 + * tab-width: 4
1054 + * c-basic-offset: 4
1055 + * End:
1056 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1057 + * vim<600: expandtab sw=4 ts=4 sts=4
1058 + */
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
1062 @@ -0,0 +1,670 @@
1063 +/*
1064 +  +----------------------------------------------------------------------+
1065 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
1083 +
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.
1089 +
1090 +   All other licensing and usage conditions are those of the PHP Group.
1091 +
1092 + */
1093 +
1094 +/* $Id: apc.c 326710 2012-07-19 20:51:04Z rasmus $ */
1095 +
1096 +#include "apc.h"
1097 +#include "apc_zend.h"
1098 +#include "apc_cache.h"
1099 +#include "apc_globals.h"
1100 +#include "php.h"
1101 +
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"
1106 +#   else
1107 +#       include "ext/pcre/php_pcre.h"
1108 +#   endif
1109 +#   include "ext/standard/php_smart_str.h"
1110 +#endif
1111 +
1112 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
1113 +
1114 +/* {{{ memory allocation wrappers */
1115 +
1116 +void* apc_emalloc(size_t n TSRMLS_DC)
1117 +{
1118 +    void* p = malloc(n);
1119 +    if (p == NULL) {
1120 +        apc_error("apc_emalloc: malloc failed to allocate %u bytes:" TSRMLS_CC, n);
1121 +        return NULL;
1122 +    }
1123 +    return p;
1124 +}
1125 +
1126 +void* apc_erealloc(void* p, size_t n TSRMLS_DC)
1127 +{
1128 +    void *new;
1129 +    new = realloc(p, n);
1130 +    if (new == NULL) {
1131 +        apc_error("apc_erealloc: realloc failed to allocate %u bytes:" TSRMLS_CC, n);
1132 +        return NULL;
1133 +    }
1134 +    return new;
1135 +}
1136 +
1137 +void apc_efree(void* p TSRMLS_DC)
1138 +{
1139 +    if (p == NULL) {
1140 +        apc_error("apc_efree: attempt to free null pointer" TSRMLS_CC);
1141 +        return;
1142 +    }
1143 +    free(p);
1144 +}
1145 +
1146 +char* APC_ALLOC apc_estrdup(const char* s TSRMLS_DC)
1147 +{
1148 +    int len;
1149 +    char* dup;
1150 +
1151 +    if (s == NULL) {
1152 +        return NULL;
1153 +    }
1154 +    len = strlen(s);
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);
1158 +        return NULL;
1159 +    }
1160 +    memcpy(dup, s, len);
1161 +    dup[len] = '\0';
1162 +    return dup;
1163 +}
1164 +
1165 +void* APC_ALLOC apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC)
1166 +{
1167 +    return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f TSRMLS_CC) : NULL;
1168 +}
1169 +
1170 +void* APC_ALLOC apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC)
1171 +{
1172 +    void* q;
1173 +
1174 +    if (p != NULL && (q = f(n TSRMLS_CC)) != NULL) {
1175 +        memcpy(q, p, n);
1176 +        return q;
1177 +    }
1178 +    return NULL;
1179 +}
1180 +
1181 +/* }}} */
1182 +
1183 +/* {{{ console display functions */
1184 +#ifdef ZTS
1185 +# define APC_PRINT_FUNCTION_PARAMETER TSRMLS_C
1186 +#else
1187 +# define APC_PRINT_FUNCTION_PARAMETER format
1188 +#endif
1189 +
1190 +#define APC_PRINT_FUNCTION(name, verbosity)                                    \
1191 +       void apc_##name(const char *format TSRMLS_DC, ...)                      \
1192 +       {                                                                       \
1193 +               va_list args;                                                   \
1194 +                                                                               \
1195 +               va_start(args, APC_PRINT_FUNCTION_PARAMETER);                   \
1196 +               php_verror(NULL, "", verbosity, format, args TSRMLS_CC);        \
1197 +               va_end(args);                                                   \
1198 +       }
1199 +
1200 +APC_PRINT_FUNCTION(error, E_ERROR)
1201 +APC_PRINT_FUNCTION(warning, E_WARNING)
1202 +APC_PRINT_FUNCTION(notice, E_NOTICE)
1203 +
1204 +#ifdef __DEBUG_APC__
1205 +APC_PRINT_FUNCTION(debug, E_NOTICE)
1206 +#else
1207 +void apc_debug(const char *format TSRMLS_DC, ...) {}
1208 +#endif
1209 +/* }}} */
1210 +
1211 +/* {{{ string and text manipulation */
1212 +
1213 +char* apc_append(const char* s, const char* t TSRMLS_DC)
1214 +{
1215 +    int slen;
1216 +    int tlen;
1217 +    char* p;
1218 +
1219 +    slen = strlen(s);
1220 +    tlen = strlen(t);
1221 +
1222 +    p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char) TSRMLS_CC);
1223 +    memcpy(p, s, slen);
1224 +    memcpy(p + slen, t, tlen + 1);
1225 +
1226 +    return p;
1227 +}
1228 +
1229 +char* apc_substr(const char* s, int start, int length TSRMLS_DC)
1230 +{
1231 +    char* substr;
1232 +    int src_len = strlen(s);
1233 +
1234 +    /* bring start into range */
1235 +    if (start < 0) {
1236 +        start = 0;
1237 +    }
1238 +    else if (start >= src_len) {
1239 +        start = src_len - 1;
1240 +    }
1241 +
1242 +    /* bring length into range */
1243 +    if (length < 0 || src_len - start < length) {
1244 +        length = src_len - start;
1245 +    }
1246 +
1247 +    /* create the substring */
1248 +    substr = apc_xmemcpy(s + start, length + 1, apc_emalloc TSRMLS_CC);
1249 +    substr[length] = '\0';
1250 +    return substr;
1251 +}
1252 +
1253 +char** apc_tokenize(const char* s, char delim TSRMLS_DC)
1254 +{
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 */
1261 +
1262 +    if (!s) {
1263 +        return NULL;
1264 +    }
1265 +
1266 +    size = 2;
1267 +    n    = 0;
1268 +    cur  = 0;
1269 +    end  = strlen(s) - 1;
1270 +
1271 +    tokens = (char**) apc_emalloc(size * sizeof(char*) TSRMLS_CC);
1272 +    tokens[n] = NULL;
1273 +
1274 +    while (cur <= end) {
1275 +        /* search for the next delimiter */
1276 +        char* p = strchr(s + cur, delim);
1277 +        next = p ? p-s : end+1;
1278 +
1279 +        /* resize token array if necessary */
1280 +        if (n == size-1) {
1281 +            size *= 2;
1282 +            tokens = (char**) apc_erealloc(tokens, size * sizeof(char*) TSRMLS_CC);
1283 +        }
1284 +
1285 +        /* save the current token */
1286 +        tokens[n] = apc_substr(s, cur, next-cur TSRMLS_CC);
1287 +
1288 +        tokens[++n] = NULL;
1289 +        cur = next + 1;
1290 +    }
1291 +
1292 +    return tokens;
1293 +}
1294 +
1295 +/* }}} */
1296 +
1297 +
1298 +/* {{{ apc_win32_restat */
1299 +#ifdef PHP_WIN32
1300 +static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
1301 +{
1302 +    HANDLE hFile;
1303 +    BY_HANDLE_FILE_INFORMATION hInfo;
1304 +
1305 +    hFile = CreateFile(fileinfo->fullpath, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1306 +
1307 +    if (!hFile) {
1308 +        apc_debug("Cannot create a file HANDLE for %s\n" TSRMLS_CC, fileinfo->fullpath);
1309 +        return -1;
1310 +    }
1311 +
1312 +    if (!GetFileInformationByHandle(hFile, &hInfo)) {
1313 +        apc_debug("Cannot get file information from handle\n" TSRMLS_CC);
1314 +        CloseHandle(hFile);
1315 +        return -1;
1316 +    }
1317 +
1318 +    CloseHandle(hFile);
1319 +
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);
1322 +
1323 +    return 0;
1324 +}
1325 +#else
1326 +static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC)
1327 +{
1328 +       return 0;
1329 +}
1330 +#endif
1331 +/* }}} */
1332 +
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))
1337 +
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)
1343 +
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])))))
1350 +    
1351 +/* {{{ stupid stringifcation */
1352 +#if DEFAULT_SLASH == '/'
1353 +    #define DEFAULT_SLASH_STRING "/"
1354 +#elif DEFAULT_SLASH == '\\'
1355 +    #define DEFAULT_SLASH_STRING "\\"
1356 +#else
1357 +    #error "Unknown value for DEFAULT_SLASH"
1358 +#endif
1359 +/* }}} */
1360 +
1361 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC)
1362 +{
1363 +    char** paths = NULL;
1364 +    char *exec_fname;
1365 +    int exec_fname_length;
1366 +    int found = 0;
1367 +    int i;
1368 +    php_stream_wrapper *wrapper = NULL;
1369 +    char *path_for_open = NULL;
1370 +
1371 +    assert(filename && fileinfo);
1372 +
1373 +
1374 +    wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC);
1375 +
1376 +    if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) {
1377 +        return -1;
1378 +    }
1379 +
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);
1384 +        }
1385 +        return -1; /* cannot stat */
1386 +    }
1387 +
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);
1392 +    }
1393 +
1394 +    if (!IS_RELATIVE_PATH(path_for_open, strlen(path_for_open))) {
1395 +        paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR TSRMLS_CC);
1396 +        if (!paths)
1397 +            return -1;
1398 +
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;
1404 +                found = 1;
1405 +                break;
1406 +            }
1407 +        }
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;
1413 +                found = 1;
1414 +            }
1415 +        }
1416 +    } else {
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);
1425 +            }
1426 +        }
1427 +    }
1428 +
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;
1443 +                found = 1;
1444 +            }
1445 +        }
1446 +    }
1447 +
1448 +    if(paths) {
1449 +        /* free the value returned by apc_tokenize */
1450 +        for (i = 0; paths[i]; i++) {
1451 +            apc_efree(paths[i] TSRMLS_CC);
1452 +        }
1453 +        apc_efree(paths TSRMLS_CC);
1454 +    }
1455 +
1456 +    return found ? apc_restat(fileinfo TSRMLS_CC) : -1;
1457 +}
1458 +
1459 +/* }}} */
1460 +
1461 +/* {{{ regular expression wrapper functions */
1462 +
1463 +#if (HAVE_PCRE || HAVE_BUNDLED_PCRE)
1464 +typedef struct {
1465 +    pcre *preg;
1466 +    pcre *nreg;
1467 +} apc_regex;
1468 +
1469 +#define APC_ADD_PATTERN(match, pat) do {\
1470 +    if(match.len > 1) {\
1471 +        smart_str_appendc(&match, '|');\
1472 +    }\
1473 +    smart_str_appendc(&match, '(');\
1474 +    while(*pat) {\
1475 +        if(*pat == '/') smart_str_appendc(&match, '\\');\
1476 +        \
1477 +        smart_str_appendc(&match, *(pat++));\
1478 +    }\
1479 +    smart_str_appendc(&match, ')');\
1480 +} while(0)
1481 +
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);\
1487 +            return NULL;\
1488 +        }\
1489 +    } else { \
1490 +        (re) = NULL;\
1491 +    }\
1492 +} while(0)
1493 +
1494 +void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
1495 +{
1496 +    apc_regex* regs;
1497 +    int npat;
1498 +    smart_str pmatch = {0,};
1499 +    smart_str nmatch = {0,};
1500 +    char* pattern;
1501 +
1502 +    if (!patterns)
1503 +        return NULL;
1504 +
1505 +    regs = (apc_regex*) apc_emalloc(sizeof(apc_regex) TSRMLS_CC);
1506 +
1507 +    smart_str_appendc(&pmatch, '/');
1508 +    smart_str_appendc(&nmatch, '/');
1509 +
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);
1515 +        } else {
1516 +            if(pattern[0] == '-') pattern += sizeof(char);
1517 +            APC_ADD_PATTERN(nmatch, pattern);
1518 +        }
1519 +    }
1520 +    smart_str_appendc(&pmatch, '/');
1521 +    smart_str_appendc(&nmatch, '/');
1522 +
1523 +    smart_str_0(&nmatch);
1524 +    smart_str_0(&pmatch);
1525 +
1526 +    APC_COMPILE_PATTERN(regs->preg, pmatch);
1527 +    APC_COMPILE_PATTERN(regs->nreg, nmatch);
1528 +
1529 +    smart_str_free(&pmatch);
1530 +    smart_str_free(&nmatch);
1531 +
1532 +    return (void*) regs;
1533 +}
1534 +
1535 +void apc_regex_destroy_array(void* p TSRMLS_DC)
1536 +{
1537 +    if (p != NULL) {
1538 +        apc_regex* regs = (apc_regex*) p;
1539 +        apc_efree(regs TSRMLS_CC);
1540 +    }
1541 +}
1542 +
1543 +#define APC_MATCH_PATTERN(re, input, output) do {\
1544 +    if (re && pcre_exec(re, NULL, (input), strlen(input), 0, 0, NULL, 0) >= 0) {\
1545 +        return (output);\
1546 +    }\
1547 +} while(0)
1548 +
1549 +
1550 +int apc_regex_match_array(void* p, const char* input)
1551 +{
1552 +    apc_regex* regs;
1553 +
1554 +    if (!p)
1555 +        return 0;
1556 +
1557 +    regs = (apc_regex*) p;
1558 +
1559 +    APC_MATCH_PATTERN(regs->preg, input, APC_POSITIVE_MATCH);
1560 +    APC_MATCH_PATTERN(regs->nreg, input, APC_NEGATIVE_MATCH);
1561 +
1562 +    return 0;
1563 +}
1564 +#else /* no pcre */
1565 +void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
1566 +{
1567 +    if(patterns && patterns[0] != NULL) {
1568 +        apc_warning("pcre missing, disabling filters" TSRMLS_CC);
1569 +    }
1570 +    return NULL;
1571 +}
1572 +void apc_regex_destroy_array(void* p)
1573 +{
1574 +    /* nothing */
1575 +}
1576 +int apc_regex_match_array(void* p, const char* input)
1577 +{
1578 +    return 0;
1579 +}
1580 +#endif
1581 +/* }}} */
1582 +
1583 +/* {{{ crc32 implementation */
1584 +
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,
1651 +};
1652 +
1653 +unsigned int apc_crc32(const char* buf, int len)
1654 +{
1655 +    int i;
1656 +    int k;
1657 +    unsigned int crc;
1658 +
1659 +    /* preconditioning */
1660 +    crc = 0xFFFFFFFF;
1661 +
1662 +    for (i = 0; i < len; i++) {
1663 +        k = (crc ^ buf[i]) & 0x000000FF;
1664 +        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
1665 +    }
1666 +
1667 +    /* postconditioning */
1668 +    return ~crc;
1669 +}
1670 +
1671 +/* crc32gen: generate the nth (0..255) crc32 table value */
1672 +#if 0
1673 +static unsigned long crc32gen(int n)
1674 +{
1675 +    int i;
1676 +    unsigned long crc;
1677 +
1678 +    crc = n;
1679 +    for (i = 8; i >= 0; i--) {
1680 +        if (crc & 1) {
1681 +            crc = (crc >> 1) ^ 0xEDB88320;
1682 +        }
1683 +        else {
1684 +            crc >>= 1;
1685 +        }
1686 +    }
1687 +    return crc;
1688 +}
1689 +#endif
1690 +
1691 +/* }}} */
1692 +
1693 +
1694 +/* {{{ apc_flip_hash() */
1695 +HashTable* apc_flip_hash(HashTable *hash) {
1696 +    zval **entry, *data;
1697 +    HashTable *new_hash;
1698 +    HashPosition pos;
1699 +
1700 +    if(hash == NULL) return hash;
1701 +
1702 +    MAKE_STD_ZVAL(data);
1703 +    ZVAL_LONG(data, 1);
1704 +    
1705 +    new_hash = emalloc(sizeof(HashTable));
1706 +    zend_hash_init(new_hash, hash->nTableSize, NULL, ZVAL_PTR_DTOR, 0);
1707 +
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);
1712 +        } else {
1713 +            zend_hash_index_update(new_hash, Z_LVAL_PP(entry), &data, sizeof(data), NULL);
1714 +        }
1715 +        Z_ADDREF_P(data);
1716 +        zend_hash_move_forward_ex(hash, &pos);
1717 +    }
1718 +    zval_ptr_dtor(&data);
1719 +
1720 +    return new_hash;
1721 +}
1722 +/* }}} */
1723 +
1724 +
1725 +/*
1726 + * Local variables:
1727 + * tab-width: 4
1728 + * c-basic-offset: 4
1729 + * End:
1730 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
1731 + * vim<600: expandtab sw=4 ts=4 sts=4
1732 + */
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
1736 @@ -0,0 +1,1383 @@
1737 +/*
1738 +  +----------------------------------------------------------------------+
1739 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
1756 +
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.
1762 +
1763 +   All other licensing and usage conditions are those of the PHP Group.
1764 +
1765 + */
1766 +
1767 +/* $Id: apc_cache.c 325482 2012-05-01 00:09:36Z rasmus $ */
1768 +
1769 +#include "apc_cache.h"
1770 +#include "apc_zend.h"
1771 +#include "apc_sma.h"
1772 +#include "apc_globals.h"
1773 +#include "SAPI.h"
1774 +#include "TSRM.h"
1775 +#include "ext/standard/md5.h"
1776 +
1777 +/* TODO: rehash when load factor exceeds threshold */
1778 +
1779 +#define CHECK(p) { if ((p) == NULL) return NULL; }
1780 +
1781 +/* {{{ key_equals */
1782 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
1783 +/* }}} */
1784 +
1785 +static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC);
1786 +
1787 +/* {{{ hash */
1788 +static unsigned long hash(apc_cache_key_t key)
1789 +{
1790 +    return (unsigned long)(key.data.file.device + key.data.file.inode);
1791 +}
1792 +/* }}} */
1793 +
1794 +/* {{{ string_nhash_8 */
1795 +#define string_nhash_8(s,len) (unsigned long)(zend_inline_hash_func((s), len))
1796 +/* }}} */
1797 +
1798 +/* {{{ murmurhash */
1799 +#if 0
1800 +static inline unsigned long murmurhash(const char *skey, size_t keylen)
1801 +{
1802 +       const long m = 0x7fd652ad;
1803 +       const long r = 16;
1804 +       unsigned int h = 0xdeadbeef;
1805 +
1806 +       while(keylen >= 4)
1807 +       {
1808 +               h += *(unsigned int*)skey;
1809 +               h *= m;
1810 +               h ^= h >> r;
1811 +
1812 +               skey += 4;
1813 +               keylen -= 4;
1814 +       }
1815 +
1816 +       switch(keylen)
1817 +       {
1818 +       case 3:
1819 +               h += skey[2] << 16;
1820 +       case 2:
1821 +               h += skey[1] << 8;
1822 +       case 1:
1823 +               h += skey[0];
1824 +               h *= m;
1825 +               h ^= h >> r;
1826 +       };
1827 +
1828 +       h *= m;
1829 +       h ^= h >> 10;
1830 +       h *= m;
1831 +       h ^= h >> 17;
1832 +
1833 +       return h;
1834 +}
1835 +#endif
1836 +/* }}} */
1837 +
1838 +
1839 +/* {{{ make_prime */
1840 +static int const primes[] = {
1841 +  257, /*   256 */
1842 +  521, /*   512 */
1843 + 1031, /*  1024 */
1844 + 2053, /*  2048 */
1845 + 3079, /*  3072 */
1846 + 4099, /*  4096 */
1847 + 5147, /*  5120 */
1848 + 6151, /*  6144 */
1849 + 7177, /*  7168 */
1850 + 8209, /*  8192 */
1851 + 9221, /*  9216 */
1852 +10243, /* 10240 */
1853 +11273, /* 11264 */
1854 +12289, /* 12288 */
1855 +13313, /* 13312 */
1856 +14341, /* 14336 */
1857 +15361, /* 15360 */
1858 +16411, /* 16384 */
1859 +17417, /* 17408 */
1860 +18433, /* 18432 */
1861 +19457, /* 19456 */
1862 +0      /* sentinel */
1863 +};
1864 +
1865 +static int make_prime(int n)
1866 +{
1867 +    int *k = (int*)primes; 
1868 +    while(*k) {
1869 +        if((*k) > n) return *k;
1870 +        k++;
1871 +    }
1872 +    return *(k-1);
1873 +}
1874 +/* }}} */
1875 +
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)
1878 +{
1879 +    slot_t* p = apc_pool_alloc(value->pool, sizeof(slot_t));
1880 +
1881 +    if (!p) return NULL;
1882 +
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) {
1886 +            return NULL;
1887 +        }
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);
1891 +        if (!fullpath) {
1892 +            return NULL;
1893 +        }
1894 +        key->data.fpfile.fullpath = fullpath;
1895 +    }
1896 +    p->key = key[0];
1897 +    p->value = value;
1898 +    p->next = next;
1899 +    p->num_hits = 0;
1900 +    p->creation_time = t;
1901 +    p->access_time = t;
1902 +    p->deletion_time = 0;
1903 +    return p;
1904 +}
1905 +/* }}} */
1906 +
1907 +/* {{{ free_slot */
1908 +static void free_slot(slot_t* slot TSRMLS_DC)
1909 +{
1910 +    apc_pool_destroy(slot->value->pool TSRMLS_CC);
1911 +}
1912 +/* }}} */
1913 +
1914 +/* {{{ remove_slot */
1915 +static void remove_slot(apc_cache_t* cache, slot_t** slot TSRMLS_DC)
1916 +{
1917 +    slot_t* dead = *slot;
1918 +    *slot = (*slot)->next;
1919 +
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);
1924 +    }
1925 +    else {
1926 +        dead->next = cache->header->deleted_list;
1927 +        dead->deletion_time = time(0);
1928 +        cache->header->deleted_list = dead;
1929 +    }
1930 +}
1931 +/* }}} */
1932 +
1933 +/* {{{ process_pending_removals */
1934 +static void process_pending_removals(apc_cache_t* cache TSRMLS_DC)
1935 +{
1936 +    slot_t** slot;
1937 +    time_t now;
1938 +
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).
1943 +     */
1944 +
1945 +    if (!cache->header->deleted_list)
1946 +        return;
1947 +
1948 +    slot = &cache->header->deleted_list;
1949 +    now = time(0);
1950 +
1951 +    while (*slot != NULL) {
1952 +        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
1953 +
1954 +        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
1955 +            slot_t* dead = *slot;
1956 +
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);
1962 +                        break;
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);
1965 +                        break;
1966 +                }
1967 +            }
1968 +            *slot = dead->next;
1969 +            free_slot(dead TSRMLS_CC);
1970 +        }
1971 +        else {
1972 +            slot = &(*slot)->next;
1973 +        }
1974 +    }
1975 +}
1976 +/* }}} */
1977 +
1978 +/* {{{ prevent_garbage_collection */
1979 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
1980 +{
1981 +    /* set reference counts on zend objects to an arbitrarily high value to
1982 +     * prevent garbage collection after execution */
1983 +
1984 +    enum { BIG_VALUE = 1000 };
1985 +
1986 +    if(entry->data.file.op_array) {
1987 +        entry->data.file.op_array->refcount[0] = BIG_VALUE;
1988 +    }
1989 +    if (entry->data.file.functions) {
1990 +        int i;
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;
1994 +        }
1995 +    }
1996 +    if (entry->data.file.classes) {
1997 +        int i;
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;
2001 +        }
2002 +    }
2003 +}
2004 +/* }}} */
2005 +
2006 +/* {{{ apc_cache_create */
2007 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC)
2008 +{
2009 +    apc_cache_t* cache;
2010 +    int cache_size;
2011 +    int num_slots;
2012 +
2013 +    num_slots = make_prime(size_hint > 0 ? size_hint : 2000);
2014 +
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*);
2017 +
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);
2021 +        return NULL;
2022 +    }
2023 +    memset(cache->shmaddr, 0, cache_size);
2024 +
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;
2032 +
2033 +    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(cache_header_t));
2034 +    cache->num_slots = num_slots;
2035 +    cache->gc_ttl = gc_ttl;
2036 +    cache->ttl = ttl;
2037 +    CREATE_LOCK(cache->header->lock);
2038 +#if NONBLOCKING_LOCK_AVAILABLE
2039 +    CREATE_LOCK(cache->header->wrlock);
2040 +#endif
2041 +    memset(cache->slots, 0, sizeof(slot_t*)*num_slots);
2042 +    cache->expunge_cb = apc_cache_expunge;
2043 +    cache->has_lock = 0;
2044 +
2045 +    return cache;
2046 +}
2047 +/* }}} */
2048 +
2049 +/* {{{ apc_cache_destroy */
2050 +void apc_cache_destroy(apc_cache_t* cache TSRMLS_DC)
2051 +{
2052 +    DESTROY_LOCK(cache->header->lock);
2053 +#if NONBLOCKING_LOCK_AVAILABLE
2054 +    DESTROY_LOCK(cache->header->wrlock);
2055 +#endif
2056 +    apc_efree(cache TSRMLS_CC);
2057 +}
2058 +/* }}} */
2059 +
2060 +/* {{{ apc_cache_clear */
2061 +void apc_cache_clear(apc_cache_t* cache TSRMLS_DC)
2062 +{
2063 +    int i;
2064 +
2065 +    if(!cache) return;
2066 +
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;
2073 +
2074 +    for (i = 0; i < cache->num_slots; i++) {
2075 +        slot_t* p = cache->slots[i];
2076 +        while (p) {
2077 +            remove_slot(cache, &p TSRMLS_CC);
2078 +        }
2079 +        cache->slots[i] = NULL;
2080 +    }
2081 +
2082 +    memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2083 +
2084 +    cache->header->busy = 0;
2085 +    CACHE_UNLOCK(cache);
2086 +}
2087 +/* }}} */
2088 +
2089 +/* {{{ apc_cache_expunge */
2090 +static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC)
2091 +{
2092 +    int i;
2093 +    time_t t;
2094 +
2095 +    t = apc_time();
2096 +
2097 +    if(!cache) return;
2098 +
2099 +    if(!cache->ttl) {
2100 +        /*
2101 +         * If cache->ttl is not set, we wipe out the entire cache when
2102 +         * we run out of space.
2103 +         */
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);
2109 +            return;
2110 +        }
2111 +        cache->header->busy = 1;
2112 +        CACHE_FAST_INC(cache, cache->header->expunges);
2113 +clear_all:
2114 +        for (i = 0; i < cache->num_slots; i++) {
2115 +            slot_t* p = cache->slots[i];
2116 +            while (p) {
2117 +                remove_slot(cache, &p TSRMLS_CC);
2118 +            }
2119 +            cache->slots[i] = NULL;
2120 +        }
2121 +        memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2122 +        cache->header->busy = 0;
2123 +        CACHE_SAFE_UNLOCK(cache);
2124 +    } else {
2125 +        slot_t **p;
2126 +        /*
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
2132 +         * on insert
2133 +         */
2134 +
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);
2140 +            return;
2141 +        }
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];
2146 +            while(*p) {
2147 +                /*
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
2150 +                 */
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);
2155 +                            continue;
2156 +                        }
2157 +                    } else if(cache->ttl) {
2158 +                        if((*p)->creation_time + cache->ttl < t) {
2159 +                            remove_slot(cache, p TSRMLS_CC);
2160 +                            continue;
2161 +                        }
2162 +                    }
2163 +                } else if((*p)->access_time < (t - cache->ttl)) {
2164 +                    remove_slot(cache, p TSRMLS_CC);
2165 +                    continue;
2166 +                }
2167 +                p = &(*p)->next;
2168 +            }
2169 +        }
2170 +
2171 +        if (!apc_sma_get_avail_size(size)) {
2172 +            /* TODO: re-do this to remove goto across locked sections */
2173 +            goto clear_all;
2174 +        }
2175 +        memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2176 +        cache->header->busy = 0;
2177 +        CACHE_SAFE_UNLOCK(cache);
2178 +    }
2179 +}
2180 +/* }}} */
2181 +
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,
2187 +                     time_t t
2188 +                     TSRMLS_DC)
2189 +{
2190 +    slot_t** slot;
2191 +
2192 +    if (!value) {
2193 +        return 0;
2194 +    }
2195 +
2196 +    apc_debug("Inserting [%s]\n" TSRMLS_CC, value->data.file.filename);
2197 +
2198 +    process_pending_removals(cache TSRMLS_CC);
2199 +
2200 +    slot = &cache->slots[key.h % cache->num_slots];
2201 +
2202 +    while(*slot) {
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);
2209 +                    break;
2210 +                }
2211 +                return 0;
2212 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
2213 +                remove_slot(cache, slot TSRMLS_CC);
2214 +                continue;
2215 +            }
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);
2221 +                break;
2222 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
2223 +                remove_slot(cache, slot TSRMLS_CC);
2224 +                continue;
2225 +            }
2226 +        }
2227 +      }
2228 +      slot = &(*slot)->next;
2229 +    }
2230 +
2231 +    if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) {
2232 +        return -1;
2233 +    }
2234 +
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);
2239 +
2240 +    return 1;
2241 +}
2242 +/* }}} */
2243 +
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)
2246 +{
2247 +    int rval;
2248 +    CACHE_LOCK(cache);
2249 +    rval = _apc_cache_insert(cache, key, value, ctxt, t TSRMLS_CC);
2250 +    CACHE_UNLOCK(cache);
2251 +    return rval;
2252 +}
2253 +/* }}} */
2254 +
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)
2257 +{
2258 +    int *rval;
2259 +    int i;
2260 +
2261 +    rval = emalloc(sizeof(int) * num_entries);
2262 +    CACHE_LOCK(cache);
2263 +    for (i=0; i < num_entries; i++) {
2264 +        if (values[i]) {
2265 +            ctxt->pool = values[i]->pool;
2266 +            rval[i] = _apc_cache_insert(cache, keys[i], values[i], ctxt, t TSRMLS_CC);
2267 +        }
2268 +    }
2269 +    CACHE_UNLOCK(cache);
2270 +    return rval;
2271 +}
2272 +/* }}} */
2273 +
2274 +
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)
2277 +{
2278 +    slot_t** slot;
2279 +    unsigned int keylen = key.data.user.identifier_len;
2280 +    apc_keyid_t *lastkey = &cache->header->lastkey;
2281 +    
2282 +    if (!value) {
2283 +        return 0;
2284 +    }
2285 +    
2286 +    if(apc_cache_busy(cache)) {
2287 +        /* cache cleanup in progress, do not wait */ 
2288 +        return 0;
2289 +    }
2290 +
2291 +    if(apc_cache_is_last_key(cache, &key, t TSRMLS_CC)) {
2292 +        /* potential cache slam */
2293 +        return 0;
2294 +    }
2295 +
2296 +    CACHE_LOCK(cache);
2297 +
2298 +    memset(lastkey, 0, sizeof(apc_keyid_t));
2299 +
2300 +    lastkey->h = key.h;
2301 +    lastkey->keylen = keylen;
2302 +    lastkey->mtime = t;
2303 +#ifdef ZTS
2304 +    lastkey->tid = tsrm_thread_id();
2305 +#else
2306 +    lastkey->pid = getpid();
2307 +#endif
2308 +    
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. 
2311 +     */
2312 +
2313 +    process_pending_removals(cache TSRMLS_CC);
2314 +    
2315 +    slot = &cache->slots[key.h % cache->num_slots];
2316 +
2317 +    while (*slot) {
2318 +        if (((*slot)->key.h == key.h) && 
2319 +            (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, keylen))) {
2320 +            /* 
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.
2325 +             */
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 ) 
2328 +                            ) ) {
2329 +                goto fail;
2330 +            }
2331 +            remove_slot(cache, slot TSRMLS_CC);
2332 +            break;
2333 +        } else 
2334 +        /* 
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
2340 +         */
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);
2344 +            continue;
2345 +        }
2346 +        slot = &(*slot)->next;
2347 +    }
2348 +
2349 +    if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) {
2350 +        goto fail;
2351 +    } 
2352 +    
2353 +    value->mem_size = ctxt->pool->size;
2354 +    cache->header->mem_size += ctxt->pool->size;
2355 +
2356 +    CACHE_FAST_INC(cache, cache->header->num_entries);
2357 +    CACHE_FAST_INC(cache, cache->header->num_inserts);
2358 +
2359 +    CACHE_UNLOCK(cache);
2360 +
2361 +    return 1;
2362 +
2363 +fail:
2364 +    CACHE_UNLOCK(cache);
2365 +
2366 +    return 0;
2367 +}
2368 +/* }}} */
2369 +
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)
2372 +{
2373 +    slot_t** slot;
2374 +    volatile slot_t* retval = NULL;
2375 +
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];
2379 +
2380 +    while (*slot) {
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*).
2389 +                     */
2390 +                    remove_slot(cache, slot TSRMLS_CC);
2391 +                    #endif
2392 +                    CACHE_SAFE_INC(cache, cache->header->num_misses);
2393 +                    CACHE_RDUNLOCK(cache);
2394 +                    return NULL;
2395 +                }
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); 
2401 +                retval = *slot;
2402 +                CACHE_RDUNLOCK(cache);
2403 +                return (slot_t*)retval;
2404 +            }
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)) {
2408 +                /* TTL Check ? */
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);
2414 +                retval = *slot;
2415 +                CACHE_RDUNLOCK(cache);
2416 +                return (slot_t*)retval;
2417 +            }
2418 +        }
2419 +      }
2420 +      slot = &(*slot)->next;
2421 +    }
2422 +    CACHE_FAST_INC(cache, cache->header->num_misses); 
2423 +    CACHE_RDUNLOCK(cache);
2424 +    return NULL;
2425 +}
2426 +/* }}} */
2427 +
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)
2430 +{
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;
2434 +}
2435 +/* }}} */
2436 +
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)
2439 +{
2440 +    slot_t** slot;
2441 +    volatile apc_cache_entry_t* value = NULL;
2442 +    unsigned long h;
2443 +
2444 +    if(apc_cache_busy(cache))
2445 +    {
2446 +        /* cache cleanup in progress */ 
2447 +        return NULL;
2448 +    }
2449 +
2450 +    CACHE_RDLOCK(cache);
2451 +
2452 +    h = string_nhash_8(strkey, keylen);
2453 +
2454 +    slot = &cache->slots[h % cache->num_slots];
2455 +
2456 +    while (*slot) {
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*).
2465 +                 */
2466 +                remove_slot(cache, slot TSRMLS_CC);
2467 +                #endif
2468 +                CACHE_FAST_INC(cache, cache->header->num_misses);
2469 +                CACHE_RDUNLOCK(cache);
2470 +                return NULL;
2471 +            }
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;
2476 +
2477 +            CACHE_FAST_INC(cache, cache->header->num_hits);
2478 +            value = (*slot)->value;
2479 +            CACHE_RDUNLOCK(cache);
2480 +            return (apc_cache_entry_t*)value;
2481 +        }
2482 +        slot = &(*slot)->next;
2483 +    }
2484
2485 +    CACHE_FAST_INC(cache, cache->header->num_misses);
2486 +    CACHE_RDUNLOCK(cache);
2487 +    return NULL;
2488 +}
2489 +/* }}} */
2490 +
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)
2493 +{
2494 +    slot_t** slot;
2495 +    volatile apc_cache_entry_t* value = NULL;
2496 +    unsigned long h;
2497 +
2498 +    if(apc_cache_busy(cache))
2499 +    {
2500 +        /* cache cleanup in progress */ 
2501 +        return NULL;
2502 +    }
2503 +
2504 +    CACHE_RDLOCK(cache);
2505 +
2506 +    h = string_nhash_8(strkey, keylen);
2507 +
2508 +    slot = &cache->slots[h % cache->num_slots];
2509 +
2510 +    while (*slot) {
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);
2516 +                return NULL;
2517 +            }
2518 +            /* Return the cache entry ptr */
2519 +            value = (*slot)->value;
2520 +            CACHE_RDUNLOCK(cache);
2521 +            return (apc_cache_entry_t*)value;
2522 +        }
2523 +        slot = &(*slot)->next;
2524 +    }
2525 +    CACHE_RDUNLOCK(cache);
2526 +    return NULL;
2527 +}
2528 +/* }}} */
2529 +
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)
2532 +{
2533 +    slot_t** slot;
2534 +    int retval;
2535 +    unsigned long h;
2536 +
2537 +    if(apc_cache_busy(cache))
2538 +    {
2539 +        /* cache cleanup in progress */ 
2540 +        return 0;
2541 +    }
2542 +
2543 +    CACHE_LOCK(cache);
2544 +
2545 +    h = string_nhash_8(strkey, keylen);
2546 +    slot = &cache->slots[h % cache->num_slots];
2547 +
2548 +    while (*slot) {
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) {
2552 +                case IS_ARRAY:
2553 +                case IS_CONSTANT_ARRAY:
2554 +                case IS_OBJECT:
2555 +                {
2556 +                    if(APCG(serializer)) {
2557 +                        retval = 0;
2558 +                        break;
2559 +                    } else {
2560 +                        /* fall through */
2561 +                    }
2562 +                }
2563 +                /* fall through */
2564 +                default:
2565 +                {
2566 +                    retval = updater(cache, (*slot)->value, data);
2567 +                    (*slot)->key.mtime = apc_time();
2568 +                }
2569 +                break;
2570 +            }
2571 +            CACHE_UNLOCK(cache);
2572 +            return retval;
2573 +        }
2574 +        slot = &(*slot)->next;
2575 +    }
2576 +    CACHE_UNLOCK(cache);
2577 +    return 0;
2578 +}
2579 +/* }}} */
2580 +
2581 +/* {{{ apc_cache_user_delete */
2582 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC)
2583 +{
2584 +    slot_t** slot;
2585 +    unsigned long h;
2586 +
2587 +    CACHE_LOCK(cache);
2588 +
2589 +    h = string_nhash_8(strkey, keylen);
2590 +
2591 +    slot = &cache->slots[h % cache->num_slots];
2592 +
2593 +    while (*slot) {
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);
2598 +            return 1;
2599 +        }
2600 +        slot = &(*slot)->next;
2601 +    }
2602 +
2603 +    CACHE_UNLOCK(cache);
2604 +    return 0;
2605 +}
2606 +/* }}} */
2607 +
2608 +/* {{{ apc_cache_delete */
2609 +int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC)
2610 +{
2611 +    slot_t** slot;
2612 +    time_t t;
2613 +    apc_cache_key_t key;
2614 +
2615 +    t = apc_time();
2616 +
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);
2620 +        return -1;
2621 +    }
2622 +
2623 +    CACHE_LOCK(cache);
2624 +
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];
2627 +
2628 +    while(*slot) {
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);
2634 +                return 1;
2635 +            }
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);
2641 +                return 1;
2642 +            }
2643 +        }
2644 +      }
2645 +      slot = &(*slot)->next;
2646 +    }
2647 +    
2648 +    memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
2649 +    
2650 +    CACHE_UNLOCK(cache);
2651 +    return 0;
2652 +
2653 +}
2654 +/* }}} */
2655 +
2656 +/* {{{ apc_cache_release */
2657 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry TSRMLS_DC)
2658 +{
2659 +    CACHE_SAFE_DEC(cache, entry->ref_count);
2660 +}
2661 +/* }}} */
2662 +
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,
2667 +                       time_t t
2668 +                       TSRMLS_DC)
2669 +{
2670 +    struct stat *tmp_buf=NULL;
2671 +    struct apc_fileinfo_t *fileinfo = NULL;
2672 +    int len;
2673 +
2674 +    assert(key != NULL);
2675 +
2676 +    if (!filename || !SG(request_info).path_translated) {
2677 +        apc_debug("No filename and no path_translated - bailing\n" TSRMLS_CC);
2678 +        goto cleanup;
2679 +    }
2680 +
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);
2687 +            key->mtime = t;
2688 +            key->type = APC_CACHE_KEY_FPFILE;
2689 +            goto success;
2690 +        } else if(APCG(canonicalize)) {
2691 +
2692 +            fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
2693 +
2694 +            if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) {
2695 +                apc_warning("apc failed to locate %s - bailing" TSRMLS_CC, filename);
2696 +                goto cleanup;
2697 +            }
2698 +
2699 +            if(!VCWD_REALPATH(fileinfo->fullpath, APCG(canon_path))) {
2700 +                apc_warning("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename);
2701 +                goto cleanup;
2702 +            }
2703 +
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);
2707 +            key->mtime = t;
2708 +            key->type = APC_CACHE_KEY_FPFILE;
2709 +            goto success;
2710 +        }
2711 +        /* fall through to stat mode */
2712 +    }
2713 +
2714 +    fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC);
2715 +
2716 +    assert(fileinfo != NULL);
2717 +
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 */
2720 +    }
2721 +
2722 +    if(tmp_buf) {
2723 +        fileinfo->st_buf.sb = *tmp_buf;
2724 +    } else {
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);
2727 +            goto cleanup;
2728 +        }
2729 +    }
2730 +
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);
2733 +        goto cleanup;
2734 +    }
2735 +
2736 +    /*
2737 +     * This is a bit of a hack.
2738 +     *
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.
2747 +     */
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);
2750 +        goto cleanup;
2751 +    }
2752 +
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;
2756 +
2757 +    /*
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.
2767 +     */
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; 
2770 +    } else {
2771 +        key->mtime = fileinfo->st_buf.sb.st_mtime;
2772 +    }
2773 +    key->type = APC_CACHE_KEY_FILE;
2774 +
2775 +success: 
2776 +
2777 +    if(fileinfo != NULL) {
2778 +        apc_php_free(fileinfo TSRMLS_CC);
2779 +    }
2780 +
2781 +    return 1;
2782 +
2783 +cleanup:
2784 +    
2785 +    if(fileinfo != NULL) {
2786 +        apc_php_free(fileinfo TSRMLS_CC);
2787 +    }
2788 +
2789 +    return 0;
2790 +}
2791 +/* }}} */
2792 +
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)
2795 +{
2796 +    assert(key != NULL);
2797 +
2798 +    if (!identifier)
2799 +        return 0;
2800 +
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);
2804 +    key->mtime = t;
2805 +    key->type = APC_CACHE_KEY_USER;
2806 +    return 1;
2807 +}
2808 +/* }}} */
2809 +
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
2816 +                                        TSRMLS_DC)
2817 +{
2818 +    apc_cache_entry_t* entry;
2819 +    apc_pool* pool = ctxt->pool;
2820 +
2821 +    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
2822 +    if (!entry) return NULL;
2823 +
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);
2827 +        return NULL;
2828 +    }
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;
2833 +
2834 +    entry->data.file.halt_offset = apc_file_halt_offset(filename TSRMLS_CC);
2835 +
2836 +    entry->type = APC_CACHE_ENTRY_FILE;
2837 +    entry->ref_count = 0;
2838 +    entry->mem_size = 0;
2839 +    entry->pool = pool;
2840 +    return entry;
2841 +}
2842 +/* }}} */
2843 +
2844 +/* {{{ apc_cache_store_zval */
2845 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
2846 +{
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;
2853 +    } else {
2854 +        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2855 +    }
2856 +
2857 +
2858 +    return dst;
2859 +}
2860 +/* }}} */
2861 +
2862 +/* {{{ apc_cache_fetch_zval */
2863 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
2864 +{
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;
2871 +    } else {
2872 +        dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC);
2873 +    }
2874 +
2875 +
2876 +    return dst;
2877 +}
2878 +/* }}} */
2879 +
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)
2882 +{
2883 +    apc_cache_entry_t* entry;
2884 +    apc_pool* pool = ctxt->pool;
2885 +
2886 +    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
2887 +    if (!entry) return NULL;
2888 +
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) {
2892 +        return NULL;
2893 +    }
2894 +    entry->data.user.val = apc_cache_store_zval(NULL, val, ctxt TSRMLS_CC);
2895 +    if(!entry->data.user.val) {
2896 +        return NULL;
2897 +    }
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;
2904 +    return entry;
2905 +}
2906 +/* }}} */
2907 +
2908 +/* {{{ */
2909 +static zval* apc_cache_link_info(apc_cache_t *cache, slot_t* p TSRMLS_DC)
2910 +{
2911 +    zval *link = NULL;
2912 +    char md5str[33];
2913 +
2914 +    ALLOC_INIT_ZVAL(link);
2915 +
2916 +    if(!link) {
2917 +        return NULL;
2918 +    }
2919 +
2920 +    array_init(link);
2921 +
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) {
2925 +
2926 +            #ifdef PHP_WIN32
2927 +            {
2928 +              char buf[20];
2929 +              sprintf(buf, "%I64d",  p->key.data.file.device);
2930 +              add_assoc_string(link, "device", buf, 1);
2931 +
2932 +              sprintf(buf, "%I64d",  p->key.data.file.inode);
2933 +              add_assoc_string(link, "inode", buf, 1);
2934 +            }
2935 +            #else
2936 +            add_assoc_long(link, "device", p->key.data.file.device);
2937 +            add_assoc_long(link, "inode", p->key.data.file.inode);
2938 +            #endif
2939 +
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);
2945 +        }
2946 +        if (APCG(file_md5)) {
2947 +               make_digest(md5str, p->key.md5);
2948 +               add_assoc_string(link, "md5", md5str, 1);
2949 +        } 
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);
2954 +    }
2955 +
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);
2963 +
2964 +    return link;
2965 +}
2966 +/* }}} */
2967 +
2968 +/* {{{ apc_cache_info */
2969 +zval* apc_cache_info(apc_cache_t* cache, zend_bool limited TSRMLS_DC)
2970 +{
2971 +    zval *info = NULL;
2972 +    zval *list = NULL;
2973 +    zval *deleted_list = NULL;
2974 +    zval *slots = NULL;
2975 +    slot_t* p;
2976 +    int i, j;
2977 +
2978 +    if(!cache) return NULL;
2979 +
2980 +    CACHE_RDLOCK(cache);
2981 +
2982 +    ALLOC_INIT_ZVAL(info);
2983 +
2984 +    if(!info) {
2985 +        CACHE_RDUNLOCK(cache);
2986 +        return NULL;
2987 +    }
2988 +
2989 +    array_init(info);
2990 +    add_assoc_long(info, "num_slots", cache->num_slots);
2991 +    add_assoc_long(info, "ttl", cache->ttl);
2992 +
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);
2997 +    
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);
3003 +#else
3004 +    add_assoc_long(info, "file_upload_progress", 0);
3005 +#endif
3006 +#if APC_MMAP
3007 +    add_assoc_stringl(info, "memory_type", "mmap", sizeof("mmap")-1, 1);
3008 +#else
3009 +    add_assoc_stringl(info, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
3010 +#endif
3011 +    add_assoc_stringl(info, "locking_type", APC_LOCK_TYPE, sizeof(APC_LOCK_TYPE)-1, 1);
3012 +
3013 +    if(!limited) {
3014 +        /* For each hashtable slot */
3015 +        ALLOC_INIT_ZVAL(list);
3016 +        array_init(list);
3017 +
3018 +        ALLOC_INIT_ZVAL(slots);
3019 +        array_init(slots);
3020 +
3021 +        for (i = 0; i < cache->num_slots; i++) {
3022 +            p = cache->slots[i];
3023 +            j = 0;
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);
3027 +                j++;
3028 +            }
3029 +            if(j != 0) {
3030 +                add_index_long(slots, (ulong)i, j);
3031 +            }
3032 +        }
3033 +
3034 +        /* For each slot pending deletion */
3035 +        ALLOC_INIT_ZVAL(deleted_list);
3036 +        array_init(deleted_list);
3037 +
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);
3041 +        }
3042 +        
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);
3046 +    }
3047 +
3048 +    CACHE_RDUNLOCK(cache);
3049 +    return info;
3050 +}
3051 +/* }}} */
3052 +
3053 +/* {{{ apc_cache_unlock */
3054 +void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC)
3055 +{
3056 +    CACHE_UNLOCK(cache);
3057 +}
3058 +/* }}} */
3059 +
3060 +/* {{{ apc_cache_busy */
3061 +zend_bool apc_cache_busy(apc_cache_t* cache)
3062 +{
3063 +    return cache->header->busy;
3064 +}
3065 +/* }}} */
3066 +
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)
3069 +{
3070 +    apc_keyid_t *lastkey = &cache->header->lastkey;
3071 +    unsigned int keylen = key->data.user.identifier_len;
3072 +#ifdef ZTS
3073 +    THREAD_T tid = tsrm_thread_id();
3074 +    #define FROM_DIFFERENT_THREAD(k) (memcmp(&((k)->tid), &tid, sizeof(THREAD_T))!=0)
3075 +#else
3076 +    pid_t pid = getpid();
3077 +    #define FROM_DIFFERENT_THREAD(k) (pid != (k)->pid) 
3078 +#endif
3079 +
3080 +
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);
3087 +                return 1;
3088 +            }
3089 +        }
3090 +    }
3091 +
3092 +    return 0;
3093 +}
3094 +/* }}} */
3095 +
3096 +#if NONBLOCKING_LOCK_AVAILABLE
3097 +/* {{{ apc_cache_write_lock */
3098 +zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC)
3099 +{
3100 +    return apc_lck_nb_lock(cache->header->wrlock);
3101 +}
3102 +/* }}} */
3103 +
3104 +/* {{{ apc_cache_write_unlock */
3105 +void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC)
3106 +{
3107 +    apc_lck_unlock(cache->header->wrlock);
3108 +}
3109 +/* }}} */
3110 +#endif
3111 +
3112 +/*
3113 + * Local variables:
3114 + * tab-width: 4
3115 + * c-basic-offset: 4
3116 + * End:
3117 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
3118 + * vim<600: expandtab sw=4 ts=4 sts=4
3119 + */
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
3123 @@ -0,0 +1,371 @@
3124 +/*
3125 +  +----------------------------------------------------------------------+
3126 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
3141 +
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.
3147 +
3148 +   All other licensing and usage conditions are those of the PHP Group.
3149 +
3150 + */
3151 +
3152 +/* $Id: apc_cache.h 324329 2012-03-18 15:29:37Z mike $ */
3153 +
3154 +#ifndef APC_CACHE_H
3155 +#define APC_CACHE_H
3156 +
3157 +/*
3158 + * This module defines the shared memory file cache. Basically all of the
3159 + * logic for storing and retrieving cache entries lives here.
3160 + */
3161 +
3162 +#include "apc.h"
3163 +#include "apc_compile.h"
3164 +#include "apc_lock.h"
3165 +#include "apc_pool.h"
3166 +#include "apc_main.h"
3167 +#include "TSRM.h"
3168 +
3169 +#define APC_CACHE_ENTRY_FILE   1
3170 +#define APC_CACHE_ENTRY_USER   2
3171 +
3172 +#define APC_CACHE_KEY_FILE     1
3173 +#define APC_CACHE_KEY_USER     2
3174 +#define APC_CACHE_KEY_FPFILE   3
3175 +
3176 +#ifdef PHP_WIN32
3177 +typedef unsigned __int64 apc_ino_t;
3178 +typedef unsigned __int64 apc_dev_t;
3179 +#else
3180 +typedef ino_t apc_ino_t;
3181 +typedef dev_t apc_dev_t;
3182 +#endif
3183 +
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); }
3189 +
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); }
3196 +#else
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);}
3202 +#endif
3203 +
3204 +#define CACHE_FAST_INC(cache, obj) { obj++; }
3205 +#define CACHE_FAST_DEC(cache, obj) { obj--; }
3206 +/* }}} */
3207 +
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 */
3211 +
3212 +typedef union _apc_cache_key_data_t {
3213 +    struct {
3214 +        apc_dev_t device;             /* the filesystem device */
3215 +        apc_ino_t inode;              /* the filesystem inode */
3216 +    } file;
3217 +    struct {
3218 +        const char *identifier;
3219 +        int identifier_len;
3220 +    } user;
3221 +    struct {
3222 +        const char *fullpath;
3223 +        int fullpath_len;
3224 +    } fpfile;
3225 +} apc_cache_key_data_t;
3226 +
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 */
3234 +};
3235 +
3236 +
3237 +typedef struct apc_keyid_t apc_keyid_t;
3238 +
3239 +struct apc_keyid_t {
3240 +    unsigned int h;
3241 +    unsigned int keylen;
3242 +    time_t mtime;
3243 +#ifdef ZTS
3244 +    THREAD_T tid;
3245 +#else
3246 +    pid_t pid;
3247 +#endif
3248 +};
3249 +/* }}} */
3250 +
3251 +/* {{{ struct definition: apc_cache_entry_t */
3252 +typedef union _apc_cache_entry_value_t {
3253 +    struct {
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 */
3259 +    } file;
3260 +    struct {
3261 +        char *info;
3262 +        int info_len;
3263 +        zval *val;
3264 +        unsigned int ttl;
3265 +    } user;
3266 +} apc_cache_entry_value_t;
3267 +
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;
3272 +    int ref_count;
3273 +    size_t mem_size;
3274 +    apc_pool *pool;
3275 +};
3276 +/* }}} */
3277 +
3278 +/*
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.
3283 + *
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.
3287 + *
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).
3291 + *
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.
3295 + */
3296 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC);
3297 +
3298 +/*
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
3301 + * when they exit.
3302 + */
3303 +extern void apc_cache_destroy(T cache TSRMLS_DC);
3304 +
3305 +/*
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.
3308 + */
3309 +extern void apc_cache_clear(T cache TSRMLS_DC);
3310 +
3311 +/*
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).
3318 + *
3319 + * key is the value created by apc_cache_make_file_key for file keys.
3320 + *
3321 + * value is a cache entry returned by apc_cache_make_entry (see below).
3322 + */
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);
3325 +
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);
3328 +
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);
3331 +
3332 +/*
3333 + * apc_cache_find searches for a cache entry by filename, and returns a
3334 + * pointer to the entry if found, NULL otherwise.
3335 + *
3336 + * key is a value created by apc_cache_make_file_key for file keys.
3337 + */
3338 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t TSRMLS_DC);
3339 +
3340 +/*
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.
3343 + *
3344 + */
3345 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
3346 +
3347 +/*
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.
3352 + *
3353 + */
3354 +extern apc_cache_entry_t* apc_cache_user_exists(T cache, char* strkey, int keylen, time_t t TSRMLS_DC);
3355 +
3356 +/*
3357 + * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it.
3358 + */
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);
3361 +
3362 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
3363 + * zval from it.
3364 + *
3365 + */
3366 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC);
3367 +
3368 +/*
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.
3374 + *
3375 + * entry is the cache entry whose ref count you want to decrement.
3376 + */
3377 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry TSRMLS_DC);
3378 +
3379 +/*
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
3383 + * directory.
3384 + *
3385 + * key points to caller-allocated storage (must not be null).
3386 + *
3387 + * filename is the path to the source file.
3388 + *
3389 + * include_path is a colon-separated list of directories to search.
3390 + *
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.
3394 + */
3395 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
3396 +                                   const char* filename,
3397 +                                   const char* include_path,
3398 +                                   time_t t
3399 +                                   TSRMLS_DC);
3400 +
3401 +/*
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.
3404 + */
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
3410 +                                                    TSRMLS_DC);
3411 +
3412 +
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);
3414 +
3415 +/*
3416 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
3417 + * and the zval to be stored.
3418 + */
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);
3420 +
3421 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
3422 +
3423 +/* {{{ struct definition: slot_t */
3424 +typedef struct slot_t slot_t;
3425 +struct 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 */
3433 +};
3434 +/* }}} */
3435 +
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) */
3452 +};
3453 +/* }}} */
3454 +
3455 +typedef void (*apc_expunge_cb_t)(T cache, size_t n TSRMLS_DC); 
3456 +
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 */
3467 +};
3468 +/* }}} */
3469 +
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);
3476 +
3477 +/* used by apc_rfc1867 to update data in-place - not to be used elsewhere */
3478 +
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);
3482 +
3483 +
3484 +#undef T
3485 +#endif
3486 +
3487 +/*
3488 + * Local variables:
3489 + * tab-width: 4
3490 + * c-basic-offset: 4
3491 + * End:
3492 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
3493 + * vim<600: expandtab sw=4 ts=4 sts=4
3494 + */
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
3498 @@ -0,0 +1,2164 @@
3499 +/*
3500 +  +----------------------------------------------------------------------+
3501 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
3518 +
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.
3524 +
3525 +   All other licensing and usage conditions are those of the PHP Group.
3526 +
3527 + */
3528 +
3529 +/* $Id: apc_compile.c 326703 2012-07-19 17:06:12Z rasmus $ */
3530 +
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"
3538 +
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);
3542 +
3543 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
3544 +
3545 +#define CHECK(p) { if ((p) == NULL) return NULL; }
3546 +
3547 +/* {{{ internal function declarations */
3548 +
3549 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC);
3550 +
3551 +/*
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.
3555 + */
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);
3560 +#endif
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);
3572 +
3573 +/*
3574 + * The "fixup" functions need for ZEND_ENGINE_2
3575 + */
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
3580 + */
3581 +#define my_fixup_function_for_execution my_fixup_function
3582 +
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
3586 +#endif
3587 +
3588 +/*
3589 + * These functions return "1" if the member/function is
3590 + * defined/overridden in the 'current' class and not inherited.
3591 + */
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);
3597 +#endif
3598 +static int my_check_copy_constant(Bucket* src, va_list args);
3599 +
3600 +/* }}} */
3601 +
3602 +/* {{{ apc php serializers */
3603 +int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS) 
3604 +{
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);
3610 +    if(strbuf.c) {
3611 +        *buf = (unsigned char*)strbuf.c;
3612 +        *buf_len = strbuf.len;
3613 +        smart_str_0(&strbuf);
3614 +        return 1; 
3615 +    }
3616 +    return 0;
3617 +}
3618 +
3619 +int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS) 
3620 +{
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;
3629 +        return 0;
3630 +    }
3631 +    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
3632 +    return 1;
3633 +}
3634 +/* }}} */
3635 +
3636 +/* {{{ check_op_array_integrity */
3637 +#if 0
3638 +static void check_op_array_integrity(zend_op_array* src)
3639 +{
3640 +    int i, j;
3641 +
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!  */
3645 +
3646 +    assert(src->refcount != NULL);
3647 +    assert(src->opcodes != NULL);
3648 +    assert(src->last > 0);
3649 +
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);
3658 +
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);
3672 +            }
3673 +        }
3674 +    }
3675 +}
3676 +#endif
3677 +/* }}} */
3678 +
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)
3681 +{
3682 +    apc_pool* pool = ctxt->pool;
3683 +
3684 +    assert(src != NULL);
3685 +
3686 +    if (!dst) {
3687 +        CHECK(dst = (zend_function*) apc_pool_alloc(pool, sizeof(src[0])));
3688 +    }
3689 +
3690 +    /* We only need to do a bitwise copy */
3691 +    memcpy(dst, src, sizeof(src[0]));
3692 +
3693 +    return dst;
3694 +}
3695 +/* }}} */
3696 +
3697 +/* {{{ my_copy_zval_ptr */
3698 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_context_t* ctxt TSRMLS_DC)
3699 +{
3700 +    zval* dst_new;
3701 +    apc_pool* pool = ctxt->pool;
3702 +    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
3703 +
3704 +    assert(src != NULL);
3705 +
3706 +    if (!dst) {
3707 +        CHECK(dst = (zval**) apc_pool_alloc(pool, sizeof(zval*)));
3708 +    }
3709 +
3710 +    if(usegc) {
3711 +        ALLOC_ZVAL(dst[0]);
3712 +        CHECK(dst[0]);
3713 +    } else {
3714 +        CHECK((dst[0] = (zval*) apc_pool_alloc(pool, sizeof(zval))));
3715 +    }
3716 +
3717 +    CHECK((dst_new = my_copy_zval(*dst, *src, ctxt TSRMLS_CC)));
3718 +
3719 +    if(dst_new != *dst) {
3720 +        if(usegc) {
3721 +            FREE_ZVAL(dst[0]);
3722 +        }
3723 +        *dst = dst_new;
3724 +    }
3725 +
3726 +    return dst;
3727 +}
3728 +/* }}} */
3729 +
3730 +/* {{{ my_serialize_object */
3731 +static zval* my_serialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3732 +{
3733 +    smart_str buf = {0};
3734 +    apc_pool* pool = ctxt->pool;
3735 +    apc_serialize_t serialize = APC_SERIALIZER_NAME(php);
3736 +    void *config = NULL;
3737 +
3738 +    if(APCG(serializer)) { /* TODO: move to ctxt */
3739 +        serialize = APCG(serializer)->serialize;
3740 +        config = APCG(serializer)->config;
3741 +    }
3742 +
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));
3747 +    }
3748 +
3749 +    if(buf.c) smart_str_free(&buf);
3750 +
3751 +    return dst;
3752 +}
3753 +/* }}} */
3754 +
3755 +/* {{{ my_unserialize_object */
3756 +static zval* my_unserialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3757 +{
3758 +    apc_unserialize_t unserialize = APC_UNSERIALIZER_NAME(php);
3759 +    unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
3760 +    void *config = NULL;
3761 +
3762 +    if(APCG(serializer)) { /* TODO: move to ctxt */
3763 +        unserialize = APCG(serializer)->unserialize;
3764 +        config = APCG(serializer)->config;
3765 +    }
3766 +
3767 +    if(unserialize(&dst, p, Z_STRLEN_P(src), config TSRMLS_CC)) {
3768 +        return dst;
3769 +    } else {
3770 +        zval_dtor(dst);
3771 +        dst->type = IS_NULL;
3772 +    }
3773 +    return dst;
3774 +}
3775 +/* }}} */
3776 +
3777 +static char *apc_string_pmemcpy(char *str, size_t len, apc_pool* pool TSRMLS_DC)
3778 +{      
3779 +#ifdef ZEND_ENGINE_2_4
3780 +#ifndef ZTS
3781 +    if (pool->type != APC_UNPOOL) {
3782 +        char * ret = (char*)apc_new_interned_string((const char*)str, len TSRMLS_CC);
3783 +        if (ret) {
3784 +            return ret;
3785 +        }
3786 +    }
3787 +#endif
3788 +#endif
3789 +    return apc_pmemcpy(str, len, pool TSRMLS_CC);
3790 +}
3791 +
3792 +/* {{{ my_copy_zval */
3793 +static APC_HOTSPOT zval* my_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
3794 +{
3795 +    zval **tmp;
3796 +    apc_pool* pool = ctxt->pool;
3797 +
3798 +    assert(dst != NULL);
3799 +    assert(src != NULL);
3800 +
3801 +    memcpy(dst, src, sizeof(src[0]));
3802 +
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);
3807 +            }
3808 +            Z_ADDREF_PP(tmp);
3809 +            return *tmp;
3810 +        }
3811 +
3812 +        zend_hash_index_update(&APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
3813 +    }
3814 +
3815 +
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);
3821 +    } else {
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));
3825 +    }
3826 +
3827 +    switch (src->type & IS_CONSTANT_TYPE_MASK) {
3828 +    case IS_RESOURCE:
3829 +    case IS_BOOL:
3830 +    case IS_LONG:
3831 +    case IS_DOUBLE:
3832 +    case IS_NULL:
3833 +        break;
3834 +
3835 +    case IS_CONSTANT:
3836 +    case IS_STRING:
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,
3840 +                                                   pool TSRMLS_CC));
3841 +        }
3842 +        break;
3843 +
3844 +    case IS_ARRAY:
3845 +    case IS_CONSTANT_ARRAY:
3846 +        if(APCG(serializer) == NULL ||
3847 +            ctxt->copy == APC_COPY_IN_OPCODE || ctxt->copy == APC_COPY_OUT_OPCODE) {
3848 +
3849 +            CHECK(dst->value.ht =
3850 +                my_copy_hashtable(NULL,
3851 +                                  src->value.ht,
3852 +                                  (ht_copy_fun_t) my_copy_zval_ptr,
3853 +                                  1,
3854 +                                  ctxt));
3855 +            break;
3856 +        } else {
3857 +            /* fall through to object case */
3858 +        }
3859 +
3860 +    case IS_OBJECT:
3861 +    
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);
3867 +        }
3868 +        break;
3869 +
3870 +    default:
3871 +        assert(0);
3872 +    }
3873 +
3874 +    return dst;
3875 +}
3876 +/* }}} */
3877 +
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)
3881 +{
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);
3887 +}
3888 +/* }}} */
3889 +
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)
3892 +{
3893 +    assert(dst != NULL);
3894 +    assert(src != NULL);
3895 +
3896 +    memcpy(dst, src, sizeof(src[0]));
3897 +
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);
3901 +
3902 +    return dst;
3903 +}
3904 +/* }}} */
3905 +#else
3906 +/* {{{ my_copy_znode */
3907 +static znode* my_copy_znode(znode* dst, znode* src, apc_context_t* ctxt TSRMLS_DC)
3908 +{
3909 +    assert(dst != NULL);
3910 +    assert(src != NULL);
3911 +
3912 +    memcpy(dst, src, sizeof(src[0]));
3913 +
3914 +#ifdef IS_CV
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);
3920 +#else
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);
3925 +#endif
3926 +
3927 +    if (src->op_type == IS_CONST) {
3928 +        if(!my_copy_zval(&dst->u.constant, &src->u.constant, ctxt TSRMLS_CC)) {
3929 +            return NULL;
3930 +        }
3931 +    }
3932 +
3933 +    return dst;
3934 +}
3935 +/* }}} */
3936 +
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)
3939 +{
3940 +    assert(dst != NULL);
3941 +    assert(src != NULL);
3942 +
3943 +    memcpy(dst, src, sizeof(src[0]));
3944 +
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));
3948 +
3949 +    return dst;
3950 +}
3951 +/* }}} */
3952 +#endif
3953 +
3954 +/* {{{ my_copy_function */
3955 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC)
3956 +{
3957 +    assert(src != NULL);
3958 +
3959 +    CHECK(dst = my_bitwise_copy_function(dst, src, ctxt TSRMLS_CC));
3960 +
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;
3966 +        break;
3967 +
3968 +    case ZEND_USER_FUNCTION:
3969 +    case ZEND_EVAL_CODE:
3970 +        CHECK(apc_copy_op_array(&dst->op_array,
3971 +                                &src->op_array,
3972 +                                ctxt TSRMLS_CC));
3973 +        break;
3974 +
3975 +    default:
3976 +        assert(0);
3977 +    }
3978 +    /*
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.
3982 +     */
3983 +
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).
3987 +     */
3988 +    dst->common.prototype = NULL;
3989 +
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
3993 +     */
3994 +    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
3995 +
3996 +
3997 +    return dst;
3998 +}
3999 +/* }}} */
4000 +
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)
4003 +{
4004 +    assert(src != NULL);
4005 +
4006 +    if (!dst) {
4007 +        CHECK(dst = (zend_function_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0])));
4008 +    }
4009 +
4010 +    /* Start with a bitwise copy */
4011 +    memcpy(dst, src, sizeof(src[0]));
4012 +
4013 +    dst->fname = NULL;
4014 +    dst->arg_info = NULL;
4015 +
4016 +    if (src->fname) {
4017 +        CHECK((dst->fname = apc_pstrdup(src->fname, ctxt->pool TSRMLS_CC)));
4018 +    }
4019 +
4020 +    if (src->arg_info) {
4021 +        CHECK((dst->arg_info = my_copy_arg_info_array(NULL,
4022 +                                                src->arg_info,
4023 +                                                src->num_args,
4024 +                                                ctxt TSRMLS_CC)));
4025 +    }
4026 +
4027 +    return dst;
4028 +}
4029 +/* }}} */
4030 +
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)
4033 +{
4034 +    apc_pool* pool = ctxt->pool;
4035 +
4036 +    assert(src != NULL);
4037 +
4038 +    if (!dst) {
4039 +        CHECK(dst = (zend_property_info*) apc_pool_alloc(pool, sizeof(*src)));
4040 +    }
4041 +
4042 +    /* Start with a bitwise copy */
4043 +    memcpy(dst, src, sizeof(*src));
4044 +
4045 +    dst->name = NULL;
4046 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
4047 +    dst->doc_comment = NULL;
4048 +#endif
4049 +
4050 +    if (src->name) {
4051 +        /* private members are stored inside property_info as a mangled
4052 +         * string of the form:
4053 +         *      \0<classname>\0<membername>\0
4054 +         */
4055 +        CHECK((dst->name = apc_string_pmemcpy(src->name, src->name_length+1, pool TSRMLS_CC)));
4056 +    }
4057 +
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)));
4061 +    }
4062 +#endif
4063 +
4064 +    return dst;
4065 +}
4066 +/* }}} */
4067 +
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)
4070 +{
4071 +    assert(src != NULL);
4072 +
4073 +    if (!dst) {
4074 +        CHECK(dst = (zend_property_info*) apc_pool_alloc(ctxt->pool, sizeof(*src)));
4075 +    }
4076 +
4077 +    /* We need only a shallow copy */
4078 +    memcpy(dst, src, sizeof(*src));
4079 +
4080 +    return dst;
4081 +}
4082 +/* }}} */
4083 +
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)
4086 +{
4087 +    uint i = 0;
4088 +
4089 +
4090 +    if (!dst) {
4091 +        CHECK(dst = (zend_arg_info*) apc_pool_alloc(ctxt->pool, (sizeof(*src) * num_args)));
4092 +    }
4093 +
4094 +    /* Start with a bitwise copy */
4095 +    memcpy(dst, src, sizeof(*src)*num_args);
4096 +
4097 +    for(i=0; i < num_args; i++) {
4098 +        CHECK((my_copy_arg_info( &dst[i], &src[i], ctxt TSRMLS_CC)));
4099 +    }
4100 +
4101 +    return dst;
4102 +}
4103 +/* }}} */
4104 +
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)
4107 +{
4108 +    apc_pool* pool = ctxt->pool;
4109 +
4110 +    assert(src != NULL);
4111 +
4112 +    if (!dst) {
4113 +        CHECK(dst = (zend_arg_info*) apc_pool_alloc(pool, sizeof(*src)));
4114 +    }
4115 +
4116 +    /* Start with a bitwise copy */
4117 +    memcpy(dst, src, sizeof(*src));
4118 +
4119 +    dst->name = NULL;
4120 +    dst->class_name = NULL;
4121 +
4122 +    if (src->name) {
4123 +        CHECK((dst->name = apc_string_pmemcpy((char *) src->name, src->name_len+1, pool TSRMLS_CC)));
4124 +    }
4125 +
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)));
4128 +    }
4129 +
4130 +    return dst;
4131 +}
4132 +/* }}} */
4133 +
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)
4136 +{
4137 +    return my_copy_class_entry(dst, src, ctxt TSRMLS_CC);
4138 +}
4139 +
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)
4142 +{
4143 +    int i = 0;
4144 +    apc_pool* pool = ctxt->pool;
4145 +
4146 +    assert(src != NULL);
4147 +
4148 +    if (!dst) {
4149 +        CHECK(dst = (zend_class_entry*) apc_pool_alloc(pool, sizeof(*src)));
4150 +    }
4151 +
4152 +    /* Start with a bitwise copy */
4153 +    memcpy(dst, src, sizeof(*src));
4154 +
4155 +    dst->name = NULL;
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));
4161 +
4162 +    if (src->name) {
4163 +        CHECK((dst->name = apc_pstrdup(src->name, pool TSRMLS_CC)));
4164 +    }
4165 +
4166 +    if(!(my_copy_hashtable_ex(&dst->function_table,
4167 +                            &src->function_table TSRMLS_CC,
4168 +                            (ht_copy_fun_t) my_copy_function,
4169 +                            0,
4170 +                            ctxt,
4171 +                            (ht_check_copy_fun_t) my_check_copy_function,
4172 +                            src))) {
4173 +        return NULL;
4174 +    }
4175 +
4176 +    /* the interfaces are populated at runtime using ADD_INTERFACE */
4177 +    dst->interfaces = NULL; 
4178 +
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])
4184 +        {
4185 +            dst->num_interfaces = i;
4186 +            break;
4187 +        }
4188 +    }
4189 +
4190 +    /* these will either be set inside my_fixup_hashtable or 
4191 +     * they will be copied out from parent inside zend_do_inheritance 
4192 +     */
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;
4204 +#endif
4205 +#ifdef ZEND_ENGINE_2_3
4206 +       dst->__callstatic = NULL;
4207 +#endif
4208 +
4209 +    /* unset function proxies */
4210 +    dst->serialize_func = NULL;
4211 +    dst->unserialize_func = NULL;
4212 +
4213 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
4214 +
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);
4222 +            } else {
4223 +                dst->default_properties_table[i] = NULL;
4224 +            }
4225 +        }
4226 +    } else {
4227 +        dst->default_properties_table = NULL;
4228 +    }
4229 +#else
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,
4234 +                            1,
4235 +                            ctxt,
4236 +                            (ht_check_copy_fun_t) my_check_copy_default_property,
4237 +                            src)));
4238 +#endif
4239 +
4240 +    CHECK((my_copy_hashtable_ex(&dst->properties_info,
4241 +                            &src->properties_info TSRMLS_CC,
4242 +                            (ht_copy_fun_t) my_copy_property_info,
4243 +                            0,
4244 +                            ctxt,
4245 +                            (ht_check_copy_fun_t) my_check_copy_property_info,
4246 +                            src)));
4247 +
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);
4251 +#endif
4252 +
4253 +#ifdef ZEND_ENGINE_2_4
4254 +    dst->default_static_members_count = src->default_static_members_count;
4255 +
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);
4261 +            } else {
4262 +                dst->default_static_members_table[i] = NULL;
4263 +            }
4264 +        }
4265 +    } else {
4266 +        dst->default_static_members_table = NULL;
4267 +    }
4268 +    dst->static_members_table = dst->default_static_members_table;
4269 +#else
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,
4275 +                            1,
4276 +                            ctxt,
4277 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
4278 +                            src,
4279 +                            &src->default_static_members));
4280 +
4281 +    if(src->static_members != &src->default_static_members)
4282 +    {
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,
4286 +                            1,
4287 +                            ctxt,
4288 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
4289 +                            src,
4290 +                            src->static_members)));
4291 +    }
4292 +    else
4293 +    {
4294 +        dst->static_members = &dst->default_static_members;
4295 +    }
4296 +#endif
4297 +
4298 +    CHECK((my_copy_hashtable_ex(&dst->constants_table,
4299 +                            &src->constants_table TSRMLS_CC,
4300 +                            (ht_copy_fun_t) my_copy_zval_ptr,
4301 +                            1,
4302 +                            ctxt,
4303 +                            (ht_check_copy_fun_t) my_check_copy_constant,
4304 +                            src)));
4305 +
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));
4309 +    }
4310 +
4311 +    if (src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)) {
4312 +        int n;
4313 +
4314 +        for (n = 0; src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)[n].fname != NULL; n++) {}
4315 +
4316 +        CHECK((ZEND_CE_BUILTIN_FUNCTIONS(dst) =
4317 +                (zend_function_entry*) apc_pool_alloc(pool, ((n + 1) * sizeof(zend_function_entry)))));
4318 +
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],
4322 +                                   ctxt TSRMLS_CC));
4323 +        }
4324 +        *(char**)&(ZEND_CE_BUILTIN_FUNCTIONS(dst)[n].fname) = NULL;
4325 +    }
4326 +
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)));
4329 +    }
4330 +
4331 +    return dst;
4332 +}
4333 +/* }}} */
4334 +
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,
4339 +                                    int holds_ptrs,
4340 +                                    apc_context_t* ctxt,
4341 +                                    ht_check_copy_fun_t check_fn,
4342 +                                    ...)
4343 +{
4344 +    Bucket* curr = NULL;
4345 +    Bucket* prev = NULL;
4346 +    Bucket* newp = NULL;
4347 +    int first = 1;
4348 +    apc_pool* pool = ctxt->pool;
4349 +
4350 +    assert(src != NULL);
4351 +
4352 +    if (!dst) {
4353 +        CHECK(dst = (HashTable*) apc_pool_alloc(pool, sizeof(src[0])));
4354 +    }
4355 +
4356 +    memcpy(dst, src, sizeof(src[0]));
4357 +
4358 +    /* allocate buckets for the new hashtable */
4359 +    CHECK((dst->arBuckets = apc_pool_alloc(pool, (dst->nTableSize * sizeof(Bucket*)))));
4360 +
4361 +    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
4362 +    dst->pInternalPointer = NULL;
4363 +    dst->pListHead = NULL;
4364 +
4365 +    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
4366 +        int n = curr->h % dst->nTableSize;
4367 +
4368 +        if(check_fn) {
4369 +            va_list args;
4370 +            va_start(args, check_fn);
4371 +
4372 +            /* Call the check_fn to see if the current bucket
4373 +             * needs to be copied out
4374 +             */
4375 +            if(!check_fn(curr, args)) {
4376 +                dst->nNumOfElements--;
4377 +                va_end(args);
4378 +                continue;
4379 +            }
4380 +
4381 +            va_end(args);
4382 +        }
4383 +
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)));
4390 +#ifndef ZTS
4391 +        } else if (pool->type != APC_UNPOOL) {
4392 +            char *arKey;
4393 +
4394 +            CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC)));
4395 +            arKey = apc_new_interned_string(curr->arKey, curr->nKeyLength TSRMLS_CC);
4396 +            if (!arKey) {
4397 +                CHECK((newp->arKey = (char*) apc_pmemcpy(curr->arKey, curr->nKeyLength, pool TSRMLS_CC)));
4398 +            } else {
4399 +                newp->arKey = arKey;
4400 +            }
4401 +#endif
4402 +        } else {
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)));
4405 +        }        
4406 +#else
4407 +        CHECK((newp = (Bucket*) apc_pmemcpy(curr,
4408 +                                  (sizeof(Bucket) + curr->nKeyLength - 1),
4409 +                                  pool TSRMLS_CC)));
4410 +#endif
4411 +
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;
4417 +        }
4418 +        else {
4419 +            newp->pNext = newp->pLast = NULL;
4420 +        }
4421 +
4422 +        dst->arBuckets[n] = newp;
4423 +
4424 +        /* copy the bucket data using our 'copy_fn' callback function */
4425 +        CHECK((newp->pData = copy_fn(NULL, curr->pData, ctxt TSRMLS_CC)));
4426 +
4427 +        if (holds_ptrs) {
4428 +            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
4429 +        }
4430 +        else {
4431 +            newp->pDataPtr = NULL;
4432 +        }
4433 +
4434 +        /* insert 'newp' into the table-thread linked list */
4435 +        newp->pListLast = prev;
4436 +        newp->pListNext = NULL;
4437 +
4438 +        if (prev) {
4439 +            prev->pListNext = newp;
4440 +        }
4441 +
4442 +        if (first) {
4443 +            dst->pListHead = newp;
4444 +            first = 0;
4445 +        }
4446 +
4447 +        prev = newp;
4448 +    }
4449 +
4450 +    dst->pListTail = newp;
4451 +
4452 +    zend_hash_internal_pointer_reset(dst);
4453 +
4454 +    return dst;
4455 +}
4456 +/* }}} */
4457 +
4458 +/* {{{ my_copy_static_variables */
4459 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
4460 +{
4461 +    if (src->static_variables == NULL) {
4462 +        return NULL;
4463 +    }
4464 +
4465 +    return my_copy_hashtable(NULL,
4466 +                             src->static_variables,
4467 +                             (ht_copy_fun_t) my_copy_zval_ptr,
4468 +                             1,
4469 +                             ctxt);
4470 +}
4471 +/* }}} */
4472 +
4473 +/* {{{ apc_copy_zval */
4474 +zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC)
4475 +{
4476 +    apc_pool* pool = ctxt->pool;
4477 +    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
4478 +
4479 +    assert(src != NULL);
4480 +
4481 +    if (!dst) {
4482 +        if(usegc) {
4483 +            ALLOC_ZVAL(dst);
4484 +            CHECK(dst);
4485 +        } else {
4486 +            CHECK(dst = (zval*) apc_pool_alloc(pool, sizeof(zval)));
4487 +        }
4488 +    }
4489 +
4490 +    CHECK(dst = my_copy_zval(dst, src, ctxt TSRMLS_CC));
4491 +    return dst;
4492 +}
4493 +/* }}} */
4494 +
4495 +/* {{{ apc_fixup_op_array_jumps */
4496 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
4497 +{
4498 +    uint i;
4499 +
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
4505 +            case ZEND_GOTO:
4506 +#endif
4507 +            case ZEND_JMP:
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);
4511 +#else
4512 +                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
4513 +#endif
4514 +                break;
4515 +            case ZEND_JMPZ:
4516 +            case ZEND_JMPNZ:
4517 +            case ZEND_JMPZ_EX:
4518 +            case ZEND_JMPNZ_EX:
4519 +#ifdef ZEND_ENGINE_2_3
4520 +            case ZEND_JMP_SET:
4521 +#endif
4522 +#ifdef ZEND_ENGINE_2_4
4523 +            case ZEND_JMP_SET_VAR:
4524 +#endif
4525 +#ifdef ZEND_ENGINE_2_4
4526 +                zo->op2.jmp_addr = dst->opcodes + (zo->op2.jmp_addr - src->opcodes);
4527 +#else
4528 +                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
4529 +#endif
4530 +                break;
4531 +            default:
4532 +                break;
4533 +        }
4534 +    }
4535 +}
4536 +/* }}} */
4537 +
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)
4540 +{
4541 +    int i;
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;
4547 +
4548 +    assert(src != NULL);
4549 +
4550 +    if (!dst) {
4551 +        CHECK(dst = (zend_op_array*) apc_pool_alloc(pool, sizeof(src[0])));
4552 +    }
4553 +
4554 +    if(APCG(apc_optimize_function)) {
4555 +        APCG(apc_optimize_function)(src TSRMLS_CC);
4556 +    }
4557 +
4558 +    /* start with a bitwise copy of the array */
4559 +    memcpy(dst, src, sizeof(src[0]));
4560 +
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
4571 +    dst->vars = NULL;
4572 +#endif
4573 +
4574 +    /* copy the arg types array (if set) */
4575 +    if (src->arg_info) {
4576 +        CHECK(dst->arg_info = my_copy_arg_info_array(NULL,
4577 +                                                src->arg_info,
4578 +                                                src->num_args,
4579 +                                                ctxt TSRMLS_CC));
4580 +    }
4581 +
4582 +    if (src->function_name) {
4583 +        CHECK(dst->function_name = apc_pstrdup(src->function_name, pool TSRMLS_CC));
4584 +    }
4585 +    if (src->filename) {
4586 +        CHECK(dst->filename = apc_pstrdup(src->filename, pool TSRMLS_CC));
4587 +    }
4588 +
4589 +    CHECK(dst->refcount = apc_pmemcpy(src->refcount,
4590 +                                      sizeof(src->refcount[0]),
4591 +                                      pool TSRMLS_CC));
4592 +
4593 +#ifdef ZEND_ENGINE_2_4
4594 +    if (src->literals) {
4595 +        zend_literal *p, *q, *end;
4596 +
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;
4600 +        while (p < end) {
4601 +            *p = *q;
4602 +            my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
4603 +            p++;
4604 +            q++;
4605 +        }
4606 +    }
4607 +#endif
4608 +
4609 +    /* deep-copy the opcodes */
4610 +    CHECK(dst->opcodes = (zend_op*) apc_pool_alloc(pool, (sizeof(zend_op) * src->last)));
4611 +
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)); */
4618 +    }
4619 +
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
4625 +            case ZEND_GOTO:
4626 +#endif
4627 +            case ZEND_JMP:
4628 +            case ZEND_JMPZ:
4629 +            case ZEND_JMPNZ:
4630 +            case ZEND_JMPZ_EX:
4631 +            case ZEND_JMPNZ_EX:
4632 +#ifdef ZEND_ENGINE_2_3
4633 +            case ZEND_JMP_SET:
4634 +#endif
4635 +#ifdef ZEND_ENGINE_2_4
4636 +            case ZEND_JMP_SET_VAR:
4637 +#endif
4638 +                if(flags != NULL) {
4639 +                    flags->has_jumps = 1;
4640 +                }
4641 +                break;
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)
4650 +                {
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 */
4660 +#else
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 */
4669 +#endif
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)
4682 +                                            TSRMLS_CC))
4683 +#else
4684 +                            else if(zend_is_auto_global(
4685 +                                            varname->u.constant.value.str.val,
4686 +                                            varname->u.constant.value.str.len
4687 +                                            TSRMLS_CC))
4688 +#endif
4689 +                            {
4690 +                                flags->unknown_global = 1;
4691 +                            }
4692 +#ifdef ZEND_ENGINE_2_4
4693 +                        } else SET_IF_AUTOGLOBAL(GLOBALS);
4694 +#else
4695 +                        }
4696 +#endif
4697 +                    }
4698 +                }
4699 +                break;
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) {
4704 +#else
4705 +                if(zo->op2.op_type == IS_CONST &&
4706 +                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
4707 +#endif
4708 +                    if(flags != NULL) {
4709 +                        flags->deep_copy = 1;
4710 +                    }
4711 +                }
4712 +                break;
4713 +            default:
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)) {
4719 +#else
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)) {
4724 +#endif
4725 +                    if(flags != NULL) {
4726 +                        flags->deep_copy = 1;
4727 +                    }
4728 +                }
4729 +                break;
4730 +        }
4731 +
4732 +        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, ctxt TSRMLS_CC))) {
4733 +            return NULL;
4734 +        }
4735 +
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;
4739 +        }
4740 +        if (zo->op2_type == IS_CONST) {
4741 +            dst->opcodes[i].op2.literal = src->opcodes[i].op2.literal - src->literals + dst->literals;
4742 +        }
4743 +        if (zo->result_type == IS_CONST) {
4744 +            dst->opcodes[i].result.literal = src->opcodes[i].result.literal - src->literals + dst->literals;
4745 +        }
4746 +#endif
4747 +
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) {
4758 +#else
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) {
4764 +#endif
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);
4776 +#else
4777 +                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
4778 +                            dzo->op1.u.constant.value.str.val = apc_pstrdup(fullpath, pool TSRMLS_CC);
4779 +#endif
4780 +                        }
4781 +                    }
4782 +                }
4783 +            }
4784 +            apc_php_free(fileinfo TSRMLS_CC);
4785 +        }
4786 +    }
4787 +
4788 +    if(flags == NULL || flags->has_jumps) {
4789 +        apc_fixup_op_array_jumps(dst,src);
4790 +    }
4791 +
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,
4796 +                                    pool TSRMLS_CC));
4797 +    }
4798 +
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));
4802 +    }
4803 +
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,
4807 +                                        pool TSRMLS_CC));
4808 +    }
4809 +
4810 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
4811 +    if (src->vars) {
4812 +        CHECK(dst->vars = apc_pmemcpy(src->vars,
4813 +                            sizeof(src->vars[0]) * src->last_var,
4814 +                            pool TSRMLS_CC));
4815 +
4816 +        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
4817 +
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,
4821 +                                pool TSRMLS_CC));
4822 +        }
4823 +    }
4824 +#endif
4825 +
4826 +    if (src->doc_comment) {
4827 +        CHECK(dst->doc_comment
4828 +                = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC));
4829 +    }
4830 +
4831 +    return dst;
4832 +}
4833 +/* }}} */
4834 +
4835 +
4836 +/* {{{ apc_copy_new_functions */
4837 +apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC)
4838 +{
4839 +    apc_function_t* array;
4840 +    int new_count;              /* number of new functions in table */
4841 +    int i;
4842 +    apc_pool* pool = ctxt->pool;
4843 +
4844 +    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
4845 +    assert(new_count >= 0);
4846 +
4847 +    CHECK(array =
4848 +        (apc_function_t*)
4849 +            apc_pool_alloc(pool, (sizeof(apc_function_t) * (new_count + 1))));
4850 +
4851 +    if (new_count == 0) {
4852 +        array[0].function = NULL;
4853 +        return array;
4854 +    }
4855 +
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));
4860 +    }
4861 +
4862 +    /* Add the next `new_count` functions to our array */
4863 +    for (i = 0; i < new_count; i++) {
4864 +        char* key;
4865 +        uint key_size;
4866 +        zend_function* fun;
4867 +
4868 +        zend_hash_get_current_key_ex(CG(function_table),
4869 +                                     &key,
4870 +                                     &key_size,
4871 +                                     NULL,
4872 +                                     0,
4873 +                                     NULL);
4874 +
4875 +        zend_hash_get_current_data(CG(function_table), (void**) &fun);
4876 +
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));
4881 +    }
4882 +
4883 +    array[i].function = NULL;
4884 +    return array;
4885 +}
4886 +/* }}} */
4887 +
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)
4890 +{
4891 +    apc_class_t* array;
4892 +    int new_count;              /* number of new classes in table */
4893 +    int i;
4894 +    apc_pool* pool = ctxt->pool;
4895 +
4896 +    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
4897 +    assert(new_count >= 0);
4898 +
4899 +    CHECK(array =
4900 +        (apc_class_t*)
4901 +            apc_pool_alloc(pool, (sizeof(apc_class_t) * (new_count + 1))));
4902 +
4903 +    if (new_count == 0) {
4904 +        array[0].class_entry = NULL;
4905 +        return array;
4906 +    }
4907 +
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));
4912 +    }
4913 +
4914 +    /* Add the next `new_count` classes to our array */
4915 +    for (i = 0; i < new_count; i++) {
4916 +        char* key;
4917 +        uint key_size;
4918 +        zend_class_entry* elem = NULL;
4919 +
4920 +        array[i].class_entry = NULL;
4921 +
4922 +        zend_hash_get_current_key_ex(CG(class_table),
4923 +                                     &key,
4924 +                                     &key_size,
4925 +                                     NULL,
4926 +                                     0,
4927 +                                     NULL);
4928 +
4929 +        zend_hash_get_current_data(CG(class_table), (void**) &elem);
4930 +
4931 +
4932 +        elem = *((zend_class_entry**)elem);
4933 +
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));
4937 +
4938 +        /*
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.
4944 +         */
4945 +
4946 +        if (elem->parent) {
4947 +            CHECK(array[i].parent_name = apc_pstrdup(elem->parent->name, pool TSRMLS_CC));
4948 +        }
4949 +        else {
4950 +            array[i].parent_name = NULL;
4951 +        }
4952 +
4953 +        zend_hash_move_forward(CG(class_table));
4954 +    }
4955 +
4956 +    array[i].class_entry = NULL;
4957 +    return array;
4958 +}
4959 +/* }}} */
4960 +
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)                    \
4971 +                                                      TSRMLS_CC);                               \
4972 +                        }
4973 +#else
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] == '_') {                       \
4980 +                                                                                                \
4981 +                            znode* varname = &zo->op1;                                          \
4982 +                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
4983 +                                                          varname->u.constant.value.str.len     \
4984 +                                                          TSRMLS_CC);                           \
4985 +                        }
4986 +#endif
4987 +
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) 
4990 +{
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.
4995 +     */
4996 +    int i=src->last;
4997 +    zend_op *zo;
4998 +    zend_op *dzo;
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);
5004 +
5005 +#define FETCH_AUTOGLOBAL(member) do { \
5006 +    if(flags && flags->member == 1) { \
5007 +        zend_is_auto_global(#member,\
5008 +                            (sizeof(#member) - 1)\
5009 +                            TSRMLS_CC);\
5010 +    } \
5011 +} while(0);
5012 +
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);
5023 +#endif
5024 +
5025 +    if(needcopy) {
5026 +
5027 +#ifdef ZEND_ENGINE_2_4
5028 +        if (src->literals) {
5029 +            zend_literal *p, *q, *end;
5030 +
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;
5036 +            while (p < end) {
5037 +                if (Z_TYPE(q->constant) == IS_CONSTANT_ARRAY) {
5038 +                    my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC);
5039 +                }
5040 +                p++;
5041 +                q++;
5042 +            }
5043 +        }
5044 +#endif
5045 +
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;
5051 +        while(i > 0) {
5052 +
5053 +#ifdef ZEND_ENGINE_2_4
5054 +            if(zo->op1_type == IS_CONST) {
5055 +               dzo->op1.literal = zo->op1.literal - src->literals + dst->literals;
5056 +            }
5057 +            if(zo->op2_type == IS_CONST) {
5058 +               dzo->op2.literal = zo->op2.literal - src->literals + dst->literals;
5059 +            }
5060 +            if(zo->result_type == IS_CONST) {
5061 +               dzo->result.literal = zo->result.literal - src->literals + dst->literals;
5062 +            }
5063 +#else
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))) {
5068 +
5069 +                if(!(my_copy_zend_op(dzo, zo, ctxt TSRMLS_CC))) {
5070 +                    assert(0); /* emalloc failed or a bad constant array */
5071 +                }
5072 +            }
5073 +#endif
5074 +
5075 +            switch(zo->opcode) {
5076 +#ifdef ZEND_ENGINE_2_3
5077 +                case ZEND_GOTO:
5078 +#endif
5079 +                case ZEND_JMP:
5080 +#ifdef ZEND_ENGINE_2_4
5081 +                    dzo->op1.jmp_addr = dst->opcodes +
5082 +                                            (zo->op1.jmp_addr - src->opcodes);
5083 +#else
5084 +                    dzo->op1.u.jmp_addr = dst->opcodes +
5085 +                                            (zo->op1.u.jmp_addr - src->opcodes);
5086 +#endif
5087 +                    break;
5088 +                case ZEND_JMPZ:
5089 +                case ZEND_JMPNZ:
5090 +                case ZEND_JMPZ_EX:
5091 +                case ZEND_JMPNZ_EX:
5092 +#ifdef ZEND_ENGINE_2_3
5093 +                case ZEND_JMP_SET:
5094 +#endif
5095 +#ifdef ZEND_ENGINE_2_4
5096 +                case ZEND_JMP_SET_VAR:
5097 +#endif
5098 +#ifdef ZEND_ENGINE_2_4
5099 +                    dzo->op2.jmp_addr = dst->opcodes +
5100 +                                            (zo->op2.jmp_addr - src->opcodes);
5101 +#else
5102 +                    dzo->op2.u.jmp_addr = dst->opcodes +
5103 +                                            (zo->op2.u.jmp_addr - src->opcodes);
5104 +#endif
5105 +                    break;
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)
5111 +                    {
5112 +                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
5113 +                    }
5114 +                    break;
5115 +                default:
5116 +                    break;
5117 +            }
5118 +            i--;
5119 +            zo++;
5120 +            dzo++;
5121 +        }
5122 +    } else {  /* !needcopy */
5123 +        /* The fetch is only required if auto_globals_jit=1  */
5124 +        if(do_prepare_fetch_global)
5125 +        {
5126 +            zo = src->opcodes;
5127 +            while(i > 0) {
5128 +
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
5133 +                  ) {
5134 +                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
5135 +                }
5136 +
5137 +                i--;
5138 +                zo++;
5139 +            }
5140 +        }
5141 +    }
5142 +    return 1;
5143 +}
5144 +/* }}} */
5145 +
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)
5148 +{
5149 +    if(dst == NULL) {
5150 +        dst = (zend_op_array*) emalloc(sizeof(src[0]));
5151 +    }
5152 +    memcpy(dst, src, sizeof(src[0]));
5153 +    dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC);
5154 +
5155 +    /* memory leak */
5156 +    dst->refcount = apc_pmemcpy(src->refcount,
5157 +                                      sizeof(src->refcount[0]),
5158 +                                      ctxt->pool TSRMLS_CC);
5159 +
5160 +    my_prepare_op_array_for_execution(dst,src, ctxt TSRMLS_CC);
5161 +
5162 +    return dst;
5163 +}
5164 +/* }}} */
5165 +
5166 +/* {{{ apc_copy_function_for_execution */
5167 +zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC)
5168 +{
5169 +    zend_function* dst;
5170 +
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);
5174 +    return dst;
5175 +}
5176 +/* }}} */
5177 +
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)
5180 +{
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);
5183 +}
5184 +/* }}} */
5185 +
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)
5188 +{
5189 +#ifdef ZEND_ENGINE_2_4
5190 +    int i;
5191 +#endif
5192 +    zend_class_entry* dst = (zend_class_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0]));
5193 +    memcpy(dst, src, sizeof(src[0]));
5194 +
5195 +    if(src->num_interfaces)
5196 +    {
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);
5202 +    }
5203 +    else
5204 +    {
5205 +        /* assert(dst->interfaces == NULL); */
5206 +    }
5207 +
5208 +    /* Deep-copy the class properties, because they will be modified */
5209 +
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);
5218 +            } else {
5219 +                dst->default_properties_table[i] = NULL;
5220 +            }
5221 +        }
5222 +    } else {
5223 +        dst->default_properties_table = NULL;
5224 +    }
5225 +#else
5226 +    my_copy_hashtable(&dst->default_properties,
5227 +                      &src->default_properties,
5228 +                      (ht_copy_fun_t) my_copy_zval_ptr,
5229 +                      1,
5230 +                      ctxt);
5231 +#endif
5232 +
5233 +    /* For derived classes, we must also copy the function hashtable (although
5234 +     * we can merely bitwise copy the functions it contains) */
5235 +
5236 +    my_copy_hashtable(&dst->function_table,
5237 +                      &src->function_table,
5238 +                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
5239 +                      0,
5240 +                      ctxt);
5241 +
5242 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
5243 +
5244 +    /* zend_do_inheritance merges properties_info.
5245 +     * Need only shallow copying as it doesn't hold the pointers.
5246 +     */
5247 +    my_copy_hashtable(&dst->properties_info,
5248 +                      &src->properties_info,
5249 +                      (ht_copy_fun_t) my_copy_property_info_for_execution,
5250 +                      0,
5251 +                      ctxt);
5252 +
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);
5256 +#endif
5257 +
5258 +    /* if inheritance results in a hash_del, it might result in
5259 +     * a pefree() of the pointers here. Deep copying required. 
5260 +     */
5261 +
5262 +    my_copy_hashtable(&dst->constants_table,
5263 +                      &src->constants_table,
5264 +                      (ht_copy_fun_t) my_copy_zval_ptr,
5265 +                      1,
5266 +                      ctxt);
5267 +
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);
5275 +            } else {
5276 +                dst->default_static_members_table[i] = NULL;
5277 +            }
5278 +        }
5279 +    } else {
5280 +        dst->default_static_members_table = NULL;
5281 +    }
5282 +    dst->static_members_table = dst->default_static_members_table;
5283 +#else
5284 +    my_copy_hashtable(&dst->default_static_members,
5285 +                      &src->default_static_members,
5286 +                      (ht_copy_fun_t) my_copy_zval_ptr,
5287 +                      1,
5288 +                      ctxt);
5289 +
5290 +    if(src->static_members != &(src->default_static_members))
5291 +    {
5292 +        dst->static_members = my_copy_hashtable(NULL,
5293 +                          src->static_members,
5294 +                          (ht_copy_fun_t) my_copy_zval_ptr,
5295 +                          1,
5296 +                          ctxt);
5297 +    }
5298 +    else 
5299 +    {
5300 +        dst->static_members = &(dst->default_static_members);
5301 +    }
5302 +#endif
5303 +
5304 +    return dst;
5305 +}
5306 +/* }}} */
5307 +
5308 +/* {{{ apc_free_class_entry_after_execution */
5309 +void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC)
5310 +{
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;
5315 +    }
5316 +    /* my_destroy_hashtable() does not play nice with refcounts */
5317 +
5318 +#ifdef ZEND_ENGINE_2_4
5319 +    if (src->default_static_members_table) {
5320 +       int i;
5321 +
5322 +       for (i = 0; i < src->default_static_members_count; i++) {
5323 +          zval_ptr_dtor(&src->default_static_members_table[i]);
5324 +       }
5325 +       efree(src->default_static_members_table);
5326 +       src->default_static_members_table = NULL;
5327 +    }
5328 +    src->static_members_table = NULL;
5329 +    if (src->default_properties_table) {
5330 +       int i;
5331 +
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]);
5335 +           }
5336 +       }
5337 +       efree(src->default_properties_table);
5338 +       src->default_properties_table = NULL;
5339 +    }
5340 +#else
5341 +    zend_hash_clean(&src->default_static_members);
5342 +    if(src->static_members != &(src->default_static_members))
5343 +    {
5344 +        zend_hash_destroy(src->static_members);
5345 +        apc_php_free(src->static_members TSRMLS_CC);
5346 +        src->static_members = NULL;
5347 +    }
5348 +    else
5349 +    {
5350 +        src->static_members = NULL;
5351 +    }
5352 +
5353 +    zend_hash_clean(&src->default_properties);
5354 +#endif
5355 +    zend_hash_clean(&src->constants_table);
5356 +
5357 +    /* TODO: more cleanup */
5358 +}
5359 +/* }}} */
5360 +
5361 +/* {{{ apc_file_halt_offset */
5362 +long apc_file_halt_offset(const char *filename TSRMLS_DC)
5363 +{
5364 +    zend_constant *c;
5365 +    char *name;
5366 +    int len;
5367 +    char haltoff[] = "__COMPILER_HALT_OFFSET__";
5368 +    long value = -1;
5369 +
5370 +    zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, filename, strlen(filename), 0);
5371 +    
5372 +    if (zend_hash_find(EG(zend_constants), name, len+1, (void **) &c) == SUCCESS) {
5373 +        value = Z_LVAL(c->value);
5374 +    }
5375 +    
5376 +    pefree(name, 0);
5377 +
5378 +    return value;
5379 +}
5380 +/* }}} */
5381 +
5382 +/* {{{ apc_do_halt_compiler_register */
5383 +void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC)
5384 +{
5385 +    char *name;
5386 +    char haltoff[] = "__COMPILER_HALT_OFFSET__";
5387 +    int len;
5388 +   
5389 +    if(halt_offset > 0) {
5390 +        
5391 +        zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, 
5392 +                                    filename, strlen(filename), 0);
5393 +        
5394 +        zend_register_long_constant(name, len+1, halt_offset, CONST_CS, 0 TSRMLS_CC);
5395 +
5396 +        pefree(name, 0);
5397 +    }
5398 +}
5399 +/* }}} */
5400 +
5401 +
5402 +
5403 +/* {{{ my_fixup_function */
5404 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
5405 +{
5406 +    zend_function* zf = p->pData;
5407 +
5408 +    #define SET_IF_SAME_NAME(member) \
5409 +    do { \
5410 +        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
5411 +            dst->member = zf; \
5412 +        } \
5413 +    } \
5414 +    while(0)
5415 +
5416 +    if(zf->common.scope == src)
5417 +    {
5418 +
5419 +        /* Fixing up the default functions for objects here since
5420 +         * we need to compare with the newly allocated functions
5421 +         *
5422 +         * caveat: a sub-class method can have the same name as the
5423 +         * parent's constructor and create problems.
5424 +         */
5425 +
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;
5429 +        else
5430 +        {
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);
5438 +#endif
5439 +#ifdef ZEND_ENGINE_2_3
5440 +            SET_IF_SAME_NAME(__callstatic);
5441 +#endif
5442 +        }
5443 +        zf->common.scope = dst;
5444 +    }
5445 +    else
5446 +    {
5447 +        /* no other function should reach here */
5448 +        assert(0);
5449 +    }
5450 +
5451 +    #undef SET_IF_SAME_NAME
5452 +}
5453 +/* }}} */
5454 +
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)
5458 +{
5459 +    zend_property_info* property_info = (zend_property_info*)p->pData;
5460 +
5461 +    if(property_info->ce == src)
5462 +    {
5463 +        property_info->ce = dst;
5464 +    }
5465 +    else
5466 +    {
5467 +        assert(0); /* should never happen */
5468 +    }
5469 +}
5470 +/* }}} */
5471 +#endif
5472 +
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)
5475 +{
5476 +    Bucket *p;
5477 +    uint i;
5478 +
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);
5484 +            p = p->pNext;
5485 +        }
5486 +    }
5487 +}
5488 +/* }}} */
5489 +
5490 +
5491 +/* {{{ my_check_copy_function */
5492 +static int my_check_copy_function(Bucket* p, va_list args)
5493 +{
5494 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
5495 +    zend_function* zf = (zend_function*)p->pData;
5496 +
5497 +    return (zf->common.scope == src);
5498 +}
5499 +/* }}} */
5500 +
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)
5504 +{
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;
5509 +
5510 +    if (parent &&
5511 +        zend_hash_quick_find(&parent->default_properties, p->arKey, 
5512 +            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
5513 +
5514 +        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
5515 +        {
5516 +            return 0;
5517 +        }
5518 +    }
5519 +
5520 +    /* possibly not in the parent */
5521 +    return 1;
5522 +}
5523 +/* }}} */
5524 +#endif
5525 +
5526 +/* {{{ my_check_copy_property_info */
5527 +static int my_check_copy_property_info(Bucket* p, va_list args)
5528 +{
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;
5533 +
5534 +#ifdef ZEND_ENGINE_2_2
5535 +    /* so much easier */
5536 +    return (child_info->ce == src);
5537 +#endif
5538 +
5539 +    if (parent &&
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)
5543 +        {
5544 +            return 1;
5545 +        }
5546 +        if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
5547 +            (child_info->flags & ZEND_ACC_PPP_MASK))
5548 +        {
5549 +            /* TODO: figure out whether ACC_CHANGED is more appropriate
5550 +             * here */
5551 +            return 1;
5552 +        }
5553 +        return 0;
5554 +    }
5555 +
5556 +    /* property doesn't exist in parent, copy into cached child */
5557 +    return 1;
5558 +}
5559 +/* }}} */
5560 +
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)
5564 +{
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;
5571 +
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);
5576 +
5577 +    if(!parent) {
5578 +        return 1;
5579 +    }
5580 +
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);
5584 +#else
5585 +    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
5586 +#endif
5587 +
5588 +    /* please refer do_inherit_property_access_check in zend_compile.c
5589 +     * to understand why we lookup in properties_info.
5590 +     */
5591 +    if((zend_hash_find(&parent->properties_info, member_name,
5592 +                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
5593 +        &&
5594 +        (zend_hash_find(&src->properties_info, member_name,
5595 +                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
5596 +    {
5597 +        if(ht == &(src->default_static_members))
5598 +        {
5599 +            parent_ht = &parent->default_static_members;
5600 +        }
5601 +        else
5602 +        {
5603 +            parent_ht = parent->static_members;
5604 +        }
5605 +
5606 +        if(zend_hash_quick_find(parent_ht, p->arKey,
5607 +                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
5608 +        {
5609 +            /* they point to the same zval */
5610 +            if(*parent_prop == *child_prop)
5611 +            {
5612 +                return 0;
5613 +            }
5614 +        }
5615 +    }
5616 +
5617 +    return 1;
5618 +}
5619 +/* }}} */
5620 +#endif
5621 +
5622 +/* {{{ my_check_copy_constant */
5623 +static int my_check_copy_constant(Bucket* p, va_list args)
5624 +{
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;
5629 +
5630 +    if (parent &&
5631 +        zend_hash_quick_find(&parent->constants_table, p->arKey, 
5632 +            p->nKeyLength, p->h, (void **) &parent_const)==SUCCESS) {
5633 +
5634 +        if((parent_const && child_const) && (*parent_const) == (*child_const))
5635 +        {
5636 +            return 0;
5637 +        }
5638 +    }
5639 +
5640 +    /* possibly not in the parent */
5641 +    return 1;
5642 +}
5643 +/* }}} */
5644 +
5645 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
5646 + *      register a optimizer callback function, returns the previous callback
5647 + */
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;
5652 +}
5653 +/* }}} */
5654 +
5655 +/*
5656 + * Local variables:
5657 + * tab-width: 4
5658 + * c-basic-offset: 4
5659 + * End:
5660 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
5661 + * vim<600: expandtab sw=4 ts=4 sts=4
5662 + */
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
5666 @@ -0,0 +1,152 @@
5667 +/*
5668 +  +----------------------------------------------------------------------+
5669 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
5685 +
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.
5691 +
5692 +   All other licensing and usage conditions are those of the PHP Group.
5693 +
5694 + */
5695 +
5696 +/* $Id: apc_compile.h 307185 2011-01-06 21:13:11Z gopalv $ */
5697 +
5698 +#ifndef APC_COMPILE_H
5699 +#define APC_COMPILE_H
5700 +
5701 +/*
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.
5705 + */
5706 +
5707 +#include "apc.h"
5708 +#include "apc_php.h"
5709 +#include "apc_main.h"
5710 +#include "apc_serializer.h"
5711 +
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 */
5718 +};
5719 +/* }}} */
5720 +
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 */
5728 +};
5729 +/* }}} */
5730 +
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 */
5736 +
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;
5748 +#endif
5749 +    unsigned int unknown_global : 1;
5750 +};
5751 +/* }}} */
5752 +
5753 +/*
5754 + * These are the top-level copy functions.
5755 + */
5756 +
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);
5762 +
5763 +#if 0
5764 +/*
5765 + * Deallocation functions corresponding to the copy functions above.
5766 + */
5767 +
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);
5772 +#endif
5773 +
5774 +/*
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
5778 + * structures.
5779 + */
5780 +
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);
5784 +
5785 +/*
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.
5789 + */
5790 +extern void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC);
5791 +
5792 +/*
5793 + * Optimization callback definition and registration function. 
5794 + */
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);
5797 +
5798 +/*
5799 + * To handle __COMPILER_HALT_OFFSET__
5800 + */
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);
5803 +
5804 +/*
5805 + * apc serialization functions
5806 + */
5807 +int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS);
5808 +int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS); 
5809 +#endif
5810 +
5811 +/*
5812 + * Local variables:
5813 + * tab-width: 4
5814 + * c-basic-offset: 4
5815 + * End:
5816 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
5817 + * vim<600: expandtab sw=4 ts=4 sts=4
5818 + */
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
5822 @@ -0,0 +1,70 @@
5823 +/*
5824 +  +----------------------------------------------------------------------+
5825 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
5841 +
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.
5847 +
5848 +   All other licensing and usage conditions are those of the PHP Group.
5849 +*/
5850 +
5851 +/* $Id: apc_debug.c 307048 2011-01-03 23:53:17Z kalle $ */
5852 +#include "apc.h"
5853 +#include <stdio.h>
5854 +#include "zend.h"
5855 +#include "zend_compile.h"
5856 +
5857 +#if defined(__DEBUG_APC__)
5858 +
5859 +/* keep track of vld_dump_oparray() signature */
5860 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
5861 +
5862 +#endif
5863 +
5864 +void dump(zend_op_array *op_array TSRMLS_DC)
5865 +{
5866 +#if defined(__DEBUG_APC__)
5867 +  vld_dump_f dump_op_array;
5868 +  DL_HANDLE handle = NULL;
5869 +
5870 +#ifdef PHP_WIN32
5871 +  handle = GetModuleHandle(NULL);
5872 +  
5873 +  if (!handle) {
5874 +       apc_warning("unable to fetch current module handle." TSRMLS_CC);
5875 +  }
5876 +#endif
5877 +  
5878 +  dump_op_array = (vld_dump_f) DL_FETCH_SYMBOL(handle, "vld_dump_oparray");
5879 +  
5880 +#ifdef PHP_WIN32
5881 +  DL_UNLOAD(handle);
5882 +#endif
5883 +
5884 +  if(dump_op_array) {
5885 +    dump_op_array(op_array TSRMLS_CC);
5886 +  
5887 +    return;
5888 +  }
5889 +  
5890 +  apc_warning("vld is not installed or something even worse." TSRMLS_CC);
5891 +#endif
5892 +}
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
5896 @@ -0,0 +1,29 @@
5897 +/*
5898 +  +----------------------------------------------------------------------+
5899 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
5915 +
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.
5921 +
5922 +   All other licensing and usage conditions are those of the PHP Group.
5923 +*/
5924 +
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
5929 @@ -0,0 +1,123 @@
5930 +/*
5931 +  +----------------------------------------------------------------------+
5932 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
5947 +
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.
5953 +
5954 +   All other licensing and usage conditions are those of the PHP Group.
5955 +
5956 + */
5957 +
5958 +/* $Id: apc_fcntl.c 307048 2011-01-03 23:53:17Z kalle $ */
5959 +
5960 +#include "apc.h"
5961 +
5962 +#ifdef APC_FCNTL_LOCKS
5963 +
5964 +#include "apc_fcntl.h"
5965 +#include <unistd.h>
5966 +#include <fcntl.h>
5967 +
5968 +int apc_fcntl_create(const char* pathname TSRMLS_DC)
5969 +{
5970 +    int fd;
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);
5975 +        if(fd > 0 ) {
5976 +            unlink(lock_path);
5977 +            return fd;
5978 +        } else {
5979 +            apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, lock_path);
5980 +            return -1;
5981 +        }
5982 +    }
5983 +    fd = open(pathname, O_RDWR|O_CREAT, 0666);
5984 +    if(fd > 0 ) {
5985 +        unlink(pathname);
5986 +        return fd;
5987 +    }
5988 +    apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, pathname);
5989 +    return -1;
5990 +}
5991 +
5992 +void apc_fcntl_destroy(int fd)
5993 +{
5994 +    close(fd);
5995 +}
5996 +
5997 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5998 +{
5999 +  int ret;
6000 +  struct flock lock;
6001 +
6002 +  lock.l_type = type;
6003 +  lock.l_start = offset;
6004 +  lock.l_whence = whence;
6005 +  lock.l_len = len;
6006 +  lock.l_pid = 0;
6007 +
6008 +  do { ret = fcntl(fd, cmd, &lock) ; }
6009 +  while(ret < 0 && errno == EINTR);
6010 +  return(ret);
6011 +}
6012 +
6013 +void apc_fcntl_lock(int fd TSRMLS_DC)
6014 +{
6015 +    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
6016 +        apc_error("apc_fcntl_lock failed:" TSRMLS_CC);
6017 +    }
6018 +}
6019 +
6020 +void apc_fcntl_rdlock(int fd TSRMLS_DC)
6021 +{
6022 +    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
6023 +        apc_error("apc_fcntl_rdlock failed:" TSRMLS_CC);
6024 +    }
6025 +}
6026 +
6027 +zend_bool apc_fcntl_nonblocking_lock(int fd TSRMLS_DC)
6028 +{
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);
6032 +    }
6033 +    return 1;
6034 +}
6035 +
6036 +void apc_fcntl_unlock(int fd TSRMLS_DC)
6037 +{
6038 +    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
6039 +        apc_error("apc_fcntl_unlock failed:" TSRMLS_CC);
6040 +    }
6041 +}
6042 +
6043 +#endif /* APC_FCNTL_LOCKS */
6044 +
6045 +/*
6046 + * Local variables:
6047 + * tab-width: 4
6048 + * c-basic-offset: 4
6049 + * End:
6050 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6051 + * vim<600: expandtab sw=4 ts=4 sts=4
6052 + */
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
6056 @@ -0,0 +1,50 @@
6057 +/*
6058 +  +----------------------------------------------------------------------+
6059 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
6074 +
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.
6080 +
6081 +   All other licensing and usage conditions are those of the PHP Group.
6082 +
6083 + */
6084 +
6085 +/* $Id: apc_fcntl.h 307048 2011-01-03 23:53:17Z kalle $ */
6086 +
6087 +#ifndef APC_FCNTL_H
6088 +#define APC_FCNTL_H
6089 +
6090 +
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);
6097 +#endif
6098 +
6099 +/*
6100 + * Local variables:
6101 + * tab-width: 4
6102 + * c-basic-offset: 4
6103 + * End:
6104 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6105 + * vim<600: expandtab sw=4 ts=4 sts=4
6106 + */
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
6110 @@ -0,0 +1,120 @@
6111 +/*
6112 +  +----------------------------------------------------------------------+
6113 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
6129 +
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.
6135 +
6136 +   All other licensing and usage conditions are those of the PHP Group.
6137 +
6138 + */
6139 +
6140 +/* $Id: apc_fcntl_win32.c 309203 2011-03-14 06:47:16Z pajoye $ */
6141 +
6142 +#include "apc.h"
6143 +#include "apc_fcntl.h"
6144 +#include <php.h>
6145 +#include <win32/flock.h>
6146 +#include <io.h>
6147 +#include <fcntl.h>
6148 +#include <sys/types.h>
6149 +#include <sys/stat.h>
6150 +
6151 +int apc_fcntl_create(const char* pathname TSRMLS_DC)
6152 +{
6153 +    char lock_file[MAXPATHLEN];
6154 +    HANDLE fd;
6155 +    DWORD tmp_dirname_len;
6156 +    char lock_filename_tpl[] = ".apc.XXXXXX";
6157 +    char *lock_filename;
6158 +
6159 +    tmp_dirname_len = GetTempPath(MAXPATHLEN, lock_file);
6160 +    if (!tmp_dirname_len) {
6161 +        return -1;
6162 +    }
6163 +
6164 +    lock_filename = _mktemp(lock_filename_tpl);
6165 +    if (lock_filename == NULL) {
6166 +      return -1;
6167 +    }
6168 +
6169 +    snprintf(lock_file + tmp_dirname_len, MAXPATHLEN - tmp_dirname_len - 1, "%s", lock_filename);
6170 +
6171 +    fd = CreateFile(lock_file,
6172 +        GENERIC_READ | GENERIC_WRITE,
6173 +        FILE_SHARE_READ | FILE_SHARE_WRITE,
6174 +        NULL,
6175 +        OPEN_ALWAYS,
6176 +        FILE_ATTRIBUTE_NORMAL,
6177 +        NULL);
6178 +
6179 +    if (fd == INVALID_HANDLE_VALUE) {
6180 +        apc_error("apc_fcntl_create: could not open %s" TSRMLS_CC, lock_file);
6181 +        return -1;
6182 +    }
6183 +
6184 +    return (int)fd;
6185 +}
6186 +
6187 +void apc_fcntl_destroy(int fd)
6188 +{
6189 +    CloseHandle((HANDLE)fd);
6190 +}
6191 +
6192 +void apc_fcntl_lock(int fd TSRMLS_DC)
6193 +{
6194 +    OVERLAPPED offset = {0, 0, 0, 0, NULL};
6195 +
6196 +    if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
6197 +        apc_error("apc_fcntl_lock failed errno:%d" TSRMLS_CC, GetLastError());
6198 +    }
6199 +}
6200 +
6201 +void apc_fcntl_rdlock(int fd TSRMLS_DC)
6202 +{
6203 +    OVERLAPPED offset = {0, 0, 0, 0, NULL};
6204 +
6205 +    if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
6206 +        apc_error("apc_fcntl_rdlock failed errno:%d" TSRMLS_CC, GetLastError());
6207 +    }
6208 +}
6209 +
6210 +void apc_fcntl_unlock(int fd TSRMLS_DC)
6211 +{
6212 +    OVERLAPPED offset = {0, 0, 0, 0, NULL};
6213 +
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);
6219 +        }
6220 +    }
6221 +}
6222 +
6223 +/*
6224 + * Local variables:
6225 + * tab-width: 4
6226 + * c-basic-offset: 4
6227 + * End:
6228 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6229 + * vim<600: expandtab sw=4 ts=4 sts=4
6230 + */
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
6234 @@ -0,0 +1,152 @@
6235 +/*
6236 +  +----------------------------------------------------------------------+
6237 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
6255 +
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.
6261 +
6262 +   All other licensing and usage conditions are those of the PHP Group.
6263 +
6264 + */
6265 +
6266 +/* $Id: apc_globals.h 307215 2011-01-07 09:54:00Z gopalv $ */
6267 +
6268 +#ifndef APC_GLOBALS_H
6269 +#define APC_GLOBALS_H
6270 +
6271 +#include "apc_cache.h"
6272 +#include "apc_stack.h"
6273 +#include "apc_php.h"
6274 +#include "apc_main.h"
6275 +
6276 +/* {{{ struct apc_rfc1867_data */
6277 +
6278 +typedef struct _apc_rfc1867_data apc_rfc1867_data;
6279 +
6280 +struct _apc_rfc1867_data {
6281 +    char tracking_key[64];
6282 +    int  key_length;
6283 +    size_t content_length;
6284 +    char filename[128];
6285 +    char name[64];
6286 +    char *temp_filename;
6287 +    int cancel_upload;
6288 +    double start_time;
6289 +    size_t bytes_processed;
6290 +    size_t prev_bytes_processed;
6291 +    int update_freq;
6292 +    double rate;
6293 +    int started;
6294 +};
6295 +/* }}} */
6296 +
6297 +
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 */
6307 +    long user_ttl;
6308 +#if APC_MMAP
6309 +    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
6310 +#endif
6311 +    char** filters;         /* array of regex filters that prevent caching */
6312 +    void* compiled_filters; /* compiled regex filters */
6313 +
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 */
6337 +#endif
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 */
6343 +#endif
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;
6358 +#endif
6359 +    char *serializer_name;       /* the serializer config option */
6360 +    apc_serializer_t *serializer;/* the actual serializer in use */
6361 +ZEND_END_MODULE_GLOBALS(apc)
6362 +
6363 +/* (the following declaration is defined in php_apc.c) */
6364 +ZEND_EXTERN_MODULE_GLOBALS(apc)
6365 +
6366 +#ifdef ZTS
6367 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
6368 +#else
6369 +# define APCG(v) (apc_globals.v)
6370 +#endif
6371 +
6372 +/* True globals */
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 */
6376 +
6377 +#endif
6378 +
6379 +/*
6380 + * Local variables:
6381 + * tab-width: 4
6382 + * c-basic-offset: 4
6383 + * End:
6384 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6385 + * vim<600: expandtab sw=4 ts=4 sts=4
6386 + */
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
6390 @@ -0,0 +1,136 @@
6391 +/*
6392 +  +----------------------------------------------------------------------+
6393 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
6411 +
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.
6417 +
6418 +   All other licensing and usage conditions are those of the PHP Group.
6419 +
6420 + */
6421 +
6422 +/* $Id: apc.h 307264 2011-01-08 13:20:20Z gopalv $ */
6423 +
6424 +#ifndef APC_H
6425 +#define APC_H
6426 +
6427 +/*
6428 + * This module defines utilities and helper functions used elsewhere in APC.
6429 + */
6430 +
6431 +/* Commonly needed C library headers. */
6432 +#include <assert.h>
6433 +#include <errno.h>
6434 +#include <stdarg.h>
6435 +#include <stdio.h>
6436 +#include <stdlib.h>
6437 +#include <string.h>
6438 +#include <time.h>
6439 +
6440 +/* UNIX headers (needed for struct stat) */
6441 +#include <sys/types.h>
6442 +#include <sys/stat.h>
6443 +#ifndef PHP_WIN32
6444 +#include <unistd.h>
6445 +#endif
6446 +
6447 +#ifdef HAVE_CONFIG_H
6448 +#include <config.h>
6449 +#endif
6450 +
6451 +#include "php.h"
6452 +#include "main/php_streams.h"
6453 +
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);
6457 +
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);
6465 +
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, ...);
6471 +
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);
6476 +
6477 +/* filesystem functions */
6478 +
6479 +typedef struct apc_fileinfo_t 
6480 +{
6481 +    char *fullpath;
6482 +    char path_buf[MAXPATHLEN];
6483 +    php_stream_statbuf st_buf;
6484 +} apc_fileinfo_t;
6485 +
6486 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC);
6487 +
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);
6492 +
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);
6495 +
6496 +/* apc_flip_hash flips keys and values for faster searching */
6497 +extern HashTable* apc_flip_hash(HashTable *hash); 
6498 +
6499 +#define APC_NEGATIVE_MATCH 1
6500 +#define APC_POSITIVE_MATCH 2
6501 +
6502 +#define apc_time() \
6503 +    (APCG(use_request_time) ? (time_t) sapi_get_request_time(TSRMLS_C) : time(0));
6504 +
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))
6510 +#else 
6511 +# define APC_UNUSED
6512 +# define APC_USED
6513 +# define APC_ALLOC 
6514 +# define APC_HOTSPOT 
6515 +#endif
6516 +
6517 +#endif
6518 +
6519 +/*
6520 + * Local variables:
6521 + * tab-width: 4
6522 + * c-basic-offset: 4
6523 + * End:
6524 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
6525 + * vim<600: expandtab sw=4 ts=4 sts=4
6526 + */
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
6530 @@ -0,0 +1,741 @@
6531 +/*
6532 +  +----------------------------------------------------------------------+
6533 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
6547 +
6548 + */
6549 +
6550 +/* $Id: apc_iterator.c 324326 2012-03-18 13:19:50Z pajoye $ */
6551 +
6552 +#include "php_apc.h"
6553 +#include "apc_iterator.h"
6554 +#include "apc_cache.h"
6555 +#include "apc_zend.h"
6556 +
6557 +#include "ext/standard/md5.h"
6558 +
6559 +#include "zend_interfaces.h"
6560 +
6561 +zend_class_entry *apc_iterator_ce;
6562 +zend_object_handlers apc_iterator_object_handlers;
6563 +
6564 +
6565 +/* {{{ apc_iterator_item */
6566 +static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp TSRMLS_DC) {
6567 +    zval *zvalue;
6568 +    char md5str[33];
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));
6572 +
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 */
6575 +#ifdef PHP_WIN32
6576 +        item->key_len = spprintf(&item->key, 0, "%I64d %I64d", slot->key.data.file.device, slot->key.data.file.inode);
6577 +#else
6578 +        item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode);
6579 +#endif
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;
6589 +    } else {
6590 +        apc_error("Internal error, invalid entry type." TSRMLS_CC);
6591 +    }
6592 +
6593 +    ALLOC_INIT_ZVAL(item->value);
6594 +    array_init(item->value);
6595 +
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);
6601 +        }
6602 +    }
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);
6609 +            }
6610 +        }
6611 +    }
6612 +    if (APC_ITER_DEVICE & iterator->format) {
6613 +        if(slot->key.type == APC_CACHE_KEY_FILE) {
6614 +#ifdef PHP_WIN32
6615 +                       char buf[20];
6616 +                       sprintf(buf, "%I64d", slot->key.data.file.device);
6617 +                       add_assoc_string(item->value, "device", buf, 1);
6618 +#else
6619 +            add_assoc_long(item->value, "device", slot->key.data.file.device);
6620 +#endif
6621 +        }
6622 +    }
6623 +    if (APC_ITER_INODE & iterator->format) {
6624 +        if(slot->key.type == APC_CACHE_KEY_FILE) {
6625 +#ifdef PHP_WIN32
6626 +                       char buf[20];
6627 +                       sprintf(buf, "%I64d", slot->key.data.file.device);
6628 +                       add_assoc_string(item->value, "device", buf, 1);
6629 +#else
6630 +            add_assoc_long(item->value, "inode", slot->key.data.file.inode);
6631 +#endif
6632 +        }
6633 +    }
6634 +    if (APC_ITER_KEY & iterator->format) {
6635 +        add_assoc_stringl(item->value, "key", item->key, (item->key_len - 1), 1);
6636 +    }
6637 +    if (APC_ITER_VALUE & iterator->format) {
6638 +        if(slot->value->type == APC_CACHE_ENTRY_USER) {
6639 +
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;
6642 +
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);
6647 +        }
6648 +    }
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);
6654 +            }
6655 +        }
6656 +    }
6657 +    if (APC_ITER_NUM_HITS & iterator->format) {
6658 +        add_assoc_long(item->value, "num_hits", slot->num_hits);
6659 +    }
6660 +    if (APC_ITER_MTIME & iterator->format) {
6661 +        add_assoc_long(item->value, "mtime", slot->key.mtime);
6662 +    }
6663 +    if (APC_ITER_CTIME & iterator->format) {
6664 +        add_assoc_long(item->value, "creation_time", slot->creation_time);
6665 +    }
6666 +    if (APC_ITER_DTIME & iterator->format) {
6667 +        add_assoc_long(item->value, "deletion_time", slot->deletion_time);
6668 +    }
6669 +    if (APC_ITER_ATIME & iterator->format) {
6670 +        add_assoc_long(item->value, "access_time", slot->access_time);
6671 +    }
6672 +    if (APC_ITER_REFCOUNT & iterator->format) {
6673 +        add_assoc_long(item->value, "ref_count", slot->value->ref_count);
6674 +    }
6675 +    if (APC_ITER_MEM_SIZE & iterator->format) {
6676 +        add_assoc_long(item->value, "mem_size", slot->value->mem_size);
6677 +    }
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);
6681 +        }
6682 +    }
6683 +
6684 +    return item;
6685 +}
6686 +/* }}} */
6687 +
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);
6692 +    return value;
6693 +}
6694 +/* }}} */
6695 +
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);
6700 +    }
6701 +    if (item->key) {
6702 +        efree(item->key);
6703 +    }
6704 +    if (item->value) {
6705 +        zval_ptr_dtor(&item->value);
6706 +    }
6707 +    efree(item);
6708 +}
6709 +/* }}} */
6710 +
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;
6714 +
6715 +    if (iterator->initialized == 0) {
6716 +        return;
6717 +    }
6718 +
6719 +    while (apc_stack_size(iterator->stack) > 0) {
6720 +        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
6721 +    }
6722 +    if (iterator->regex) {
6723 +        efree(iterator->regex);
6724 +    }
6725 +    if (iterator->search_hash) {
6726 +        zend_hash_destroy(iterator->search_hash);
6727 +        efree(iterator->search_hash);
6728 +    }
6729 +    iterator->initialized = 0;
6730 +
6731 +}
6732 +/* }}} */
6733 +
6734 +/* {{{ acp_iterator_free */
6735 +static void apc_iterator_free(void *object TSRMLS_DC) {
6736 +    zend_object_std_dtor(object TSRMLS_CC);
6737 +    efree(object);
6738 +}
6739 +/* }}} */
6740 +
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;
6745 +
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;
6752 +#endif
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;
6757 +
6758 +    return retval;
6759 +}
6760 +/* }}} */
6761 +
6762 +/* {{{ apc_iterator_search_match
6763 + *       Verify if the key matches oru search parameters
6764 + */
6765 +static int apc_iterator_search_match(apc_iterator_t *iterator, slot_t **slot) {
6766 +    char *key;
6767 +    int key_len;
6768 +    char *fname_key = NULL;
6769 +    int fname_key_len = 0;
6770 +    int rval = 1;
6771 +
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;
6782 +    } else {
6783 +        return 0;
6784 +    }
6785 +
6786 +#ifdef ITERATOR_PCRE
6787 +    if (iterator->regex) {
6788 +        rval = (pcre_exec(iterator->re, NULL, key, strlen(key), 0, 0, NULL, 0) >= 0);
6789 +    }
6790 +#endif
6791 +            
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);
6796 +        }
6797 +    }
6798 +
6799 +    return rval;
6800 +}
6801 +/* }}} */
6802 +
6803 +/* {{{ apc_iterator_check_expiry */
6804 +static int apc_iterator_check_expiry(apc_cache_t* cache, slot_t **slot, time_t t)
6805 +{
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) {
6809 +                return 0;
6810 +            }
6811 +        } else if(cache->ttl) {
6812 +            if((*slot)->creation_time + cache->ttl < t) {
6813 +                return 0;
6814 +            }
6815 +        }
6816 +    } else if((*slot)->access_time < (t - cache->ttl)) {
6817 +        return 0;
6818 +    }
6819 +
6820 +    return 1;
6821 +}
6822 +/* }}} */
6823 +
6824 +/* {{{ apc_iterator_fetch_active */
6825 +static int apc_iterator_fetch_active(apc_iterator_t *iterator TSRMLS_DC) {
6826 +    int count=0;
6827 +    slot_t **slot;
6828 +    apc_iterator_item_t *item;
6829 +    time_t t;
6830 +
6831 +    t = apc_time();
6832 +
6833 +    while (apc_stack_size(iterator->stack) > 0) {
6834 +        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
6835 +    }
6836 +
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];
6840 +        while(*slot) {
6841 +            if (apc_iterator_check_expiry(iterator->cache, slot, t)) {
6842 +                if (apc_iterator_search_match(iterator, slot)) {
6843 +                    count++;
6844 +                    item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
6845 +                    if (item) {
6846 +                        apc_stack_push(iterator->stack, item TSRMLS_CC);
6847 +                    }
6848 +                }
6849 +            }
6850 +            slot = &(*slot)->next;
6851 +        }
6852 +        iterator->slot_idx++;
6853 +    }
6854 +    CACHE_UNLOCK(iterator->cache);
6855 +    iterator->stack_idx = 0;
6856 +    return count;
6857 +}
6858 +/* }}} */
6859 +
6860 +/* {{{ apc_iterator_fetch_deleted */
6861 +static int apc_iterator_fetch_deleted(apc_iterator_t *iterator TSRMLS_DC) {
6862 +    int count=0;
6863 +    slot_t **slot;
6864 +    apc_iterator_item_t *item;
6865 +
6866 +    CACHE_LOCK(iterator->cache);
6867 +    slot = &iterator->cache->header->deleted_list;
6868 +    while ((*slot) && count <= iterator->slot_idx) {
6869 +        count++;
6870 +        slot = &(*slot)->next;
6871 +    }
6872 +    count = 0;
6873 +    while ((*slot) && count < iterator->chunk_size) {
6874 +        if (apc_iterator_search_match(iterator, slot)) {
6875 +            count++;
6876 +            item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC);
6877 +            if (item) {
6878 +                apc_stack_push(iterator->stack, item TSRMLS_CC);
6879 +            }
6880 +        }
6881 +        slot = &(*slot)->next;
6882 +    }
6883 +    CACHE_UNLOCK(iterator->cache);
6884 +    iterator->slot_idx += count;
6885 +    iterator->stack_idx = 0;
6886 +    return count;
6887 +}
6888 +/* }}} */
6889 +
6890 +/* {{{ apc_iterator_totals */
6891 +static void apc_iterator_totals(apc_iterator_t *iterator TSRMLS_DC) {
6892 +    slot_t **slot;
6893 +    int i;
6894 +
6895 +    CACHE_LOCK(iterator->cache);
6896 +    for (i=0; i < iterator->cache->num_slots; i++) {
6897 +        slot = &iterator->cache->slots[i];
6898 +        while((*slot)) {
6899 +            if (apc_iterator_search_match(iterator, slot)) {
6900 +                iterator->size += (*slot)->value->mem_size;
6901 +                iterator->hits += (*slot)->num_hits;
6902 +                iterator->count++;
6903 +            }
6904 +            slot = &(*slot)->next;
6905 +        }
6906 +    }
6907 +    CACHE_UNLOCK(iterator->cache);
6908 +    iterator->totals_flag = 1;
6909 +}
6910 +/* }}} */
6911 +
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);
6916 +    char *cachetype;
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;
6922 +
6923 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zlll", &cachetype, &cachetype_len, &search, &format, &chunk_size, &list) == FAILURE) {
6924 +        return;
6925 +    }
6926 +
6927 +    if (!APCG(enabled)) {
6928 +        apc_error("APC must be enabled to use APCIterator." TSRMLS_CC);
6929 +    }
6930 +
6931 +    if (chunk_size < 0) {
6932 +        apc_error("APCIterator chunk size must be 0 or greater." TSRMLS_CC);
6933 +        return;
6934 +    }
6935 +
6936 +    if (format > APC_ITER_ALL) {
6937 +        apc_error("APCIterator format is invalid." TSRMLS_CC);
6938 +        return;
6939 +    }
6940 +
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;
6945 +    } else {
6946 +        apc_warning("APCIterator invalid list type." TSRMLS_CC);
6947 +        return;
6948 +    }
6949 +
6950 +    if(!strcasecmp(cachetype,"user")) {
6951 +        iterator->cache = apc_user_cache;
6952 +    } else {
6953 +        iterator->cache = apc_cache;
6954 +    }
6955 +
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);
6974 +
6975 +        if(!iterator->re) {
6976 +            apc_error("Could not compile regular expression: %s" TSRMLS_CC, Z_STRVAL_P(search));
6977 +        }
6978 +#else
6979 +        apc_error("Regular expressions support is not enabled, please enable PCRE for APCIterator regex support" TSRMLS_CC);
6980 +#endif
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));
6984 +    }
6985 +    iterator->initialized = 1;
6986 +}
6987 +/* }}} */
6988 +
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);
6992 +
6993 +    if (zend_parse_parameters_none() == FAILURE) {
6994 +        return;
6995 +    }
6996 +
6997 +    if (iterator->initialized == 0) {
6998 +        RETURN_FALSE;
6999 +    }
7000 +
7001 +    iterator->slot_idx = 0;
7002 +    iterator->stack_idx = 0;
7003 +    iterator->key_idx = 0;
7004 +    iterator->fetch(iterator TSRMLS_CC);
7005 +}
7006 +/* }}} */
7007 +
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);
7011 +
7012 +    if (zend_parse_parameters_none() == FAILURE) {
7013 +        return;
7014 +    }
7015 +
7016 +    if (iterator->initialized == 0) {
7017 +        RETURN_FALSE;
7018 +    }
7019 +
7020 +    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7021 +        iterator->fetch(iterator TSRMLS_CC);
7022 +    }
7023 +
7024 +    RETURN_BOOL(apc_stack_size(iterator->stack) == 0 ? 0 : 1);
7025 +}
7026 +/* }}} */
7027 +
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);
7032 +
7033 +    if (zend_parse_parameters_none() == FAILURE) {
7034 +        return;
7035 +    }
7036 +
7037 +    if (iterator->initialized == 0) {
7038 +        RETURN_FALSE;
7039 +    }
7040 +
7041 +    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7042 +        if (iterator->fetch(iterator TSRMLS_CC) == 0) {
7043 +            RETURN_FALSE;
7044 +        }
7045 +    }
7046 +
7047 +    item = apc_stack_get(iterator->stack, iterator->stack_idx);
7048 +    RETURN_ZVAL(item->value, 1, 0);
7049 +}
7050 +/* }}} */
7051 +
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);
7056 +
7057 +    if (zend_parse_parameters_none() == FAILURE) {
7058 +        return;
7059 +    }
7060 +
7061 +    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
7062 +        RETURN_FALSE;
7063 +    }
7064 +
7065 +    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
7066 +        if (iterator->fetch(iterator TSRMLS_CC) == 0) {
7067 +            RETURN_FALSE;
7068 +        }
7069 +    }
7070 +
7071 +    item = apc_stack_get(iterator->stack, iterator->stack_idx);
7072 +
7073 +    if (item->key) {
7074 +        RETURN_STRINGL(item->key, (item->key_len-1), 1);
7075 +    } else {
7076 +        RETURN_LONG(iterator->key_idx);
7077 +    }
7078 +}
7079 +/* }}} */
7080 +
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);
7084 +
7085 +    if (zend_parse_parameters_none() == FAILURE) {
7086 +        return;
7087 +    }
7088 +
7089 +    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
7090 +        RETURN_FALSE;
7091 +    }
7092 +
7093 +    iterator->stack_idx++;
7094 +    iterator->key_idx++;
7095 +
7096 +    RETURN_TRUE;
7097 +}
7098 +/* }}} */
7099 +
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);
7103 +
7104 +    if (zend_parse_parameters_none() == FAILURE) {
7105 +        return;
7106 +    }
7107 +
7108 +    if (iterator->initialized == 0) {
7109 +        RETURN_FALSE;
7110 +    }
7111 +
7112 +    if (iterator->totals_flag == 0) {
7113 +        apc_iterator_totals(iterator TSRMLS_CC);
7114 +    }
7115 +
7116 +    RETURN_LONG(iterator->hits);
7117 +}
7118 +/* }}} */
7119 +
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);
7123 +
7124 +    if (zend_parse_parameters_none() == FAILURE) {
7125 +        return;
7126 +    }
7127 +
7128 +    if (iterator->initialized == 0) {
7129 +        RETURN_FALSE;
7130 +    }
7131 +
7132 +    if (iterator->totals_flag == 0) {
7133 +        apc_iterator_totals(iterator TSRMLS_CC);
7134 +    }
7135 +
7136 +    RETURN_LONG(iterator->size);
7137 +}
7138 +/* }}} */
7139 +
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);
7143 +
7144 +    if (zend_parse_parameters_none() == FAILURE) {
7145 +        return;
7146 +    }
7147 +
7148 +    if (iterator->initialized == 0) {
7149 +        RETURN_FALSE;
7150 +    }
7151 +
7152 +    if (iterator->totals_flag == 0) {
7153 +        apc_iterator_totals(iterator TSRMLS_CC);
7154 +    }
7155 +
7156 +    RETURN_LONG(iterator->count);
7157 +}
7158 +/* }}} */
7159 +
7160 +/* {{{ arginfo */
7161 +#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
7162 +# define PHP_APC_ARGINFO
7163 +#else
7164 +# define PHP_APC_ARGINFO static
7165 +#endif
7166 +
7167 +PHP_APC_ARGINFO
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()
7175 +
7176 +PHP_APC_ARGINFO
7177 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator_void, 0, 0, 0)
7178 +ZEND_END_ARG_INFO()
7179 +/* }}} */
7180 +
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}
7193 +};
7194 +/* }}} */
7195 +
7196 +/* {{{ apc_iterator_init */
7197 +int apc_iterator_init(int module_number TSRMLS_DC) {
7198 +    zend_class_entry ce;
7199 +
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);
7204 +
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);
7207 +
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);
7225 +
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;
7228 +
7229 +    return SUCCESS;
7230 +}
7231 +/* }}} */
7232 +
7233 +
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;
7238 +
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);
7241 +        return 0;
7242 +    }
7243 +    iterator = (apc_iterator_t*)zend_object_store_get_object(zobj TSRMLS_CC);
7244 +
7245 +    if (iterator->initialized == 0) {
7246 +        return 0;
7247 +    }
7248 +
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);
7254 +            } else {
7255 +                apc_cache_user_delete(apc_user_cache, item->key, item->key_len TSRMLS_CC);
7256 +            }
7257 +        }
7258 +    }
7259 +
7260 +    return 1;
7261 +}
7262 +
7263 +
7264 +/*
7265 + * Local variables:
7266 + * tab-width: 4
7267 + * c-basic-offset: 4
7268 + * End:
7269 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
7270 + * vim<600: expandtab sw=4 ts=4 sts=4
7271 + */
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
7275 @@ -0,0 +1,117 @@
7276 +/*
7277 +  +----------------------------------------------------------------------+
7278 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
7292 +
7293 + */
7294 +
7295 +/* $Id: apc_iterator.h 307048 2011-01-03 23:53:17Z kalle $ */
7296 +
7297 +#ifndef APC_ITERATOR_H
7298 +#define APC_ITERATOR_H
7299 +
7300 +#include "apc.h"
7301 +#include "apc_stack.h"
7302 +
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"
7307 +#   else
7308 +#       include "ext/pcre/php_pcre.h"
7309 +#   endif
7310 +#   include "ext/standard/php_smart_str.h"
7311 +#   define ITERATOR_PCRE 1
7312 +#endif
7313 +
7314 +
7315 +#define APC_ITERATOR_NAME "APCIterator"
7316 +
7317 +#define APC_DEFAULT_CHUNK_SIZE 100
7318 +
7319 +#define APC_LIST_ACTIVE   0x1
7320 +#define APC_LIST_DELETED  0x2
7321 +
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)
7337 +
7338 +#define APC_ITER_NONE       (0x00000000L)
7339 +#define APC_ITER_ALL        (0xffffffffL)
7340 +
7341 +typedef void* (*apc_iterator_item_cb_t)(slot_t **slot);
7342 +
7343 +
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 */
7358 +#endif
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 */
7367 +} apc_iterator_t;
7368 +/* }}} */
7369 +
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 */
7375 +    zval *value;
7376 +} apc_iterator_item_t;
7377 +/* }}} */
7378 +
7379 +
7380 +extern int apc_iterator_init(int module_number TSRMLS_DC);
7381 +extern int apc_iterator_delete(zval *zobj TSRMLS_DC);
7382 +
7383 +#endif
7384 +
7385 +/*
7386 + * Local variables:
7387 + * tab-width: 4
7388 + * c-basic-offset: 4
7389 + * End:
7390 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
7391 + * vim<600: expandtab sw=4 ts=4 sts=4
7392 + */
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
7396 @@ -0,0 +1,160 @@
7397 +/*
7398 +  +----------------------------------------------------------------------+
7399 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
7415 +
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.
7421 +
7422 +   All other licensing and usage conditions are those of the PHP Group.
7423 +
7424 + */
7425 +
7426 +/* $Id: apc_lock.h 311339 2011-05-22 17:18:49Z gopalv $ */
7427 +
7428 +#ifndef APC_LOCK
7429 +#define APC_LOCK
7430 +
7431 +#ifdef HAVE_CONFIG_H
7432 +# include <config.h>
7433 +#endif
7434 +
7435 +#include "apc.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"
7442 +
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(); }
7450 +/* }}} */
7451 +
7452 +/* atomic operations : rdlocks are impossible without these */
7453 +#if HAVE_ATOMIC_OPERATIONS
7454 +# ifdef PHP_WIN32
7455 +#  define ATOMIC_INC(a) InterlockedIncrement(&a)
7456 +#  define ATOMIC_DEC(a) InterlockedDecrement(&a)
7457 +# else
7458 +#  define ATOMIC_INC(a) __sync_add_and_fetch(&a, 1)
7459 +#  define ATOMIC_DEC(a) __sync_sub_and_fetch(&a, 1)
7460 +# endif
7461 +#endif
7462 +
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);
7524 +# endif
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)
7536 +#else
7537 +# define APC_LOCK_TYPE "File Locks"
7538 +# ifdef HAVE_ATOMIC_OPERATIONS
7539 +#  define RDLOCK_AVAILABLE 1
7540 +# endif
7541 +# ifdef PHP_WIN32
7542 +#  define NONBLOCKING_LOCK_AVAILABLE 0
7543 +# else
7544 +#  define NONBLOCKING_LOCK_AVAILABLE 1
7545 +# endif
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)
7554 +#endif
7555 +
7556 +#endif
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
7560 @@ -0,0 +1,1030 @@
7561 +/*
7562 +  +----------------------------------------------------------------------+
7563 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
7580 +
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.
7586 +
7587 +   All other licensing and usage conditions are those of the PHP Group.
7588 +
7589 + */
7590 +
7591 +/* $Id: apc_main.c 324326 2012-03-18 13:19:50Z pajoye $ */
7592 +
7593 +#include "apc_php.h"
7594 +#include "apc_main.h"
7595 +#include "apc.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"
7605 +#include "SAPI.h"
7606 +#include "php_scandir.h"
7607 +#include "ext/standard/php_var.h"
7608 +#include "ext/standard/md5.h"
7609 +
7610 +#define APC_MAX_SERIALIZERS 16
7611 +
7612 +/* {{{ module variables */
7613 +
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,}};
7618 +
7619 +/* }}} */
7620 +
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)
7623 +{
7624 +    zend_compile_t *retval = old_compile_file;
7625 +
7626 +    if (ptr != NULL) old_compile_file = ptr;
7627 +    return retval;
7628 +}
7629 +/* }}} */
7630 +
7631 +/* {{{ install_function */
7632 +static int install_function(apc_function_t fn, apc_context_t* ctxt, int lazy TSRMLS_DC)
7633 +{
7634 +    int status;
7635 +
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),
7639 +                              fn.name,
7640 +                              fn.name_len+1,
7641 +                              &fn,
7642 +                              sizeof(apc_function_t),
7643 +                              NULL);
7644 +#else
7645 +    if(0) {
7646 +#endif
7647 +    } else {
7648 +        zend_function *func = apc_copy_function_for_execution(fn.function, ctxt TSRMLS_CC);
7649 +        status = zend_hash_add(EG(function_table),
7650 +                              fn.name,
7651 +                              fn.name_len+1,
7652 +                              func,
7653 +                              sizeof(fn.function[0]),
7654 +                              NULL);
7655 +        efree(func);
7656 +    }
7657 +
7658 +    if (status == FAILURE) {
7659 +        /* apc_error("Cannot redeclare %s()" TSRMLS_CC, fn.name); */
7660 +    }
7661 +
7662 +    return status;
7663 +}
7664 +/* }}} */
7665 +
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,};
7671 +    TSRMLS_FETCH();
7672 +
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;
7675 +
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),
7679 +                                  fn->name,
7680 +                                  fn->name_len+1,
7681 +                                  *fe,
7682 +                                  sizeof(zend_function),
7683 +                                  NULL);
7684 +    }
7685 +
7686 +    return status;
7687 +}
7688 +/* }}} */
7689 +
7690 +/* {{{ install_class */
7691 +static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC)
7692 +{
7693 +    zend_class_entry* class_entry = cl.class_entry;
7694 +    zend_class_entry* parent = NULL;
7695 +    int status;
7696 +    zend_class_entry** allocated_ce = NULL;
7697 +
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
7703 +     * calls.
7704 +     */
7705 +
7706 +    if(cl.name_len != 0 && cl.name[0] == '\0') {
7707 +        if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
7708 +            return SUCCESS;
7709 +        }
7710 +    }
7711 +
7712 +    if(lazy && cl.name_len != 0 && cl.name[0] != '\0') {
7713 +        status = zend_hash_add(APCG(lazy_class_table),
7714 +                               cl.name,
7715 +                               cl.name_len+1,
7716 +                               &cl,
7717 +                               sizeof(apc_class_t),
7718 +                               NULL);
7719 +        if(status == FAILURE) {
7720 +            zend_error(E_ERROR, "Cannot redeclare class %s", cl.name);
7721 +        }
7722 +        return status;
7723 +    }
7724 +
7725 +    /*
7726 +     * XXX: We need to free this somewhere...
7727 +     */
7728 +    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*) TSRMLS_CC);
7729 +
7730 +    if(!allocated_ce) {
7731 +        return FAILURE;
7732 +    }
7733 +
7734 +    *allocated_ce =
7735 +    class_entry =
7736 +        apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC);
7737 +
7738 +
7739 +    /* restore parent class pointer for compile-time inheritance */
7740 +    if (cl.parent_name != NULL) {
7741 +        zend_class_entry** parent_ptr = NULL;
7742 +        /*
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. 
7748 +         * 
7749 +         * missing parent == re-compile. 
7750 +         *
7751 +         * whether __autoload is enabled or not, because __autoload errors
7752 +         * cause php to die.
7753 +         *
7754 +         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
7755 +         * zend_lookup_class_ex does it internally anyway!
7756 +         */
7757 +        status = zend_lookup_class_ex(cl.parent_name,
7758 +                                    strlen(cl.parent_name), 
7759 +#ifdef ZEND_ENGINE_2_4
7760 +                                    NULL,
7761 +#endif
7762 +                                    0,
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);
7767 +            }
7768 +            class_entry->parent = NULL;
7769 +            return status;
7770 +        }
7771 +        else {
7772 +            parent = *parent_ptr;
7773 +            class_entry->parent = parent;
7774 +            zend_do_inheritance(class_entry, parent TSRMLS_CC);
7775 +        }
7776 +
7777 +
7778 +    }
7779 +
7780 +    status = zend_hash_add(EG(class_table),
7781 +                           cl.name,
7782 +                           cl.name_len+1,
7783 +                           allocated_ce,
7784 +                           sizeof(zend_class_entry*),
7785 +                           NULL);
7786 +
7787 +    if (status == FAILURE) {
7788 +        apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name);
7789 +    }
7790 +    return status;
7791 +}
7792 +/* }}} */
7793 +
7794 +/* {{{ apc_lookup_class_hook */
7795 +int apc_lookup_class_hook(char *name, int len, ulong hash, zend_class_entry ***ce) {
7796 +
7797 +    apc_class_t *cl;
7798 +    apc_context_t ctxt = {0,};
7799 +    TSRMLS_FETCH();
7800 +
7801 +    if(zend_is_compiling(TSRMLS_C)) { return FAILURE; }
7802 +
7803 +    if(zend_hash_quick_find(APCG(lazy_class_table), name, len, hash, (void**)&cl) == FAILURE) {
7804 +        return FAILURE;
7805 +    }
7806 +
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;
7809 +
7810 +    if(install_class(*cl, &ctxt, 0 TSRMLS_CC) == FAILURE) {
7811 +        apc_warning("apc_lookup_class_hook: could not install %s" TSRMLS_CC, name);
7812 +        return FAILURE;
7813 +    }
7814 +
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);
7817 +        return FAILURE;
7818 +    }
7819 +
7820 +    return SUCCESS;
7821 +
7822 +}
7823 +/* }}} */
7824 +
7825 +/* {{{ uninstall_class */
7826 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
7827 +{
7828 +    int status;
7829 +
7830 +    status = zend_hash_del(EG(class_table),
7831 +                           cl.name,
7832 +                           cl.name_len+1);
7833 +    if (status == FAILURE) {
7834 +        apc_error("Cannot delete class %s" TSRMLS_CC, cl.name);
7835 +    }
7836 +    return status;
7837 +}
7838 +/* }}} */
7839 +
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)
7842 +{
7843 +    zval *internal_ar = va_arg(args, zval *),
7844 +         *user_ar     = va_arg(args, zval *);
7845 +    zend_function *func = pf->function;
7846 +
7847 +    if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
7848 +        return 0;
7849 +    }
7850 +
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);
7855 +    }
7856 +
7857 +    return 0;
7858 +}
7859 +
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)
7862 +{
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;
7868 +
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);
7872 +    }
7873 +    return ZEND_HASH_APPLY_KEEP;
7874 +}
7875 +/* }}} */
7876 +
7877 +/* }}} */
7878 +
7879 +/* {{{ apc_defined_function_hook */
7880 +int apc_defined_function_hook(zval *internal, zval *user) {
7881 +    TSRMLS_FETCH();
7882 +    zend_hash_apply_with_arguments(APCG(lazy_function_table) 
7883 +#ifdef ZEND_ENGINE_2_3
7884 +    TSRMLS_CC
7885 +#endif
7886 +    ,(apply_func_args_t) copy_function_name, 2, internal, user);
7887 +  return 1;
7888 +}
7889 +/* }}} */
7890 +
7891 +/* {{{ apc_declared_class_hook */
7892 +int apc_declared_class_hook(zval *classes, zend_uint mask, zend_uint comply) {
7893 +    TSRMLS_FETCH();
7894 +    zend_hash_apply_with_arguments(APCG(lazy_class_table) 
7895 +#ifdef ZEND_ENGINE_2_3
7896 +    TSRMLS_CC
7897 +#endif
7898 +    , (apply_func_args_t) copy_class_or_interface_name, 3, classes, mask, comply);
7899 +  return 1;
7900 +}
7901 +/* }}} */
7902 +
7903 +/* {{{ cached_compile */
7904 +static zend_op_array* cached_compile(zend_file_handle* h,
7905 +                                        int type,
7906 +                                        apc_context_t* ctxt TSRMLS_DC)
7907 +{
7908 +    apc_cache_entry_t* cache_entry;
7909 +    int i, ii;
7910 +
7911 +    cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
7912 +    assert(cache_entry != NULL);
7913 +
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;
7919 +            }
7920 +        }
7921 +    }
7922 +
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);
7927 +        }
7928 +    }
7929 +
7930 +    apc_do_halt_compiler_register(cache_entry->data.file.filename, cache_entry->data.file.halt_offset TSRMLS_CC);
7931 +
7932 +
7933 +    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array, ctxt TSRMLS_CC);
7934 +
7935 +default_compile:
7936 +
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);
7940 +        }
7941 +    }
7942 +
7943 +    apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
7944 +
7945 +    apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
7946 +
7947 +    /* cannot free up cache data yet, it maybe in use */
7948 +
7949 +    return NULL;
7950 +}
7951 +/* }}} */
7952 +
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;
7959 +    char *path;
7960 +    apc_context_t ctxt;
7961 +
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));
7965 +
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) {
7971 +        return FAILURE;
7972 +    }
7973 +
7974 +    ctxt.pool = apc_pool_create(APC_MEDIUM_POOL, apc_sma_malloc, apc_sma_free, 
7975 +                                                 apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
7976 +    if (!ctxt.pool) {
7977 +        apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
7978 +        return FAILURE;
7979 +    }
7980 +    ctxt.copy = APC_COPY_IN_OPCODE;
7981 +
7982 +    if(APCG(file_md5)) {
7983 +        int n;
7984 +        unsigned char buf[1024];
7985 +        PHP_MD5_CTX context;
7986 +        php_stream *stream;
7987 +        char *filename;
7988 +
7989 +        if(h->opened_path) {
7990 +            filename = h->opened_path;
7991 +        } else {
7992 +            filename = h->filename;
7993 +        }
7994 +        stream = php_stream_open_wrapper(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
7995 +        if(stream) {
7996 +            PHP_MD5Init(&context);
7997 +            while((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
7998 +                PHP_MD5Update(&context, buf, n);
7999 +            }
8000 +            PHP_MD5Final(key->md5, &context);
8001 +            php_stream_close(stream);
8002 +            if(n<0) {
8003 +                apc_warning("Error while reading '%s' for md5 generation." TSRMLS_CC, filename);
8004 +            }
8005 +        } else {
8006 +            apc_warning("Unable to open '%s' for md5 generation." TSRMLS_CC, filename);
8007 +        }
8008 +    }
8009 +
8010 +    if(!(alloc_op_array = apc_copy_op_array(NULL, *op_array, &ctxt TSRMLS_CC))) {
8011 +        goto freepool;
8012 +    }
8013 +
8014 +    if(!(alloc_functions = apc_copy_new_functions(num_functions, &ctxt TSRMLS_CC))) {
8015 +        goto freepool;
8016 +    }
8017 +    if(!(alloc_classes = apc_copy_new_classes(*op_array, num_classes, &ctxt TSRMLS_CC))) {
8018 +        goto freepool;
8019 +    }
8020 +
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;
8024 +
8025 +    apc_debug("2. h->opened_path=[%s]  h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
8026 +
8027 +    if(!(*cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) {
8028 +        goto freepool;
8029 +    }
8030 +
8031 +    return SUCCESS;
8032 +
8033 +freepool:
8034 +    apc_pool_destroy(ctxt.pool TSRMLS_CC);
8035 +    ctxt.pool = NULL;
8036 +
8037 +    return FAILURE;
8038 +
8039 +}
8040 +/* }}} */
8041 +
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)
8046 +{
8047 +    apc_cache_key_t key;
8048 +    apc_cache_entry_t* cache_entry;
8049 +    zend_op_array* op_array = NULL;
8050 +    time_t t;
8051 +    apc_context_t ctxt = {0,};
8052 +    int bailout=0;
8053 +    const char* filename = NULL;
8054 +
8055 +    if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
8056 +        return old_compile_file(h, type TSRMLS_CC);
8057 +    }
8058 +
8059 +    if(h->opened_path) {
8060 +        filename = h->opened_path;
8061 +    } else {
8062 +        filename = h->filename;
8063 +    }
8064 +
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);
8068 +
8069 +        if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
8070 +            return old_compile_file(h, type TSRMLS_CC);
8071 +        }
8072 +    } else if(!APCG(cache_by_default)) {
8073 +        return old_compile_file(h, type TSRMLS_CC);
8074 +    }
8075 +    APCG(current_cache) = apc_cache;
8076 +
8077 +
8078 +    t = apc_time();
8079 +
8080 +    apc_debug("1. h->opened_path=[%s]  h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename);
8081 +
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);
8085 +    }
8086 +
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;
8091 +    } else {
8092 +        cache_entry = NULL;
8093 +        ctxt.force_update = 1;
8094 +    }
8095 +
8096 +    if (cache_entry != NULL) {
8097 +        int dummy = 1;
8098 +        
8099 +        ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free,
8100 +                                                apc_sma_protect, apc_sma_unprotect TSRMLS_CC);
8101 +        if (!ctxt.pool) {
8102 +            apc_warning("Unable to allocate memory for pool." TSRMLS_CC);
8103 +            return old_compile_file(h, type TSRMLS_CC);
8104 +        }
8105 +        ctxt.copy = APC_COPY_OUT_OPCODE;
8106 +        
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);
8110 +
8111 +        apc_stack_push(APCG(cache_stack), cache_entry TSRMLS_CC);
8112 +        op_array = cached_compile(h, type, &ctxt TSRMLS_CC);
8113 +
8114 +        if(op_array) {
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);
8118 +#endif
8119 +            /* this is an unpool, which has no cleanup - this only free's the pool header */
8120 +            apc_pool_destroy(ctxt.pool TSRMLS_CC);
8121 +            
8122 +            /* We might leak fds without this hack */
8123 +            if (h->type != ZEND_HANDLE_FILENAME) {
8124 +                zend_llist_add_element(&CG(open_files), h); 
8125 +            }
8126 +            return op_array;
8127 +        }
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);
8132 +        }
8133 +        /* TODO: check what happens with EG(included_files) */
8134 +    }
8135 +
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 */
8142 +        }
8143 +        if(tmp_buf) {
8144 +            fileinfo.st_buf.sb = *tmp_buf;
8145 +        } else {
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);
8149 +            }
8150 +        }
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);
8154 +        }
8155 +        key.mtime = fileinfo.st_buf.sb.st_mtime;
8156 +    }
8157 +
8158 +    HANDLE_BLOCK_INTERRUPTIONS();
8159 +
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);
8165 +        }
8166 +    }
8167 +#endif
8168 +
8169 +    zend_try {
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);
8175 +                ctxt.pool = NULL;
8176 +            }
8177 +        }
8178 +    } zend_catch {
8179 +        bailout=1; /* in the event of a bailout, ensure we don't create a dead-lock */
8180 +    } zend_end_try();
8181 +
8182 +    APCG(current_cache) = NULL;
8183 +
8184 +#if NONBLOCKING_LOCK_AVAILABLE
8185 +    if(APCG(write_lock)) {
8186 +        apc_cache_write_unlock(apc_cache TSRMLS_CC);
8187 +    }
8188 +#endif
8189 +    HANDLE_UNBLOCK_INTERRUPTIONS();
8190 +
8191 +    if (bailout) zend_bailout();
8192 +
8193 +    return op_array;
8194 +}
8195 +/* }}} */
8196 +
8197 +/* {{{ data preload */
8198 +
8199 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8200 +
8201 +static zval* data_unserialize(const char *filename TSRMLS_DC)
8202 +{
8203 +    zval* retval;
8204 +    long len = 0;
8205 +    struct stat sb;
8206 +    char *contents, *tmp;
8207 +    FILE *fp;
8208 +    php_unserialize_data_t var_hash;
8209 +
8210 +    if(VCWD_STAT(filename, &sb) == -1) {
8211 +        return NULL;
8212 +    }
8213 +
8214 +    fp = fopen(filename, "rb");
8215 +
8216 +    len = sizeof(char)*sb.st_size;
8217 +
8218 +    tmp = contents = malloc(len);
8219 +
8220 +    if(!contents) {
8221 +       return NULL;
8222 +    }
8223 +
8224 +    if(fread(contents, 1, len, fp) < 1) {      
8225 +      free(contents);
8226 +      return NULL;
8227 +    }
8228 +
8229 +    MAKE_STD_ZVAL(retval);
8230 +
8231 +    PHP_VAR_UNSERIALIZE_INIT(var_hash);
8232 +    
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);
8236 +        return NULL;
8237 +    }
8238 +
8239 +    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
8240 +
8241 +    free(contents);
8242 +    fclose(fp);
8243 +
8244 +    return retval;
8245 +}
8246 +
8247 +static int apc_load_data(const char *data_file TSRMLS_DC)
8248 +{
8249 +    char *p;
8250 +    char key[MAXPATHLEN] = {0,};
8251 +    unsigned int key_len;
8252 +    zval *data;
8253 +
8254 +    p = strrchr(data_file, DEFAULT_SLASH);
8255 +
8256 +    if(p && p[1]) {
8257 +        strlcpy(key, p+1, sizeof(key));
8258 +        p = strrchr(key, '.');
8259 +
8260 +        if(p) {
8261 +            p[0] = '\0';
8262 +            key_len = strlen(key);
8263 +
8264 +            data = data_unserialize(data_file TSRMLS_CC);
8265 +            if(data) {
8266 +                _apc_store(key, key_len, data, 0, 1 TSRMLS_CC);
8267 +            }
8268 +            return 1;
8269 +        }
8270 +    }
8271 +
8272 +    return 0;
8273 +}
8274 +
8275 +static int apc_walk_dir(const char *path TSRMLS_DC)
8276 +{
8277 +    char file[MAXPATHLEN]={0,};
8278 +    int ndir, i;
8279 +    char *p = NULL;
8280 +    struct dirent **namelist = NULL;
8281 +
8282 +    if ((ndir = php_scandir(path, &namelist, 0, php_alphasort)) > 0)
8283 +    {
8284 +        for (i = 0; i < ndir; i++)
8285 +        {
8286 +            /* check for extension */
8287 +            if (!(p = strrchr(namelist[i]->d_name, '.'))
8288 +                    || (p && strcmp(p, ".data")))
8289 +            {
8290 +                free(namelist[i]);
8291 +                continue;
8292 +            }
8293 +            snprintf(file, MAXPATHLEN, "%s%c%s",
8294 +                    path, DEFAULT_SLASH, namelist[i]->d_name);
8295 +            if(!apc_load_data(file TSRMLS_CC))
8296 +            {
8297 +                /* print error */
8298 +            }
8299 +            free(namelist[i]);
8300 +        }
8301 +        free(namelist);
8302 +    }
8303 +
8304 +    return 1;
8305 +}
8306 +
8307 +void apc_data_preload(TSRMLS_D)
8308 +{
8309 +    if(!APCG(preload_path)) return;
8310 +
8311 +    apc_walk_dir(APCG(preload_path) TSRMLS_CC);
8312 +}
8313 +/* }}} */
8314 +
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)
8319 +{
8320 +    int i;
8321 +    apc_serializer_t *serializer;
8322 +
8323 +    for(i = 0; i < APC_MAX_SERIALIZERS; i++) {
8324 +        serializer = &apc_serializers[i];
8325 +        if(!serializer->name) {
8326 +            /* empty entry */
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;
8332 +            return 1;
8333 +        }
8334 +    }
8335 +
8336 +    return 0;
8337 +}
8338 +
8339 +apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC)
8340 +{
8341 +    int i;
8342 +    apc_serializer_t *serializer;
8343 +
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;
8348 +        }
8349 +    }
8350 +    return NULL;
8351 +}
8352 +
8353 +apc_serializer_t* apc_get_serializers(TSRMLS_D)
8354 +{
8355 +    return &(apc_serializers[0]);
8356 +}
8357 +/* }}} */
8358 +
8359 +/* {{{ module init and shutdown */
8360 +
8361 +int apc_module_init(int module_number TSRMLS_DC)
8362 +{
8363 +    /* apc initialization */
8364 +#if APC_MMAP
8365 +    apc_sma_init(APCG(shm_segments), APCG(shm_size), APCG(mmap_file_mask) TSRMLS_CC);
8366 +#else
8367 +    apc_sma_init(APCG(shm_segments), APCG(shm_size), NULL TSRMLS_CC);
8368 +#endif
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);
8371 +
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);
8378 +
8379 +    /* test out the constant function pointer */
8380 +    apc_register_serializer("php", APC_SERIALIZER_NAME(php), APC_UNSERIALIZER_NAME(php), NULL TSRMLS_CC);
8381 +
8382 +    assert(apc_serializers[0].name != NULL);
8383 +
8384 +    apc_pool_init();
8385 +
8386 +    apc_data_preload(TSRMLS_C);
8387 +
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);
8392 +    }
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);
8396 +    }
8397 +#else
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;
8401 +    }
8402 +#endif
8403 +
8404 +#ifdef ZEND_ENGINE_2_4
8405 +#ifndef ZTS
8406 +    apc_interned_strings_init(TSRMLS_C);
8407 +#endif
8408 +#endif
8409 +
8410 +    APCG(initialized) = 1;
8411 +    return 0;
8412 +}
8413 +
8414 +int apc_module_shutdown(TSRMLS_D)
8415 +{
8416 +    if (!APCG(initialized))
8417 +        return 0;
8418 +
8419 +    /* restore compilation */
8420 +    zend_compile_file = old_compile_file;
8421 +
8422 +    /*
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.
8427 +     * 
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.
8431 +     */
8432 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
8433 +        int i;
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);
8440 +            }
8441 +        }
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);
8447 +            }
8448 +        }
8449 +        apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
8450 +    }
8451 +
8452 +#ifdef ZEND_ENGINE_2_4
8453 +#ifndef ZTS
8454 +    apc_interned_strings_shutdown(TSRMLS_C);
8455 +#endif
8456 +#endif
8457 +
8458 +    apc_cache_destroy(apc_cache TSRMLS_CC);
8459 +    apc_cache_destroy(apc_user_cache TSRMLS_CC);
8460 +    apc_sma_cleanup(TSRMLS_C);
8461 +
8462 +    APCG(initialized) = 0;
8463 +    return 0;
8464 +}
8465 +
8466 +/* }}} */
8467 +
8468 +/* {{{ process init and shutdown */
8469 +int apc_process_init(int module_number TSRMLS_DC)
8470 +{
8471 +    return 0;
8472 +}
8473 +
8474 +int apc_process_shutdown(TSRMLS_D)
8475 +{
8476 +    return 0;
8477 +}
8478 +/* }}} */
8479 +
8480 +
8481 +/* {{{ apc_deactivate */
8482 +static void apc_deactivate(TSRMLS_D)
8483 +{
8484 +    /* The execution stack was unwound, which prevented us from decrementing
8485 +     * the reference counts on active cache entries in `my_execute`.
8486 +     */
8487 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
8488 +        int i;
8489 +        zend_class_entry* zce = NULL;
8490 +        void ** centry = (void*)(&zce);
8491 +        zend_class_entry** pzce = NULL;
8492 +
8493 +        apc_cache_entry_t* cache_entry =
8494 +            (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
8495 +
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)
8503 +                {
8504 +                    /* double inclusion of conditional classes ends up failing 
8505 +                     * this lookup the second time around.
8506 +                     */
8507 +                    continue;
8508 +                }
8509 +
8510 +                zce = *pzce;
8511 +
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);
8515 +
8516 +                apc_free_class_entry_after_execution(zce TSRMLS_CC);
8517 +            }
8518 +        }
8519 +        apc_cache_release(apc_cache, cache_entry TSRMLS_CC);
8520 +    }
8521 +}
8522 +/* }}} */
8523 +
8524 +/* {{{ request init and shutdown */
8525 +
8526 +int apc_request_init(TSRMLS_D)
8527 +{
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);
8533 +    }
8534 +
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);
8538 +    }
8539 +
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);
8544 +    }
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);
8548 +    }
8549 +#endif
8550 +
8551 +#ifdef APC_FILEHITS
8552 +    ALLOC_INIT_ZVAL(APCG(filehits));
8553 +    array_init(APCG(filehits));
8554 +#endif
8555 +
8556 +    return 0;
8557 +}
8558 +
8559 +int apc_request_shutdown(TSRMLS_D)
8560 +{
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));
8565 +    }
8566 +    if(APCG(lazy_function_table)) {
8567 +        zend_hash_destroy(APCG(lazy_function_table));
8568 +        efree(APCG(lazy_function_table));
8569 +    }
8570 +#endif
8571 +
8572 +    apc_deactivate(TSRMLS_C);
8573 +
8574 +#ifdef APC_FILEHITS
8575 +    zval_ptr_dtor(&APCG(filehits));
8576 +#endif
8577 +    return 0;
8578 +}
8579 +
8580 +/* }}} */
8581 +
8582 +
8583 +/*
8584 + * Local variables:
8585 + * tab-width: 4
8586 + * c-basic-offset: 4
8587 + * End:
8588 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8589 + * vim<600: expandtab sw=4 ts=4 sts=4
8590 + */
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
8594 @@ -0,0 +1,88 @@
8595 +/*
8596 +  +----------------------------------------------------------------------+
8597 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
8615 +
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.
8621 +
8622 +   All other licensing and usage conditions are those of the PHP Group.
8623 +
8624 + */
8625 +
8626 +/* $Id: apc_main.h 308594 2011-02-23 12:35:33Z gopalv $ */
8627 +
8628 +#ifndef APC_MAIN_H
8629 +#define APC_MAIN_H
8630 +
8631 +#include "apc_pool.h"
8632 +#include "apc_serializer.h"
8633 +
8634 +/*
8635 + * This module provides the primary interface between PHP and APC.
8636 + */
8637 +
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);
8644 +
8645 +typedef enum _apc_copy_type {
8646 +    APC_NO_COPY = 0,
8647 +    APC_COPY_IN_OPCODE,
8648 +    APC_COPY_OUT_OPCODE,
8649 +    APC_COPY_IN_USER,
8650 +    APC_COPY_OUT_USER
8651 +} apc_copy_type;
8652 +
8653 +typedef struct _apc_context_t
8654 +{
8655 +    apc_pool *pool;
8656 +    apc_copy_type copy;
8657 +    unsigned int force_update:1;
8658 +} apc_context_t;
8659 +
8660 +/* {{{ struct apc_serializer_t */
8661 +typedef struct apc_serializer_t apc_serializer_t;
8662 +struct apc_serializer_t {
8663 +    const char *name;
8664 +    apc_serialize_t serialize;
8665 +    apc_unserialize_t unserialize;
8666 +    void *config;
8667 +};
8668 +/* }}} */
8669 +
8670 +apc_serializer_t* apc_get_serializers(TSRMLS_D);
8671 +apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC);
8672 +
8673 +#endif
8674 +
8675 +/*
8676 + * Local variables:
8677 + * tab-width: 4
8678 + * c-basic-offset: 4
8679 + * End:
8680 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8681 + * vim<600: expandtab sw=4 ts=4 sts=4
8682 + */
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
8686 @@ -0,0 +1,177 @@
8687 +/*
8688 +  +----------------------------------------------------------------------+
8689 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
8703 +
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.
8709 +
8710 +   All other licensing and usage conditions are those of the PHP Group.
8711 +
8712 + */
8713 +
8714 +/* $Id: apc_mmap.c 307048 2011-01-03 23:53:17Z kalle $ */
8715 +
8716 +#include "apc.h"
8717 +#include "apc_mmap.h"
8718 +#include "apc_lock.h"
8719 +
8720 +#if APC_MMAP
8721 +
8722 +#include <fcntl.h>
8723 +#include <sys/types.h>
8724 +#include <sys/mman.h>
8725 +
8726 +/*
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.
8732 + */
8733 +#ifndef MAP_NOSYNC
8734 +#define MAP_NOSYNC 0
8735 +#endif
8736 +
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
8740 +#endif
8741 +
8742 +apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC)
8743 +{
8744 +    apc_segment_t segment; 
8745 +
8746 +    int fd = -1;
8747 +    int flags = MAP_SHARED | MAP_NOSYNC;
8748 +    int remap = 1;
8749 +
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);
8754 +#else
8755 +        fd = -1;
8756 +        flags = MAP_SHARED | MAP_ANON;
8757 +        remap = 0;
8758 +#endif
8759 +    } else if(!strcmp(file_mask,"/dev/zero")) { 
8760 +        fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
8761 +        if(fd == -1) {
8762 +            apc_error("apc_mmap: open on /dev/zero failed:" TSRMLS_CC);
8763 +            goto error;
8764 +        }
8765 +        remap = 0; /* cannot remap */
8766 +    } else if(strstr(file_mask,".shm")) {
8767 +        /*
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.
8776 +         */
8777 +        if(!mktemp(file_mask)) {
8778 +            apc_error("apc_mmap: mktemp on %s failed:" TSRMLS_CC, file_mask);
8779 +            goto error;
8780 +        }
8781 +        fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
8782 +        if(fd == -1) {
8783 +            apc_error("apc_mmap: shm_open on %s failed:" TSRMLS_CC, file_mask);
8784 +            goto error;
8785 +        }
8786 +        if (ftruncate(fd, size) < 0) {
8787 +            close(fd);
8788 +            shm_unlink(file_mask);
8789 +            apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
8790 +            goto error;
8791 +        }
8792 +        shm_unlink(file_mask);
8793 +    } else {
8794 +        /*
8795 +         * Otherwise we do a normal filesystem mmap
8796 +         */
8797 +        fd = mkstemp(file_mask);
8798 +        if(fd == -1) {
8799 +            apc_error("apc_mmap: mkstemp on %s failed:" TSRMLS_CC, file_mask);
8800 +            goto error;
8801 +        }
8802 +        if (ftruncate(fd, size) < 0) {
8803 +            close(fd);
8804 +            unlink(file_mask);
8805 +            apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC);
8806 +            goto error;
8807 +        }
8808 +        unlink(file_mask);
8809 +    }
8810 +
8811 +    segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
8812 +    segment.size = size;
8813 +
8814 +#ifdef APC_MEMPROTECT
8815 +    if(remap) {
8816 +        segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0);
8817 +    } else {
8818 +        segment.roaddr = NULL;
8819 +    }
8820 +#endif
8821 +
8822 +    if((long)segment.shmaddr == -1) {
8823 +        apc_error("apc_mmap: mmap failed:" TSRMLS_CC);
8824 +    }
8825 +
8826 +    if(fd != -1) close(fd);
8827 +    
8828 +    return segment;
8829 +
8830 +error:
8831 +
8832 +    segment.shmaddr = (void*)-1;
8833 +    segment.size = 0;
8834 +#ifdef APC_MEMPROTECT
8835 +    segment.roaddr = NULL;
8836 +#endif
8837 +    return segment;
8838 +}
8839 +
8840 +void apc_unmap(apc_segment_t *segment TSRMLS_DC)
8841 +{
8842 +    if (munmap(segment->shmaddr, segment->size) < 0) {
8843 +        apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
8844 +    }
8845 +
8846 +#ifdef APC_MEMPROTECT
8847 +    if (segment->roaddr && munmap(segment->roaddr, segment->size) < 0) {
8848 +        apc_warning("apc_unmap: munmap failed:" TSRMLS_CC);
8849 +    }
8850 +#endif
8851 +
8852 +}
8853 +
8854 +#endif
8855 +
8856 +/*
8857 + * Local variables:
8858 + * tab-width: 4
8859 + * c-basic-offset: 4
8860 + * End:
8861 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8862 + * vim<600: expandtab sw=4 ts=4 sts=4
8863 + */
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
8867 @@ -0,0 +1,54 @@
8868 +/*
8869 +  +----------------------------------------------------------------------+
8870 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
8884 +
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.
8890 +
8891 +   All other licensing and usage conditions are those of the PHP Group.
8892 +
8893 + */
8894 +
8895 +/* $Id: apc_mmap.h 307048 2011-01-03 23:53:17Z kalle $ */
8896 +
8897 +#ifndef APC_MMAP_H
8898 +#define APC_MMAP_H
8899 +
8900 +#include <limits.h>
8901 +
8902 +#include "apc.h"
8903 +#include "apc_sma.h"
8904 +
8905 +/* Wrapper functions for shared memory mapped files */
8906 +
8907 +#if APC_MMAP
8908 +apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC);
8909 +void apc_unmap(apc_segment_t* segment TSRMLS_DC);
8910 +#endif
8911 +
8912 +#endif
8913 +
8914 +/*
8915 + * Local variables:
8916 + * tab-width: 4
8917 + * c-basic-offset: 4
8918 + * End:
8919 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
8920 + * vim<600: expandtab sw=4 ts=4 sts=4
8921 + */
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
8925 @@ -0,0 +1,1362 @@
8926 +<?php
8927 +/*
8928 +  +----------------------------------------------------------------------+
8929 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
8945 +
8946 +   All other licensing and usage conditions are those of the PHP Group.
8947 +
8948 + */
8949 +
8950 +$VERSION='$Id: apc.php 325483 2012-05-01 00:34:04Z rasmus $';
8951 +
8952 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
8953 +if (file_exists("apc.conf.php")) include("apc.conf.php");
8954 +////////////////////////////////////////////////////////
8955 +
8956 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
8957 +
8958 +defaults('USE_AUTHENTICATION',1);                      // Use (internal) authentication - best choice if 
8959 +                                                                                       // no other authentication is available
8960 +                                                                                       // If set to 0:
8961 +                                                                                       //  There will be no further authentication. You 
8962 +                                                                                       //  will have to handle this by yourself!
8963 +                                                                                       // If set to 1:
8964 +                                                                                       //  You need to change ADMIN_PASSWORD to make
8965 +                                                                                       //  this work!
8966 +defaults('ADMIN_USERNAME','apc');                      // Admin Username
8967 +defaults('ADMIN_PASSWORD','password');         // Admin Password - CHANGE THIS TO ENABLE!!!
8968 +
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
8971 +
8972 +//defaults('DATE_FORMAT', "d.m.Y H:i:s");      // German
8973 +defaults('DATE_FORMAT', 'Y/m/d H:i:s');        // US
8974 +
8975 +defaults('GRAPH_SIZE',200);                                    // Image size
8976 +
8977 +//defaults('PROXY', 'tcp://127.0.0.1:8080');
8978 +
8979 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
8980 +
8981 +
8982 +// "define if not defined"
8983 +function defaults($d,$v) {
8984 +       if (!defined($d)) define($d,$v); // or just @define(...)
8985 +}
8986 +
8987 +// rewrite $PHP_SELF to block XSS attacks
8988 +//
8989 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';
8990 +$time = time();
8991 +$host = php_uname('n');
8992 +if($host) { $host = '('.$host.')'; }
8993 +if (isset($_SERVER['SERVER_ADDR'])) {
8994 +  $host .= ' ('.$_SERVER['SERVER_ADDR'].')';
8995 +}
8996 +
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);
9003 +
9004 +// check validity of input variables
9005 +$vardom=array(
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
9010 +
9011 +       'IMG'   => '/^[123]$/',                 // image to generate
9012 +       'LO'    => '/^1$/',                             // login requested
9013 +
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
9020 +);
9021 +
9022 +// default cache mode
9023 +$cache_mode='opcode';
9024 +
9025 +// cache scope
9026 +$scope_list=array(
9027 +       'A' => 'cache_list',
9028 +       'D' => 'deleted_list'
9029 +);
9030 +
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;
9039 +       } else {
9040 +               $_REQUEST = array();
9041 +       }
9042 +}
9043 +
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];
9050 +       } else {
9051 +               $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
9052 +       }
9053 +}
9054 +
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';
9062 +
9063 +$MY_SELF=
9064 +       "$PHP_SELF".
9065 +       "?SCOPE=".$MYREQUEST['SCOPE'].
9066 +       "&SORT1=".$MYREQUEST['SORT1'].
9067 +       "&SORT2=".$MYREQUEST['SORT2'].
9068 +       "&COUNT=".$MYREQUEST['COUNT'];
9069 +$MY_SELF_WO_SORT=
9070 +       "$PHP_SELF".
9071 +       "?SCOPE=".$MYREQUEST['SCOPE'].
9072 +       "&COUNT=".$MYREQUEST['COUNT'];
9073 +
9074 +// authentication needed?
9075 +//
9076 +if (!USE_AUTHENTICATION) {
9077 +       $AUTHENTICATED=1;
9078 +} else {
9079 +       $AUTHENTICATED=0;
9080 +       if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
9081 +
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");
9088 +
9089 +                       echo <<<EOB
9090 +                               <html><body>
9091 +                               <h1>Rejected!</h1>
9092 +                               <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
9093 +                               <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
9094 +                               </body></html>
9095 +EOB;
9096 +                       exit;
9097 +                       
9098 +               } else {
9099 +                       $AUTHENTICATED=1;
9100 +               }
9101 +       }
9102 +}
9103 +       
9104 +// select cache mode
9105 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
9106 +       $cache_mode='user';
9107 +}
9108 +// clear cache
9109 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
9110 +       apc_clear_cache($cache_mode);
9111 +}
9112 +
9113 +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
9114 +       apc_delete($MYREQUEST['DU']);
9115 +}
9116 +
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.";
9119 +  exit;
9120 +}
9121 +
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
9125 +
9126 +// don't cache this page
9127 +//
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
9131 +
9132 +function duration($ts) {
9133 +    global $time;
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;
9140 +    $str = '';
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";
9151 +    return $str;
9152 +}
9153 +
9154 +// create graphics
9155 +//
9156 +function graphics_avail() {
9157 +       return extension_loaded('gd');
9158 +}
9159 +if (isset($MYREQUEST['IMG']))
9160 +{
9161 +       if (!graphics_avail()) {
9162 +               exit(0);
9163 +       }
9164 +
9165 +       function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
9166 +               $r=$diameter/2;
9167 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
9168 +
9169 +               
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);
9175 +               } else {
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);
9182 +               }
9183 +               if ($text) {
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);     
9187 +                               
9188 +                       } else {
9189 +                               imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
9190 +                       }
9191 +               }
9192 +       } 
9193 +
9194 +       function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
9195 +               $r=$diameter/2;
9196 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
9197 +
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);     
9201 +                               
9202 +               } else {
9203 +                       imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
9204 +               }
9205 +       } 
9206 +       
9207 +       function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
9208 +               global $col_black;
9209 +               $x1=$x+$w-1;
9210 +               $y1=$y+$h-1;
9211 +
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);
9216 +               if ($text) {
9217 +                       if ($placeindex>0) {
9218 +                       
9219 +                               if ($placeindex<16)
9220 +                               {
9221 +                                       $px=5;
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);     
9226 +                                       
9227 +                               } else {
9228 +                                       if ($placeindex<31) {
9229 +                                               $px=$x+40*2;
9230 +                                               $py=($placeindex-15)*12+6;
9231 +                                       } else {
9232 +                                               $px=$x+40*2+100*intval(($placeindex-15)/15);
9233 +                                               $py=($placeindex%15)*12+6;
9234 +                                       }
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);   
9238 +                               }
9239 +                       } else {
9240 +                               imagestring($im,4,$x+5,$y1-16,$text,$color1);
9241 +                       }
9242 +               }
9243 +       }
9244 +
9245 +
9246 +       $size = GRAPH_SIZE; // image size
9247 +       if ($MYREQUEST['IMG']==3)
9248 +               $image = imagecreate(2*$size+150, $size+10);
9249 +       else
9250 +               $image = imagecreate($size+50, $size+10);
9251 +
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);
9257 +
9258 +       switch ($MYREQUEST['IMG']) {
9259 +       
9260 +       case 1:
9261 +               $s=$mem['num_seg']*$mem['seg_size'];
9262 +               $a=$mem['avail_mem'];
9263 +               $x=$y=$size/2;
9264 +               $fuzz = 0.000001;
9265 +
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.
9268 +               $angle_from = 0;
9269 +               $string_placement=array();
9270 +               for($i=0; $i<$mem['num_seg']; $i++) {   
9271 +                       $ptr = 0;
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));
9282 +                                               }
9283 +                                       }
9284 +                                       $angle_from = $angle_to;
9285 +                               }
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));
9292 +                                       }
9293 +                               }
9294 +                               $angle_from = $angle_to;
9295 +                               $ptr = $block['offset']+$block['size'];
9296 +                       }
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));
9303 +                               }
9304 +                       }
9305 +               }
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])));
9308 +               }
9309 +               break;
9310 +               
9311 +       case 2: 
9312 +               $s=$cache['num_hits']+$cache['num_misses'];
9313 +               $a=$cache['num_hits'];
9314 +               
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));
9317 +               break;
9318 +               
9319 +       case 3:
9320 +               $s=$mem['num_seg']*$mem['seg_size'];
9321 +               $a=$mem['avail_mem'];
9322 +               $x=130;
9323 +               $y=1;
9324 +               $j=1;
9325 +
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++) {   
9329 +                       $ptr = 0;
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;
9335 +                                       if ($h>0) {
9336 +                                                $j++;
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);
9339 +                                        }
9340 +                                       $y+=$h;
9341 +                               }
9342 +                               $h=(GRAPH_SIZE-5)*($block['size'])/$s;
9343 +                               if ($h>0) {
9344 +                                        $j++;
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);
9347 +                                }
9348 +                               $y+=$h;
9349 +                               $ptr = $block['offset']+$block['size'];
9350 +                       }
9351 +                       if ($ptr < $mem['seg_size']) { // memory at the end 
9352 +                               $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
9353 +                               if ($h > 0) {
9354 +                                       fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
9355 +                               }
9356 +                       }
9357 +               }
9358 +               break;
9359 +       case 4: 
9360 +               $s=$cache['num_hits']+$cache['num_misses'];
9361 +               $a=$cache['num_hits'];
9362 +                       
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));
9365 +               break;
9366 +       
9367 +       }
9368 +       header("Content-type: image/png");
9369 +       imagepng($image);
9370 +       exit;
9371 +}
9372 +
9373 +// pretty printer for byte values
9374 +//
9375 +function bsize($s) {
9376 +       foreach (array('','K','M','G') as $i => $k) {
9377 +               if ($s < 1024) break;
9378 +               $s/=1024;
9379 +       }
9380 +       return sprintf("%5.1f %sBytes",$s,$k);
9381 +}
9382 +
9383 +// sortable table header in "scripts for this host" view
9384 +function sortheader($key,$name,$extra='') {
9385 +       global $MYREQUEST, $MY_SELF_WO_SORT;
9386 +       
9387 +       if ($MYREQUEST['SORT1']==$key) {
9388 +               $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
9389 +       }
9390 +       return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
9391 +
9392 +}
9393 +
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>";
9401 +       } else {
9402 +               return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
9403 +       }
9404 +}
9405 +
9406 +function put_login_link($s="Login")
9407 +{
9408 +       global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
9409 +       // needs ADMIN_PASSWORD to be changed!
9410 +       //
9411 +       if (!USE_AUTHENTICATION) {
9412 +               return;
9413 +       } else if (ADMIN_PASSWORD=='password')
9414 +       {
9415 +               print <<<EOB
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>
9417 +EOB;
9418 +       } else if ($AUTHENTICATED) {
9419 +               print <<<EOB
9420 +                       '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
9421 +EOB;
9422 +       } else{
9423 +               print <<<EOB
9424 +                       <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
9425 +EOB;
9426 +       }
9427 +}
9428 +
9429 +function block_sort($array1, $array2)
9430 +{
9431 +       if ($array1['offset'] > $array2['offset']) {
9432 +               return 1;
9433 +       } else {
9434 +               return -1;
9435 +       }
9436 +}
9437 +
9438 +
9439 +?>
9440 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
9441 +<html>
9442 +<head><title>APC INFO <?php echo $host ?></title>
9443 +<style><!--
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; }
9456 +
9457 +
9458 +div.head div.login {
9459 +       position:absolute;
9460 +       right: 1em;
9461 +       top: 1.2em;
9462 +       color:white;
9463 +       width:6em;
9464 +       }
9465 +div.head div.login a {
9466 +       position:absolute;
9467 +       right: 0em;
9468 +       background:rgb(119,123,180);
9469 +       border:solid rgb(102,102,153) 2px;
9470 +       color:white;
9471 +       font-weight:bold;
9472 +       padding:0.1em 0.5em 0.1em 0.5em;
9473 +       text-decoration:none;
9474 +       }
9475 +div.head div.login a:hover {
9476 +       background:rgb(193,193,244);
9477 +       }
9478 +
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);
9484 +       color:black;
9485 +       border-right: solid black 1px;
9486 +       border-bottom: solid black 1px;
9487 +       font-style:italic;
9488 +       font-size:1em;
9489 +       padding-left:1.2em;
9490 +       padding-right:1.2em;
9491 +       text-align:right;
9492 +       }
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; }
9496 +hr.apc {
9497 +       background:white;
9498 +       border-bottom:solid rgb(102,102,153) 1px;
9499 +       border-style:none;
9500 +       border-top:solid rgb(102,102,153) 10px;
9501 +       height:12px;
9502 +       margin:0;
9503 +       margin-top:1px;
9504 +       padding:0;
9505 +}
9506 +
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%}
9509 +ol.menu a {
9510 +       background:rgb(153,153,204);
9511 +       border:solid rgb(102,102,153) 2px;
9512 +       color:white;
9513 +       font-weight:bold;
9514 +       margin-right:0em;
9515 +       padding:0.1em 0.5em 0.1em 0.5em;
9516 +       text-decoration:none;
9517 +       margin-left: 5px;
9518 +       }
9519 +ol.menu a.child_active {
9520 +       background:rgb(153,153,204);
9521 +       border:solid rgb(102,102,153) 2px;
9522 +       color:white;
9523 +       font-weight:bold;
9524 +       margin-right:0em;
9525 +       padding:0.1em 0.5em 0.1em 0.5em;
9526 +       text-decoration:none;
9527 +       border-left: solid black 5px;
9528 +       margin-left: 0px;
9529 +       }
9530 +ol.menu span.active {
9531 +       background:rgb(153,153,204);
9532 +       border:solid rgb(102,102,153) 2px;
9533 +       color:black;
9534 +       font-weight:bold;
9535 +       margin-right:0em;
9536 +       padding:0.1em 0.5em 0.1em 0.5em;
9537 +       text-decoration:none;
9538 +       border-left: solid black 5px;
9539 +       }
9540 +ol.menu span.inactive {
9541 +       background:rgb(193,193,244);
9542 +       border:solid rgb(182,182,233) 2px;
9543 +       color:white;
9544 +       font-weight:bold;
9545 +       margin-right:0em;
9546 +       padding:0.1em 0.5em 0.1em 0.5em;
9547 +       text-decoration:none;
9548 +       margin-left: 5px;
9549 +       }
9550 +ol.menu a:hover {
9551 +       background:rgb(193,193,244);
9552 +       text-decoration:none;
9553 +       }
9554 +       
9555 +       
9556 +div.info {
9557 +       background:rgb(204,204,204);
9558 +       border:solid rgb(204,204,204) 1px;
9559 +       margin-bottom:1em;
9560 +       }
9561 +div.info h2 {
9562 +       background:rgb(204,204,204);
9563 +       color:black;
9564 +       font-size:1em;
9565 +       margin:0;
9566 +       padding:0.1em 1em 0.1em 1em;
9567 +       }
9568 +div.info table {
9569 +       border:solid rgb(204,204,204) 1px;
9570 +       border-spacing:0;
9571 +       width:100%;
9572 +       }
9573 +div.info table th {
9574 +       background:rgb(204,204,204);
9575 +       color:white;
9576 +       margin:0;
9577 +       padding:0.1em 1em 0.1em 1em;
9578 +       }
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 {
9586 +       color:black;
9587 +       font-size:1.1em;
9588 +       margin-left:-0.3em;
9589 +       }
9590 +
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; }
9597 +
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; }
9601 +
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}
9608 +
9609 +span.box {
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;
9614 +       margin-right:1em;
9615 +}
9616 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
9617 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
9618 +
9619 +div.authneeded {
9620 +       background:rgb(238,238,238);
9621 +       border:solid rgb(204,204,204) 1px;
9622 +       color:rgb(200,0,0);
9623 +       font-size:1.2em;
9624 +       font-weight:bold;
9625 +       padding:2em;
9626 +       text-align:center;
9627 +       }
9628 +       
9629 +input {
9630 +       background:rgb(153,153,204);
9631 +       border:solid rgb(102,102,153) 2px;
9632 +       color:white;
9633 +       font-weight:bold;
9634 +       margin-right:1em;
9635 +       padding:0.1em 0.5em 0.1em 0.5em;
9636 +       }
9637 +//-->
9638 +</style>
9639 +</head>
9640 +<body>
9641 +<div class="head">
9642 +       <h1 class="apc">
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>
9645 +       </h1>
9646 +       <div class="login">
9647 +       <?php put_login_link(); ?>
9648 +       </div>
9649 +       <hr class="apc">
9650 +</div>
9651 +<?php
9652 +
9653 +
9654 +// Display main Menu
9655 +echo <<<EOB
9656 +       <ol class=menu>
9657 +       <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
9658 +EOB;
9659 +echo
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');
9664 +}
9665 +echo
9666 +       menu_entry(3,'User Cache Entries'),
9667 +       menu_entry(9,'Version Check');
9668 +       
9669 +if ($AUTHENTICATED) {
9670 +       echo <<<EOB
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>
9672 +EOB;
9673 +}
9674 +echo <<<EOB
9675 +       </ol>
9676 +EOB;
9677 +
9678 +
9679 +// CONTENT
9680 +echo <<<EOB
9681 +       <div class=content>
9682 +EOB;
9683 +
9684 +// MAIN SWITCH STATEMENT 
9685 +
9686 +switch ($MYREQUEST['OB']) {
9687 +
9688 +
9689 +
9690 +
9691 +
9692 +// -----------------------------------------------
9693 +// Host Stats
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']);
9714 +       $i=0;
9715 +       echo <<< EOB
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>
9720 +EOB;
9721 +
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";
9726 +
9727 +       echo <<<EOB
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)
9730 +    </td></tr>
9731 +EOB;
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>';
9735 +       echo <<<EOB
9736 +               </tbody></table>
9737 +               </div>
9738 +
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>
9749 +               </tbody></table>
9750 +               </div>
9751 +
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>
9762 +
9763 +               </tbody></table>
9764 +               </div>
9765 +
9766 +               <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
9767 +EOB;
9768 +
9769 +       $j = 0;
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";
9772 +               $j = 1 - $j;
9773 +       }
9774 +
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>";
9777 +       else
9778 +               $mem_note = "Memory Usage";
9779 +
9780 +       echo <<< EOB
9781 +               </tbody></table>
9782 +               </div>
9783 +
9784 +               <div class="graph div3"><h2>Host Status Diagrams</h2>
9785 +               <table cellspacing=0><tbody>
9786 +EOB;
9787 +       $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
9788 +       echo <<<EOB
9789 +               <tr>
9790 +               <td class=td-0>$mem_note</td>
9791 +               <td class=td-1>Hits &amp; Misses</td>
9792 +               </tr>
9793 +EOB;
9794 +
9795 +       echo
9796 +               graphics_avail() ? 
9797 +                         '<tr>'.
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"
9800 +                       : "",
9801 +               '<tr>',
9802 +               '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
9803 +               '<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
9804 +               '</tr>',
9805 +               '<tr>',
9806 +               '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
9807 +               '<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
9808 +       echo <<< EOB
9809 +               </tr>
9810 +               </tbody></table>
9811 +
9812 +               <br/>
9813 +               <h2>Detailed Memory Usage and Fragmentation</h2>
9814 +               <table cellspacing=0><tbody>
9815 +               <tr>
9816 +               <td class=td-0 colspan=2><br/>
9817 +EOB;
9818 +
9819 +       // Fragementation: (freeseg - 1) / total_seg
9820 +       $nseg = $freeseg = $fragsize = $freetotal = 0;
9821 +       for($i=0; $i<$mem['num_seg']; $i++) {
9822 +               $ptr = 0;
9823 +               foreach($mem['block_lists'][$i] as $block) {
9824 +                       if ($block['offset'] != $ptr) {
9825 +                               ++$nseg;
9826 +                       }
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'];
9831 +               }
9832 +               $freeseg += count($mem['block_lists'][$i]);
9833 +       }
9834 +       
9835 +       if ($freeseg > 1) {
9836 +               $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
9837 +       } else {
9838 +               $frag = "0%";
9839 +       }
9840 +
9841 +       if (graphics_avail()) {
9842 +               $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
9843 +               echo <<<EOB
9844 +                       <img alt="" $size src="$PHP_SELF?IMG=3&$time">
9845 +EOB;
9846 +       }
9847 +       echo <<<EOB
9848 +               </br>Fragmentation: $frag
9849 +               </td>
9850 +               </tr>
9851 +EOB;
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";
9858 +          }
9859 +        }
9860 +        echo <<<EOB
9861 +               </tbody></table>
9862 +               </div>
9863 +EOB;
9864 +               
9865 +       break;
9866 +
9867 +
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/>&nbsp;<br/>';
9874 +               put_login_link("Login now!");
9875 +               echo '</div>';
9876 +               break;
9877 +       }
9878 +       $fieldname='info';
9879 +       $fieldheading='User Entry Label';
9880 +       $fieldkey='info';
9881 +
9882 +// -----------------------------------------------
9883 +// System Cache Entries                
9884 +// -----------------------------------------------
9885 +case OB_SYS_CACHE:     
9886 +       if (!isset($fieldname))
9887 +       {
9888 +               $fieldname='filename';
9889 +               $fieldheading='Script Filename';
9890 +               if(ini_get("apc.stat")) $fieldkey='inode';
9891 +               else $fieldkey='filename'; 
9892 +       }
9893 +       if (!empty($MYREQUEST['SH']))
9894 +       {
9895 +               echo <<< EOB
9896 +                       <div class="info"><table cellspacing=0><tbody>
9897 +                       <tr><th>Attribute</th><th>Value</th></tr>
9898 +EOB;
9899 +
9900 +               $m=0;
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>&lt;hidden&gt;</i>/',$value);
9908 +                                       }
9909 +
9910 +                                       if ($k == "num_hits") {
9911 +                                               $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
9912 +                                       }
9913 +                                       if ($k == 'deletion_time') {
9914 +                                               if(!$entry['deletion_time']) $value = "None";
9915 +                                       }
9916 +                                       echo
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>",
9920 +                                               "</tr>";
9921 +                                       $m=1-$m;
9922 +                               }
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";
9928 +                               }
9929 +                               break;
9930 +                       }
9931 +               }
9932 +
9933 +               echo <<<EOB
9934 +                       </tbody></table>
9935 +                       </div>
9936 +EOB;
9937 +               break;
9938 +       }
9939 +
9940 +       $cols=6;
9941 +       echo <<<EOB
9942 +               <div class=sorting><form>Scope:
9943 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
9944 +               <select name=SCOPE>
9945 +EOB;
9946 +       echo 
9947 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
9948 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
9949 +               "</select>",
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>";
9960 +       echo 
9961 +               '</select>',
9962 +               '<select name=SORT2>',
9963 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
9964 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
9965 +               '</select>',
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>',
9975 +               '</select>',
9976 +    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
9977 +               '&nbsp;<input type=submit value="GO!">',
9978 +               '</form></div>';
9979 +
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>';
9986 +     break;
9987 +   }
9988 +  }
9989 +
9990 +  echo
9991 +               '<div class="info"><table cellspacing=0><tbody>',
9992 +               '<tr>',
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>';
9999 +
10000 +       if($fieldname=='info') {
10001 +               $cols+=2;
10002 +                echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
10003 +       }
10004 +       echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
10005 +
10006 +       // builds list with alpha numeric sortable keys
10007 +       //
10008 +       $list = array();
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;
10019 +               }
10020 +               if (!$AUTHENTICATED) {
10021 +                       // hide all path entries if not logged in
10022 +                       $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry);
10023 +               } else {
10024 +                       $list[$k.$entry[$fieldname]]=$entry;
10025 +               }
10026 +       }
10027 +
10028 +       if ($list) {
10029 +               
10030 +               // sort list
10031 +               //
10032 +               switch ($MYREQUEST['SORT2']) {
10033 +                       case "A":       krsort($list);  break;
10034 +                       case "D":       ksort($list);   break;
10035 +               }
10036 +               
10037 +               // output list
10038 +               $i=0;
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');
10042 +        echo
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>';
10050 +
10051 +        if($fieldname=='info') {
10052 +          if($entry['ttl'])
10053 +            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
10054 +          else
10055 +            echo '<td class="td-n center">None</td>';
10056 +        }
10057 +        if ($entry['deletion_time']) {
10058 +
10059 +          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
10060 +        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
10061 +
10062 +          echo '<td class="td-last center">';
10063 +          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
10064 +          echo '</td>';
10065 +        } else {
10066 +          echo '<td class="td-last center"> &nbsp; </td>';
10067 +        }
10068 +        echo '</tr>';
10069 +        $i++;
10070 +        if ($i == $MYREQUEST['COUNT'])
10071 +          break;
10072 +      }
10073 +               }
10074 +               
10075 +       } else {
10076 +               echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
10077 +       }
10078 +       echo <<< EOB
10079 +               </tbody></table>
10080 +EOB;
10081 +
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>';
10084 +       }
10085 +
10086 +       echo <<< EOB
10087 +               </div>
10088 +EOB;
10089 +       break;
10090 +
10091 +
10092 +// -----------------------------------------------
10093 +// Per-Directory System Cache Entries
10094 +// -----------------------------------------------
10095 +case OB_SYS_CACHE_DIR: 
10096 +       if (!$AUTHENTICATED) {
10097 +               break;
10098 +       }
10099 +
10100 +       echo <<<EOB
10101 +               <div class=sorting><form>Scope:
10102 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
10103 +               <select name=SCOPE>
10104 +EOB;
10105 +       echo 
10106 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
10107 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
10108 +               "</select>",
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>",
10116 +               '</select>',
10117 +               '<select name=SORT2>',
10118 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
10119 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
10120 +               '</select>',
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>',
10130 +               '</select>',
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 +               '&nbsp;<input type=submit value="GO!">',
10137 +               '</form></div>',
10138 +
10139 +               '<div class="info"><table cellspacing=0><tbody>',
10140 +               '<tr>',
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>',
10147 +               '</tr>';
10148 +
10149 +       // builds list with alpha numeric sortable keys
10150 +       //
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);
10156 +               }
10157 +               if (!isset($tmp[$n])) {
10158 +                       $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
10159 +               }
10160 +               $tmp[$n]['hits'] += $entry['num_hits'];
10161 +               $tmp[$n]['size'] += $entry['mem_size'];
10162 +               ++$tmp[$n]['ents'];
10163 +       }
10164 +
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;
10173 +               }
10174 +               $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
10175 +       }
10176 +
10177 +       if ($list) {
10178 +               
10179 +               // sort list
10180 +               //
10181 +               switch ($MYREQUEST['SORT2']) {
10182 +                       case "A":       krsort($list);  break;
10183 +                       case "D":       ksort($list);   break;
10184 +               }
10185 +               
10186 +               // output list
10187 +               $i = 0;
10188 +               foreach($list as $entry) {
10189 +                       echo
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>',
10197 +                               '</tr>';
10198 +
10199 +                       if (++$i == $MYREQUEST['COUNT']) break;
10200 +               }
10201 +               
10202 +       } else {
10203 +               echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
10204 +       }
10205 +       echo <<< EOB
10206 +               </tbody></table>
10207 +EOB;
10208 +
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>';
10211 +       }
10212 +
10213 +       echo <<< EOB
10214 +               </div>
10215 +EOB;
10216 +       break;
10217 +
10218 +// -----------------------------------------------
10219 +// Version check
10220 +// -----------------------------------------------
10221 +case OB_VERSION_CHECK:
10222 +       echo <<<EOB
10223 +               <div class="info"><h2>APC Version Information</h2>
10224 +               <table cellspacing=0><tbody>
10225 +               <tr>
10226 +               <th></th>
10227 +               </tr>
10228 +EOB;
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);
10232 +  } else {
10233 +    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
10234 +  }
10235 +       if (!$rss) {
10236 +               echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
10237 +       } else {
10238 +               $apcversion = phpversion('apc');
10239 +
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>';
10244 +                       $i = 3;
10245 +               } else {
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>
10249 +                               </div>';
10250 +                       $i = -1;
10251 +               }
10252 +               echo '</td></tr>';
10253 +               echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
10254 +
10255 +               preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
10256 +               next($match[2]); next($match[2]);
10257 +
10258 +               while (list(,$v) = each($match[2])) {
10259 +                       list(,$ver) = explode(' ', $v, 2);
10260 +                       if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
10261 +                               break;
10262 +                       } else if (!$i--) {
10263 +                               break;
10264 +                       }
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>";
10267 +                       next($match[2]);
10268 +               }
10269 +               echo '</td></tr>';
10270 +       }
10271 +       echo <<< EOB
10272 +               </tbody></table>
10273 +               </div>
10274 +EOB;
10275 +       break;
10276 +
10277 +}
10278 +
10279 +echo <<< EOB
10280 +       </div>
10281 +EOB;
10282 +
10283 +?>
10284 +
10285 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
10286 +</body>
10287 +</html>
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
10291 @@ -0,0 +1,81 @@
10292 +/*
10293 +  +----------------------------------------------------------------------+
10294 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
10312 +
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.
10318 +
10319 +   All other licensing and usage conditions are those of the PHP Group.
10320 +
10321 + */
10322 +
10323 +/* $Id: apc_php.h 313808 2011-07-28 06:17:10Z gopalv $ */
10324 +
10325 +#ifndef APC_PHP_H
10326 +#define APC_PHP_H
10327 +
10328 +/*
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.
10332 + */
10333 +
10334 +#include "php.h"
10335 +#include "zend.h"
10336 +#include "zend_API.h"
10337 +#include "zend_compile.h"
10338 +#include "zend_hash.h"
10339 +#include "zend_extensions.h"
10340 +
10341 +#if ZEND_MODULE_API_NO >= 20100409
10342 +#define ZEND_ENGINE_2_4
10343 +#endif
10344 +#if ZEND_MODULE_API_NO > 20060613
10345 +#define ZEND_ENGINE_2_3
10346 +#endif
10347 +#if ZEND_MODULE_API_NO > 20050922
10348 +#define ZEND_ENGINE_2_2
10349 +#endif
10350 +#if ZEND_MODULE_API_NO > 20050921
10351 +#define ZEND_ENGINE_2_1
10352 +#endif
10353 +#ifdef ZEND_ENGINE_2_1
10354 +#include "zend_vm.h"
10355 +#endif
10356 +
10357 +#ifndef IS_CONSTANT_TYPE_MASK
10358 +#define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
10359 +#endif
10360 +
10361 +#include "rfc1867.h"
10362 +
10363 +#endif
10364 +
10365 +/*
10366 + * Local variables:
10367 + * tab-width: 4
10368 + * c-basic-offset: 4
10369 + * End:
10370 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
10371 + * vim<600: expandtab sw=4 ts=4 sts=4
10372 + */
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
10376 @@ -0,0 +1,98 @@
10377 +/*
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 +   +----------------------------------------------------------------------+
10393 + */
10394
10395 +/* $Id: apc_php_pcre.h 307048 2011-01-03 23:53:17Z kalle $ */
10396 +
10397 +#ifndef PHP_PCRE_H
10398 +#define PHP_PCRE_H
10399 +
10400 +#if HAVE_PCRE || HAVE_BUNDLED_PCRE
10401 +
10402 +#if HAVE_BUNDLED_PCRE
10403 +#include "ext/pcre/pcrelib/pcre.h"
10404 +#else
10405 +#include "pcre.h"
10406 +#endif
10407 +
10408 +#if HAVE_LOCALE_H
10409 +#include <locale.h>
10410 +#endif
10411 +
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);
10419 +
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);
10423 +
10424 +extern zend_module_entry pcre_module_entry;
10425 +#define pcre_module_ptr &pcre_module_entry
10426 +
10427 +typedef struct {
10428 +       pcre *re;
10429 +       pcre_extra *extra;
10430 +       int preg_options;
10431 +#if HAVE_SETLOCALE
10432 +       char *locale;
10433 +       unsigned const char *tables;
10434 +#endif
10435 +       int compile_options;
10436 +       int refcount;
10437 +} pcre_cache_entry;
10438 +
10439 +PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC);
10440 +
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);
10443 +
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);
10446 +
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);
10449 +
10450 +PHPAPI void  php_pcre_grep_impl(   pcre_cache_entry *pce, zval *input, zval *return_value,
10451 +       long flags TSRMLS_DC);
10452 +
10453 +ZEND_BEGIN_MODULE_GLOBALS(pcre)
10454 +       HashTable pcre_cache;
10455 +       long backtrack_limit;
10456 +       long recursion_limit;
10457 +       int  error_code;
10458 +ZEND_END_MODULE_GLOBALS(pcre)
10459 +
10460 +#ifdef ZTS
10461 +# define PCRE_G(v) TSRMG(pcre_globals_id, zend_pcre_globals *, v)
10462 +#else
10463 +# define PCRE_G(v)     (pcre_globals.v)
10464 +#endif
10465 +
10466 +#else
10467 +
10468 +#define pcre_module_ptr NULL
10469 +
10470 +#endif /* HAVE_PCRE || HAVE_BUNDLED_PCRE */
10471 +
10472 +#define phpext_pcre_ptr pcre_module_ptr
10473 +
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
10478 @@ -0,0 +1,507 @@
10479 +/*
10480 +  +----------------------------------------------------------------------+
10481 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
10495 +
10496 +   This software was contributed to PHP by Yahoo! Inc. in 2008.
10497 +
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.
10501 +
10502 +   All other licensing and usage conditions are those of the PHP Group.
10503 +
10504 + */
10505 +
10506 +/* $Id: apc_pool.c 307555 2011-01-18 07:17:21Z gopalv $ */
10507 +
10508 +
10509 +#include "apc_pool.h"
10510 +#include <assert.h>
10511 +
10512 +#ifdef HAVE_VALGRIND_MEMCHECK_H
10513 +#include <valgrind/memcheck.h>
10514 +#endif
10515 +
10516 +
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);
10520 +/* }}} */
10521 +
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
10528 +                           TSRMLS_DC)
10529 +{
10530 +    if(pool_type == APC_UNPOOL) {
10531 +        return apc_unpool_create(pool_type, allocate, deallocate,
10532 +                                            protect, unprotect TSRMLS_CC);
10533 +    }
10534 +
10535 +    return apc_realpool_create(pool_type, allocate, deallocate, 
10536 +                                          protect,  unprotect TSRMLS_CC);
10537 +}
10538 +/* }}} */
10539 +
10540 +/* {{{ apc_pool_destroy */
10541 +void apc_pool_destroy(apc_pool *pool TSRMLS_DC)
10542 +{
10543 +    apc_free_t deallocate = pool->deallocate;
10544 +    apc_pcleanup_t cleanup = pool->cleanup;
10545 +
10546 +    cleanup(pool TSRMLS_CC);
10547 +    deallocate(pool TSRMLS_CC);
10548 +}
10549 +/* }}} */
10550 +
10551 +/* {{{ apc_unpool implementation */
10552 +
10553 +typedef struct _apc_unpool apc_unpool;
10554 +
10555 +struct _apc_unpool {
10556 +    apc_pool parent;
10557 +    /* apc_unpool is a lie! */
10558 +};
10559 +
10560 +static void* apc_unpool_alloc(apc_pool* pool, size_t size TSRMLS_DC) 
10561 +{
10562 +    apc_unpool *upool = (apc_unpool*)pool;
10563 +
10564 +    apc_malloc_t allocate = upool->parent.allocate;
10565 +
10566 +    upool->parent.size += size;
10567 +    upool->parent.used += size;
10568 +
10569 +    return allocate(size TSRMLS_CC);
10570 +}
10571 +
10572 +static void apc_unpool_free(apc_pool* pool, void *ptr TSRMLS_DC)
10573 +{
10574 +    apc_unpool *upool = (apc_unpool*) pool;
10575 +
10576 +    apc_free_t deallocate = upool->parent.deallocate;
10577 +
10578 +    deallocate(ptr TSRMLS_CC);
10579 +}
10580 +
10581 +static void apc_unpool_cleanup(apc_pool* pool TSRMLS_DC)
10582 +{
10583 +}
10584 +
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
10588 +                   TSRMLS_DC)
10589 +{
10590 +    apc_unpool* upool = allocate(sizeof(apc_unpool) TSRMLS_CC);
10591 +
10592 +    if (!upool) {
10593 +        return NULL;
10594 +    }
10595 +
10596 +    upool->parent.type = type;
10597 +    upool->parent.allocate = allocate;
10598 +    upool->parent.deallocate = deallocate;
10599 +
10600 +    upool->parent.protect = protect;
10601 +    upool->parent.unprotect = unprotect;
10602 +
10603 +    upool->parent.palloc = apc_unpool_alloc;
10604 +    upool->parent.pfree  = apc_unpool_free;
10605 +
10606 +    upool->parent.cleanup = apc_unpool_cleanup;
10607 +
10608 +    upool->parent.used = 0;
10609 +    upool->parent.size = 0;
10610 +
10611 +    return &(upool->parent);
10612 +}
10613 +/* }}} */
10614 +
10615 +
10616 +/*{{{ apc_realpool implementation */
10617 +
10618 +/* {{{ typedefs */
10619 +typedef struct _pool_block
10620 +{
10621 +    size_t              avail;
10622 +    size_t              capacity;
10623 +    unsigned char       *mark;
10624 +    struct _pool_block  *next;
10625 +    unsigned             :0; /* this should align to word */
10626 +    /* data comes here */
10627 +}pool_block;
10628 +
10629 +/*
10630 +   parts in ? are optional and turned on for fun, memory loss,
10631 +   and for something else that I forgot about ... ah, debugging
10632 +
10633 +                 |--------> data[]         |<-- non word boundary (too)
10634 +   +-------------+--------------+-----------+-------------+-------------->>>
10635 +   | pool_block  | ?sizeinfo<1> | block<1>  | ?redzone<1> | ?sizeinfo<2>
10636 +   |             |  (size_t)    |           | padded left |
10637 +   +-------------+--------------+-----------+-------------+-------------->>>
10638 + */
10639 +
10640 +typedef struct _apc_realpool apc_realpool;
10641 +
10642 +struct _apc_realpool
10643 +{
10644 +    struct _apc_pool parent;
10645 +
10646 +    size_t     dsize;
10647 +    void       *owner;
10648 +
10649 +    unsigned long count;
10650 +
10651 +    pool_block *head;
10652 +    pool_block first; 
10653 +};
10654 +
10655 +/* }}} */
10656 +
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
10663 +};
10664 +
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 */
10670 +
10671 +#define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t))
10672 +
10673 +#define MARK_REDZONE(block, redsize) do {\
10674 +       memcpy(block, decaff, redsize );\
10675 +    } while(0)
10676 +
10677 +#define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0)
10678 +
10679 +/* }}} */
10680 +
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);\
10686 +} while(0)
10687 +
10688 +/* {{{ create_pool_block */
10689 +static pool_block* create_pool_block(apc_realpool *rpool, size_t size TSRMLS_DC)
10690 +{
10691 +    apc_malloc_t allocate = rpool->parent.allocate;
10692 +
10693 +    size_t realsize = sizeof(pool_block) + ALIGNWORD(size);
10694 +
10695 +    pool_block* entry = allocate(realsize TSRMLS_CC);
10696 +
10697 +    if (!entry) {
10698 +        return NULL;
10699 +    }
10700 +
10701 +    INIT_POOL_BLOCK(rpool, entry, size);
10702 +    
10703 +    rpool->parent.size += realsize;
10704 +
10705 +    rpool->count++;
10706 +
10707 +    return entry;
10708 +}
10709 +/* }}} */
10710 +
10711 +/* {{{ apc_realpool_alloc */
10712 +static void* apc_realpool_alloc(apc_pool *pool, size_t size TSRMLS_DC)
10713 +{
10714 +    apc_realpool *rpool = (apc_realpool*)pool;
10715 +    unsigned char *p = NULL;
10716 +    size_t realsize = ALIGNWORD(size);
10717 +    size_t poolsize;
10718 +    unsigned char *redzone  = NULL;
10719 +    size_t redsize  = 0;
10720 +    size_t *sizeinfo= NULL;
10721 +    pool_block *entry = NULL;
10722 +    unsigned long i;
10723 +    
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 */
10727 +    } else {
10728 +        redsize = realsize - size; /* use padding space */
10729 +    }
10730 +
10731 +    if(APC_POOL_HAS_SIZEINFO(pool)) {
10732 +        realsize += ALIGNWORD(sizeof(size_t));
10733 +    }
10734 +
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) {
10739 +            goto found;
10740 +        }
10741 +    }
10742 +
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;
10748 +    }
10749 +
10750 +    poolsize = ALIGNSIZE(realsize, rpool->dsize);
10751 +
10752 +    entry = create_pool_block(rpool, poolsize TSRMLS_CC);
10753 +
10754 +    if(!entry) {
10755 +        return NULL;
10756 +    }
10757 +
10758 +found:
10759 +    p = entry->mark;
10760 +
10761 +    if(APC_POOL_HAS_SIZEINFO(pool)) {
10762 +        sizeinfo = (size_t*)p;
10763 +        p += SIZEINFO_SIZE;
10764 +        *sizeinfo = size;
10765 +    }
10766 +
10767 +    redzone = p + size;
10768 +
10769 +    if(APC_POOL_HAS_REDZONES(pool)) {
10770 +        MARK_REDZONE(redzone, redsize);
10771 +    }
10772 +
10773 +#ifdef VALGRIND_MAKE_MEM_NOACCESS
10774 +    if(redsize != 0) {
10775 +        VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
10776 +    }
10777 +#endif
10778 +
10779 +    entry->avail -= realsize;
10780 +    entry->mark  += realsize;
10781 +    pool->used   += realsize;
10782 +
10783 +#ifdef VALGRIND_MAKE_MEM_UNDEFINED
10784 +    /* need to write before reading data off this */
10785 +    VALGRIND_MAKE_MEM_UNDEFINED(p, size);
10786 +#endif
10787 +
10788 +    return (void*)p;
10789 +}
10790 +/* }}} */
10791 +
10792 +/* {{{ apc_realpool_check_integrity */
10793 +/*
10794 + * Checking integrity at runtime, does an
10795 + * overwrite check only when the sizeinfo
10796 + * is set.
10797 + *
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.
10801 + */
10802 +static APC_USED int apc_realpool_check_integrity(apc_realpool *rpool) 
10803 +{
10804 +    apc_pool *pool = &(rpool->parent); 
10805 +    pool_block *entry;
10806 +    size_t *sizeinfo = NULL;
10807 +    unsigned char *start;
10808 +    size_t realsize;
10809 +    unsigned char   *redzone;
10810 +    size_t redsize;
10811 +
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)) {
10815 +            return 0;
10816 +        }
10817 +    }
10818 +
10819 +    if(!APC_POOL_HAS_REDZONES(pool) ||
10820 +        !APC_POOL_HAS_SIZEINFO(pool)) {
10821 +        (void)pool; /* remove unused warning */
10822 +        return 1;
10823 +    }
10824 +
10825 +    for(entry = rpool->head; entry != NULL; entry = entry->next) {
10826 +        start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
10827 +
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.
10833 +             */
10834 +            redzone = start + SIZEINFO_SIZE + (*sizeinfo);
10835 +            redsize = REDZONE_SIZE(*sizeinfo);
10836 +#ifdef VALGRIND_MAKE_MEM_DEFINED
10837 +            VALGRIND_MAKE_MEM_DEFINED(redzone, redsize);
10838 +#endif
10839 +            if(!CHECK_REDZONE(redzone, redsize))
10840 +            {
10841 +                /*
10842 +                fprintf(stderr, "Redzone check failed for %p\n", 
10843 +                                start + ALIGNWORD(sizeof(size_t)));*/
10844 +                return 0;
10845 +            }
10846 +#ifdef VALGRIND_MAKE_MEM_NOACCESS
10847 +            VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
10848 +#endif
10849 +            realsize = SIZEINFO_SIZE + *sizeinfo + redsize;
10850 +            start += realsize;
10851 +        }
10852 +    }
10853 +
10854 +    return 1;
10855 +}
10856 +/* }}} */
10857 +
10858 +/* {{{ apc_realpool_free */
10859 +/*
10860 + * free does not do anything other than
10861 + * check for redzone values when free'ing
10862 + * data areas.
10863 + */
10864 +static void apc_realpool_free(apc_pool *pool, void *p TSRMLS_DC)
10865 +{
10866 +}
10867 +/* }}} */
10868 +
10869 +static void apc_realpool_cleanup(apc_pool *pool TSRMLS_DC) 
10870 +{
10871 +    pool_block *entry;
10872 +    pool_block *tmp;
10873 +    apc_realpool *rpool = (apc_realpool*)pool;
10874 +    apc_free_t deallocate = pool->deallocate;
10875 +
10876 +    assert(apc_realpool_check_integrity(rpool)!=0);
10877 +
10878 +    entry = rpool->head;
10879 +
10880 +    while(entry->next != NULL) {
10881 +        tmp = entry->next;
10882 +        deallocate(entry TSRMLS_CC);
10883 +        entry = tmp;
10884 +    }
10885 +}
10886 +
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
10890 +                                                         TSRMLS_DC)
10891 +{
10892 +
10893 +    size_t dsize = 0;
10894 +    apc_realpool *rpool;
10895 +
10896 +    switch(type & APC_POOL_SIZE_MASK) {
10897 +        case APC_SMALL_POOL:
10898 +            dsize = 512;
10899 +            break;
10900 +
10901 +        case APC_LARGE_POOL:
10902 +            dsize = 8192;
10903 +            break;
10904 +
10905 +        case APC_MEDIUM_POOL:
10906 +            dsize = 4096;
10907 +            break;
10908 +
10909 +        default:
10910 +            return NULL;
10911 +    }
10912 +
10913 +    rpool = (apc_realpool*)allocate((sizeof(apc_realpool) + ALIGNWORD(dsize)) TSRMLS_CC);
10914 +
10915 +    if(!rpool) {
10916 +        return NULL;
10917 +    }
10918 +
10919 +    rpool->parent.type = type;
10920 +
10921 +    rpool->parent.allocate = allocate;
10922 +    rpool->parent.deallocate = deallocate;
10923 +
10924 +    rpool->parent.size = sizeof(apc_realpool) + ALIGNWORD(dsize);
10925 +
10926 +    rpool->parent.palloc = apc_realpool_alloc;
10927 +    rpool->parent.pfree  = apc_realpool_free;
10928 +
10929 +    rpool->parent.protect = protect;
10930 +    rpool->parent.unprotect = unprotect;
10931 +
10932 +    rpool->parent.cleanup = apc_realpool_cleanup;
10933 +
10934 +    rpool->dsize = dsize;
10935 +    rpool->head = NULL;
10936 +    rpool->count = 0;
10937 +
10938 +    INIT_POOL_BLOCK(rpool, &(rpool->first), dsize);
10939 +
10940 +    return &(rpool->parent);
10941 +}
10942 +
10943 +
10944 +/* }}} */
10945 +
10946 +/* {{{ apc_pool_init */
10947 +void apc_pool_init()
10948 +{
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);
10954 +#endif
10955 +}
10956 +/* }}} */
10957 +
10958 +/* {{{ apc_pstrdup */
10959 +void* APC_ALLOC apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC)
10960 +{
10961 +    return s != NULL ? apc_pmemcpy(s, (strlen(s) + 1), pool TSRMLS_CC) : NULL;
10962 +}
10963 +/* }}} */
10964 +
10965 +/* {{{ apc_pmemcpy */
10966 +void* APC_ALLOC apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC)
10967 +{
10968 +    void* q;
10969 +
10970 +    if (p != NULL && (q = apc_pool_alloc(pool, n)) != NULL) {
10971 +        memcpy(q, p, n);
10972 +        return q;
10973 +    }
10974 +    return NULL;
10975 +}
10976 +/* }}} */
10977 +
10978 +/*
10979 + * Local variables:
10980 + * tab-width: 4
10981 + * c-basic-offset: 4
10982 + * End:
10983 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
10984 + * vim<600: expandtab sw=4 ts=4 sts=4
10985 + */
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
10989 @@ -0,0 +1,114 @@
10990 +/*
10991 +  +----------------------------------------------------------------------+
10992 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11006 +
11007 +   This software was contributed to PHP by Yahoo! Inc. in 2008.
11008 +
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.
11012 +
11013 +   All other licensing and usage conditions are those of the PHP Group.
11014 +
11015 + */
11016 +
11017 +/* $Id: apc_pool.h 307048 2011-01-03 23:53:17Z kalle $ */
11018 +
11019 +#ifndef APC_POOL_H
11020 +#define APC_POOL_H
11021 +
11022 +#include "apc.h"
11023 +#include "apc_sma.h"
11024 +
11025 +/* #define APC_POOL_DEBUG 1 */
11026 +
11027 +typedef enum {
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
11037 +#endif
11038 +} apc_pool_type;
11039 +
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)
11043 +#else
11044 +/* let gcc optimize away the optional features */
11045 +#define APC_POOL_HAS_SIZEINFO(pool) (0)
11046 +#define APC_POOL_HAS_REDZONES(pool) (0)
11047 +#endif
11048 +
11049 +
11050 +typedef struct _apc_pool apc_pool;
11051 +
11052 +typedef void  (*apc_pcleanup_t)(apc_pool *pool TSRMLS_DC);
11053 +
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);
11056 +
11057 +typedef void* (*apc_protect_t)  (void *p);
11058 +typedef void* (*apc_unprotect_t)(void *p);
11059 +
11060 +struct _apc_pool {
11061 +    apc_pool_type   type;
11062 +
11063 +    apc_malloc_t    allocate;
11064 +    apc_free_t      deallocate;
11065 +
11066 +    apc_palloc_t    palloc;
11067 +    apc_pfree_t     pfree;
11068 +
11069 +       apc_protect_t   protect;
11070 +       apc_unprotect_t unprotect;
11071 +
11072 +    apc_pcleanup_t  cleanup;
11073 +
11074 +    size_t          size;
11075 +    size_t          used;
11076 +
11077 +    /* apc_realpool and apc_unpool add more here */
11078 +};
11079 +
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))
11082 +
11083 +#define apc_pool_protect(pool, ptr)  (pool->protect ? \
11084 +                                                                               (pool)->protect((ptr)) : (ptr))
11085 +
11086 +#define apc_pool_unprotect(pool, ptr)  (pool->unprotect ? \
11087 +                                                                                       (pool)->unprotect((ptr)) : (ptr))
11088 +
11089 +extern void apc_pool_init();
11090 +
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
11096 +                                                       TSRMLS_DC);
11097 +
11098 +extern void apc_pool_destroy(apc_pool* pool TSRMLS_DC);
11099 +
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);
11102 +
11103 +#endif
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
11107 @@ -0,0 +1,111 @@
11108 +/*
11109 +  +----------------------------------------------------------------------+
11110 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11124 +
11125 + */
11126 +
11127 +/* $Id: apc_pthreadmutex.c 307048 2011-01-03 23:53:17Z kalle $ */
11128 +
11129 +#include "apc_pthreadmutex.h"
11130 +
11131 +#ifdef APC_PTHREADMUTEX_LOCKS
11132 +
11133 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC) 
11134 +{
11135 +    int result;
11136 +    pthread_mutexattr_t* attr;
11137 +    attr = malloc(sizeof(pthread_mutexattr_t));
11138 +
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);
11146 +    }
11147 +
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);
11152 +       }
11153 +#endif
11154 +
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);
11163 +    }
11164 +
11165 +    if(pthread_mutex_init(lock, attr)) { 
11166 +        apc_error("unable to initialize pthread lock" TSRMLS_CC);
11167 +    }
11168 +    return lock;
11169 +}
11170 +
11171 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
11172 +{
11173 +    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
11174 +}
11175 +
11176 +void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC)
11177 +{
11178 +    int result;
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);
11184 +    }
11185 +}
11186 +
11187 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC)
11188 +{
11189 +    if(pthread_mutex_unlock(lock)) {
11190 +        apc_error("unable to unlock pthread lock" TSRMLS_CC);
11191 +    }
11192 +}
11193 +
11194 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC)
11195 +{
11196 +    int rval;
11197 +    rval = pthread_mutex_trylock(lock);
11198 +    if(rval == EBUSY) {     /* Lock is already held */
11199 +        return 0;
11200 +    } else if(rval == 0) {  /* Obtained lock */
11201 +        return 1;
11202 +    } else {                /* Other error */
11203 +        apc_error("unable to obtain pthread trylock" TSRMLS_CC);
11204 +        return 0;
11205 +    }
11206 +}
11207 +
11208 +
11209 +#endif
11210 +
11211 +/*
11212 + * Local variables:
11213 + * tab-width: 4
11214 + * c-basic-offset: 4
11215 + * End:
11216 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11217 + * vim<600: expandtab sw=4 ts=4 sts=4
11218 + */
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
11222 @@ -0,0 +1,48 @@
11223 +/*
11224 +  +----------------------------------------------------------------------+
11225 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11239 +
11240 + */
11241 +
11242 +/* $Id: apc_pthreadmutex.h 307048 2011-01-03 23:53:17Z kalle $ */
11243 +
11244 +#ifndef APC_PTHREADMUTEX_H
11245 +#define APC_PTHREADMUTEX_H
11246 +
11247 +#include "apc.h"
11248 +
11249 +#ifdef APC_PTHREADMUTEX_LOCKS
11250 +
11251 +#include <pthread.h>
11252 +
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);
11258 +
11259 +#endif
11260 +
11261 +#endif
11262 +
11263 +/*
11264 + * Local variables:
11265 + * tab-width: 4
11266 + * c-basic-offset: 4
11267 + * End:
11268 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11269 + * vim<600: expandtab sw=4 ts=4 sts=4
11270 + */
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
11274 @@ -0,0 +1,120 @@
11275 +/*
11276 +  +----------------------------------------------------------------------+
11277 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11291 +
11292 + */
11293 +
11294 +/* $Id: $ */
11295 +
11296 +#include "apc_pthreadrwlock.h"
11297 +
11298 +#ifdef APC_PTHREADRW_LOCKS
11299 +
11300 +pthread_rwlock_t *apc_pthreadrwlock_create(pthread_rwlock_t *lock TSRMLS_DC) 
11301 +{
11302 +    int result;
11303 +    pthread_rwlockattr_t attr;
11304 +
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);
11312 +    }
11313 +
11314 +#ifdef __USE_UNIX98
11315 +       pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
11316 +#endif
11317 +
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);
11325 +    }
11326 +
11327 +    if(pthread_rwlock_init(lock, &attr)) { 
11328 +        apc_error("unable to initialize pthread rwlock" TSRMLS_CC);
11329 +    }
11330 +
11331 +    pthread_rwlockattr_destroy(&attr);
11332 +
11333 +    return lock;
11334 +}
11335 +
11336 +void apc_pthreadrwlock_destroy(pthread_rwlock_t *lock)
11337 +{
11338 +    return; /* we don't actually destroy the rwlock, as it would destroy it for all processes */
11339 +}
11340 +
11341 +void apc_pthreadrwlock_lock(pthread_rwlock_t *lock TSRMLS_DC)
11342 +{
11343 +    int result;
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);
11349 +    }
11350 +}
11351 +
11352 +void apc_pthreadrwlock_rdlock(pthread_rwlock_t *lock TSRMLS_DC)
11353 +{
11354 +    int result;
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);
11360 +    }
11361 +}
11362 +
11363 +void apc_pthreadrwlock_unlock(pthread_rwlock_t *lock TSRMLS_DC)
11364 +{
11365 +    if(pthread_rwlock_unlock(lock)) {
11366 +        apc_error("unable to unlock pthread lock" TSRMLS_CC);
11367 +    }
11368 +}
11369 +
11370 +zend_bool apc_pthreadrwlock_nonblocking_lock(pthread_rwlock_t *lock TSRMLS_DC)
11371 +{
11372 +    int rval;
11373 +    rval = pthread_rwlock_trywrlock(lock);
11374 +    if(rval == EBUSY) {     /* Lock is already held */
11375 +        return 0;
11376 +    } else if(rval == 0) {  /* Obtained lock */
11377 +        return 1;
11378 +    } else {                /* Other error */
11379 +        apc_error("unable to obtain pthread trylock" TSRMLS_CC);
11380 +        return 0;
11381 +    }
11382 +}
11383 +
11384 +
11385 +#endif
11386 +
11387 +/*
11388 + * Local variables:
11389 + * tab-width: 4
11390 + * c-basic-offset: 4
11391 + * End:
11392 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11393 + * vim<600: expandtab sw=4 ts=4 sts=4
11394 + */
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
11398 @@ -0,0 +1,49 @@
11399 +/*
11400 +  +----------------------------------------------------------------------+
11401 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11415 +
11416 + */
11417 +
11418 +/* $Id: apc_pthreadrwlock.h 302175 2010-08-13 06:20:28Z kalle $ */
11419 +
11420 +#ifndef APC_PTHREADRWLOCK_H
11421 +#define APC_PTHREADRWLOCK_H
11422 +
11423 +#include "apc.h"
11424 +
11425 +#ifdef APC_PTHREADRW_LOCKS
11426 +
11427 +#include <pthread.h>
11428 +
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);
11435 +
11436 +#endif
11437 +
11438 +#endif
11439 +
11440 +/*
11441 + * Local variables:
11442 + * tab-width: 4
11443 + * c-basic-offset: 4
11444 + * End:
11445 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11446 + * vim<600: expandtab sw=4 ts=4 sts=4
11447 + */
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
11451 @@ -0,0 +1,236 @@
11452 +/*
11453 +  +----------------------------------------------------------------------+
11454 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11468 +
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.
11474 +
11475 +   All other licensing and usage conditions are those of the PHP Group.
11476 +
11477 + */
11478 +
11479 +/* $Id: apc_rfc1867.c 309694 2011-03-25 18:47:38Z rasmus $*/
11480 +
11481 +#include "apc.h"
11482 +#include "apc_globals.h"
11483 +#include "rfc1867.h"
11484 +
11485 +#ifdef PHP_WIN32
11486 +#include "win32/time.h"
11487 +#endif
11488 +
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);
11492 +
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;
11496 +
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;
11505 +                return 1;
11506 +            }
11507 +        }
11508 +    }
11509 +
11510 +    return 0;
11511 +}
11512 +
11513 +static double my_time() {
11514 +    struct timeval a;
11515 +    double t;
11516 +    gettimeofday(&a, NULL);
11517 +    t = a.tv_sec + (a.tv_usec/1000000.00);
11518 +    return t;
11519 +}
11520 +
11521 +
11522 +#define RFC1867_DATA(name) \
11523 +                ((request_data)->name)
11524 +
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;
11528 +
11529 +    switch (event) {
11530 +        case MULTIPART_EVENT_START:
11531 +            {
11532 +                multipart_event_start *data = (multipart_event_start *) event_data;
11533 +                
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;
11547 +                
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); 
11550 +                }
11551 +            }
11552 +            break;
11553 +
11554 +        case MULTIPART_EVENT_FORMDATA:
11555 +            {
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) { 
11560 +                    
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);
11565 +                        break;
11566 +                    }
11567 +
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)); 
11571 +                        break;
11572 +                    }
11573 +
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;
11578 +                }
11579 +            }
11580 +            break;
11581 +
11582 +        case MULTIPART_EVENT_FILE_START:
11583 +            {
11584 +                RFC1867_DATA(started) = 1;
11585 +                if(*RFC1867_DATA(tracking_key)) {
11586 +                    multipart_event_file_start *data = (multipart_event_file_start *) event_data;
11587 +
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);
11602 +                }
11603 +            }
11604 +            break;
11605 +
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);
11622 +                    }
11623 +                    RFC1867_DATA(prev_bytes_processed) = RFC1867_DATA(bytes_processed);
11624 +                }
11625 +            }
11626 +            break;
11627 +
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;
11635 +                } else {
11636 +                    RFC1867_DATA(temp_filename) = "";
11637 +                }
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);
11650 +            }
11651 +            break;
11652 +
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);
11672 +            }
11673 +            break;
11674 +    }
11675 +
11676 +    return SUCCESS;
11677 +}
11678 +
11679 +#endif
11680 +/*
11681 + * Local variables:
11682 + * tab-width: 4
11683 + * c-basic-offset: 4
11684 + * End:
11685 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11686 + * vim<600: expandtab sw=4 ts=4 sts=4
11687 + */
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
11691 @@ -0,0 +1,192 @@
11692 +/*
11693 +  +----------------------------------------------------------------------+
11694 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11708 +
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.
11714 +
11715 +   All other licensing and usage conditions are those of the PHP Group.
11716 +
11717 + */
11718 +
11719 +/* $Id: apc_sem.c 307048 2011-01-03 23:53:17Z kalle $ */
11720 +
11721 +#include "apc.h"
11722 +
11723 +#ifdef APC_SEM_LOCKS
11724 +
11725 +#include "apc_sem.h"
11726 +#include "php.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>
11732 +
11733 +#if HAVE_SEMUN
11734 +/* we have semun, no need to define */
11735 +#else
11736 +#undef HAVE_SEMUN
11737 +union semun {
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 */
11743 +};
11744 +#define HAVE_SEMUN 1
11745 +#endif
11746 +
11747 +#ifndef SEM_R
11748 +# define SEM_R 0444
11749 +#endif
11750 +#ifndef SEM_A
11751 +# define SEM_A 0222
11752 +#endif
11753 +
11754 +/* always use SEM_UNDO, otherwise we risk deadlock */
11755 +#define USE_SEM_UNDO
11756 +
11757 +#ifdef USE_SEM_UNDO
11758 +# define UNDO SEM_UNDO
11759 +#else
11760 +# define UNDO 0
11761 +#endif
11762 +
11763 +int apc_sem_create(int proj, int initval TSRMLS_DC)
11764 +{
11765 +    int semid;
11766 +    int perms = 0777;
11767 +    union semun arg;
11768 +    key_t key = IPC_PRIVATE;
11769 +
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);
11775 +        }
11776 +    }
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);
11781 +        }
11782 +        /* insert <sleazy way to avoid race condition> here */
11783 +    }
11784 +    else {
11785 +        apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key);
11786 +    }
11787 +
11788 +    return semid;
11789 +}
11790 +
11791 +void apc_sem_destroy(int semid)
11792 +{
11793 +    /* we expect this call to fail often, so we do not check */
11794 +    union semun arg;
11795 +    semctl(semid, 0, IPC_RMID, arg);
11796 +}
11797 +
11798 +void apc_sem_lock(int semid TSRMLS_DC)
11799 +{
11800 +    struct sembuf op;
11801 +
11802 +    op.sem_num = 0;
11803 +    op.sem_op  = -1;
11804 +    op.sem_flg = UNDO;
11805 +
11806 +    if (semop(semid, &op, 1) < 0) {
11807 +        if (errno != EINTR) {
11808 +            apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid);
11809 +        }
11810 +    }
11811 +}
11812 +
11813 +int apc_sem_nonblocking_lock(int semid TSRMLS_DC) 
11814 +{
11815 +    struct sembuf op;
11816 +
11817 +    op.sem_num = 0;
11818 +    op.sem_op  = -1;
11819 +    op.sem_flg = UNDO | IPC_NOWAIT;
11820 +
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);
11826 +      }
11827 +    }
11828 +
11829 +    return 1;  /* Lock obtained */
11830 +}
11831 +
11832 +void apc_sem_unlock(int semid TSRMLS_DC)
11833 +{
11834 +    struct sembuf op;
11835 +
11836 +    op.sem_num = 0;
11837 +    op.sem_op  = 1;
11838 +    op.sem_flg = UNDO;
11839 +
11840 +    if (semop(semid, &op, 1) < 0) {
11841 +        if (errno != EINTR) {
11842 +            apc_error("apc_sem_unlock: semop(%d) failed:" TSRMLS_CC, semid);
11843 +        }
11844 +    }
11845 +}
11846 +
11847 +void apc_sem_wait_for_zero(int semid TSRMLS_DC)
11848 +{
11849 +    struct sembuf op;
11850 +
11851 +    op.sem_num = 0;
11852 +    op.sem_op  = 0;
11853 +    op.sem_flg = UNDO;
11854 +
11855 +    if (semop(semid, &op, 1) < 0) {
11856 +        if (errno != EINTR) {
11857 +            apc_error("apc_sem_waitforzero: semop(%d) failed:" TSRMLS_CC, semid);
11858 +        }
11859 +    }
11860 +}
11861 +
11862 +int apc_sem_get_value(int semid TSRMLS_DC)
11863 +{
11864 +    union semun arg;
11865 +    unsigned short val[1];
11866 +
11867 +    arg.array = val;
11868 +    if (semctl(semid, 0, GETALL, arg) < 0) {
11869 +        apc_error("apc_sem_getvalue: semctl(%d,...) failed:" TSRMLS_CC, semid);
11870 +    }
11871 +    return val[0];
11872 +}
11873 +
11874 +#endif /* APC_SEM_LOCKS */
11875 +
11876 +/*
11877 + * Local variables:
11878 + * tab-width: 4
11879 + * c-basic-offset: 4
11880 + * End:
11881 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11882 + * vim<600: expandtab sw=4 ts=4 sts=4
11883 + */
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
11887 @@ -0,0 +1,52 @@
11888 +/*
11889 +  +----------------------------------------------------------------------+
11890 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11904 +
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.
11910 +
11911 +   All other licensing and usage conditions are those of the PHP Group.
11912 +
11913 + */
11914 +
11915 +/* $Id: apc_sem.h 307048 2011-01-03 23:53:17Z kalle $ */
11916 +
11917 +#ifndef APC_SEM_H
11918 +#define APC_SEM_H
11919 +
11920 +/* Wrapper functions for SysV sempahores */
11921 +
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);
11929 +
11930 +#endif
11931 +
11932 +/*
11933 + * Local variables:
11934 + * tab-width: 4
11935 + * c-basic-offset: 4
11936 + * End:
11937 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
11938 + * vim<600: expandtab sw=4 ts=4 sts=4
11939 + */
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
11943 @@ -0,0 +1,84 @@
11944 +/*
11945 +  +----------------------------------------------------------------------+
11946 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
11960 +
11961 + */
11962 +
11963 +/* $Id: $ */
11964 +
11965 +#ifndef APC_SERIALIZER_H
11966 +#define APC_SERIALIZER_H
11967 +
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
11971 +
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
11974 +
11975 +typedef int (*apc_serialize_t)(APC_SERIALIZER_ARGS);
11976 +typedef int (*apc_unserialize_t)(APC_UNSERIALIZER_ARGS);
11977 +
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);
11982 +
11983 +/*
11984 + * ABI version for constant hooks. Increment this any time you make any changes
11985 + * to any function in this file.
11986 + */
11987 +#define APC_SERIALIZER_ABI "0"
11988 +#define APC_SERIALIZER_CONSTANT "\000apc_register_serializer-" APC_SERIALIZER_ABI
11989 +
11990 +#if !defined(APC_UNUSED)
11991 +# if defined(__GNUC__)
11992 +#  define APC_UNUSED __attribute__((unused))
11993 +# else
11994 +# define APC_UNUSED
11995 +# endif
11996 +#endif
11997 +
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)
12002 +{
12003 +    zval apc_magic_constant;
12004 +    int retval = 0;
12005 +
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);
12011 +        }
12012 +        zval_dtor(&apc_magic_constant);
12013 +    }
12014 +
12015 +    return retval;
12016 +}
12017 +
12018 +#endif
12019 +
12020 +/*
12021 + * Local variables:
12022 + * tab-width: 4
12023 + * c-basic-offset: 4
12024 + * End:
12025 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12026 + * vim<600: expandtab sw=4 ts=4 sts=4
12027 + */
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
12031 @@ -0,0 +1,116 @@
12032 +/*
12033 +  +----------------------------------------------------------------------+
12034 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
12049 +
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.
12055 +
12056 +   All other licensing and usage conditions are those of the PHP Group.
12057 +
12058 + */
12059 +
12060 +/* $Id: apc_shm.c 307259 2011-01-08 12:05:24Z gopalv $ */
12061 +
12062 +#include "apc_shm.h"
12063 +#include "apc.h"
12064 +#ifdef PHP_WIN32
12065 +/* shm functions are available in TSRM */
12066 +#include <tsrm/tsrm_win32.h>
12067 +#define key_t long
12068 +#else
12069 +#include <sys/ipc.h>
12070 +#include <sys/shm.h>
12071 +#include <sys/stat.h>
12072 +#endif
12073 +
12074 +#ifndef SHM_R
12075 +# define SHM_R 0444 /* read permission */
12076 +#endif
12077 +#ifndef SHM_A
12078 +# define SHM_A 0222 /* write permission */
12079 +#endif
12080 +
12081 +int apc_shm_create(int proj, size_t size TSRMLS_DC)
12082 +{
12083 +    int shmid;                 /* shared memory id */
12084 +    int oflag;                 /* permissions on shm */
12085 +    key_t key = IPC_PRIVATE;   /* shm key */
12086 +
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));
12090 +    }
12091 +
12092 +    return shmid;
12093 +}
12094 +
12095 +void apc_shm_destroy(int shmid)
12096 +{
12097 +    /* we expect this call to fail often, so we do not check */
12098 +    shmctl(shmid, IPC_RMID, 0);
12099 +}
12100 +
12101 +apc_segment_t apc_shm_attach(int shmid, size_t size TSRMLS_DC)
12102 +{
12103 +    apc_segment_t segment; /* shm segment */
12104 +
12105 +    if ((long)(segment.shmaddr = shmat(shmid, 0, 0)) == -1) {
12106 +        apc_error("apc_shm_attach: shmat failed:" TSRMLS_CC);
12107 +    }
12108 +
12109 +#ifdef APC_MEMPROTECT
12110 +    
12111 +    if ((long)(segment.roaddr = shmat(shmid, 0, SHM_RDONLY)) == -1) {
12112 +        segment.roaddr = NULL;
12113 +    }
12114 +
12115 +#endif
12116 +
12117 +    segment.size = size;
12118 +
12119 +    /*
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.
12122 +     */
12123 +    apc_shm_destroy(shmid);
12124 +    return segment;
12125 +}
12126 +
12127 +void apc_shm_detach(apc_segment_t* segment TSRMLS_DC)
12128 +{
12129 +    if (shmdt(segment->shmaddr) < 0) {
12130 +        apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
12131 +    }
12132 +
12133 +#ifdef APC_MEMPROTECT
12134 +    if (segment->roaddr && shmdt(segment->roaddr) < 0) {
12135 +        apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC);
12136 +    }
12137 +#endif
12138 +}
12139 +
12140 +/*
12141 + * Local variables:
12142 + * tab-width: 4
12143 + * c-basic-offset: 4
12144 + * End:
12145 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12146 + * vim<600: expandtab sw=4 ts=4 sts=4
12147 + */
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
12151 @@ -0,0 +1,56 @@
12152 +/*
12153 +  +----------------------------------------------------------------------+
12154 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
12168 +
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.
12174 +
12175 +   All other licensing and usage conditions are those of the PHP Group.
12176 +
12177 + */
12178 +
12179 +/* $Id: apc_shm.h 307259 2011-01-08 12:05:24Z gopalv $ */
12180 +
12181 +#ifndef APC_SHM_H
12182 +#define APC_SHM_H
12183 +
12184 +#include <sys/types.h>
12185 +#ifdef PHP_WIN32
12186 +#include <time.h>
12187 +#endif
12188 +
12189 +#include "apc_sma.h"
12190 +
12191 +/* Wrapper functions for unix shared memory */
12192 +
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);
12197 +
12198 +#endif
12199 +
12200 +/*
12201 + * Local variables:
12202 + * tab-width: 4
12203 + * c-basic-offset: 4
12204 + * End:
12205 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12206 + * vim<600: expandtab sw=4 ts=4 sts=4
12207 + */
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
12211 @@ -0,0 +1,197 @@
12212 +/*
12213 +  +----------------------------------------------------------------------+
12214 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
12228 +
12229 +   This software was contributed to PHP by Facebook Inc. in 2007.
12230 +
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.
12234 +
12235 +   All other licensing and usage conditions are those of the PHP Group.
12236 + */
12237 +
12238 + /* $Id: apc_signal.c 307048 2011-01-03 23:53:17Z kalle $ */
12239 +
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)
12246 +  */
12247 +
12248 +#include "apc.h"
12249 +
12250 +#if HAVE_SIGACTION
12251 +#include <signal.h>
12252 +#include "apc_globals.h"
12253 +#include "apc_sma.h"
12254 +#include "apc_signal.h"
12255 +
12256 +static apc_signal_info_t apc_signal_info = {0};
12257 +
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);
12261 +
12262 +/* {{{ apc_core_unmap 
12263 + *  Coredump signal handler, unmaps shm and calls previously installed handlers 
12264 + */
12265 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) 
12266 +{
12267 +    TSRMLS_FETCH();
12268 +       
12269 +    apc_sma_cleanup(TSRMLS_C);
12270 +    apc_rehandle_signal(signo, siginfo, context);
12271 +
12272 +#if !defined(WIN32) && !defined(NETWARE)
12273 +    kill(getpid(), signo);
12274 +#else
12275 +    raise(signo);
12276 +#endif
12277 +} /* }}} */
12278 +
12279 +/* {{{ apc_rehandle_signal
12280 + *  Call the previously registered handler for a signal
12281 + */
12282 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
12283 +{
12284 +    int i;
12285 +    apc_signal_entry_t p_sig = {0};
12286 +
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);
12292 +            } else {
12293 +                (*(void (*)(int))p_sig.handler)(signo);
12294 +            }
12295 +        }
12296 +    }
12297 +
12298 +} /* }}} */
12299 +
12300 +/* {{{ apc_register_signal
12301 + *  Set a handler for a previously installed signal and save so we can 
12302 + *  callback when handled 
12303 + */
12304 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC)
12305 +{
12306 +    struct sigaction sa = {{0}};
12307 +    apc_signal_entry_t p_sig = {0};
12308 +
12309 +    if (sigaction(signo, NULL, &sa) == 0) {
12310 +        if ((void*)sa.sa_handler == (void*)handler) {
12311 +            return SUCCESS;
12312 +        }
12313 +
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;
12318 +
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;
12322 +        } else {
12323 +            /* inherit flags and mask if already set */
12324 +            sigemptyset(&sa.sa_mask);
12325 +            sa.sa_flags = 0;
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;
12331 +#endif
12332 +        }
12333 +        sa.sa_handler = (void*)handler;
12334 +
12335 +        if (sigaction(signo, &sa, NULL) < 0) {
12336 +            apc_warning("Error installing apc signal handler for %d" TSRMLS_CC, signo);
12337 +        }
12338 +
12339 +        return SUCCESS;
12340 +    }
12341 +    return FAILURE;
12342 +} /* }}} */
12343 +
12344 +/* {{{ apc_set_signals
12345 + *  Install our signal handlers */
12346 +void apc_set_signals(TSRMLS_D) 
12347 +{
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 */
12355 +#ifdef SIGBUS
12356 +        apc_register_signal(SIGBUS, apc_core_unmap TSRMLS_CC);
12357 +#endif
12358 +#ifdef SIGABORT
12359 +        apc_register_signal(SIGABORT, apc_core_unmap TSRMLS_CC);
12360 +#endif
12361 +#ifdef SIGEMT
12362 +        apc_register_signal(SIGEMT, apc_core_unmap TSRMLS_CC);
12363 +#endif
12364 +#ifdef SIGIOT
12365 +        apc_register_signal(SIGIOT, apc_core_unmap TSRMLS_CC);
12366 +#endif
12367 +#ifdef SIGQUIT
12368 +        apc_register_signal(SIGQUIT, apc_core_unmap TSRMLS_CC);
12369 +#endif
12370 +#ifdef SIGSYS
12371 +        apc_register_signal(SIGSYS, apc_core_unmap TSRMLS_CC);
12372 +#endif
12373 +#ifdef SIGTRAP
12374 +        apc_register_signal(SIGTRAP, apc_core_unmap TSRMLS_CC);
12375 +#endif
12376 +#ifdef SIGXCPU
12377 +        apc_register_signal(SIGXCPU, apc_core_unmap TSRMLS_CC);
12378 +#endif
12379 +#ifdef SIGXFSZ
12380 +        apc_register_signal(SIGXFSZ, apc_core_unmap TSRMLS_CC);
12381 +#endif
12382 +    }
12383 +} /* }}} */
12384 +
12385 +/* {{{ apc_set_signals
12386 + *  cleanup signals for shutdown */
12387 +void apc_shutdown_signals(TSRMLS_D) 
12388 +{
12389 +    int i=0;
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);
12393 +        }
12394 +        apc_efree(apc_signal_info.prev TSRMLS_CC);
12395 +        apc_signal_info.installed = 0; /* just in case */
12396 +    }
12397 +}
12398 +
12399 +#endif  /* HAVE_SIGACTION */
12400 +
12401 +/*
12402 + * Local variables:
12403 + * tab-width: 4
12404 + * c-basic-offset: 4
12405 + * End:
12406 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12407 + * vim<600: expandtab sw=4 ts=4 sts=4
12408 + */
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
12412 @@ -0,0 +1,51 @@
12413 +/*
12414 +  +----------------------------------------------------------------------+
12415 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
12429 +
12430 + */
12431 +
12432 +/* $Id: apc_signal.h 307048 2011-01-03 23:53:17Z kalle $ */
12433 +
12434 +#ifndef APC_SIGNAL_H
12435 +#define APC_SIGNAL_H
12436 +
12437 +#include "apc.h"
12438 +#include "apc_php.h"
12439 +
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;
12445 +
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;
12450 +
12451 +void apc_set_signals(TSRMLS_D);
12452 +void apc_shutdown_signals(TSRMLS_D);
12453 +
12454 +#endif
12455 +
12456 +/*
12457 + * Local variables:
12458 + * tab-width: 4
12459 + * c-basic-offset: 4
12460 + * End:
12461 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
12462 + * vim<600: expandtab sw=4 ts=4 sts=4
12463 + */
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
12467 @@ -0,0 +1,765 @@
12468 +/*
12469 +  +----------------------------------------------------------------------+
12470 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
12485 +
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.
12491 +
12492 +   All other licensing and usage conditions are those of the PHP Group.
12493 +
12494 + */
12495 +
12496 +/* $Id: apc_sma.c 309489 2011-03-21 00:00:54Z pajoye $ */
12497 +
12498 +#include "apc_sma.h"
12499 +#include "apc.h"
12500 +#include "apc_globals.h"
12501 +#include "apc_lock.h"
12502 +#include "apc_shm.h"
12503 +#include "apc_cache.h"
12504 +
12505 +#include <limits.h>
12506 +#include "apc_mmap.h"
12507 +
12508 +#ifdef HAVE_VALGRIND_MEMCHECK_H
12509 +#include <valgrind/memcheck.h>
12510 +#endif
12511 +
12512 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
12513 +
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 */
12519 +
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];
12527 +#endif
12528 +};
12529 +
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)
12534 +
12535 +
12536 +/* do not enable for threaded http servers */
12537 +/* #define __APC_SMA_DEBUG__ 1 */
12538 +
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;
12545 +#endif
12546 +
12547 +#define APC_SMA_CANARIES 1
12548 +
12549 +typedef struct block_t block_t;
12550 +struct 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 */
12557 +#endif
12558 +#ifdef __APC_SMA_DEBUG__
12559 +    size_t id;         /* identifier for the memory block */
12560 +#endif
12561 +};
12562 +
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. */
12566 +
12567 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
12568 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
12569 +
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)
12573 +
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
12579 +#else
12580 +    #define SET_CANARY(v) 
12581 +    #define CHECK_CANARY(v)
12582 +    #define RESET_CANARY(v)
12583 +#endif
12584 +
12585 +
12586 +/* {{{ MINBLOCKSIZE */
12587 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
12588 +/* }}} */
12589 +
12590 +#if 0
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
12593 + */
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;
12598 +    size_t avail;
12599 +
12600 +    /* Verify free list */
12601 +    if (verbose) apc_warning("Free List: " TSRMLS_CC);
12602 +    while(1) {
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);
12610 +            assert(0);
12611 +        }
12612 +        if (prv && cur->fprev != OFFSET(prv)) {
12613 +            apc_warning("Previous pointer does not point to previous!" TSRMLS_CC);
12614 +            assert(0);
12615 +        }
12616 +        prv = cur;
12617 +    }
12618 +    assert(avail == header->avail);
12619 +
12620 +    /* Verify each block */
12621 +    if (verbose) apc_warning("Block List: " TSRMLS_CC);
12622 +    cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12623 +    while(1) {
12624 +        if(!cur->fnext) {
12625 +            if (verbose) apc_warning(" 0x%x[%d] (s%d) (u)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
12626 +        } else {
12627 +            if (verbose) apc_warning(" 0x%x[%d] (s%d) (f)" TSRMLS_CC, cur, OFFSET(cur), cur->size);
12628 +        }
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)));
12633 +        } else {
12634 +            cur = NEXT_SBLOCK(cur);
12635 +        }
12636 +        if (prv == cur) {
12637 +            apc_warning("Circular list detected!" TSRMLS_CC);
12638 +            assert(0);
12639 +        }
12640 +        prv = cur;
12641 +    }
12642 +}
12643 +/* }}} */
12644 +#endif
12645 +
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)
12648 +{
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));
12655 +
12656 +    realsize = ALIGNWORD(size + block_size);
12657 +
12658 +    /*
12659 +     * First, insure that the segment contains at least realsize free bytes,
12660 +     * even if they are not contiguous.
12661 +     */
12662 +    shmaddr = header;
12663 +
12664 +    if (header->avail < realsize) {
12665 +        return -1;
12666 +    }
12667 +
12668 +    prvnextfit = 0;     /* initially null (no fit) */
12669 +    prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12670 +    CHECK_CANARY(prv);
12671 +
12672 +    while (prv->fnext != 0) {
12673 +        cur = BLOCKAT(prv->fnext);
12674 +#ifdef __APC_SMA_DEBUG__
12675 +        CHECK_CANARY(cur);
12676 +#endif
12677 +        /* If it can fit realsize bytes in cur block, stop searching */
12678 +        if (cur->size >= realsize) {
12679 +            prvnextfit = prv;
12680 +            break;
12681 +        }
12682 +        prv = cur;
12683 +    }
12684 +
12685 +    if (prvnextfit == 0) {
12686 +        return -1;
12687 +    }
12688 +
12689 +    prv = prvnextfit;
12690 +    cur = BLOCKAT(prv->fnext);
12691 +
12692 +    CHECK_CANARY(prv);
12693 +    CHECK_CANARY(cur);
12694 +
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 */
12701 +    } else {
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 */
12705 +
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 */
12713 +        SET_CANARY(nxt);
12714 +
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__
12721 +        nxt->id = -1;
12722 +#endif
12723 +    }
12724 +
12725 +    cur->fnext = 0;
12726 +
12727 +    /* update the block header */
12728 +    header->avail -= cur->size;
12729 +#if ALLOC_DISTRIBUTION
12730 +    header->adist[(int)(log(size)/log(2))]++;
12731 +#endif
12732 +
12733 +    SET_CANARY(cur);
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);
12737 +#endif
12738 +
12739 +    return OFFSET(cur) + block_size;
12740 +}
12741 +/* }}} */
12742 +
12743 +/* {{{ sma_deallocate: deallocates the block at the given offset */
12744 +static APC_HOTSPOT size_t sma_deallocate(void* shmaddr, size_t offset)
12745 +{
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 */
12751 +
12752 +    offset -= ALIGNWORD(sizeof(struct block_t));
12753 +    assert(offset >= 0);
12754 +
12755 +    /* find position of new block in free list */
12756 +    cur = BLOCKAT(offset);
12757 +
12758 +    /* update the block header */
12759 +    header = (sma_header_t*) shmaddr;
12760 +    header->avail += cur->size;
12761 +    size = cur->size;
12762 +
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);
12771 +        cur = prv;
12772 +    }
12773 +
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 ? */
12784 +#endif
12785 +        RESET_CANARY(nxt);
12786 +    }
12787 +
12788 +    NEXT_SBLOCK(cur)->prev_size = cur->size;
12789 +
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);
12796 +
12797 +    return size;
12798 +}
12799 +/* }}} */
12800 +
12801 +/* {{{ apc_sma_init */
12802 +
12803 +void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC)
12804 +{
12805 +    uint i;
12806 +
12807 +    if (sma_initialized) {
12808 +        return;
12809 +    }
12810 +    sma_initialized = 1;
12811 +
12812 +#if APC_MMAP
12813 +    /*
12814 +     * I don't think multiple anonymous mmaps makes any sense
12815 +     * so force sma_numseg to 1 in this case
12816 +     */
12817 +    if(!mmap_file_mask || 
12818 +       (mmap_file_mask && !strlen(mmap_file_mask)) ||
12819 +       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
12820 +        sma_numseg = 1;
12821 +    } else {
12822 +        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
12823 +    }
12824 +#else
12825 +    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
12826 +#endif
12827 +
12828 +    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
12829 +
12830 +    sma_segments = (apc_segment_t*) apc_emalloc((sma_numseg * sizeof(apc_segment_t)) TSRMLS_CC);
12831 +
12832 +    for (i = 0; i < sma_numseg; i++) {
12833 +        sma_header_t*   header;
12834 +        block_t     *first, *empty, *last;
12835 +        void*       shmaddr;
12836 +
12837 +#if APC_MMAP
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);
12840 +#else
12841 +        sma_segments[i] = apc_shm_attach(apc_shm_create(i, sma_segsize TSRMLS_CC), sma_segsize TSRMLS_CC);
12842 +#endif
12843 +        
12844 +        sma_segments[i].size = sma_segsize;
12845 +
12846 +        shmaddr = sma_segments[i].shmaddr;
12847 +
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
12853 +        {
12854 +           int j;
12855 +           for(j=0; j<30; j++) header->adist[j] = 0;
12856 +        }
12857 +#endif
12858 +        first = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
12859 +        first->size = 0;
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__
12865 +        block->id = -1;
12866 +#endif
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__
12874 +        empty->id = -1;
12875 +#endif
12876 +        last = BLOCKAT(empty->fnext);
12877 +        last->size = 0;
12878 +        last->fnext = 0;
12879 +        last->fprev =  OFFSET(empty);
12880 +        last->prev_size = empty->size;
12881 +        SET_CANARY(last);
12882 +#ifdef __APC_SMA_DEBUG__
12883 +        last->id = -1;
12884 +#endif
12885 +    }
12886 +}
12887 +/* }}} */
12888 +
12889 +/* {{{ apc_sma_cleanup */
12890 +void apc_sma_cleanup(TSRMLS_D)
12891 +{
12892 +    uint i;
12893 +
12894 +    assert(sma_initialized);
12895 +
12896 +    for (i = 0; i < sma_numseg; i++) {
12897 +        apc_lck_destroy(SMA_LCK(i));
12898 +#if APC_MMAP
12899 +        apc_unmap(&sma_segments[i] TSRMLS_CC);
12900 +#else
12901 +        apc_shm_detach(&sma_segments[i] TSRMLS_CC);
12902 +#endif
12903 +    }
12904 +    sma_initialized = 0;
12905 +    apc_efree(sma_segments TSRMLS_CC);
12906 +}
12907 +/* }}} */
12908 +
12909 +/* {{{ apc_sma_malloc_ex */
12910 +void* apc_sma_malloc_ex(size_t n, size_t fragment, size_t* allocated TSRMLS_DC)
12911 +{
12912 +    size_t off;
12913 +    uint i;
12914 +    int nuked = 0;
12915 +
12916 +restart:
12917 +    assert(sma_initialized);
12918 +    LOCK(SMA_LCK(sma_lastseg));
12919 +
12920 +    off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
12921 +
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);
12928 +    }
12929 +
12930 +    if (off != -1) {
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);
12935 +#endif
12936 +        return p;
12937 +    }
12938 +    
12939 +    UNLOCK(SMA_LCK(sma_lastseg));
12940 +
12941 +    for (i = 0; i < sma_numseg; i++) {
12942 +        if (i == sma_lastseg) {
12943 +            continue;
12944 +        }
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);
12953 +        }
12954 +        if (off != -1) {
12955 +            void* p = (void *)(SMA_ADDR(i) + off);
12956 +            UNLOCK(SMA_LCK(i));
12957 +            sma_lastseg = i;
12958 +#ifdef VALGRIND_MALLOCLIKE_BLOCK
12959 +            VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
12960 +#endif
12961 +            return p;
12962 +        }
12963 +        UNLOCK(SMA_LCK(i));
12964 +    }
12965 +
12966 +    /* I've tried being nice, but now you're just asking for it */
12967 +    if(!nuked) {
12968 +        apc_cache->expunge_cb(apc_cache, (n+fragment) TSRMLS_CC);
12969 +        apc_user_cache->expunge_cb(apc_user_cache, (n+fragment) TSRMLS_CC);
12970 +        nuked = 1;
12971 +        goto restart;
12972 +    }
12973 +
12974 +    /* now, I've truly and well given up */
12975 +
12976 +    return NULL;
12977 +}
12978 +/* }}} */
12979 +
12980 +/* {{{ apc_sma_malloc */
12981 +void* apc_sma_malloc(size_t n TSRMLS_DC)
12982 +{
12983 +    size_t allocated;
12984 +    void *p = apc_sma_malloc_ex(n, MINBLOCKSIZE, &allocated TSRMLS_CC);
12985 +
12986 +    return p;
12987 +}
12988 +/* }}} */
12989 +
12990 +/* {{{ apc_sma_realloc */
12991 +void* apc_sma_realloc(void *p, size_t n TSRMLS_DC)
12992 +{
12993 +    apc_sma_free(p TSRMLS_CC);
12994 +    return apc_sma_malloc(n TSRMLS_CC);
12995 +}
12996 +/* }}} */
12997 +
12998 +/* {{{ apc_sma_strdup */
12999 +char* apc_sma_strdup(const char* s TSRMLS_DC)
13000 +{
13001 +    void* q;
13002 +    int len;
13003 +
13004 +    if(!s) return NULL;
13005 +
13006 +    len = strlen(s)+1;
13007 +    q = apc_sma_malloc(len TSRMLS_CC);
13008 +    if(!q) return NULL;
13009 +    memcpy(q, s, len);
13010 +    return q;
13011 +}
13012 +/* }}} */
13013 +
13014 +/* {{{ apc_sma_free */
13015 +void apc_sma_free(void* p TSRMLS_DC)
13016 +{
13017 +    uint i;
13018 +    size_t offset;
13019 +    size_t d_size;
13020 +
13021 +    if (p == NULL) {
13022 +        return;
13023 +    }
13024 +
13025 +    assert(sma_initialized);
13026 +
13027 +    
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);
13036 +#endif
13037 +            return;
13038 +        }
13039 +    }
13040 +
13041 +    apc_error("apc_sma_free: could not locate address %p" TSRMLS_CC, p);
13042 +}
13043 +/* }}} */
13044 +
13045 +#ifdef APC_MEMPROTECT
13046 +/* {{{ */
13047 +void* apc_sma_protect(void *p)
13048 +{
13049 +    unsigned int i = 0;
13050 +    size_t offset;
13051 +
13052 +    if (p == NULL) {
13053 +        return NULL;
13054 +    }
13055 +
13056 +    if(SMA_RO(sma_lastseg) == NULL) return p;
13057 +
13058 +    offset = (size_t)((char *)p - SMA_ADDR(sma_lastseg));
13059 +
13060 +    if(p >= (void*)SMA_ADDR(sma_lastseg) && offset < sma_segsize) {
13061 +        return SMA_RO(sma_lastseg) + offset;
13062 +    }
13063 +
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;
13068 +        }
13069 +    }
13070 +
13071 +    return NULL;
13072 +}
13073 +/* }}} */
13074 +
13075 +/* {{{ */
13076 +void* apc_sma_unprotect(void *p)
13077 +{
13078 +    unsigned int i = 0;
13079 +    size_t offset;
13080 +
13081 +    if (p == NULL) {
13082 +        return NULL;
13083 +    }
13084 +
13085 +    if(SMA_RO(sma_lastseg) == NULL) return p;
13086 +
13087 +    offset = (size_t)((char *)p - SMA_RO(sma_lastseg));
13088 +
13089 +    if(p >= (void*)SMA_RO(sma_lastseg) && offset < sma_segsize) {
13090 +        return SMA_ADDR(sma_lastseg) + offset;
13091 +    }
13092 +
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;
13097 +        }
13098 +    }
13099 +
13100 +    return NULL;
13101 +}
13102 +/* }}} */
13103 +#else
13104 +/* {{{ */
13105 +void* apc_sma_protect(void *p) { return p; }
13106 +void* apc_sma_unprotect(void *p) { return p; }
13107 +/* }}} */
13108 +#endif
13109 +
13110 +/* {{{ apc_sma_info */
13111 +apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC)
13112 +{
13113 +    apc_sma_info_t* info;
13114 +    apc_sma_link_t** link;
13115 +    uint i;
13116 +    char* shmaddr;
13117 +    block_t* prv;
13118 +
13119 +    if (!sma_initialized) {
13120 +        return NULL;
13121 +    }
13122 +
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)));
13126 +
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;
13130 +    }
13131 +
13132 +    if(limited) return info;
13133 +
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)));
13139 +
13140 +        link = &info->list[i];
13141 +
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);
13147 +#endif
13148 +
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;
13154 +
13155 +            prv = cur;
13156 +
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);
13160 +#endif
13161 +
13162 +        }
13163 +        RDUNLOCK(SMA_LCK(i));
13164 +    }
13165 +
13166 +    return info;
13167 +}
13168 +/* }}} */
13169 +
13170 +/* {{{ apc_sma_free_info */
13171 +void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC)
13172 +{
13173 +    int i;
13174 +
13175 +    for (i = 0; i < info->num_seg; i++) {
13176 +        apc_sma_link_t* p = info->list[i];
13177 +        while (p) {
13178 +            apc_sma_link_t* q = p;
13179 +            p = p->next;
13180 +            apc_efree(q TSRMLS_CC);
13181 +        }
13182 +    }
13183 +    apc_efree(info->list TSRMLS_CC);
13184 +    apc_efree(info TSRMLS_CC);
13185 +}
13186 +/* }}} */
13187 +
13188 +/* {{{ apc_sma_get_avail_mem */
13189 +size_t apc_sma_get_avail_mem()
13190 +{
13191 +    size_t avail_mem = 0;
13192 +    uint i;
13193 +
13194 +    for (i = 0; i < sma_numseg; i++) {
13195 +        sma_header_t* header = SMA_HDR(i);
13196 +        avail_mem += header->avail;
13197 +    }
13198 +    return avail_mem;
13199 +}
13200 +/* }}} */
13201 +
13202 +/* {{{ apc_sma_get_avail_size */
13203 +zend_bool apc_sma_get_avail_size(size_t size)
13204 +{
13205 +    uint i;
13206 +
13207 +    for (i = 0; i < sma_numseg; i++) {
13208 +       sma_header_t* header = SMA_HDR(i);
13209 +               if (header->avail > size) {
13210 +                       return 1;
13211 +               }
13212 +    }
13213 +    return 0;
13214 +}
13215 +/* }}} */
13216 +
13217 +
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;
13222 +}
13223 +#endif
13224 +
13225 +/*
13226 + * Local variables:
13227 + * tab-width: 4
13228 + * c-basic-offset: 4
13229 + * End:
13230 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13231 + * vim<600: expandtab sw=4 ts=4 sts=4
13232 + */
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
13236 @@ -0,0 +1,103 @@
13237 +/*
13238 +  +----------------------------------------------------------------------+
13239 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13253 +
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.
13259 +
13260 +   All other licensing and usage conditions are those of the PHP Group.
13261 +
13262 + */
13263 +
13264 +/* $Id: apc_sma.h 307048 2011-01-03 23:53:17Z kalle $ */
13265 +
13266 +#ifndef APC_SMA_H
13267 +#define APC_SMA_H
13268 +
13269 +#define ALLOC_DISTRIBUTION 0
13270 +
13271 +#include "apc.h"
13272 +
13273 +/* Simple shared memory allocator */
13274 +
13275 +typedef struct _apc_segment_t apc_segment_t;
13276 +
13277 +struct _apc_segment_t {
13278 +    size_t size;
13279 +    void* shmaddr;
13280 +#ifdef APC_MEMPROTECT
13281 +    void* roaddr;
13282 +#endif
13283 +};
13284 +
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();
13294 +#endif
13295 +
13296 +extern void* apc_sma_protect(void *p);
13297 +extern void* apc_sma_unprotect(void *p);
13298 +
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 */
13305 +};
13306 +/* }}} */
13307 +
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 */
13314 +};
13315 +/* }}} */
13316 +
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);
13319 +
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();
13323 +
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))
13328 +/* }}} */
13329 +
13330 +#endif
13331 +
13332 +/*
13333 + * Local variables:
13334 + * tab-width: 4
13335 + * c-basic-offset: 4
13336 + * End:
13337 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13338 + * vim<600: expandtab sw=4 ts=4 sts=4
13339 + */
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
13343 @@ -0,0 +1,66 @@
13344 +/*
13345 +  +----------------------------------------------------------------------+
13346 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13360 +
13361 + */
13362 +
13363 +/* $Id: apc_spin.c 307048 2011-01-03 23:53:17Z kalle $ */
13364 +
13365 +#include "apc_spin.h"
13366 +
13367 +#ifdef APC_SPIN_LOCKS
13368 +
13369 +slock_t *apc_slock_create(slock_t *lock)
13370 +{
13371 +   S_INIT_LOCK(lock);
13372 +   return lock;
13373 +}
13374 +
13375 +void apc_slock_destroy(slock_t *lock)
13376 +{
13377 +    return;
13378 +}
13379 +
13380 +void apc_slock_lock(slock_t *lock TSRMLS_DC)
13381 +{
13382 +    S_LOCK(lock);
13383 +}
13384 +
13385 +void apc_slock_unlock(slock_t *lock)
13386 +{
13387 +    S_UNLOCK(lock);
13388 +}
13389 +
13390 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
13391 +{
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 
13395 +     */
13396 +    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
13397 +}
13398 +
13399 +
13400 +#endif
13401 +
13402 +/*
13403 + * Local variables:
13404 + * tab-width: 4
13405 + * c-basic-offset: 4
13406 + * End:
13407 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13408 + * vim<600: expandtab sw=4 ts=4 sts=4
13409 + */
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
13413 @@ -0,0 +1,48 @@
13414 +/*
13415 +  +----------------------------------------------------------------------+
13416 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13430 +
13431 + */
13432 +
13433 +/* $Id: apc_spin.h 307048 2011-01-03 23:53:17Z kalle $ */
13434 +
13435 +#ifndef APC_SPIN_H
13436 +#define APC_SPIN_H
13437 +
13438 +#include "apc.h"
13439 +
13440 +#ifdef APC_SPIN_LOCKS
13441 +
13442 +#include "pgsql_s_lock.h"
13443 +
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);
13449 +
13450 +#endif
13451 +
13452 +#endif
13453 +
13454 +/*
13455 + * Local variables:
13456 + * tab-width: 4
13457 + * c-basic-offset: 4
13458 + * End:
13459 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13460 + * vim<600: expandtab sw=4 ts=4 sts=4
13461 + */
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
13465 @@ -0,0 +1,106 @@
13466 +/*
13467 +  +----------------------------------------------------------------------+
13468 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13482 +
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.
13488 +
13489 +   All other licensing and usage conditions are those of the PHP Group.
13490 +
13491 + */
13492 +
13493 +/* $Id: apc_stack.c 307048 2011-01-03 23:53:17Z kalle $ */
13494 +
13495 +#include "apc.h"
13496 +#include "apc_stack.h"
13497 +
13498 +struct apc_stack_t {
13499 +    void** data;
13500 +    int capacity;
13501 +    int size;
13502 +};
13503 +
13504 +apc_stack_t* apc_stack_create(int size_hint TSRMLS_DC)
13505 +{
13506 +    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t) TSRMLS_CC);
13507 +
13508 +    stack->capacity = (size_hint > 0) ? size_hint : 10;
13509 +    stack->size = 0;
13510 +    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity TSRMLS_CC);
13511 +
13512 +    return stack;
13513 +}
13514 +
13515 +void apc_stack_destroy(apc_stack_t* stack TSRMLS_DC)
13516 +{
13517 +    if (stack != NULL) {
13518 +        apc_efree(stack->data TSRMLS_CC);
13519 +        apc_efree(stack TSRMLS_CC);
13520 +    }
13521 +}
13522 +
13523 +void apc_stack_clear(apc_stack_t* stack)
13524 +{
13525 +    assert(stack != NULL);
13526 +    stack->size = 0;
13527 +}
13528 +
13529 +void apc_stack_push(apc_stack_t* stack, void* item TSRMLS_DC)
13530 +{
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);
13535 +    }
13536 +    stack->data[stack->size++] = item;
13537 +}
13538 +
13539 +void* apc_stack_pop(apc_stack_t* stack)
13540 +{
13541 +    assert(stack != NULL && stack->size > 0);
13542 +    return stack->data[--stack->size];
13543 +}
13544 +
13545 +void* apc_stack_top(apc_stack_t* stack)
13546 +{
13547 +    assert(stack != NULL && stack->size > 0);
13548 +    return stack->data[stack->size-1];
13549 +}
13550 +
13551 +void* apc_stack_get(apc_stack_t* stack, int n)
13552 +{
13553 +    assert(stack != NULL && stack->size > n);
13554 +    return stack->data[n];
13555 +}
13556 +
13557 +int apc_stack_size(apc_stack_t* stack)
13558 +{
13559 +    assert(stack != NULL);
13560 +    return stack->size;
13561 +}
13562 +
13563 +
13564 +/*
13565 + * Local variables:
13566 + * tab-width: 4
13567 + * c-basic-offset: 4
13568 + * End:
13569 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13570 + * vim<600: expandtab sw=4 ts=4 sts=4
13571 + */
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
13575 @@ -0,0 +1,58 @@
13576 +/*
13577 +  +----------------------------------------------------------------------+
13578 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13593 +
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.
13599 +
13600 +   All other licensing and usage conditions are those of the PHP Group.
13601 +
13602 + */
13603 +
13604 +/* $Id: apc_stack.h 307048 2011-01-03 23:53:17Z kalle $ */
13605 +
13606 +#ifndef APC_STACK_H
13607 +#define APC_STACK_H
13608 +
13609 +/* Basic stack datatype */
13610 +
13611 +#define T apc_stack_t*
13612 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
13613 +
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);
13622 +
13623 +#undef T
13624 +#endif
13625 +
13626 +/*
13627 + * Local variables:
13628 + * tab-width: 4
13629 + * c-basic-offset: 4
13630 + * End:
13631 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13632 + * vim<600: expandtab sw=4 ts=4 sts=4
13633 + */
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
13637 @@ -0,0 +1,261 @@
13638 +/*
13639 +  +----------------------------------------------------------------------+
13640 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13654 +
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.
13660 +
13661 +   All other licensing and usage conditions are those of the PHP Group.
13662 +
13663 + */
13664 +
13665 +/* $Id: apc_string.c 326089 2012-06-11 04:29:57Z rasmus $ */
13666 +
13667 +#include "apc.h"
13668 +#include "apc_globals.h"
13669 +#include "apc_php.h"
13670 +#include "apc_lock.h"
13671 +
13672 +#ifdef ZEND_ENGINE_2_4
13673 +
13674 +#ifndef ZTS
13675 +typedef struct _apc_interned_strings_data_t {
13676 +    char *interned_strings_start;
13677 +    char *interned_strings_end;
13678 +    char *interned_strings_top;
13679 +    apc_lck_t lock;
13680 +    HashTable interned_strings;
13681 +} apc_interned_strings_data_t;
13682 +
13683 +apc_interned_strings_data_t *apc_interned_strings_data = NULL;
13684 +
13685 +#define APCSG(v) (apc_interned_strings_data->v)
13686 +
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);
13692 +
13693 +static const char *apc_dummy_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC)
13694 +{
13695 +    return str;
13696 +}
13697 +
13698 +static void apc_dummy_interned_strings_snapshot_for_php(TSRMLS_D)
13699 +{
13700 +}
13701 +
13702 +static void apc_dummy_interned_strings_restore_for_php(TSRMLS_D)
13703 +{
13704 +}
13705 +#endif
13706 +
13707 +const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC)
13708 +{
13709 +#ifndef ZTS
13710 +    ulong h;
13711 +    uint nIndex;
13712 +    Bucket *p;
13713 +
13714 +    if (arKey >= APCSG(interned_strings_start) && arKey < APCSG(interned_strings_end)) {
13715 +        return arKey;
13716 +    }
13717 +
13718 +    h = zend_inline_hash_func(arKey, nKeyLength);
13719 +    nIndex = h & APCSG(interned_strings).nTableMask;
13720 +
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)) {
13725 +                return p->arKey;
13726 +            }
13727 +        }
13728 +        p = p->pNext;
13729 +    }
13730 +   
13731 +    if (APCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1) >=
13732 +        APCSG(interned_strings_end)) {
13733 +        /* no memory */
13734 +        return NULL;
13735 +    }
13736 +
13737 +    p = (Bucket *) APCSG(interned_strings_top);
13738 +    APCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1);
13739 +
13740 +    p->arKey = (char*)(p+1);
13741 +    memcpy(p->arKey, arKey, nKeyLength);
13742 +    ((char *)p->arKey)[nKeyLength] = '\0';
13743 +    p->nKeyLength = nKeyLength;
13744 +    p->h = h;
13745 +    p->pData = &p->pDataPtr;
13746 +    p->pDataPtr = p;
13747 +
13748 +    p->pNext = APCSG(interned_strings).arBuckets[nIndex];
13749 +    p->pLast = NULL;
13750 +    if (p->pNext) {
13751 +        p->pNext->pLast = p;
13752 +    }
13753 +    APCSG(interned_strings).arBuckets[nIndex] = p;
13754 +
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;
13760 +    }
13761 +    if (!APCSG(interned_strings).pListHead) {
13762 +        APCSG(interned_strings).pListHead = p;
13763 +    }
13764 +
13765 +    APCSG(interned_strings).nNumOfElements++;
13766 +
13767 +    return p->arKey;
13768 +#else
13769 +    return zend_new_interned_string(arKey, nKeyLength, 0 TSRMLS_CC);
13770 +#endif
13771 +}
13772 +
13773 +#ifndef ZTS
13774 +static void apc_copy_internal_strings(TSRMLS_D)
13775 +{
13776 +    Bucket *p, *q;
13777 +
13778 +    p = CG(function_table)->pListHead;
13779 +    while (p) {
13780 +        if (p->nKeyLength) {
13781 +            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13782 +        }
13783 +        p = p->pListNext;
13784 +    }
13785 +
13786 +    p = CG(class_table)->pListHead;
13787 +    while (p) {
13788 +        zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr);
13789 +
13790 +        if (p->nKeyLength) {
13791 +            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13792 +        }
13793 +
13794 +               if (ce->name) {
13795 +            ce->name = apc_new_interned_string(ce->name, ce->name_length+1 TSRMLS_CC);
13796 +               }
13797 +
13798 +        q = ce->properties_info.pListHead;
13799 +        while (q) {
13800 +            zend_property_info *info = (zend_property_info*)(q->pData);
13801 +
13802 +            if (q->nKeyLength) {
13803 +                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13804 +            }
13805 +
13806 +            if (info->name) {
13807 +                info->name = apc_new_interned_string(info->name, info->name_length+1 TSRMLS_CC);
13808 +            }
13809 +
13810 +            q = q->pListNext;
13811 +        }
13812 +
13813 +        q = ce->function_table.pListHead;
13814 +        while (q) {
13815 +            if (q->nKeyLength) {
13816 +                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13817 +            }
13818 +            q = q->pListNext;
13819 +        }
13820 +
13821 +        q = ce->constants_table.pListHead;
13822 +        while (q) {
13823 +            if (q->nKeyLength) {
13824 +                q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC);
13825 +            }
13826 +            q = q->pListNext;
13827 +        }
13828 +
13829 +        p = p->pListNext;
13830 +    }
13831 +
13832 +    p = EG(zend_constants)->pListHead;
13833 +    while (p) {
13834 +        if (p->nKeyLength) {
13835 +            p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC);
13836 +       }
13837 +        p = p->pListNext;
13838 +    }
13839 +}
13840 +
13841 +void apc_interned_strings_init(TSRMLS_D)
13842 +{
13843 +    int count = APCG(shm_strings_buffer) / (sizeof(Bucket) + sizeof(Bucket*) * 2);
13844 +
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));
13847 +
13848 +    CREATE_LOCK(APCSG(lock));
13849 +
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));
13853 +   
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);
13857 +
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;
13863 +
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;
13869 +
13870 +    apc_copy_internal_strings(TSRMLS_C);
13871 +}
13872 +
13873 +void apc_interned_strings_shutdown(TSRMLS_D)
13874 +{      
13875 +    zend_hash_clean(CG(function_table));
13876 +    zend_hash_clean(CG(class_table));
13877 +    zend_hash_clean(EG(zend_constants));
13878 +
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;
13884 +
13885 +    DESTROY_LOCK(APCSG(lock));
13886 +}
13887 +#endif
13888 +
13889 +#endif
13890 +
13891 +/*
13892 + * Local variables:
13893 + * tab-width: 4
13894 + * c-basic-offset: 4
13895 + * End:
13896 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13897 + * vim<600: expandtab sw=4 ts=4 sts=4
13898 + */
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
13902 @@ -0,0 +1,51 @@
13903 +/*
13904 +  +----------------------------------------------------------------------+
13905 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13919 +
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.
13925 +
13926 +   All other licensing and usage conditions are those of the PHP Group.
13927 +
13928 + */
13929 +
13930 +/* $Id: apc_string.h 324145 2012-03-12 11:38:28Z pajoye $ */
13931 +
13932 +#ifndef APC_STRING
13933 +#define APC_STRING
13934 +
13935 +#include "apc.h"
13936 +
13937 +#ifndef ZTS
13938 +void apc_interned_strings_init(TSRMLS_D);
13939 +void apc_interned_strings_shutdown(TSRMLS_D);
13940 +#endif
13941 +
13942 +const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC);
13943 +
13944 +#endif
13945 +
13946 +/*
13947 + * Local variables:
13948 + * tab-width: 4
13949 + * c-basic-offset: 4
13950 + * End:
13951 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
13952 + * vim<600: expandtab sw=4 ts=4 sts=4
13953 + */
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
13957 @@ -0,0 +1,133 @@
13958 +/*
13959 +  +----------------------------------------------------------------------+
13960 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
13974 + */
13975 +/* $Id$ */
13976 +/*
13977 + These APIs are not actually exposed nor documented. But should work fine
13978 + from a binary as available since XP without signature changes.
13979 +*/
13980 +/*
13981 +TODOs:
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.
13985 + */
13986 +/* $Id: $ */
13987 +
13988 +#include <php.h>
13989 +
13990 +#ifdef APC_SRWLOCK_KERNEL
13991 +#include "apc_windows_srwlock_kernel.h"
13992 +
13993 +/*
13994 +For references:
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);
14000 +*/
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);
14007 +
14008 +tRtlInitializeResource        pRtlInitializeResource = 0;
14009 +tRtlDeleteResource            pRtlDeleteResource = 0;
14010 +tRtlAcquireResourceExclusive  pRtlAcquireResourceExclusive = 0;
14011 +tRtlAcquireResourceShared     pRtlAcquireResourceShared = 0;
14012 +tRtlReleaseResource           pRtlReleaseResource = 0;
14013 +tRtlDumpResource              pRtlDumpResource = 0;
14014 +
14015 +HINSTANCE ntdll;
14016 +
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) 
14019 +{
14020 +    ntdll = LoadLibrary("ntdll.dll");
14021 +    if (ntdll == 0) {
14022 +      return NULL;
14023 +    }
14024 +
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) {
14033 +        return NULL;
14034 +    }
14035 +    pRtlInitializeResource(lock);
14036 +    return lock;
14037 +}
14038 +
14039 +void apc_windows_cs_destroy(apc_windows_cs_rwlock_t *lock)
14040 +{
14041 +    __try
14042 +    {
14043 +        pRtlDeleteResource(lock);
14044 +    }
14045 +        __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
14046 +               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
14047 +    {
14048 +        /* Ignore exception (resource was freed during shutdown of another thread) */
14049 +    }
14050 +    FreeLibrary(ntdll);
14051 +    return;
14052 +}
14053 +
14054 +void apc_windows_cs_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14055 +{
14056 +    pRtlAcquireResourceExclusive(lock, 1);
14057 +}
14058 +
14059 +void apc_windows_cs_rdlock(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14060 +{
14061 +    pRtlAcquireResourceShared(lock, 1);
14062 +}
14063 +
14064 +void apc_windows_cs_unlock_rd(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14065 +{
14066 +    pRtlReleaseResource(lock);
14067 +}
14068 +
14069 +void apc_windows_cs_unlock_wr(apc_windows_cs_rwlock_t *lock TSRMLS_DC)
14070 +{
14071 +    pRtlReleaseResource(lock);
14072 +}
14073 +
14074 +/* debugging purposes, output using trace msgs */
14075 +void apc_windows_cs_status(apc_windows_cs_rwlock_t *lock)
14076 +{
14077 +    pRtlDumpResource(lock);
14078 +    return;
14079 +}
14080 +
14081 +#endif
14082 +
14083 +/*
14084 + * Local variables:
14085 + * tab-width: 4
14086 + * c-basic-offset: 4
14087 + * End:
14088 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14089 + * vim<600: expandtab sw=4 ts=4 sts=4
14090 + */
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
14094 @@ -0,0 +1,74 @@
14095 +/*
14096 +  +----------------------------------------------------------------------+
14097 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
14111 + */
14112 +/* $Id$ */
14113 +
14114 +#ifndef APC_WINDOWS_CS_RWLOCK_H
14115 +#define APC_WINDOWS_CS_RWLOCK_H
14116 +
14117 +#include "apc.h"
14118 +
14119 +#ifdef APC_SRWLOCK_KERNEL
14120 +
14121 +typedef struct _RTL_RWLOCK {
14122 +   RTL_CRITICAL_SECTION rtlCS;
14123 +
14124 +   HANDLE hSharedReleaseSemaphore;
14125 +   UINT   uSharedWaiters;
14126 +
14127 +   HANDLE hExclusiveReleaseSemaphore;
14128 +   UINT   uExclusiveWaiters;
14129 +
14130 +   INT    iNumberActive;
14131 +   HANDLE hOwningThreadId;
14132 +   DWORD  dwTimeoutBoost;
14133 +   PVOID  pDebugInfo;
14134 +} RTL_RWLOCK, *LPRTL_RWLOCK;
14135 +
14136 +#define apc_windows_cs_rwlock_t RTL_RWLOCK
14137 +
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;
14146 +};
14147 +
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);
14156 +# endif
14157 +#endif
14158 +
14159 +#endif
14160 +
14161 +/*
14162 + * Local variables:
14163 + * tab-width: 4
14164 + * c-basic-offset: 4
14165 + * End:
14166 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14167 + * vim<600: expandtab sw=4 ts=4 sts=4
14168 + */
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
14172 @@ -0,0 +1,271 @@
14173 +/*
14174 +  +----------------------------------------------------------------------+
14175 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
14189 +
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.
14195 +
14196 +   All other licensing and usage conditions are those of the PHP Group.
14197 +
14198 + */
14199 +
14200 +/* $Id: apc_zend.c 307048 2011-01-03 23:53:17Z kalle $ */
14201 +
14202 +#include "apc_zend.h"
14203 +#include "apc_globals.h"
14204 +
14205 +/* true global */
14206 +int apc_reserved_offset;
14207 +
14208 +void* apc_php_malloc(size_t n TSRMLS_DC)
14209 +{
14210 +    return emalloc(n);
14211 +}
14212 +
14213 +void apc_php_free(void* p TSRMLS_DC)
14214 +{
14215 +    efree(p);
14216 +}
14217 +
14218 +#ifdef APC_OPCODE_OVERRIDE
14219 +
14220 +static opcode_handler_t *apc_original_opcode_handlers;
14221 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
14222 +
14223 +#define APC_EX_T(offset)                    (*(temp_variable *)((char*)execute_data->Ts + offset))
14224 +
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)
14227 +{
14228 +    *freeval = NULL;
14229 +
14230 +    switch (op_type) {
14231 +        case IS_CONST:
14232 +            return node->zv;
14233 +        case IS_VAR:
14234 +            return APC_EX_T(node->var).var.ptr;
14235 +        case IS_TMP_VAR:
14236 +            return (*freeval = &APC_EX_T(node->var).tmp_var);
14237 +        case IS_CV:
14238 +        {
14239 +            zval ***ret = &execute_data->CVs[node->var];
14240 +
14241 +            if (!*ret) {
14242 +                zend_compiled_variable *cv = &EG(active_op_array)->vars[node->var];
14243 +
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);
14247 +                }
14248 +            }
14249 +            return **ret;
14250 +        }
14251 +        case IS_UNUSED:
14252 +        default:
14253 +            return NULL;
14254 +    }
14255 +}
14256 +#else
14257 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
14258 +{
14259 +    *freeval = NULL;
14260 +
14261 +    switch (node->op_type) {
14262 +        case IS_CONST:
14263 +            return &(node->u.constant);
14264 +        case IS_VAR:
14265 +            return APC_EX_T(node->u.var).var.ptr;
14266 +        case IS_TMP_VAR:
14267 +            return (*freeval = &APC_EX_T(node->u.var).tmp_var);
14268 +#ifdef ZEND_ENGINE_2_1
14269 +        case IS_CV:
14270 +        {
14271 +            zval ***ret = &execute_data->CVs[node->u.var];
14272 +
14273 +            if (!*ret) {
14274 +                zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
14275 +
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);
14279 +                }
14280 +            }
14281 +            return **ret;
14282 +        }
14283 +#endif
14284 +        case IS_UNUSED:
14285 +        default:
14286 +            return NULL;
14287 +    }
14288 +}
14289 +#endif
14290 +
14291 +static int ZEND_FASTCALL apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
14292 +{
14293 +    APC_ZEND_OPLINE
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;
14300 +    int ret = 0;
14301 +    apc_opflags_t* flags = NULL;
14302 +
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);
14307 +    }
14308 +
14309 +    inc_filename = apc_get_zval_ptr(opline->op1_type, &opline->op1, &freeop1, execute_data TSRMLS_CC);
14310 +#else
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);
14314 +    }
14315 +
14316 +    inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
14317 +#endif
14318 +
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;
14324 +    }
14325 +
14326 +    wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
14327 +
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);
14332 +        }
14333 +        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14334 +    }
14335 +
14336 +    if (!full_path) {
14337 +       full_path = path_for_open;
14338 +    }
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);
14344 +        }
14345 +#else
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);
14349 +        }
14350 +#endif
14351 +        if (inc_filename == &tmp_inc_filename) {
14352 +            zval_dtor(&tmp_inc_filename);
14353 +        }
14354 +        if (freeop1) {
14355 +            zval_dtor(freeop1);
14356 +        }
14357 +        execute_data->opline++;
14358 +        return 0;
14359 +    }
14360 +
14361 +    if (inc_filename == &tmp_inc_filename) {
14362 +        zval_dtor(&tmp_inc_filename);
14363 +    }
14364 +
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]);
14368 +    }
14369 +
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.
14373 +         */
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;
14378 +#else
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;
14382 +#endif
14383 +    } else {
14384 +        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
14385 +    }
14386 +
14387 +    return ret;
14388 +}
14389 +
14390 +void apc_zend_init(TSRMLS_D)
14391 +{
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 */
14399 +        return;
14400 +    }
14401 +
14402 +    memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
14403 +
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;
14408 +#else
14409 +    apc_original_opcode_handlers = apc_opcode_handlers;
14410 +#endif
14411 +
14412 +    APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
14413 +}
14414 +
14415 +void apc_zend_shutdown(TSRMLS_D)
14416 +{
14417 +    if (!APCG(include_once)) {
14418 +        /* Nothing changed, nothing to restore */
14419 +        return;
14420 +    }
14421 +
14422 +#ifdef ZEND_ENGINE_2_1
14423 +    zend_opcode_handlers = apc_original_opcode_handlers;
14424 +#else
14425 +    memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
14426 +#endif
14427 +}
14428 +
14429 +#else /* Opcode Overrides unavailable */
14430 +
14431 +void apc_zend_init(TSRMLS_D) { }
14432 +void apc_zend_shutdown(TSRMLS_D) { }
14433 +
14434 +#endif /* APC_OPCODE_OVERRIDE */
14435 +
14436 +/*
14437 + * Local variables:
14438 + * tab-width: 4
14439 + * c-basic-offset: 4
14440 + * End:
14441 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14442 + * vim<600: expandtab sw=4 ts=4 sts=4
14443 + */
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
14447 @@ -0,0 +1,191 @@
14448 +/*
14449 +  +----------------------------------------------------------------------+
14450 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
14464 +
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.
14470 +
14471 +   All other licensing and usage conditions are those of the PHP Group.
14472 +
14473 + */
14474 +
14475 +/* $Id: apc_zend.h 326712 2012-07-19 21:33:27Z rasmus $ */
14476 +
14477 +#ifndef APC_ZEND_H
14478 +#define APC_ZEND_H
14479 +
14480 +/* Utilities for interfacing with the zend engine */
14481 +
14482 +#include "apc.h"
14483 +#include "apc_php.h"
14484 +
14485 +#ifndef Z_REFCOUNT_P
14486 +#define Z_REFCOUNT_P(pz)              (pz)->refcount
14487 +#define Z_REFCOUNT_PP(ppz)            Z_REFCOUNT_P(*(ppz))
14488 +#endif
14489 +
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)
14493 +#endif
14494 +
14495 +#ifndef Z_ADDREF_P
14496 +#define Z_ADDREF_P(pz)                (pz)->refcount++
14497 +#define Z_ADDREF_PP(ppz)              Z_ADDREF_P(*(ppz))
14498 +#endif
14499 +
14500 +#ifndef Z_DELREF_P
14501 +#define Z_DELREF_P(pz)                (pz)->refcount--
14502 +#define Z_DELREF_PP(ppz)              Z_DELREF_P(*(ppz))
14503 +#endif
14504 +
14505 +#ifndef Z_ISREF_P
14506 +#define Z_ISREF_P(pz)                 (pz)->is_ref
14507 +#define Z_ISREF_PP(ppz)               Z_ISREF_P(*(ppz))
14508 +#endif
14509 +
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))
14513 +#endif
14514 +
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))
14518 +#endif
14519 +
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)
14523 +#endif
14524 +
14525 +
14526 +extern void* apc_php_malloc(size_t n TSRMLS_DC);
14527 +extern void apc_php_free(void* p TSRMLS_DC);
14528 +
14529 +extern void apc_zend_init(TSRMLS_D);
14530 +extern void apc_zend_shutdown(TSRMLS_D);
14531 +
14532 +
14533 +/* offset for apc info in op_array->reserved */
14534 +extern int apc_reserved_offset;
14535 +
14536 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
14537 +# define ZEND_VM_KIND_CALL  1
14538 +#endif
14539 +
14540 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
14541 +# define ZEND_VM_KIND   ZEND_VM_KIND_CALL
14542 +#endif
14543 +
14544 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
14545 +# define APC_OPCODE_OVERRIDE
14546 +#endif
14547 +
14548 +#ifdef APC_OPCODE_OVERRIDE
14549 +
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)
14558 +{
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     */
14577 +    };
14578 +#ifdef ZEND_ENGINE_2_4
14579 +    return (opline->opcode * 25) + (apc_vm_decode[opline->op1_type] * 5) + apc_vm_decode[opline->op2_type];
14580 +#else
14581 +    return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
14582 +#endif
14583 +}
14584 +
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 */
14593 +# else
14594 +#  define APC_OPCODE_HANDLER_COUNT          ((25 * 151) + 1)
14595 +# endif
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; }
14597 +
14598 +#else /* ZE2.0 */
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;
14603 +#endif
14604 +
14605 +#ifndef ZEND_FASTCALL  /* Added in ZE2.3.0 */
14606 +#define ZEND_FASTCALL
14607 +#endif
14608 +
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, "")
14612 +#endif
14613 +
14614 +
14615 +#endif  /* APC_OPCODE_OVERRIDE */
14616 +
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
14622 +#else
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
14627 +#endif
14628 +
14629 +#endif  /* APC_ZEND_H */
14630 +
14631 +/*
14632 + * Local variables:
14633 + * tab-width: 4
14634 + * c-basic-offset: 4
14635 + * End:
14636 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
14637 + * vim<600: expandtab sw=4 ts=4 sts=4
14638 + */
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
14642 @@ -0,0 +1,249 @@
14643 +
14644 +3.1.2 : 2008-12-12
14645 +
14646 +- pecl package.xml/build fixes (bjori)
14647 +
14648 +3.1.1 : 2008-12-12
14649 +
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)
14665 +
14666 +3.0.19: 2008-05-14
14667 +- Safe-mode and fast-cgi fixes
14668 +- Fix double-free of builtin_functions
14669 +- php 5.3 fixes
14670 +
14671 +3.0.18: 2008-03-29
14672 +- Revert apc_expunge_cb bug-fix
14673 +- Misc memleaks
14674 +
14675 +3.0.17: 2008-03-26
14676 +- Crash fixes
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)
14680 +  
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)
14688 +
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)
14699 +  
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)
14708 +
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)
14729 +
14730 +3.0.12p2: 2006-09-05
14731 +- Package version up
14732 +
14733 +3.0,12p1: 2006-09-05
14734 +- PHP4 build fixes
14735 +
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)
14746 +
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)
14760 +
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
14765 +  lot of includes.
14766 +
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.
14769 +
14770 +3.0.9: 2006-03-04
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)
14788 +
14789 +3.0.8: 2005-08-24
14790 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
14791 +Cache corruption fix in cache-full cleanup code (Gopal)
14792 +
14793 +3.0.7: 2005-08-16
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)
14802 +
14803 +3.0.6: 2005-07-30
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)
14811 +
14812 +3.0.5: 2005-07-27
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)
14817 +
14818 +3.0.4: 2005-07-18
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
14822 +
14823 +3.0.3: 2005-07-05
14824 +- Fix compile problem against PHP 5.0.x
14825 +
14826 +3.0.2: 2005-07-05
14827 +- Better shm error message
14828 +
14829 +3.0.1: 2005-07-05
14830 +- PHP4 build fix
14831 +
14832 +3.0: 2005-06-23
14833 +- PHP 5.1 support (Arun, Gopal, Rasmus)
14834 +- Major Inheritance bug fix (Arun, Gopal)
14835 +
14836 +2.0: 2003-02-10
14837 +- ground-up rewrite sharing none of the original source code (djc)
14838 +
14839 +1.0.10:
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
14844 +  2001-05-15]
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]
14850 +
14851 +1.0.9:
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 
14856 +
14857 +1.0.8:
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]
14865 +
14866 +1.0.7:
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]
14870 +
14871 +1.0.6:
14872 +- support for mtime in mmap [yg,gws 2001-01-27]
14873 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
14874 +
14875 +1.0.5:
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]
14879 +
14880 +1.0.4:
14881 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
14882 +
14883 +1.0.3:
14884 +- fixed support for class inheritance [djc 2001-01-16]
14885 +
14886 +1.0.2:
14887 +- support for inherited classes [gws 2001-01-15]
14888 +- support for intialization of class variables and objects [gws 2001-01-13]
14889 +
14890 +1.0.1:
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
14895 @@ -0,0 +1,404 @@
14896 +dnl
14897 +dnl $Id: config.m4 326700 2012-07-19 11:56:57Z ab $
14898 +dnl
14899 +
14900 +PHP_ARG_ENABLE(apc, whether to enable APC support,
14901 +[  --enable-apc           Enable APC support])
14902 +
14903 +AC_ARG_ENABLE(apc-debug,
14904 +[  --enable-apc-debug     Enable APC debugging], 
14905 +[
14906 +  PHP_APC_DEBUG=$enableval
14907 +], 
14908 +[
14909 +  PHP_APC_DEBUG=no
14910 +])
14911 +
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')) ],
14915 +[
14916 +  PHP_APC_FILEHITS=$enableval
14917 +       AC_MSG_RESULT($enableval)
14918 +], 
14919 +[
14920 +  PHP_APC_FILEHITS=no
14921 +       AC_MSG_RESULT(no)
14922 +])
14923 +
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],
14928 +[
14929 +  PHP_APC_MMAP=$enableval
14930 +  AC_MSG_RESULT($enableval)
14931 +], [
14932 +  PHP_APC_MMAP=yes
14933 +  AC_MSG_RESULT(yes)
14934 +])
14935 +
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],
14940 +[
14941 +  PHP_APC_SEM=$enableval
14942 +  AC_MSG_RESULT($enableval)
14943 +], [
14944 +  PHP_APC_SEM=no
14945 +  AC_MSG_RESULT(no)
14946 +])
14947 +
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 ],
14952 +[
14953 +  PHP_APC_PTHREADMUTEX=$enableval
14954 +  AC_MSG_RESULT($enableval)
14955 +],
14956 +[
14957 +  PHP_APC_PTHREADMUTEX=yes
14958 +  AC_MSG_RESULT(yes)
14959 +])
14960 +
14961 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
14962 +       orig_LIBS="$LIBS"
14963 +       LIBS="$LIBS -lpthread"
14964 +       AC_TRY_RUN(
14965 +                       [
14966 +                               #include <sys/types.h>
14967 +                               #include <pthread.h>
14968 +                                main() {
14969 +                               pthread_mutex_t mutex;
14970 +                               pthread_mutexattr_t attr;       
14971 +
14972 +                               if(pthread_mutexattr_init(&attr)) { 
14973 +                                       puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
14974 +                                       return -1; 
14975 +                               }
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.");
14978 +                                       return -1; 
14979 +                               }       
14980 +                               if(pthread_mutex_init(&mutex, &attr)) { 
14981 +                                       puts("Unable to initialize the mutex (pthread_mutex_init).");
14982 +                                       return -1; 
14983 +                               }
14984 +                               if(pthread_mutexattr_destroy(&attr)) { 
14985 +                                       puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
14986 +                                       return -1; 
14987 +                               }
14988 +                               if(pthread_mutex_destroy(&mutex)) { 
14989 +                                       puts("Unable to destroy mutex (pthread_mutex_destroy).");
14990 +                                       return -1; 
14991 +                               }
14992 +
14993 +                               puts("pthread mutexs are supported!");
14994 +                               return 0;
14995 +                                }
14996 +                       ],
14997 +                       [ dnl -Success-
14998 +                               PHP_ADD_LIBRARY(pthread)
14999 +                       ],
15000 +                       [ dnl -Failure-
15001 +                               AC_MSG_WARN([It doesn't appear that pthread mutexes are supported on your system])
15002 +                       PHP_APC_PTHREADMUTEX=no
15003 +                       ],
15004 +                       [
15005 +                               PHP_ADD_LIBRARY(pthread)
15006 +                       ]
15007 +       )
15008 +       LIBS="$orig_LIBS"
15009 +fi
15010 +
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 ],
15015 +[
15016 +  PHP_APC_PTHREADRWLOCK=$enableval
15017 +  AC_MSG_RESULT($enableval)
15018 +],
15019 +[
15020 +  PHP_APC_PTHREADRWLOCK=no
15021 +  AC_MSG_RESULT(no)
15022 +])
15023 +
15024 +if test "$PHP_APC_PTHREADRWLOCK" != "no"; then
15025 +       orig_LIBS="$LIBS"
15026 +       LIBS="$LIBS -lpthread"
15027 +       AC_TRY_RUN(
15028 +                       [
15029 +                               #include <sys/types.h>
15030 +                               #include <pthread.h>
15031 +                                main() {
15032 +                               pthread_rwlock_t rwlock;
15033 +                               pthread_rwlockattr_t attr;      
15034 +
15035 +                               if(pthread_rwlockattr_init(&attr)) { 
15036 +                                       puts("Unable to initialize pthread attributes (pthread_rwlockattr_init).");
15037 +                                       return -1; 
15038 +                               }
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.");
15041 +                                       return -1; 
15042 +                               }       
15043 +                               if(pthread_rwlock_init(&rwlock, &attr)) { 
15044 +                                       puts("Unable to initialize the rwlock (pthread_rwlock_init).");
15045 +                                       return -1; 
15046 +                               }
15047 +                               if(pthread_rwlockattr_destroy(&attr)) { 
15048 +                                       puts("Unable to destroy rwlock attributes (pthread_rwlockattr_destroy).");
15049 +                                       return -1; 
15050 +                               }
15051 +                               if(pthread_rwlock_destroy(&rwlock)) { 
15052 +                                       puts("Unable to destroy rwlock (pthread_rwlock_destroy).");
15053 +                                       return -1; 
15054 +                               }
15055 +
15056 +                               puts("pthread rwlocks are supported!");
15057 +                               return 0;
15058 +                                }
15059 +                       ],
15060 +                       [ dnl -Success-
15061 +                               PHP_ADD_LIBRARY(pthread)
15062 +                               APC_CFLAGS="-D_GNU_SOURCE"
15063 +                       ],
15064 +                       [ dnl -Failure-
15065 +                               AC_MSG_WARN([It doesn't appear that pthread rwlocks are supported on your system])
15066 +                               PHP_APC_PTHREADRWLOCK=no
15067 +                       ],
15068 +                       [
15069 +                               PHP_ADD_LIBRARY(pthread)
15070 +                       ]
15071 +       )
15072 +       LIBS="$orig_LIBS"
15073 +fi
15074 +
15075 +       AC_CACHE_CHECK([whether the target compiler supports builtin atomics], PHP_cv_APC_GCC_ATOMICS, [
15076 +
15077 +                       AC_TRY_LINK([],[
15078 +                                       int foo = 0;
15079 +                                       __sync_fetch_and_add(&foo, 1);
15080 +                                       __sync_bool_compare_and_swap(&foo, 0, 1);
15081 +                                       return __sync_fetch_and_add(&foo, 1);
15082 +                               ],
15083 +                               [PHP_cv_APC_GCC_ATOMICS=yes],
15084 +                               [PHP_cv_APC_GCC_ATOMICS=no])
15085 +               ])
15086 +
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])
15090 +               else
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
15095 +                       fi
15096 +       fi
15097 +
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 ],
15102 +[
15103 +  PHP_APC_SPINLOCKS=$enableval
15104 +  AC_MSG_RESULT($enableval)
15105 +],
15106 +[
15107 +  PHP_APC_SPINLOCKS=no
15108 +  AC_MSG_RESULT(no)
15109 +])
15110 +
15111 +
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],
15116 +[
15117 +  PHP_APC_MEMPROTECT=$enableval
15118 +  AC_MSG_RESULT($enableval)
15119 +], [
15120 +  PHP_APC_MEMPROTECT=no
15121 +  AC_MSG_RESULT(no)
15122 +])
15123 +
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, [ ])
15127 +
15128 +       if test "$PHP_APC_DEBUG" != "no"; then
15129 +               AC_DEFINE(__DEBUG_APC__, 1, [ ])
15130 +       fi
15131 +
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, [ ])
15140 +       else 
15141 +               AC_DEFINE(APC_FCNTL_LOCKS, 1, [ ])
15142 +       fi
15143 +  
15144 +       if test "$PHP_APC_MEMPROTECT" != "no"; then
15145 +               AC_DEFINE(APC_MEMPROTECT, 1, [ shm/mmap memory protection ])
15146 +       fi
15147 +
15148 +  AC_CACHE_CHECK(for zend_set_lookup_function_hook, php_cv_zend_set_lookup_function_hook,
15149 +  [
15150 +    orig_cflags=$CFLAGS
15151 +    CFLAGS="$INCLUDES $EXTRA_INCLUDES"
15152 +    AC_TRY_COMPILE([
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;
15157 +#endif], [
15158 +      php_cv_zend_set_lookup_function_hook=yes
15159 +    ],[
15160 +      php_cv_zend_set_lookup_function_hook=no
15161 +    ])
15162 +    CFLAGS=$orig_cflags
15163 +  ])
15164 +  if test "$php_cv_zend_set_lookup_function_hook" = "yes"; then
15165 +    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 1, [ ])
15166 +  else
15167 +    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 0, [ ])
15168 +  fi
15169 +
15170 +  AC_CHECK_FUNCS(sigaction)
15171 +  AC_CACHE_CHECK(for union semun, php_cv_semun,
15172 +  [
15173 +    AC_TRY_COMPILE([
15174 +#include <sys/types.h>
15175 +#include <sys/ipc.h>
15176 +#include <sys/sem.h>
15177 +    ], [union semun x; x.val=1], [
15178 +      php_cv_semun=yes
15179 +    ],[
15180 +      php_cv_semun=no
15181 +    ])
15182 +  ])
15183 +  if test "$php_cv_semun" = "yes"; then
15184 +    AC_DEFINE(HAVE_SEMUN, 1, [ ])
15185 +  else
15186 +    AC_DEFINE(HAVE_SEMUN, 0, [ ])
15187 +  fi
15188 +
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],
15193 +  [
15194 +    PHP_APC_VALGRIND=$enableval
15195 +    AC_MSG_RESULT($enableval)
15196 +  ], [
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])])
15201 +  ])
15202 +
15203 +  apc_sources="apc.c php_apc.c \
15204 +               apc_cache.c \
15205 +               apc_compile.c \
15206 +               apc_debug.c \
15207 +               apc_fcntl.c \
15208 +               apc_main.c \
15209 +               apc_mmap.c \
15210 +               apc_sem.c \
15211 +               apc_shm.c \
15212 +               apc_pthreadmutex.c \
15213 +               apc_pthreadrwlock.c \
15214 +               apc_spin.c \
15215 +               pgsql_s_lock.c \
15216 +               apc_sma.c \
15217 +               apc_stack.c \
15218 +               apc_zend.c \
15219 +               apc_rfc1867.c \
15220 +               apc_signal.c \
15221 +               apc_pool.c \
15222 +               apc_iterator.c \
15223 +               apc_bin.c \
15224 +               apc_string.c "
15225 +
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, [ ])
15232 +fi
15233 +
15234 +PHP_ARG_ENABLE(coverage,  whether to include code coverage symbols,
15235 +[  --enable-coverage           DEVELOPERS ONLY!!], no, no)
15236 +
15237 +if test "$PHP_COVERAGE" = "yes"; then
15238 +
15239 +  if test "$GCC" != "yes"; then
15240 +    AC_MSG_ERROR([GCC is required for --enable-coverage])
15241 +  fi
15242 +  
15243 +  dnl Check if ccache is being used
15244 +  case `$php_shtool path $CC` in
15245 +    *ccache*[)] gcc_ccache=yes;;
15246 +    *[)] gcc_ccache=no;;
15247 +  esac
15248 +
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.])
15251 +  fi
15252 +  
15253 +  lcov_version_list="1.5 1.6 1.7 1.9"
15254 +
15255 +  AC_CHECK_PROG(LCOV, lcov, lcov)
15256 +  AC_CHECK_PROG(GENHTML, genhtml, genhtml)
15257 +  PHP_SUBST(LCOV)
15258 +  PHP_SUBST(GENHTML)
15259 +
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)"
15267 +        fi
15268 +      done
15269 +    ])
15270 +  else
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])
15273 +  fi
15274 +
15275 +  case $php_cv_lcov_version in
15276 +    ""|invalid[)]
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])
15279 +      LCOV="exit 0;"
15280 +      ;;
15281 +  esac
15282 +
15283 +  if test -z "$GENHTML"; then
15284 +    AC_MSG_ERROR([Could not find genhtml from the LCOV package])
15285 +  fi
15286 +
15287 +  PHP_ADD_MAKEFILE_FRAGMENT
15288 +
15289 +  dnl Remove all optimization flags from CFLAGS
15290 +  changequote({,})
15291 +  CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'`
15292 +  CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'`
15293 +  changequote([,])
15294 +
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"
15298 +fi
15299 +dnl vim: set ts=2 
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
15303 @@ -0,0 +1,60 @@
15304 +// $Id: config.w32 309203 2011-03-14 06:47:16Z pajoye $
15305 +// vim:ft=javascript
15306 +
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');
15314 +
15315 +if(PHP_APC != 'no')
15316 +{
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';
15321 +
15322 +       if(PHP_APC_DEBUG != 'no')
15323 +       {
15324 +               ADD_FLAG('CFLAGS_APC', '/D __DEBUG_APC__=1');
15325 +       }
15326 +
15327 +       if(PHP_APC_FILEHITS != 'no')
15328 +       {
15329 +               AC_DEFINE('APC_FILEHITS', 1);
15330 +       }
15331 +
15332 +       if(PHP_APC_MEMPROTECT != 'no')
15333 +       {
15334 +               AC_DEFINE('APC_MEMPROTECT', 1);
15335 +       }
15336 +
15337 +       if(PHP_APC_SRWLOCK_NATIVE != 'no') {
15338 +               AC_DEFINE('APC_SRWLOCK_NATIVE', 1);
15339 +       } else {
15340 +               if(PHP_APC_SRWLOCK_KERNEL != 'no') {
15341 +                       AC_DEFINE('APC_SRWLOCK_KERNEL', 1);
15342 +                       ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1');
15343 +
15344 +                       apc_sources += ' apc_windows_srwlock_kernel.c';
15345 +               } else {
15346 +                       if(PHP_APC_SPINLOCKS != 'no') {
15347 +                               AC_DEFINE('APC_SPIN_LOCKS', 1);
15348 +                               ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1');
15349 +
15350 +                               apc_sources += ' apc_spin.c pgsql_s_lock.c';
15351 +                       } else {
15352 +                               AC_DEFINE('APC_FCNTL_LOCKS', 1);
15353 +                       }
15354 +               }
15355 +       }
15356 +
15357 +       AC_DEFINE('HAVE_APC', 1);
15358 +       AC_DEFINE('HAVE_ATOMIC_OPERATIONS', 1);
15359 +
15360 +       PHP_INSTALL_HEADERS("ext/apc", "apc_serializer.h");
15361 +
15362 +       EXTENSION('apc', apc_sources);
15363 +}
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
15367 @@ -0,0 +1,407 @@
15368 +Installation Instructions for APC
15369 +---------------------------------
15370 +
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.
15375 +
15376 +CVS Instructions
15377 +----------------
15378 +Building from CVS can be done like this:
15379 +
15380 +  svn co http://svn.php.net/repository/pecl/apc/trunk apc
15381 +  cd apc
15382 +  phpize
15383 +  ./configure --with-php-config=/usr/local/php/bin/php-config
15384 +  make
15385 +  export TEST_PHP_ARGS='-n'
15386 +  make test
15387 +  make install
15388 +
15389 +Suggested Configuration (in your php.ini file)
15390 +----------------------------------------------
15391 +  extension=apc.so
15392 +  apc.enabled=1
15393 +  apc.shm_size=128M
15394 +  apc.ttl=7200
15395 +  apc.user_ttl=7200
15396 +  apc.enable_cli=1
15397 +
15398 +These are fully described at the bottom of this file.
15399 +
15400 ++---------------------+
15401 +| QUICK INSTALL (DSO) |
15402 ++---------------------+
15403 +
15404 +These instructions assume your PHP installation is located in /usr/local/php and you
15405 +want Apache optimizations (--with-apxs).
15406 +
15407 +$ gunzip -c apc_x.y.tar.gz | tar xf -
15408 +$ cd apc_x.y
15409 +$ /usr/local/php/bin/phpize
15410 +$ ./configure --with-php-config=/usr/local/php/bin/php-config
15411 +$ make
15412 +$ make install
15413 +
15414 +You will probably need to run the final command (make install) as root.
15415 +
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.
15419 +
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:
15422 +
15423 +    extension="apc.so"
15424 +
15425 +Replace "/path/to/php/extensions" with whatever path was displayed when you
15426 +ran make install above.
15427 +
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.
15430 +
15431 ++------------------------+
15432 +| QUICK INSTALL (Static) |
15433 ++------------------------+
15434 +
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.)
15438 +
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
15441 +configure script.
15442 +
15443 +$ cd ext
15444 +$ gunzip -c apc_x.y.tar.gz | tar xf -
15445 +$ cd ..
15446 +$ ./buildconf
15447 +$ ./config.nice
15448 +$ make
15449 +$ make install
15450 +
15451 +Once this is complete, simply restart your web server. You do not need to
15452 +modify your php.ini file to enable APC.
15453 +
15454 ++-----------------+
15455 +| VERBOSE INSTALL |
15456 ++-----------------+
15457 +
15458 +These instructions assume your PHP installation is located in /usr/local/php.
15459 +
15460 +1.  Unpack your distribution file.
15461 +
15462 +    You will have downloaded a file named something like apc_x.y.tar.gz.
15463 +    Unzip this file with a command like
15464 +    
15465 +        gunzip apc_x.y.tar.gz
15466 +    
15467 +    Next you have to untar it with
15468 +    
15469 +        tar xvf apc_x.y.tar
15470 +
15471 +    This will create an apc_x.y directory. cd into this new directory:
15472 +
15473 +        cd apc_x.y
15474 +
15475 +2.  Run phpize.
15476 +
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.)
15481 +
15482 +    Run the phpize command:
15483 +    
15484 +        /usr/local/php/bin/phpize
15485 +
15486 +    Its output should resemble this:
15487 +
15488 +        autoheader: `config.h.in' is created
15489 +        You should update your `aclocal.m4' by running aclocal.
15490 +        Configuring for:
15491 +          PHP Api Version:   20020918
15492 +          Zend Module Api No:   20020429
15493 +          Zend Extension Api No:   20021010
15494
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.
15499
15500 +3.  Run the configure script.
15501
15502 +    phpize creates a configure script. The only option you need to specify is
15503 +    the location of your php-config script:
15504 +
15505 +        ./configure --enable-apc
15506 +
15507 +    php-config should be located in the same directory as phpize.
15508 +
15509 +    If you prefer to use mmap instead of the default IPC shared memory support,
15510 +    add --enable-apc-mmap to your configure line. 
15511 +
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.
15516 +
15517 +4.  Compile and install the files. Simply type: make install
15518 +
15519 +    (You may need to be root in order to install)
15520 +
15521 +    If you encounter errors from libtool or gcc during this step, please
15522 +    contact the project maintainer (dcowgill@php.net).
15523 +
15524 +5.  Edit your php.ini
15525 +
15526 +    make install should have printed a line resembling the following:
15527 +
15528 +        Installing shared extensions: /path/to/extension/
15529 +
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):
15532 +
15533 +        extension="apc.so"
15534 +
15535 +    If you don't have a php.ini file in that location, you can create it now.
15536 +
15537 +6.  Restart the web server and test the installation.
15538 +
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:
15542 +
15543 +        <?php phpinfo() ?>
15544 +
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.
15547 +
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.
15553 +
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.
15558 +
15559 ++-----------------+
15560 +| CONFIGURING APC |
15561 ++-----------------+
15562 +
15563 +Although the default APC settings are fine for many installations, serious
15564 +users should consider tuning the following parameters:
15565 +
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).
15573 +                            (Default: 1)
15574 +                            
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.
15582 +                            (Default: 1)
15583 +                            
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.
15588 +                            (Default: 30)
15589 +
15590 +                            
15591 +    apc.optimization        This option has been deprecated.
15592 +                            (Default: 0)
15593 +    
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.
15599 +                            (Default: 1000)
15600 +
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;
15604 +                            (Default: 4096)
15605 +
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
15611 +                            cached.  
15612 +                            (Default: 0)
15613 +
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
15619 +                            cached.  
15620 +                            (Default: 0)
15621 +
15622 +
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.
15631 +                            (Default: 3600)
15632 +
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.
15636 +                            (Default: On)
15637 +
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.
15649 +                            (Default: "")
15650 +
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 
15662 +                            anonymous mmap.
15663 +                            (Default: "")
15664 +
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
15676 +                            feature.
15677 +                            (Default: 0)
15678 +
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.
15699 +                            (Default: 2)
15700 +
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.
15706 +                            (Default: 0)
15707 +
15708 +    apc.max_file_size       Prevents large files from being cached.  
15709 +                            (Default: 1M)
15710 +
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.
15714 +                            (Default: 1)
15715 +
15716 +    apc.canonicalize        Whether to canonicalize paths in stat=0 mode or
15717 +                            fall back to stat behaviour if set to 0
15718 +                            (Default: 0)
15719 +
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.
15726 +                            (Default: 1)
15727 +
15728 +    apc.report_autofilter   Logs any scripts that were automatically excluded from being
15729 +                            cached due to early/late binding issues.
15730 +                            (Default: 0)
15731 +
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.
15739 +
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.
15743 +                            (Default: 0)
15744 +
15745 +    apc.rfc1867_prefix      Key prefix to use for the user cache entry generated by
15746 +                            rfc1867 upload progress functionality.  
15747 +                            (Default: "upload_")
15748 +
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")
15752 +
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 
15759 +                            slower uploads.
15760 +                            (Default: 0)
15761 +
15762 +    apc.localcache         ** REMOVED 
15763 +    apc.localcache.size    ** REMOVED
15764 +    
15765 +    apc.include_once_override 
15766 +                            Optimize include_once and require_once calls and avoid the 
15767 +                            expensive system calls used.
15768 +                            (Default: 0)
15769 +
15770 +    apc.serializer 
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
15778 @@ -0,0 +1,68 @@
15779 +-------------------------------------------------------------------- 
15780 +                  The PHP License, version 3.01
15781 +Copyright (c) 1999 - 2011 The PHP Group. All rights reserved.
15782 +-------------------------------------------------------------------- 
15783 +
15784 +Redistribution and use in source and binary forms, with or without
15785 +modification, is permitted provided that the following conditions
15786 +are met:
15787 +
15788 +  1. Redistributions of source code must retain the above copyright
15789 +     notice, this list of conditions and the following disclaimer.
15790
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
15794 +     distribution.
15795
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.
15799 +  
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"
15805
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.
15816 +
15817 +  6. Redistributions of any form whatsoever must retain the following
15818 +     acknowledgment:
15819 +     "This product includes PHP software, freely available from
15820 +     <http://www.php.net/software/>".
15821 +
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.
15834 +
15835 +-------------------------------------------------------------------- 
15836 +
15837 +This software consists of voluntary contributions made by many
15838 +individuals on behalf of the PHP Group.
15839 +
15840 +The PHP Group can be contacted via Email at group@php.net.
15841 +
15842 +For more information on the PHP Group and the PHP project, 
15843 +please see <http://www.php.net>.
15844 +
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
15850 @@ -0,0 +1,43 @@
15851 +This is the NOTICE file that holds acknowledgements and stuff.
15852 +
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.
15858 +
15859 +Creators:
15860 +    Daniel Cowgill
15861 +    George Schlossnagle
15862 +
15863 +PHP5 support and major features by:
15864 +    Arun C. Murthy 
15865 +    Gopal Vijayaraghavan
15866 +    Rasmus Lerdorf
15867 +
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.
15873 +
15874 +All other licensing and usage conditions are those of the PHP Group.
15875 +
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.
15879 +
15880 +Contributors:
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
15886 +
15887 +Special Thanks:
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
15897 @@ -0,0 +1,391 @@
15898 +/*
15899 +  +----------------------------------------------------------------------+
15900 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
15916 +
15917 + */
15918 +
15919 +/* $Id: pgsql_s_lock.c 307048 2011-01-03 23:53:17Z kalle $ */
15920 +
15921 +/*-------------------------------------------------------------------------
15922 + *
15923 + * s_lock.c
15924 + *        Hardware-dependent implementation of spinlocks.
15925 + *
15926 + *
15927 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
15928 + * Portions Copyright (c) 1994, Regents of the University of California
15929 + *
15930 + *
15931 + * IDENTIFICATION
15932 + *       $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
15933 + *
15934 + *-------------------------------------------------------------------------
15935 + */
15936 +/* #include "postgres.h"  -- Removed for APC */
15937 +
15938 +/* -- Added for APC -- */
15939 +#include "apc.h"
15940 +#ifdef APC_SPIN_LOCKS
15941 +
15942 +#ifdef S_LOCK_TEST
15943 +#include <stdio.h>
15944 +#endif
15945 +#ifndef WIN32
15946 +#include <sys/select.h>
15947 +#endif
15948 +/* ---- */
15949 +
15950 +#include <time.h>
15951 +#ifdef WIN32
15952 +#include "win32/unistd.h"
15953 +#else
15954 +#include <unistd.h>
15955 +#endif
15956 +
15957 +/* #include "storage/s_lock.h" -- Removed for APC */
15958 +#include "pgsql_s_lock.h"
15959 +
15960 +static int     spins_per_delay = DEFAULT_SPINS_PER_DELAY;
15961 +
15962 +
15963 +/* -- APC specific additions ------------------------------*/
15964 +/* The following dependencies have been copied from 
15965 + * other pgsql source files.  The original locations 
15966 + * have been noted.
15967 + */
15968 +
15969 +/* -- from include/c.h -- */
15970 +#ifndef TRUE
15971 +#define TRUE  1
15972 +#endif
15973 +
15974 +#ifndef FALSE
15975 +#define FALSE 0
15976 +#endif
15977 +
15978 +/* -- from include/pg_config_manual.h -- */
15979 +#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
15980 +
15981 +/*
15982 + * Max
15983 + *    Return the maximum of two numbers.
15984 + */
15985 +#define Max(x, y)   ((x) > (y) ? (x) : (y))
15986 +
15987 +/* -- from include/c.h -- */
15988 +/*
15989 + * Min
15990 + *    Return the minimum of two numbers.
15991 + */
15992 +#define Min(x, y)   ((x) < (y) ? (x) : (y))
15993 +
15994 +
15995 +/* -- from backend/port/win32/signal.c -- */
15996 +/*
15997 + * pg_usleep --- delay the specified number of microseconds.
15998 + *
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.
16002 + *
16003 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
16004 + */
16005 +void
16006 +pg_usleep(long microsec)
16007 +{
16008 +       if (microsec > 0)
16009 +       {
16010 +#ifndef WIN32
16011 +               struct timeval delay;
16012 +
16013 +               delay.tv_sec = microsec / 1000000L;
16014 +               delay.tv_usec = microsec % 1000000L;
16015 +               (void) select(0, NULL, NULL, NULL, &delay);
16016 +#else
16017 +               SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
16018 +#endif
16019 +       }
16020 +}
16021 +
16022 +/* -- End APC specific additions ------------------------------*/
16023 +
16024 +
16025 +/*
16026 + * s_lock_stuck() - complain about a stuck spinlock
16027 + */
16028 +static void
16029 +s_lock_stuck(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
16030 +{
16031 +#if defined(S_LOCK_TEST)
16032 +       fprintf(stderr,
16033 +                       "\nStuck spinlock (%p) detected at %s:%d.\n",
16034 +                       lock, file, line);
16035 +       exit(1);
16036 +#else
16037 +  /* -- Removed for APC
16038 +       elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
16039 +                lock, file, line);
16040 +  */
16041 +  apc_error("Stuck spinlock (%p) detected" TSRMLS_CC, lock);
16042 +#endif
16043 +}
16044 +
16045 +
16046 +/*
16047 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
16048 + */
16049 +void
16050 +s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC)
16051 +{
16052 +       /*
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.
16060 +        *
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.
16066 +        *
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.
16078 +        *
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
16083 +        * spent.
16084 +        *
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.
16089 +        */
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
16095 +
16096 +       int                     spins = 0;
16097 +       int                     delays = 0;
16098 +       int                     cur_delay = 0;
16099 +  
16100 +       while (TAS(lock))
16101 +       {
16102 +               /* CPU-specific delay each time through the loop */
16103 +               SPIN_DELAY();
16104 +
16105 +               /* Block the process every spins_per_delay tries */
16106 +               if (++spins >= spins_per_delay)
16107 +               {
16108 +                       if (++delays > NUM_DELAYS)
16109 +                               s_lock_stuck(lock, file, line TSRMLS_CC);
16110 +
16111 +                       if (cur_delay == 0) /* first time to delay? */
16112 +                               cur_delay = MIN_DELAY_MSEC;
16113 +
16114 +                       pg_usleep(cur_delay * 1000L);
16115 +
16116 +#if defined(S_LOCK_TEST)
16117 +                       fprintf(stdout, "*");
16118 +                       fflush(stdout);
16119 +#endif
16120 +
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;
16127 +
16128 +                       spins = 0;
16129 +               }
16130 +       }
16131 +
16132 +       /*
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.
16140 +        *
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.
16146 +        */
16147 +       if (cur_delay == 0)
16148 +       {
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);
16152 +       }
16153 +       else
16154 +       {
16155 +               if (spins_per_delay > MIN_SPINS_PER_DELAY)
16156 +                       spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
16157 +       }
16158 +}
16159 +
16160 +
16161 +#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
16162 +/*
16163 + * Set local copy of spins_per_delay during backend startup.
16164 + *
16165 + * NB: this has to be pretty fast as it is called while holding a spinlock
16166 + */
16167 +void
16168 +set_spins_per_delay(int shared_spins_per_delay)
16169 +{
16170 +       spins_per_delay = shared_spins_per_delay;
16171 +}
16172 +
16173 +/*
16174 + * Update shared estimate of spins_per_delay during backend exit.
16175 + *
16176 + * NB: this has to be pretty fast as it is called while holding a spinlock
16177 + */
16178 +int
16179 +update_spins_per_delay(int shared_spins_per_delay)
16180 +{
16181 +       /*
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.
16186 +        *
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).
16190 +        */
16191 +       return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
16192 +}
16193 +#endif
16194 +
16195 +/*
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.
16199 + *
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.
16202 + */
16203 +
16204 +
16205 +#ifdef HAVE_SPINLOCKS                  /* skip spinlocks if requested */
16206 +
16207 +
16208 +#if defined(__GNUC__)
16209 +
16210 +/*
16211 + * All the gcc flavors that are not inlined
16212 + */
16213 +
16214 +
16215 +/*
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.
16219 + */
16220 +#if defined(__m68k__) && !defined(__linux__)
16221 +/* really means: extern int tas(slock_t* **lock); */
16222 +static void
16223 +tas_dummy()
16224 +{
16225 +       __asm__         __volatile__(
16226 +#if defined(__NetBSD__) && defined(__ELF__)
16227 +/* no underscore for label and % for registers */
16228 +                                                                                "\
16229 +.global                tas                             \n\
16230 +tas:                                                   \n\
16231 +                       movel   %sp@(0x4),%a0   \n\
16232 +                       tas     %a0@            \n\
16233 +                       beq     _success        \n\
16234 +                       moveq   #-128,%d0       \n\
16235 +                       rts                             \n\
16236 +_success:                                              \n\
16237 +                       moveq   #0,%d0          \n\
16238 +                       rts                             \n"
16239 +#else
16240 +                                                                                "\
16241 +.global                _tas                            \n\
16242 +_tas:                                                  \n\
16243 +                       movel   sp@(0x4),a0     \n\
16244 +                       tas     a0@                     \n\
16245 +                       beq     _success        \n\
16246 +                       moveq   #-128,d0        \n\
16247 +                       rts                                     \n\
16248 +_success:                                              \n\
16249 +                       moveq   #0,d0           \n\
16250 +                       rts                                     \n"
16251 +#endif   /* __NetBSD__ && __ELF__ */
16252 +       );
16253 +}
16254 +#endif   /* __m68k__ && !__linux__ */
16255 +#else                                                  /* not __GNUC__ */
16256 +
16257 +/*
16258 + * All non gcc
16259 + */
16260 +
16261 +
16262 +#if defined(sun3)
16263 +static void
16264 +tas_dummy()                                            /* really means: extern int tas(slock_t
16265 +                                                                * *lock); */
16266 +{
16267 +       asm("LLA0:");
16268 +       asm("   .data");
16269 +       asm("   .text");
16270 +       asm("|#PROC# 04");
16271 +       asm("   .globl  _tas");
16272 +       asm("_tas:");
16273 +       asm("|#PROLOGUE# 1");
16274 +       asm("   movel   sp@(0x4),a0");
16275 +       asm("   tas a0@");
16276 +       asm("   beq LLA1");
16277 +       asm("   moveq   #-128,d0");
16278 +       asm("   rts");
16279 +       asm("LLA1:");
16280 +       asm("   moveq   #0,d0");
16281 +       asm("   rts");
16282 +       asm("   .data");
16283 +}
16284 +#endif   /* sun3 */
16285 +#endif   /* not __GNUC__ */
16286 +#endif   /* HAVE_SPINLOCKS */
16287 +
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
16292 @@ -0,0 +1,928 @@
16293 +/*
16294 +  +----------------------------------------------------------------------+
16295 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
16311 +
16312 + */
16313 +
16314 +/* $Id: pgsql_s_lock.h 307048 2011-01-03 23:53:17Z kalle $ */
16315 +
16316 +/*-------------------------------------------------------------------------
16317 + *
16318 + * s_lock.h
16319 + *        Hardware-dependent implementation of spinlocks.
16320 + *
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.
16323 + *
16324 + *     The following hardware-dependent macros must be provided for each
16325 + *     supported platform:
16326 + *
16327 + *     void S_INIT_LOCK(slock_t *lock)
16328 + *             Initialize a spinlock (to the unlocked state).
16329 + *
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.
16334 + *
16335 + *     void S_UNLOCK(slock_t *lock)
16336 + *             Unlock a previously acquired lock.
16337 + *
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.
16341 + *
16342 + *     void SPIN_DELAY(void)
16343 + *             Delay operation to occur inside spinlock wait loop.
16344 + *
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.
16348 + *
16349 + *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
16350 + *     TAS():
16351 + *
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.
16356 + *
16357 + *     TAS() is NOT part of the API, and should never be called directly.
16358 + *
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.
16363 + *
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.
16368 + *
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.
16372 + *
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.
16379 + *
16380 + *
16381 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
16382 + * Portions Copyright (c) 1994, Regents of the University of California
16383 + *
16384 + *       $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
16385 + *
16386 + *-------------------------------------------------------------------------
16387 + */
16388 +#ifndef S_LOCK_H
16389 +#define S_LOCK_H
16390 +
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 +/****************************************************************************/
16397 +
16398 +
16399 +/* #include "storage/pg_sema.h"   -- Removed for APC */
16400 +
16401 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
16402 +
16403 +#ifdef HAVE_SPINLOCKS  /* skip spinlocks if requested */
16404 +
16405 +
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.
16411 + */
16412 +
16413 +/*----------
16414 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
16415 +
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
16423 +
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.
16432 + *----------
16433 + */
16434 +
16435 +
16436 +#ifdef __i386__                /* 32-bit i386 */
16437 +#define HAS_TEST_AND_SET
16438 +
16439 +typedef unsigned char slock_t;
16440 +
16441 +#define TAS(lock) tas(lock)
16442 +
16443 +static __inline__ int
16444 +tas(volatile slock_t *lock)
16445 +{
16446 +       register slock_t _res = 1;
16447 +
16448 +       /*
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.
16452 +        */
16453 +       __asm__ __volatile__(
16454 +               "       cmpb    $0,%1   \n"
16455 +               "       jne             1f              \n"
16456 +               "       lock                    \n"
16457 +               "       xchgb   %0,%1   \n"
16458 +               "1: \n"
16459 +:              "+q"(_res), "+m"(*lock)
16460 +:
16461 +:              "memory", "cc");
16462 +       return (int) _res;
16463 +}
16464 +
16465 +#define SPIN_DELAY() spin_delay()
16466 +
16467 +static __inline__ void
16468 +spin_delay(void)
16469 +{
16470 +       /*
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
16476 +        * performance:
16477 +        *
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.
16492 +        */
16493 +       __asm__ __volatile__(
16494 +               " rep; nop                      \n");
16495 +}
16496 +
16497 +#endif  /* __i386__ */
16498 +
16499 +
16500 +#ifdef __x86_64__              /* AMD Opteron, Intel EM64T */
16501 +#define HAS_TEST_AND_SET
16502 +
16503 +typedef unsigned char slock_t;
16504 +
16505 +#define TAS(lock) tas(lock)
16506 +
16507 +static __inline__ int
16508 +tas(volatile slock_t *lock)
16509 +{
16510 +       register slock_t _res = 1;
16511 +
16512 +       /*
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.
16516 +        */
16517 +       __asm__ __volatile__(
16518 +               "       lock                    \n"
16519 +               "       xchgb   %0,%1   \n"
16520 +:              "+q"(_res), "+m"(*lock)
16521 +:
16522 +:              "memory", "cc");
16523 +       return (int) _res;
16524 +}
16525 +
16526 +#define SPIN_DELAY() spin_delay()
16527 +
16528 +static __inline__ void
16529 +spin_delay(void)
16530 +{
16531 +       /*
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.
16534 +        */
16535 +       __asm__ __volatile__(
16536 +               " rep; nop                      \n");
16537 +}
16538 +
16539 +#endif  /* __x86_64__ */
16540 +
16541 +
16542 +#if defined(__ia64__) || defined(__ia64)       /* Intel Itanium */
16543 +#define HAS_TEST_AND_SET
16544 +
16545 +typedef unsigned int slock_t;
16546 +
16547 +#define TAS(lock) tas(lock)
16548 +
16549 +#ifndef __INTEL_COMPILER
16550 +
16551 +static __inline__ int
16552 +tas(volatile slock_t *lock)
16553 +{
16554 +       long int        ret;
16555 +
16556 +       __asm__ __volatile__(
16557 +               "       xchg4   %0=%1,%2        \n"
16558 +:              "=r"(ret), "+m"(*lock)
16559 +:              "r"(1)
16560 +:              "memory");
16561 +       return (int) ret;
16562 +}
16563 +
16564 +#else /* __INTEL_COMPILER */
16565 +
16566 +static __inline__ int
16567 +tas(volatile slock_t *lock)
16568 +{
16569 +       int             ret;
16570 +
16571 +       ret = _InterlockedExchange(lock,1);     /* this is a xchg asm macro */
16572 +
16573 +       return ret;
16574 +}
16575 +
16576 +#endif /* __INTEL_COMPILER */
16577 +#endif  /* __ia64__ || __ia64 */
16578 +
16579 +
16580 +#if defined(__arm__) || defined(__arm)
16581 +#define HAS_TEST_AND_SET
16582 +
16583 +typedef unsigned char slock_t;
16584 +
16585 +#define TAS(lock) tas(lock)
16586 +
16587 +static __inline__ int
16588 +tas(volatile slock_t *lock)
16589 +{
16590 +       register slock_t _res = 1;
16591 +
16592 +       __asm__ __volatile__(
16593 +               "       swpb    %0, %0, [%2]    \n"
16594 +:              "+r"(_res), "+m"(*lock)
16595 +:              "r"(lock)
16596 +:              "memory");
16597 +       return (int) _res;
16598 +}
16599 +
16600 +#endif  /* __arm__ */
16601 +
16602 +
16603 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
16604 +#if defined(__s390__) || defined(__s390x__)
16605 +#define HAS_TEST_AND_SET
16606 +
16607 +typedef unsigned int slock_t;
16608 +
16609 +#define TAS(lock)         tas(lock)
16610 +
16611 +static __inline__ int
16612 +tas(volatile slock_t *lock)
16613 +{
16614 +       int                     _res = 0;
16615 +
16616 +       __asm__ __volatile__(
16617 +               "       cs      %0,%3,0(%2)             \n"
16618 +:              "+d"(_res), "+m"(*lock)
16619 +:              "a"(lock), "d"(1)
16620 +:              "memory", "cc");
16621 +       return _res;
16622 +}
16623 +
16624 +#endif  /* __s390__ || __s390x__ */
16625 +
16626 +
16627 +#if defined(__sparc__)         /* Sparc */
16628 +#define HAS_TEST_AND_SET
16629 +
16630 +typedef unsigned char slock_t;
16631 +
16632 +#define TAS(lock) tas(lock)
16633 +
16634 +static __inline__ int
16635 +tas(volatile slock_t *lock)
16636 +{
16637 +       register slock_t _res;
16638 +
16639 +       /*
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.
16643 +        */
16644 +       __asm__ __volatile__(
16645 +               "       ldstub  [%2], %0        \n"
16646 +:              "=r"(_res), "+m"(*lock)
16647 +:              "r"(lock)
16648 +:              "memory");
16649 +       return (int) _res;
16650 +}
16651 +
16652 +#endif  /* __sparc__ */
16653 +
16654 +
16655 +/* PowerPC */
16656 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
16657 +#define HAS_TEST_AND_SET
16658 +
16659 +#if defined(__ppc64__) || defined(__powerpc64__)
16660 +typedef unsigned long slock_t;
16661 +#else
16662 +typedef unsigned int slock_t;
16663 +#endif
16664 +
16665 +#define TAS(lock) tas(lock)
16666 +/*
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.
16669 + */
16670 +static __inline__ int
16671 +tas(volatile slock_t *lock)
16672 +{
16673 +       slock_t _t;
16674 +       int _res;
16675 +
16676 +       __asm__ __volatile__(
16677 +"      lwarx   %0,0,%3         \n"
16678 +"      cmpwi   %0,0            \n"
16679 +"      bne     1f                      \n"
16680 +"      addi    %0,%0,1         \n"
16681 +"      stwcx.  %0,0,%3         \n"
16682 +"      beq     2f              \n"
16683 +"1:    li      %1,1            \n"
16684 +"      b               3f                      \n"
16685 +"2:                                            \n"
16686 +"      isync                           \n"
16687 +"      li      %1,0            \n"
16688 +"3:                                            \n"
16689 +
16690 +:      "=&r"(_t), "=r"(_res), "+m"(*lock)
16691 +:      "r"(lock)
16692 +:      "memory", "cc");
16693 +       return _res;
16694 +}
16695 +
16696 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
16697 +#define S_UNLOCK(lock) \
16698 +do \
16699 +{ \
16700 +       __asm__ __volatile__ (" sync \n"); \
16701 +       *((volatile slock_t *) (lock)) = 0; \
16702 +} while (0)
16703 +
16704 +#endif /* powerpc */
16705 +
16706 +
16707 +/* Linux Motorola 68k */
16708 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
16709 +#define HAS_TEST_AND_SET
16710 +
16711 +typedef unsigned char slock_t;
16712 +
16713 +#define TAS(lock) tas(lock)
16714 +
16715 +static __inline__ int
16716 +tas(volatile slock_t *lock)
16717 +{
16718 +       register int rv;
16719 +
16720 +       __asm__ __volatile__(
16721 +               "       clrl    %0              \n"
16722 +               "       tas             %1              \n"
16723 +               "       sne             %0              \n"
16724 +:              "=d"(rv), "+m"(*lock)
16725 +:
16726 +:              "memory", "cc");
16727 +       return rv;
16728 +}
16729 +
16730 +#endif  /* (__mc68000__ || __m68k__) && __linux__ */
16731 +
16732 +
16733 +/*
16734 + * VAXen -- even multiprocessor ones
16735 + * (thanks to Tom Ivar Helbekkmo)
16736 + */
16737 +#if defined(__vax__)
16738 +#define HAS_TEST_AND_SET
16739 +
16740 +typedef unsigned char slock_t;
16741 +
16742 +#define TAS(lock) tas(lock)
16743 +
16744 +static __inline__ int
16745 +tas(volatile slock_t *lock)
16746 +{
16747 +       register int    _res;
16748 +
16749 +       __asm__ __volatile__(
16750 +               "       movl    $1, %0                  \n"
16751 +               "       bbssi   $0, (%2), 1f    \n"
16752 +               "       clrl    %0                              \n"
16753 +               "1: \n"
16754 +:              "=&r"(_res), "+m"(*lock)
16755 +:              "r"(lock)
16756 +:              "memory");
16757 +       return _res;
16758 +}
16759 +
16760 +#endif  /* __vax__ */
16761 +
16762 +
16763 +#if defined(__ns32k__)         /* National Semiconductor 32K */
16764 +#define HAS_TEST_AND_SET
16765 +
16766 +typedef unsigned char slock_t;
16767 +
16768 +#define TAS(lock) tas(lock)
16769 +
16770 +static __inline__ int
16771 +tas(volatile slock_t *lock)
16772 +{
16773 +       register int    _res;
16774 +
16775 +       __asm__ __volatile__(
16776 +               "       sbitb   0, %1   \n"
16777 +               "       sfsd    %0              \n"
16778 +:              "=r"(_res), "+m"(*lock)
16779 +:
16780 +:              "memory");
16781 +       return _res;
16782 +}
16783 +
16784 +#endif  /* __ns32k__ */
16785 +
16786 +
16787 +#if defined(__alpha) || defined(__alpha__)     /* Alpha */
16788 +/*
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.
16793 + */
16794 +#define HAS_TEST_AND_SET
16795 +
16796 +typedef unsigned long slock_t;
16797 +
16798 +#define TAS(lock)  tas(lock)
16799 +
16800 +static __inline__ int
16801 +tas(volatile slock_t *lock)
16802 +{
16803 +       register slock_t _res;
16804 +
16805 +       __asm__ __volatile__(
16806 +               "       ldq             $0, %1  \n"
16807 +               "       bne             $0, 2f  \n"
16808 +               "       ldq_l   %0, %1  \n"
16809 +               "       bne             %0, 2f  \n"
16810 +               "       mov             1,  $0  \n"
16811 +               "       stq_c   $0, %1  \n"
16812 +               "       beq             $0, 2f  \n"
16813 +               "       mb                              \n"
16814 +               "       br              3f              \n"
16815 +               "2:     mov             1, %0   \n"
16816 +               "3:                                     \n"
16817 +:              "=&r"(_res), "+m"(*lock)
16818 +:
16819 +:              "memory", "0");
16820 +       return (int) _res;
16821 +}
16822 +
16823 +#define S_UNLOCK(lock) \
16824 +do \
16825 +{\
16826 +       __asm__ __volatile__ (" mb \n"); \
16827 +       *((volatile slock_t *) (lock)) = 0; \
16828 +} while (0)
16829 +
16830 +#endif /* __alpha || __alpha__ */
16831 +
16832 +
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
16837 +
16838 +typedef unsigned int slock_t;
16839 +
16840 +#define TAS(lock) tas(lock)
16841 +
16842 +static __inline__ int
16843 +tas(volatile slock_t *lock)
16844 +{
16845 +       register volatile slock_t *_l = lock;
16846 +       register int _res;
16847 +       register int _tmp;
16848 +
16849 +       __asm__ __volatile__(
16850 +               "       .set push           \n"
16851 +               "       .set mips2          \n"
16852 +               "       .set noreorder      \n"
16853 +               "       .set nomacro        \n"
16854 +               "       ll      %0, %2      \n"
16855 +               "       or      %1, %0, 1   \n"
16856 +               "       sc      %1, %2      \n"
16857 +               "       xori    %1, 1       \n"
16858 +               "       or      %0, %0, %1  \n"
16859 +               "       sync                \n"
16860 +               "       .set pop              "
16861 +:              "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
16862 +:
16863 +:              "memory");
16864 +       return _res;
16865 +}
16866 +
16867 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
16868 +#define S_UNLOCK(lock) \
16869 +do \
16870 +{ \
16871 +       __asm__ __volatile__( \
16872 +               "       .set push           \n" \
16873 +               "       .set mips2          \n" \
16874 +               "       .set noreorder      \n" \
16875 +               "       .set nomacro        \n" \
16876 +               "       sync                \n" \
16877 +               "       .set pop              "); \
16878 +       *((volatile slock_t *) (lock)) = 0; \
16879 +} while (0)
16880 +
16881 +#endif /* __mips__ && !__sgi */
16882 +
16883 +
16884 +/* These live in s_lock.c, but only for gcc */
16885 +
16886 +
16887 +#if defined(__m68k__) && !defined(__linux__)   /* non-Linux Motorola 68k */
16888 +#define HAS_TEST_AND_SET
16889 +
16890 +typedef unsigned char slock_t;
16891 +#endif
16892 +
16893 +
16894 +#endif /* __GNUC__ */
16895 +
16896 +
16897 +
16898 +/*
16899 + * ---------------------------------------------------------------------
16900 + * Platforms that use non-gcc inline assembly:
16901 + * ---------------------------------------------------------------------
16902 + */
16903 +
16904 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
16905 +
16906 +
16907 +#if defined(USE_UNIVEL_CC)             /* Unixware compiler */
16908 +#define HAS_TEST_AND_SET
16909 +
16910 +typedef unsigned char slock_t;
16911 +
16912 +#define TAS(lock)      tas(lock)
16913 +
16914 +asm int
16915 +tas(volatile slock_t *s_lock)
16916 +{
16917 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
16918 +%mem s_lock
16919 +       pushl %ebx
16920 +       movl s_lock, %ebx
16921 +       movl $255, %eax
16922 +       lock
16923 +       xchgb %al, (%ebx)
16924 +       popl %ebx
16925 +}
16926 +
16927 +#endif  /* defined(USE_UNIVEL_CC) */
16928 +
16929 +
16930 +#if defined(__alpha) || defined(__alpha__)     /* Tru64 Unix Alpha compiler */
16931 +/*
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.
16938 + */
16939 +#define HAS_TEST_AND_SET
16940 +
16941 +typedef unsigned long slock_t;
16942 +
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)
16947 +
16948 +#endif  /* __alpha || __alpha__ */
16949 +
16950 +
16951 +#if defined(__hppa) || defined(__hppa__)       /* HP PA-RISC, GCC and HP compilers */
16952 +/*
16953 + * HP's PA-RISC
16954 + *
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.
16959 + *
16960 + * When using gcc, we can inline the required assembly code.
16961 + */
16962 +#define HAS_TEST_AND_SET
16963 +
16964 +typedef struct
16965 +{
16966 +       int                     sema[4];
16967 +} slock_t;
16968 +
16969 +#define TAS_ACTIVE_WORD(lock)  ((volatile int *) (((long) (lock) + 15) & ~15))
16970 +
16971 +#if defined(__GNUC__)
16972 +
16973 +static __inline__ int
16974 +tas(volatile slock_t *lock)
16975 +{
16976 +       volatile int *lockword = TAS_ACTIVE_WORD(lock);
16977 +       register int lockval;
16978 +
16979 +       __asm__ __volatile__(
16980 +               "       ldcwx   0(0,%2),%0      \n"
16981 +:              "=r"(lockval), "+m"(*lockword)
16982 +:              "r"(lockword)
16983 +:              "memory");
16984 +       return (lockval == 0);
16985 +}
16986 +
16987 +#endif /* __GNUC__ */
16988 +
16989 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
16990 +
16991 +#define S_INIT_LOCK(lock) \
16992 +       do { \
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; \
16998 +       } while (0)
16999 +
17000 +#define S_LOCK_FREE(lock)      (*TAS_ACTIVE_WORD(lock) != 0)
17001 +
17002 +#endif  /* __hppa || __hppa__ */
17003 +
17004 +
17005 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
17006 +
17007 +#define HAS_TEST_AND_SET
17008 +
17009 +typedef unsigned int slock_t;
17010 +
17011 +#include <ia64/sys/inline.h>
17012 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
17013 +
17014 +#endif /* HPUX on IA64, non gcc */
17015 +
17016 +
17017 +#if defined(__sgi)     /* SGI compiler */
17018 +/*
17019 + * SGI IRIX 5
17020 + * slock_t is defined as a unsigned long. We use the standard SGI
17021 + * mutex API.
17022 + *
17023 + * The following comment is left for historical reasons, but is probably
17024 + * not a good idea since the mutex ABI is supported.
17025 + *
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.
17029 + */
17030 +#define HAS_TEST_AND_SET
17031 +
17032 +typedef unsigned long slock_t;
17033 +
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 */
17040 +
17041 +
17042 +#if defined(sinix)             /* Sinix */
17043 +/*
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)
17047 + */
17048 +#define HAS_TEST_AND_SET
17049 +
17050 +#include "abi_mutex.h"
17051 +typedef abilock_t slock_t;
17052 +
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 */
17058 +
17059 +
17060 +#if defined(_AIX)      /* AIX */
17061 +/*
17062 + * AIX (POWER)
17063 + */
17064 +#define HAS_TEST_AND_SET
17065 +
17066 +typedef unsigned int slock_t;
17067 +
17068 +#define TAS(lock)                      _check_lock(lock, 0, 1)
17069 +#define S_UNLOCK(lock)         _clear_lock(lock, 0)
17070 +#endif  /* _AIX */
17071 +
17072 +
17073 +#if defined (nextstep)         /* Nextstep */
17074 +#define HAS_TEST_AND_SET
17075 +
17076 +typedef struct mutex slock_t;
17077 +
17078 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
17079 +
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 */
17086 +
17087 +
17088 +/* These are in s_lock.c */
17089 +
17090 +
17091 +#if defined(sun3)              /* Sun3 */
17092 +#define HAS_TEST_AND_SET
17093 +
17094 +typedef unsigned char slock_t;
17095 +#endif
17096 +
17097 +
17098 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
17099 +#define HAS_TEST_AND_SET
17100 +
17101 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
17102 +typedef unsigned int slock_t;
17103 +#else
17104 +typedef unsigned char slock_t;
17105 +#endif
17106 +
17107 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
17108 +                                                                         slock_t cmp);
17109 +
17110 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
17111 +#endif
17112 +
17113 +
17114 +#ifdef WIN32_ONLY_COMPILER
17115 +typedef LONG slock_t;
17116 +
17117 +#define HAS_TEST_AND_SET
17118 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
17119 +
17120 +#define SPIN_DELAY() spin_delay()
17121 +
17122 +static __forceinline void
17123 +spin_delay(void)
17124 +{
17125 +       /* See comment for gcc code. Same code, MASM syntax */
17126 +       __asm rep nop;
17127 +}
17128 +
17129 +#endif
17130 +
17131 +  
17132 +#endif /* !defined(HAS_TEST_AND_SET) */
17133 +
17134 +
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. */ 
17140 +#endif
17141 +
17142 +
17143 +#else  /* !HAVE_SPINLOCKS */
17144 +
17145 +
17146 +/*
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.
17150 + */
17151 +
17152 +/* -- Removed for APC
17153 +typedef PGSemaphoreData slock_t;
17154 +
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);
17159 +
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)
17164 +*/
17165 +
17166 +#endif /* HAVE_SPINLOCKS */
17167 +
17168 +
17169 +/*
17170 + * Default Definitions - override these above as needed.
17171 + */
17172 +
17173 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
17174 +
17175 +#if !defined(S_LOCK)
17176 +#define S_LOCK(lock) \
17177 +       do { \
17178 +               if (TAS(lock)) \
17179 +                       s_lock((lock), __FILE__, __LINE__ TSRMLS_CC); \
17180 +       } while (0)
17181 +#endif  /* S_LOCK */
17182 +
17183 +#if !defined(S_LOCK_FREE)
17184 +#define S_LOCK_FREE(lock)      (*(lock) == 0)
17185 +#endif  /* S_LOCK_FREE */
17186 +
17187 +#if !defined(S_UNLOCK)
17188 +#define S_UNLOCK(lock)         (*((volatile slock_t *) (lock)) = 0)
17189 +#endif  /* S_UNLOCK */
17190 +
17191 +#if !defined(S_INIT_LOCK)
17192 +#define S_INIT_LOCK(lock)      S_UNLOCK(lock)
17193 +#endif  /* S_INIT_LOCK */
17194 +
17195 +#if !defined(SPIN_DELAY)
17196 +#define SPIN_DELAY()   ((void) 0)
17197 +#endif  /* SPIN_DELAY */
17198 +
17199 +#if !defined(TAS)
17200 +extern int     tas(volatile slock_t *lock);            /* in port/.../tas.s, or
17201 +                                                                                                * s_lock.c */
17202 +
17203 +#define TAS(lock)              tas(lock)
17204 +#endif  /* TAS */
17205 +
17206 +
17207 +/*
17208 + * Platform-independent out-of-line support routines
17209 + */
17210 +extern void s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC);
17211 +
17212 +/* Support for dynamic adjustment of spins_per_delay */
17213 +#define DEFAULT_SPINS_PER_DELAY  100
17214 +
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);
17218 +#endif
17219 +
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
17224 @@ -0,0 +1,1716 @@
17225 +/*
17226 +  +----------------------------------------------------------------------+
17227 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
17242 +
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.
17248 +
17249 +   All other licensing and usage conditions are those of the PHP Group.
17250 +
17251 + */
17252 +
17253 +/* $Id: php_apc.c 325875 2012-05-27 17:15:26Z felipe $ */
17254 +
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>
17269 +#endif
17270 +#include "SAPI.h"
17271 +#include "rfc1867.h"
17272 +#include "php_apc.h"
17273 +#include "ext/standard/md5.h"
17274 +
17275 +#if HAVE_SIGACTION
17276 +#include "apc_signal.h"
17277 +#endif
17278 +
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);
17299 +/* }}} */
17300 +
17301 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
17302 +ZEND_DECLARE_MODULE_GLOBALS(apc)
17303 +
17304 +/* True globals */
17305 +apc_cache_t* apc_cache = NULL;
17306 +apc_cache_t* apc_user_cache = NULL;
17307 +
17308 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
17309 +{
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));
17326 +#endif
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;
17336 +}
17337 +
17338 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
17339 +{
17340 +    /* deallocate the ignore patterns */
17341 +    if (apc_globals->filters != NULL) {
17342 +        int i;
17343 +        for (i=0; apc_globals->filters[i] != NULL; i++) {
17344 +            apc_efree(apc_globals->filters[i] TSRMLS_CC);
17345 +        }
17346 +        apc_efree(apc_globals->filters TSRMLS_CC);
17347 +    }
17348 +
17349 +    /* the stack should be empty */
17350 +    assert(apc_stack_size(apc_globals->cache_stack) == 0);
17351 +
17352 +    /* apc cleanup */
17353 +    apc_stack_destroy(apc_globals->cache_stack TSRMLS_CC);
17354 +
17355 +    /* the rest of the globals are cleaned up in apc_module_shutdown() */
17356 +}
17357 +
17358 +static long apc_atol(const char *str, int str_len)
17359 +{
17360 +#if PHP_MAJOR_VERSION >= 6 || PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
17361 +    return zend_atol(str, str_len);
17362 +#else
17363 +    /* Re-implement zend_atol() for 5.2.x */
17364 +    long retval;
17365 +
17366 +    if (!str_len) {
17367 +        str_len = strlen(str);
17368 +    }
17369 +
17370 +    retval = strtol(str, NULL, 0);
17371 +
17372 +    if (str_len > 0) {
17373 +        switch (str[str_len - 1]) {
17374 +            case 'g':
17375 +            case 'G':
17376 +                retval *= 1024;
17377 +                /* break intentionally missing */
17378 +            case 'm':
17379 +            case 'M':
17380 +                retval *= 1024;
17381 +                /* break intentionally missing */
17382 +            case 'k':
17383 +            case 'K':
17384 +                retval *= 1024;
17385 +                break;
17386 +        }
17387 +    }
17388 +
17389 +    return retval;
17390 +#endif
17391 +}
17392 +
17393 +/* }}} */
17394 +
17395 +/* {{{ PHP_INI */
17396 +
17397 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
17398 +{
17399 +    APCG(filters) = apc_tokenize(new_value, ',' TSRMLS_CC);
17400 +    return SUCCESS;
17401 +}
17402 +/* }}} */
17403 +
17404 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
17405 +{
17406 +#if APC_MMAP
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");
17409 +    }
17410 +    APCG(shm_segments) = 1;
17411 +#else
17412 +    APCG(shm_segments) = zend_atoi(new_value, new_value_length);
17413 +#endif
17414 +    return SUCCESS;
17415 +}
17416 +/* }}} */
17417 +
17418 +static PHP_INI_MH(OnUpdateShmSize) /* {{{ */
17419 +{
17420 +    long s = apc_atol(new_value, new_value_length);
17421 +
17422 +    if(s <= 0) {
17423 +        return FAILURE;
17424 +    }
17425 +
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;
17430 +    }
17431 +
17432 +    APCG(shm_size) = s;
17433 +
17434 +    return SUCCESS;
17435 +}
17436 +/* }}} */
17437 +
17438 +#ifdef MULTIPART_EVENT_FORMDATA
17439 +static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
17440 +{
17441 +    int tmp;
17442 +    tmp = zend_atoi(new_value, new_value_length);
17443 +    if(tmp < 0) {
17444 +        apc_error("rfc1867_freq must be greater than or equal to zero." TSRMLS_CC);
17445 +        return FAILURE;
17446 +    }
17447 +    if(new_value[new_value_length-1] == '%') {
17448 +        if(tmp > 100) {
17449 +            apc_error("rfc1867_freq cannot be over 100%%" TSRMLS_CC);
17450 +            return FAILURE;
17451 +        }
17452 +        APCG(rfc1867_freq) = tmp / 100.0;
17453 +    } else {
17454 +        APCG(rfc1867_freq) = tmp;
17455 +    }
17456 +    return SUCCESS;
17457 +}
17458 +/* }}} */
17459 +#endif
17460 +
17461 +PHP_INI_BEGIN()
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)
17467 +#endif
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)
17474 +#if APC_MMAP
17475 +STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
17476 +#endif
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)
17494 +#endif
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)
17502 +PHP_INI_END()
17503 +
17504 +/* }}} */
17505 +
17506 +/* {{{ PHP_MINFO_FUNCTION(apc) */
17507 +static PHP_MINFO_FUNCTION(apc)
17508 +{
17509 +    apc_serializer_t *serializer = NULL;
17510 +    smart_str names = {0,};
17511 +    int i;
17512 +
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");
17518 +#else
17519 +    php_info_print_table_row(2, "APC Debugging", "Disabled");
17520 +#endif
17521 +#if APC_MMAP
17522 +    php_info_print_table_row(2, "MMAP Support", "Enabled");
17523 +    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
17524 +#else
17525 +    php_info_print_table_row(2, "MMAP Support", "Disabled");
17526 +#endif
17527 +    php_info_print_table_row(2, "Locking type", APC_LOCK_TYPE);
17528 +
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);
17534 +    }
17535 +
17536 +    if(names.c) {
17537 +        smart_str_0(&names);
17538 +        php_info_print_table_row(2, "Serialization Support", names.c);
17539 +        smart_str_free(&names);
17540 +    } else {
17541 +        php_info_print_table_row(2, "Serialization Support", "broken");
17542 +    }
17543 +
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();
17548 +}
17549 +/* }}} */
17550 +
17551 +#ifdef MULTIPART_EVENT_FORMDATA
17552 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
17553 +#endif
17554 +
17555 +/* {{{ PHP_MINIT_FUNCTION(apc) */
17556 +static PHP_MINIT_FUNCTION(apc)
17557 +{
17558 +    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
17559 +
17560 +    REGISTER_INI_ENTRIES();
17561 +
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;
17565 +    }
17566 +
17567 +    if (APCG(enabled)) {
17568 +        if(APCG(initialized)) {
17569 +            apc_process_init(module_number TSRMLS_CC);
17570 +        } else {
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;
17578 +            }
17579 +#endif
17580 +            apc_iterator_init(module_number TSRMLS_CC);
17581 +        }
17582 +
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);
17585 +    }
17586 +
17587 +    return SUCCESS;
17588 +}
17589 +/* }}} */
17590 +
17591 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
17592 +static PHP_MSHUTDOWN_FUNCTION(apc)
17593 +{
17594 +    if(APCG(enabled)) {
17595 +        apc_process_shutdown(TSRMLS_C);
17596 +        apc_zend_shutdown(TSRMLS_C);
17597 +        apc_module_shutdown(TSRMLS_C);
17598 +#ifndef ZTS
17599 +        php_apc_shutdown_globals(&apc_globals);
17600 +#endif
17601 +#if HAVE_SIGACTION
17602 +        apc_shutdown_signals(TSRMLS_C);
17603 +#endif
17604 +    }
17605 +#ifdef ZTS
17606 +    ts_free_id(apc_globals_id);
17607 +#endif
17608 +    UNREGISTER_INI_ENTRIES();
17609 +    return SUCCESS;
17610 +}
17611 +/* }}} */
17612 +
17613 +/* {{{ PHP_RINIT_FUNCTION(apc) */
17614 +static PHP_RINIT_FUNCTION(apc)
17615 +{
17616 +    if(APCG(enabled)) {
17617 +        apc_request_init(TSRMLS_C);
17618 +
17619 +#if HAVE_SIGACTION
17620 +        apc_set_signals(TSRMLS_C);
17621 +#endif
17622 +    }
17623 +    return SUCCESS;
17624 +}
17625 +/* }}} */
17626 +
17627 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
17628 +static PHP_RSHUTDOWN_FUNCTION(apc)
17629 +{
17630 +    if(APCG(enabled)) {
17631 +        apc_request_shutdown(TSRMLS_C);
17632 +    }
17633 +    return SUCCESS;
17634 +}
17635 +/* }}} */
17636 +
17637 +/* {{{ proto array apc_cache_info([string type [, bool limited]]) */
17638 +PHP_FUNCTION(apc_cache_info)
17639 +{
17640 +    zval* info;
17641 +    char *cache_type;
17642 +    int ct_len;
17643 +    zend_bool limited = 0;
17644 +
17645 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
17646 +        return;
17647 +    }
17648 +
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);
17655 +            return;
17656 +#else
17657 +            RETURN_FALSE;
17658 +#endif
17659 +        } else {
17660 +            info = apc_cache_info(apc_cache, limited TSRMLS_CC);
17661 +        }
17662 +    } else {
17663 +        info = apc_cache_info(apc_cache, limited TSRMLS_CC);
17664 +    }
17665 +
17666 +    if(!info) {
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");
17668 +        RETURN_FALSE;
17669 +    }
17670 +
17671 +    RETURN_ZVAL(info, 0, 1);
17672 +
17673 +}
17674 +/* }}} */
17675 +
17676 +/* {{{ proto void apc_clear_cache([string cache]) */
17677 +PHP_FUNCTION(apc_clear_cache)
17678 +{
17679 +    char *cache_type;
17680 +    int ct_len = 0;
17681 +
17682 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
17683 +        return;
17684 +    }
17685 +
17686 +    if(ct_len) {
17687 +        if(!strcasecmp(cache_type, "user")) {
17688 +            apc_cache_clear(apc_user_cache TSRMLS_CC);
17689 +            RETURN_TRUE;
17690 +        }
17691 +    }
17692 +    apc_cache_clear(apc_cache TSRMLS_CC);
17693 +    RETURN_TRUE;
17694 +}
17695 +/* }}} */
17696 +
17697 +/* {{{ proto array apc_sma_info([bool limited]) */
17698 +PHP_FUNCTION(apc_sma_info)
17699 +{
17700 +    apc_sma_info_t* info;
17701 +    zval* block_lists;
17702 +    int i;
17703 +    zend_bool limited = 0;
17704 +
17705 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
17706 +        return;
17707 +    }
17708 +
17709 +    info = apc_sma_info(limited TSRMLS_CC);
17710 +
17711 +    if(!info) {
17712 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
17713 +        RETURN_FALSE;
17714 +    }
17715 +
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());
17720 +
17721 +    if(limited) {
17722 +        apc_sma_free_info(info TSRMLS_CC);
17723 +        return;
17724 +    }
17725 +
17726 +#if ALLOC_DISTRIBUTION
17727 +    {
17728 +        size_t *adist = apc_sma_get_alloc_distribution();
17729 +        zval* list;
17730 +        ALLOC_INIT_ZVAL(list);
17731 +        array_init(list);
17732 +        for(i=0; i<30; i++) {
17733 +            add_next_index_long(list, adist[i]);
17734 +        }
17735 +        add_assoc_zval(return_value, "adist", list);
17736 +    }
17737 +#endif
17738 +    ALLOC_INIT_ZVAL(block_lists);
17739 +    array_init(block_lists);
17740 +
17741 +    for (i = 0; i < info->num_seg; i++) {
17742 +        apc_sma_link_t* p;
17743 +        zval* list;
17744 +
17745 +        ALLOC_INIT_ZVAL(list);
17746 +        array_init(list);
17747 +
17748 +        for (p = info->list[i]; p != NULL; p = p->next) {
17749 +            zval* link;
17750 +
17751 +            ALLOC_INIT_ZVAL(link);
17752 +            array_init(link);
17753 +
17754 +            add_assoc_long(link, "size", p->size);
17755 +            add_assoc_long(link, "offset", p->offset);
17756 +            add_next_index_zval(list, link);
17757 +        }
17758 +        add_next_index_zval(block_lists, list);
17759 +    }
17760 +    add_assoc_zval(return_value, "block_lists", block_lists);
17761 +    apc_sma_free_info(info TSRMLS_CC);
17762 +}
17763 +/* }}} */
17764 +
17765 +/* {{{ */
17766 +int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC) 
17767 +{
17768 +    if(!APCG(enabled)) {
17769 +        return 0;
17770 +    }
17771 +
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);
17775 +    }
17776 +
17777 +    HANDLE_BLOCK_INTERRUPTIONS();
17778 +    APCG(current_cache) = apc_user_cache;
17779 +    
17780 +    if (!_apc_cache_user_update(apc_user_cache, strkey, strkey_len + 1, updater, data TSRMLS_CC)) {
17781 +        HANDLE_UNBLOCK_INTERRUPTIONS();
17782 +        return 0;
17783 +    }
17784 +
17785 +    APCG(current_cache) = NULL;
17786 +    HANDLE_UNBLOCK_INTERRUPTIONS();
17787 +
17788 +    return 1;
17789 +}
17790 +/* }}} */
17791 +    
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;
17796 +    time_t t;
17797 +    apc_context_t ctxt={0,};
17798 +    int ret = 1;
17799 +
17800 +    t = apc_time();
17801 +
17802 +    if(!APCG(enabled)) return 0;
17803 +
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);
17807 +    }
17808 +
17809 +    HANDLE_BLOCK_INTERRUPTIONS();
17810 +
17811 +    APCG(current_cache) = apc_user_cache;
17812 +
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);
17816 +        return 0;
17817 +    }
17818 +    ctxt.copy = APC_COPY_IN_USER;
17819 +    ctxt.force_update = 0;
17820 +
17821 +    if(!ctxt.pool) {
17822 +        ret = 0;
17823 +        goto nocache;
17824 +    }
17825 +
17826 +    if (!apc_cache_make_user_key(&key, strkey, strkey_len, t)) {
17827 +        goto freepool;
17828 +    }
17829 +
17830 +    if (apc_cache_is_last_key(apc_user_cache, &key, t TSRMLS_CC)) {
17831 +        goto freepool;
17832 +    }
17833 +
17834 +    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len, val, &ctxt, ttl TSRMLS_CC))) {
17835 +        goto freepool;
17836 +    }
17837 +
17838 +    if (!apc_cache_user_insert(apc_user_cache, key, entry, &ctxt, t, exclusive TSRMLS_CC)) {
17839 +freepool:
17840 +        apc_pool_destroy(ctxt.pool TSRMLS_CC);
17841 +        ret = 0;
17842 +    }
17843 +
17844 +nocache:
17845 +
17846 +    APCG(current_cache) = NULL;
17847 +
17848 +    HANDLE_UNBLOCK_INTERRUPTIONS();
17849 +
17850 +    return ret;
17851 +}
17852 +/* }}} */
17853 +
17854 +/* {{{ apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
17855 + */
17856 +static void apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
17857 +{
17858 +    zval *key = NULL;
17859 +    zval *val = NULL;
17860 +    long ttl = 0L;
17861 +    HashTable *hash;
17862 +    HashPosition hpos;
17863 +    zval **hentry;
17864 +    char *hkey=NULL;
17865 +    uint hkey_len;
17866 +    ulong hkey_idx;
17867 +
17868 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &key, &val, &ttl) == FAILURE) {
17869 +        return;
17870 +    }
17871 +
17872 +    if (!key) RETURN_FALSE;
17873 +
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);
17880 +            if (hkey) {
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 */
17883 +                }
17884 +                hkey = NULL;
17885 +            } else {
17886 +                add_index_long(return_value, hkey_idx, -1);  /* -1: insertion error */
17887 +            }
17888 +            zend_hash_move_forward_ex(hash, &hpos);
17889 +        }
17890 +        return;
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))
17894 +            RETURN_TRUE;
17895 +    } else {
17896 +        apc_warning("apc_store expects key parameter to be a string or an array of key/value pairs." TSRMLS_CC);
17897 +    }
17898 +
17899 +    RETURN_FALSE;
17900 +}
17901 +/* }}} */
17902 +
17903 +/* {{{ proto int apc_store(mixed key, mixed var [, long ttl ])
17904 + */
17905 +PHP_FUNCTION(apc_store) {
17906 +    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
17907 +}
17908 +/* }}} */
17909 +
17910 +/* {{{ proto int apc_add(mixed key, mixed var [, long ttl ])
17911 + */
17912 +PHP_FUNCTION(apc_add) {
17913 +    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
17914 +}
17915 +/* }}} */
17916 +
17917 +/* {{{ inc_updater */
17918 +
17919 +struct _inc_update_args {
17920 +    long step;
17921 +    long lval;
17922 +};
17923 +
17924 +static int inc_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
17925 +
17926 +    struct _inc_update_args *args = (struct _inc_update_args*) data;
17927 +    
17928 +    zval* val = entry->data.user.val;
17929 +
17930 +    if(Z_TYPE_P(val) == IS_LONG) {
17931 +        Z_LVAL_P(val) += args->step;
17932 +        args->lval = Z_LVAL_P(val);
17933 +        return 1;
17934 +    }
17935 +
17936 +    return 0;
17937 +}
17938 +/* }}} */
17939 +
17940 +/* {{{ proto long apc_inc(string key [, long step [, bool& success]])
17941 + */
17942 +PHP_FUNCTION(apc_inc) {
17943 +    char *strkey;
17944 +    int strkey_len;
17945 +    struct _inc_update_args args = {1L, -1};
17946 +    zval *success = NULL;
17947 +
17948 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
17949 +        return;
17950 +    }
17951 +    
17952 +       if (success) {
17953 +               zval_dtor(success);
17954 +       }
17955 +
17956 +    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
17957 +        if(success) ZVAL_TRUE(success);
17958 +        RETURN_LONG(args.lval);
17959 +    }
17960 +    
17961 +    if(success) ZVAL_FALSE(success);
17962 +    
17963 +    RETURN_FALSE;
17964 +}
17965 +/* }}} */
17966 +
17967 +/* {{{ proto long apc_dec(string key [, long step [, bool &success]])
17968 + */
17969 +PHP_FUNCTION(apc_dec) {
17970 +    char *strkey;
17971 +    int strkey_len;
17972 +    struct _inc_update_args args = {1L, -1};
17973 +    zval *success = NULL;
17974 +
17975 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
17976 +        return;
17977 +    }
17978 +    
17979 +       if (success) {
17980 +               zval_dtor(success);
17981 +       }
17982 +
17983 +    args.step = args.step * -1;
17984 +
17985 +    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
17986 +        if(success) ZVAL_TRUE(success);
17987 +        RETURN_LONG(args.lval);
17988 +    }
17989 +    
17990 +    if(success) ZVAL_FALSE(success);
17991 +    
17992 +    RETURN_FALSE;
17993 +}
17994 +/* }}} */
17995 +
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;
18002 +
18003 +    if(Z_TYPE_P(val) == IS_LONG) {
18004 +        if(Z_LVAL_P(val) == old) {
18005 +            Z_LVAL_P(val) = new;
18006 +            return 1;
18007 +        }
18008 +    }
18009 +
18010 +    return 0;
18011 +}
18012 +/* }}} */
18013 +
18014 +/* {{{ proto int apc_cas(string key, int old, int new)
18015 + */
18016 +PHP_FUNCTION(apc_cas) {
18017 +    char *strkey;
18018 +    int strkey_len;
18019 +    long vals[2];
18020 +
18021 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &strkey, &strkey_len, &vals[0], &vals[1]) == FAILURE) {
18022 +        return;
18023 +    }
18024 +
18025 +    if(_apc_update(strkey, strkey_len, cas_updater, &vals TSRMLS_CC)) RETURN_TRUE;
18026 +    RETURN_FALSE;
18027 +}
18028 +/* }}} */
18029 +
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);
18032 +}
18033 +
18034 +/* {{{ proto mixed apc_fetch(mixed key[, bool &success])
18035 + */
18036 +PHP_FUNCTION(apc_fetch) {
18037 +    zval *key;
18038 +    zval *success = NULL;
18039 +    HashTable *hash;
18040 +    HashPosition hpos;
18041 +    zval **hentry;
18042 +    zval *result;
18043 +    zval *result_entry;
18044 +    char *strkey;
18045 +    int strkey_len;
18046 +    apc_cache_entry_t* entry;
18047 +    time_t t;
18048 +    apc_context_t ctxt = {0,};
18049 +
18050 +    if(!APCG(enabled)) RETURN_FALSE;
18051 +
18052 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == FAILURE) {
18053 +        return;
18054 +    }
18055 +
18056 +    t = apc_time();
18057 +
18058 +    if (success) {
18059 +        ZVAL_BOOL(success, 0);
18060 +    }
18061 +
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);
18065 +        RETURN_FALSE;
18066 +    }
18067 +    ctxt.copy = APC_COPY_OUT_USER;
18068 +    ctxt.force_update = 0;
18069 +
18070 +    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
18071 +        convert_to_string(key);
18072 +    }
18073 +
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);
18079 +        if(entry) {
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);
18083 +        } else {
18084 +            goto freepool;
18085 +        }
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);
18094 +                goto freepool;
18095 +            }
18096 +            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1), t TSRMLS_CC);
18097 +            if(entry) {
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);
18105 +        }
18106 +        RETVAL_ZVAL(result, 0, 1);
18107 +    } else {
18108 +        apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC);
18109 +freepool:
18110 +        apc_pool_destroy(ctxt.pool TSRMLS_CC);
18111 +        RETURN_FALSE;
18112 +    }
18113 +
18114 +    if (success) {
18115 +        ZVAL_BOOL(success, 1);
18116 +    }
18117 +
18118 +    apc_pool_destroy(ctxt.pool TSRMLS_CC);
18119 +    return;
18120 +}
18121 +/* }}} */
18122 +
18123 +/* {{{ proto mixed apc_exists(mixed key)
18124 + */
18125 +PHP_FUNCTION(apc_exists) {
18126 +    zval *key;
18127 +    HashTable *hash;
18128 +    HashPosition hpos;
18129 +    zval **hentry;
18130 +    char *strkey;
18131 +    int strkey_len;
18132 +    apc_cache_entry_t* entry;
18133 +    zval *result;
18134 +    zval *result_entry;
18135 +    time_t t;
18136 +
18137 +    if(!APCG(enabled)) RETURN_FALSE;
18138 +
18139 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
18140 +        return;
18141 +    }
18142 +
18143 +    t = apc_time();
18144 +
18145 +    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
18146 +        convert_to_string(key);
18147 +    }
18148 +
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);
18154 +        if(entry) {
18155 +            RETURN_TRUE;
18156 +        }
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);
18165 +                RETURN_FALSE;
18166 +            }
18167 +
18168 +            entry = apc_cache_user_exists(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t TSRMLS_CC);
18169 +            if(entry) {
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);
18175 +        }
18176 +        RETURN_ZVAL(result, 0, 1);
18177 +    } else {
18178 +        apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC);
18179 +    }
18180 +
18181 +    RETURN_FALSE;
18182 +}
18183 +/* }}} */
18184 +
18185 +
18186 +/* {{{ proto mixed apc_delete(mixed keys)
18187 + */
18188 +PHP_FUNCTION(apc_delete) {
18189 +    zval *keys;
18190 +
18191 +    if(!APCG(enabled)) RETURN_FALSE;
18192 +
18193 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
18194 +        return;
18195 +    }
18196 +
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)) {
18200 +            RETURN_TRUE;
18201 +        } else {
18202 +            RETURN_FALSE;
18203 +        }
18204 +    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
18205 +        HashTable *hash = Z_ARRVAL_P(keys);
18206 +        HashPosition hpos;
18207 +        zval **hentry;
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);
18218 +            }
18219 +            zend_hash_move_forward_ex(hash, &hpos);
18220 +        }
18221 +        return;
18222 +    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
18223 +        if (apc_iterator_delete(keys TSRMLS_CC)) {
18224 +            RETURN_TRUE;
18225 +        } else {
18226 +            RETURN_FALSE;
18227 +        }
18228 +    } else {
18229 +        apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18230 +    }
18231 +}
18232 +/* }}} */
18233 +
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.
18238 + */
18239 +PHP_FUNCTION(apc_delete_file) {
18240 +    zval *keys;
18241 +
18242 +    if(!APCG(enabled)) RETURN_FALSE;
18243 +
18244 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
18245 +        return;
18246 +    }
18247 +
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) {
18251 +            RETURN_FALSE;
18252 +        } else {
18253 +            RETURN_TRUE;
18254 +        }
18255 +    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
18256 +        HashTable *hash = Z_ARRVAL_P(keys);
18257 +        HashPosition hpos;
18258 +        zval **hentry;
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);
18269 +            }
18270 +            zend_hash_move_forward_ex(hash, &hpos);
18271 +        }
18272 +        return;
18273 +    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
18274 +        if (apc_iterator_delete(keys TSRMLS_CC)) {
18275 +            RETURN_TRUE;
18276 +        } else {
18277 +            RETURN_FALSE;
18278 +        }
18279 +    } else {
18280 +        apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC);
18281 +    }
18282 +}
18283 +/* }}} */
18284 +
18285 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
18286 +    char *const_key;
18287 +    unsigned int const_key_len;
18288 +    zval **entry;
18289 +    HashPosition pos;
18290 +
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) {
18293 +        zend_constant c;
18294 +        int key_type;
18295 +        ulong num_key;
18296 +
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);
18300 +            continue;
18301 +        }
18302 +        switch(Z_TYPE_PP(entry)) {
18303 +            case IS_LONG:
18304 +            case IS_DOUBLE:
18305 +            case IS_STRING:
18306 +            case IS_BOOL:
18307 +            case IS_RESOURCE:
18308 +            case IS_NULL:
18309 +                break;
18310 +            default:
18311 +                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
18312 +                continue;
18313 +        }
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);
18321 +
18322 +        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
18323 +    }
18324 +}
18325 +
18326 +/* {{{ proto mixed apc_define_constants(string key, array constants [, bool case_sensitive])
18327 + */
18328 +PHP_FUNCTION(apc_define_constants) {
18329 +    char *strkey;
18330 +    int strkey_len;
18331 +    zval *constants = NULL;
18332 +    zend_bool case_sensitive = 1;
18333 +    int argc = ZEND_NUM_ARGS();
18334 +
18335 +    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
18336 +        return;
18337 +    }
18338 +
18339 +    if(!strkey_len) RETURN_FALSE;
18340 +
18341 +    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
18342 +    if(_apc_store(strkey, strkey_len + 1, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
18343 +    RETURN_FALSE;
18344 +} /* }}} */
18345 +
18346 +/* {{{ proto mixed apc_load_constants(string key [, bool case_sensitive])
18347 + */
18348 +PHP_FUNCTION(apc_load_constants) {
18349 +    char *strkey;
18350 +    int strkey_len;
18351 +    apc_cache_entry_t* entry;
18352 +    time_t t;
18353 +    zend_bool case_sensitive = 1;
18354 +
18355 +    if(!APCG(enabled)) RETURN_FALSE;
18356 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
18357 +        return;
18358 +    }
18359 +
18360 +    if(!strkey_len) RETURN_FALSE;
18361 +
18362 +    t = apc_time();
18363 +
18364 +    entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC);
18365 +
18366 +    if(entry) {
18367 +        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
18368 +        apc_cache_release(apc_user_cache, entry TSRMLS_CC);
18369 +        RETURN_TRUE;
18370 +    } else {
18371 +        RETURN_FALSE;
18372 +    }
18373 +}
18374 +/* }}} */
18375 +
18376 +/* {{{ proto mixed apc_compile_file(mixed filenames [, bool atomic])
18377 + */
18378 +PHP_FUNCTION(apc_compile_file) {
18379 +    zval *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;
18389 +    time_t t;
18390 +    zval **hentry;
18391 +    HashPosition hpos;
18392 +    int i=0, c=0;
18393 +    int *rval=NULL;
18394 +    int count=0;
18395 +    zend_bool atomic=1;
18396 +    apc_context_t ctxt = {0,};
18397 +    zend_execute_data *orig_current_execute_data;
18398 +    int atomic_fail;
18399 +
18400 +    if(!APCG(enabled)) RETURN_FALSE;
18401 +
18402 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &file, &atomic) == FAILURE) {
18403 +        return;
18404 +    }
18405 +
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);
18408 +        RETURN_FALSE;
18409 +    }
18410 +
18411 +    HANDLE_BLOCK_INTERRUPTIONS();
18412 +    APCG(current_cache) = apc_cache;
18413 +
18414 +    /* reset filters and cache_by_default */
18415 +    filters = APCG(filters);
18416 +    APCG(filters) = NULL;
18417 +
18418 +    cache_by_default = APCG(cache_by_default);
18419 +    APCG(cache_by_default) = 1;
18420 +
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;
18433 +
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;
18440 +
18441 +        orig_current_execute_data = EG(current_execute_data);
18442 +        zend_try {
18443 +            op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
18444 +        } zend_catch {
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);
18449 +            op_array = NULL;
18450 +        } zend_end_try();
18451 +        if(op_array != NULL) {
18452 +            /* Free up everything */
18453 +            destroy_op_array(op_array TSRMLS_CC);
18454 +            efree(op_array);
18455 +            RETVAL_TRUE;
18456 +        } else {
18457 +            RETVAL_FALSE;
18458 +        }
18459 +        zend_destroy_file_handle(&file_handle TSRMLS_CC);
18460 +
18461 +    } else { /* IS_ARRAY */
18462 +
18463 +        array_init(return_value);
18464 +
18465 +        t = apc_time();
18466 +
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);
18474 +                break;
18475 +            }
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;
18480 +
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);
18484 +                break;
18485 +            }
18486 +
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);
18491 +            }
18492 +
18493 +            orig_current_execute_data = EG(current_execute_data);
18494 +            zend_try {
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);
18500 +                }
18501 +            } zend_catch {
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();
18510 +
18511 +            zend_destroy_file_handle(&file_handle TSRMLS_CC);
18512 +            if(op_arrays[i] != NULL) {
18513 +                count++;
18514 +            }
18515 +
18516 +            /* clean out the function/class tables */
18517 +            zend_hash_clean(&cg_function_table);
18518 +            zend_hash_clean(&cg_class_table);
18519 +
18520 +            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
18521 +            i++;
18522 +        }
18523 +
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);
18529 +            atomic_fail = 0;
18530 +        } else {
18531 +            atomic_fail = 1;
18532 +        }
18533 +
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);
18541 +                }
18542 +            }
18543 +            if (op_arrays[c]) {
18544 +                destroy_op_array(op_arrays[c] TSRMLS_CC);
18545 +                efree(op_arrays[c]);
18546 +            }
18547 +            if (atomic_fail && cache_entries[c]) {
18548 +                apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC);
18549 +            }
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);
18554 +            }
18555 +            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
18556 +        }
18557 +        efree(op_arrays);
18558 +        efree(keys);
18559 +        efree(cache_entries);
18560 +        if (rval) {
18561 +            efree(rval);
18562 +        }
18563 +
18564 +    }
18565 +
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;
18574 +
18575 +    /* Restore global settings */
18576 +    APCG(filters) = filters;
18577 +    APCG(cache_by_default) = cache_by_default;
18578 +
18579 +    APCG(current_cache) = NULL;
18580 +    HANDLE_UNBLOCK_INTERRUPTIONS();
18581 +
18582 +}
18583 +/* }}} */
18584 +
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.
18588 + */
18589 +PHP_FUNCTION(apc_bin_dump) {
18590 +
18591 +    zval *z_files = NULL, *z_user_vars = NULL;
18592 +    HashTable *h_files, *h_user_vars;
18593 +    apc_bd_t *bd;
18594 +
18595 +    if(!APCG(enabled)) {
18596 +        apc_warning("APC is not enabled, apc_bin_dump not available." TSRMLS_CC);
18597 +        RETURN_FALSE;
18598 +    }
18599 +
18600 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &z_files, &z_user_vars) == FAILURE) {
18601 +        return;
18602 +    }
18603 +
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);
18607 +    if(bd) {
18608 +        RETVAL_STRINGL((char*)bd, bd->size-1, 0);
18609 +    } else {
18610 +        apc_error("Unknown error encountered during apc_bin_dump." TSRMLS_CC);
18611 +        RETVAL_NULL();
18612 +    }
18613 +
18614 +    return;
18615 +}
18616 +
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.
18619 + */
18620 +PHP_FUNCTION(apc_bin_dumpfile) {
18621 +
18622 +    zval *z_files = NULL, *z_user_vars = NULL;
18623 +    HashTable *h_files, *h_user_vars;
18624 +    char *filename = NULL;
18625 +    int filename_len;
18626 +    long flags=0;
18627 +    zval *zcontext = NULL;
18628 +    php_stream_context *context = NULL;
18629 +    php_stream *stream;
18630 +    int numbytes = 0;
18631 +    apc_bd_t *bd;
18632 +
18633 +    if(!APCG(enabled)) {
18634 +        apc_warning("APC is not enabled, apc_bin_dumpfile not available." TSRMLS_CC);
18635 +        RETURN_FALSE;
18636 +    }
18637 +
18638 +
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) {
18640 +        return;
18641 +    }
18642 +
18643 +    if(!filename_len) {
18644 +        apc_error("apc_bin_dumpfile filename argument must be a valid filename." TSRMLS_CC);
18645 +        RETURN_FALSE;
18646 +    }
18647 +
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);
18651 +    if(!bd) {
18652 +        apc_error("Unknown error encountered during apc_bin_dumpfile." TSRMLS_CC);
18653 +        RETURN_FALSE;
18654 +    }
18655 +
18656 +
18657 +    /* Most of the following has been taken from the file_get/put_contents functions */
18658 +
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) {
18663 +        efree(bd);
18664 +        apc_error("Unable to write to file in apc_bin_dumpfile." TSRMLS_CC);
18665 +        RETURN_FALSE;
18666 +    }
18667 +
18668 +    if (flags & LOCK_EX && php_stream_lock(stream, LOCK_EX)) {
18669 +        php_stream_close(stream);
18670 +        efree(bd);
18671 +        apc_error("Unable to get a lock on file in apc_bin_dumpfile." TSRMLS_CC);
18672 +        RETURN_FALSE;
18673 +    }
18674 +
18675 +    numbytes = php_stream_write(stream, (char*)bd, bd->size);
18676 +    if(numbytes != bd->size) {
18677 +        numbytes = -1;
18678 +    }
18679 +
18680 +    php_stream_close(stream);
18681 +    efree(bd);
18682 +
18683 +    if(numbytes < 0) {
18684 +        apc_error("Only %d of %d bytes written, possibly out of free disk space" TSRMLS_CC, numbytes, bd->size);
18685 +        RETURN_FALSE;
18686 +    }
18687 +
18688 +    RETURN_LONG(numbytes);
18689 +}
18690 +
18691 +/* {{{ proto mixed apc_bin_load(string data, [int flags])
18692 +    Load the given binary dump into the APC file/user cache.
18693 + */
18694 +PHP_FUNCTION(apc_bin_load) {
18695 +
18696 +    int data_len;
18697 +    char *data;
18698 +    long flags = 0;
18699 +
18700 +    if(!APCG(enabled)) {
18701 +        apc_warning("APC is not enabled, apc_bin_load not available." TSRMLS_CC);
18702 +        RETURN_FALSE;
18703 +    }
18704 +
18705 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags) == FAILURE) {
18706 +        return;
18707 +    }
18708 +
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);
18711 +        RETURN_FALSE;
18712 +    }
18713 +
18714 +    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
18715 +
18716 +    RETURN_TRUE;
18717 +}
18718 +
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.
18721 + */
18722 +PHP_FUNCTION(apc_bin_loadfile) {
18723 +
18724 +    char *filename;
18725 +    int filename_len;
18726 +    zval *zcontext = NULL;
18727 +    long flags;
18728 +    php_stream_context *context = NULL;
18729 +    php_stream *stream;
18730 +    char *data;
18731 +    int len;
18732 +
18733 +    if(!APCG(enabled)) {
18734 +        apc_warning("APC is not enabled, apc_bin_loadfile not available." TSRMLS_CC);
18735 +        RETURN_FALSE;
18736 +    }
18737 +
18738 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!l", &filename, &filename_len, &zcontext, &flags) == FAILURE) {
18739 +        return;
18740 +    }
18741 +
18742 +    if(!filename_len) {
18743 +        apc_error("apc_bin_loadfile filename argument must be a valid filename." TSRMLS_CC);
18744 +        RETURN_FALSE;
18745 +    }
18746 +
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);
18750 +    if (!stream) {
18751 +        apc_error("Unable to read from file in apc_bin_loadfile." TSRMLS_CC);
18752 +        RETURN_FALSE;
18753 +    }
18754 +
18755 +    len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0);
18756 +    if(len == 0) {
18757 +        apc_warning("File passed to apc_bin_loadfile was empty: %s." TSRMLS_CC, filename);
18758 +        RETURN_FALSE;
18759 +    } else if(len < 0) {
18760 +        apc_warning("Error reading file passed to apc_bin_loadfile: %s." TSRMLS_CC, filename);
18761 +        RETURN_FALSE;
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);
18764 +        RETURN_FALSE;
18765 +    }
18766 +    php_stream_close(stream);
18767 +
18768 +    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
18769 +    efree(data);
18770 +
18771 +    RETURN_TRUE;
18772 +}
18773 +/* }}} */
18774 +
18775 +/* {{{ arginfo */
18776 +#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
18777 +# define PHP_APC_ARGINFO
18778 +#else
18779 +# define PHP_APC_ARGINFO static
18780 +#endif
18781 +
18782 +PHP_APC_ARGINFO
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()
18788 +
18789 +PHP_APC_ARGINFO
18790 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_clear_cache, 0, 0, 0)
18791 +    ZEND_ARG_INFO(0, info)
18792 +ZEND_END_ARG_INFO()
18793 +
18794 +PHP_APC_ARGINFO
18795 +ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_sma_info, 0, 0, 0)
18796 +    ZEND_ARG_INFO(0, limited)
18797 +ZEND_END_ARG_INFO()
18798 +
18799 +PHP_APC_ARGINFO
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()
18804 +
18805 +PHP_APC_ARGINFO
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()
18811 +
18812 +PHP_APC_ARGINFO
18813 +ZEND_BEGIN_ARG_INFO(arginfo_apc_delete_file, 0)
18814 +    ZEND_ARG_INFO(0, keys)
18815 +ZEND_END_ARG_INFO()
18816 +
18817 +PHP_APC_ARGINFO
18818 +ZEND_BEGIN_ARG_INFO(arginfo_apc_delete, 0)
18819 +    ZEND_ARG_INFO(0, keys)
18820 +ZEND_END_ARG_INFO()
18821 +
18822 +PHP_APC_ARGINFO
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()
18827 +
18828 +PHP_APC_ARGINFO
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()
18834 +
18835 +PHP_APC_ARGINFO
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()
18841 +
18842 +PHP_APC_ARGINFO
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()
18847 +
18848 +PHP_APC_ARGINFO
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()
18853 +
18854 +PHP_APC_ARGINFO
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()
18859 +
18860 +PHP_APC_ARGINFO
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()
18868 +
18869 +PHP_APC_ARGINFO
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()
18874 +
18875 +PHP_APC_ARGINFO
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()
18881 +
18882 +PHP_APC_ARGINFO
18883 +ZEND_BEGIN_ARG_INFO(arginfo_apc_exists, 0)
18884 +    ZEND_ARG_INFO(0, keys)
18885 +ZEND_END_ARG_INFO()
18886 +/* }}} */
18887 +
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}
18910 +};
18911 +/* }}} */
18912 +
18913 +/* {{{ module definition structure */
18914 +
18915 +zend_module_entry apc_module_entry = {
18916 +    STANDARD_MODULE_HEADER,
18917 +    "apc",
18918 +    apc_functions,
18919 +    PHP_MINIT(apc),
18920 +    PHP_MSHUTDOWN(apc),
18921 +    PHP_RINIT(apc),
18922 +    PHP_RSHUTDOWN(apc),
18923 +    PHP_MINFO(apc),
18924 +    PHP_APC_VERSION,
18925 +    STANDARD_MODULE_PROPERTIES
18926 +};
18927 +
18928 +#ifdef COMPILE_DL_APC
18929 +ZEND_GET_MODULE(apc)
18930 +#endif
18931 +/* }}} */
18932 +
18933 +/*
18934 + * Local variables:
18935 + * tab-width: 4
18936 + * c-basic-offset: 4
18937 + * End:
18938 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
18939 + * vim<600: expandtab sw=4 ts=4 sts=4
18940 + */
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
18944 @@ -0,0 +1,54 @@
18945 +/*
18946 +  +----------------------------------------------------------------------+
18947 +  | APC                                                                  |
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 +  +----------------------------------------------------------------------+
18963 +
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.
18969 +
18970 +   All other licensing and usage conditions are those of the PHP Group.
18971 +
18972 + */
18973 +
18974 +/* $Id: php_apc.h 326713 2012-07-19 22:07:31Z rasmus $ */
18975 +
18976 +#ifndef PHP_APC_H
18977 +#define PHP_APC_H
18978 +
18979 +#include "apc_php.h"
18980 +#include "apc_globals.h"
18981 +
18982 +#define PHP_APC_VERSION "3.1.11"
18983 +
18984 +extern zend_module_entry apc_module_entry;
18985 +#define apc_module_ptr &apc_module_entry
18986 +
18987 +#define phpext_apc_ptr apc_module_ptr
18988 +
18989 +#endif /* PHP_APC_H */
18990 +
18991 +/*
18992 + * Local variables:
18993 + * tab-width: 4
18994 + * c-basic-offset: 4
18995 + * End:
18996 + * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
18997 + * vim<600: expandtab sw=4 ts=4 sts=4
18998 + */
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
19002 @@ -0,0 +1,361 @@
19003 +APC Quick-Start Braindump
19004 +
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.
19007 +
19008 +1. Install and use APC a bit so you know what it does from the end-user's
19009 +   perspective.  
19010 +   user-space functions are all explained here: 
19011 +
19012 +2. Grab the current APC code from CVS:
19013 +    
19014 +    cvs -d:pserver:cvsread@cvs.php.net:/repository login
19015 +    Password: phpfi
19016 +    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
19017 +
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.  
19021 +
19022 +3. Build it.
19023 +
19024 +   cd pecl/apc
19025 +   phpize
19026 +   ./configure --enable-apc --enable-mmap
19027 +   make
19028 +   cp modules/apc.so /usr/local/lib/php
19029 +   apachectl restart
19030 +
19031 +4. Debugging Hints
19032 +
19033 +     apachectl stop
19034 +     gdb /usr/bin/httpd
19035 +     break ??
19036 +     run -X
19037 +
19038 +   Grab the .gdbinit from the PHP source tree and have a look at the macros.
19039 +
19040 +5. Look through apc/apc_sma.c
19041 +   It is a pretty standard memory allocator.
19042 +
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
19045 +
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.
19052 +
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.  
19056 +
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)
19060 +   block headers.
19061 +
19062 +   The code for this is:
19063 +
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));
19070 +     block->size = 0;
19071 +     block->next = sizeof(header_t) + sizeof(block_t);
19072 +     block = BLOCKAT(block->next);
19073 +     block->size = header->avail;
19074 +     block->next = 0;
19075 +
19076 +   So the shared memory looks like this:
19077 +
19078 +     +--------+-------+---------------------------------+
19079 +     | header | block |             block               |
19080 +     +--------+-------+---------------------------------+
19081 +
19082 +   sma_shmaddrs[0] gives you the address of header
19083 +
19084 +   The blocks are just a simple offset-based linked list (so no pointers):
19085 +
19086 +     typedef struct block_t block_t;
19087 +     struct 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 */
19093 +#endif
19094 +     };
19095 +
19096 +   The BLOCKAT macro turns an offset into an actual address for you:
19097 +
19098 +     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
19099 +
19100 +   where shmaddr = sma_shaddrs[0]
19101 +
19102 +   And the OFFSET macro goes the other way:
19103 +
19104 +     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
19105 +
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:
19110 +
19111 +     +--------+-------+-------+-------------------------+
19112 +     | header | block | block |         block           |
19113 +     +--------+-------+-------+-------------------------+
19114 +
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:
19117 +
19118 +     +--------+-------+       +-------------------------+
19119 +     | header | block |------>|         block           |
19120 +     +--------+-------+       +-------------------------+
19121 +
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
19125 +   the segment.
19126 +
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.
19136 +  
19137 +   Of course, anytime we fiddle with our shared memory segment we lock using
19138 +   the locking macros, LOCK() and UNLOCK().
19139 +
19140 +   That should mostly take care of the low-level shared memory handling.
19141 +
19142 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
19143 +   cache logic.
19144 +
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.  
19147 +  
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.
19158 +
19159 +   The cache is stored in/described by this struct allocated locally using
19160 +   emalloc():
19161 +
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 */
19169 +     };
19170 +
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.
19173 +
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().
19179 +
19180 +   The header looks like this:
19181 +
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 */
19187 +     };
19188 +
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.
19191 +
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:
19194 +
19195 +     typedef struct slot_t slot_t;
19196 +     struct 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 */
19204 +     };
19205 +
19206 +   The slot_t *next there is a linked list to other slots that happened to hash to the
19207 +   same array position.
19208 +
19209 +   apc_cache_insert() shows what happens on a new cache insert.
19210 +
19211 +     slot = &cache->slots[hash(key) % cache->num_slots];
19212 +
19213 +   cache->slots is our array of slots in the segment.  hash() is simply:
19214 +
19215 +     static unsigned int hash(apc_cache_key_t key)
19216 +     {
19217 +         return key.data.file.device + key.data.file.inode;
19218 +     }
19219 +
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.
19225 +
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
19228 +   the array:
19229 +
19230 +     *slot = make_slot(key, value, *slot, t)
19231 +
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:
19234 +
19235 +     while (*slot) {
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);
19240 +                break;
19241 +            }
19242 +            UNLOCK(cache);
19243 +            return 0;
19244 +        } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
19245 +             remove_slot(cache, slot);
19246 +             continue;
19247 +         }
19248 +         slot = &(*slot)->next;
19249 +     }
19250 +
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
19256 +   doing anything.
19257 +
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.
19265 +
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.
19269 +
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:
19278 +
19279 +     typedef union _apc_cache_key_data_t {
19280 +         struct {
19281 +             int device;             /* the filesystem device */
19282 +             int inode;              /* the filesystem inode */
19283 +         } file;
19284 +         struct {
19285 +             char *identifier;
19286 +         } user;
19287 +     } apc_cache_key_data_t;
19288 +
19289 +     struct apc_cache_key_t {
19290 +         apc_cache_key_data_t data;
19291 +         int mtime;                  /* the mtime of this cached entry */
19292 +     };   
19293 +
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.
19296 +
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:
19299 +
19300 +     typedef union _apc_cache_entry_value_t {
19301 +         struct {
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 */
19306 +         } file;
19307 +         struct {
19308 +             char *info;
19309 +             zval *val;
19310 +             unsigned int ttl;
19311 +         } user;
19312 +     } apc_cache_entry_value_t;
19313 +
19314 +   And then the actual cache entry:
19315 +
19316 +     struct apc_cache_entry_t {
19317 +         apc_cache_entry_value_t data;
19318 +         unsigned char type;
19319 +         int ref_count;
19320 +     };
19321 +
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.
19325 +
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
19332 +   that point. 
19333 +
19334 +7. my_compile_file() and apc_compile.c
19335 +
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.
19345 +
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:
19348 +
19349 +      op_array = old_compile_file(h, type TSRMLS_CC);
19350 +
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.  
19356 +
19357 +8. The Optimizer
19358 +   
19359 +   The optimizer has been deprecated.
19360 +
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.
19363 +
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
19367 @@ -0,0 +1,32 @@
19368 +--TEST--
19369 +APC: apc_store/fetch with strings
19370 +--SKIPIF--
19371 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19372 +--INI--
19373 +apc.enabled=1
19374 +apc.enable_cli=1
19375 +apc.file_update_protection=0
19376 +--FILE--
19377 +<?php
19378 +
19379 +$foo = 'hello world';
19380 +var_dump($foo);
19381 +apc_store('foo',$foo);
19382 +$bar = apc_fetch('foo');
19383 +var_dump($bar);
19384 +$bar = 'nice';
19385 +var_dump($bar);
19386 +
19387 +apc_store('foo\x00bar', $foo);
19388 +$bar = apc_fetch('foo\x00bar');
19389 +var_dump($bar);
19390 +
19391 +?>
19392 +===DONE===
19393 +<?php exit(0); ?>
19394 +--EXPECTF--
19395 +string(11) "hello world"
19396 +string(11) "hello world"
19397 +string(4) "nice"
19398 +string(11) "hello world"
19399 +===DONE===
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
19403 @@ -0,0 +1,34 @@
19404 +--TEST--
19405 +APC: apc_store/fetch with objects
19406 +--SKIPIF--
19407 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19408 +--INI--
19409 +apc.enabled=1
19410 +apc.enable_cli=1
19411 +apc.file_update_protection=0
19412 +--FILE--
19413 +<?php
19414 +
19415 +class foo { }
19416 +$foo = new foo;
19417 +var_dump($foo);
19418 +apc_store('foo',$foo);
19419 +unset($foo);
19420 +$bar = apc_fetch('foo');
19421 +var_dump($bar);
19422 +$bar->a = true;
19423 +var_dump($bar);
19424 +
19425 +?>
19426 +===DONE===
19427 +<?php exit(0); ?>
19428 +--EXPECTF--
19429 +object(foo)#%d (0) {
19430 +}
19431 +object(foo)#%d (0) {
19432 +}
19433 +object(foo)#%d (1) {
19434 +  ["a"]=>
19435 +  bool(true)
19436 +}
19437 +===DONE===
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
19441 @@ -0,0 +1,117 @@
19442 +--TEST--
19443 +APC: apc_store/fetch with objects (php 5.3)
19444 +--SKIPIF--
19445 +<?php
19446 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
19447 +    if(version_compare(zend_version(), '2.3.0') < 0) {
19448 +               echo "skip\n";
19449 +       }
19450 +?>
19451 +--INI--
19452 +apc.enabled=1
19453 +apc.enable_cli=1
19454 +apc.file_update_protection=0
19455 +--FILE--
19456 +<?php
19457 +
19458 +class foo { }
19459 +$foo = new foo;
19460 +var_dump($foo);
19461 +apc_store('foo',$foo);
19462 +unset($foo);
19463 +$bar = apc_fetch('foo');
19464 +var_dump($bar);
19465 +$bar->a = true;
19466 +var_dump($bar);
19467 +
19468 +class bar extends foo
19469 +{
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
19473 +       
19474 +       function __construct()
19475 +       {
19476 +               $this->bar = true;
19477 +       }
19478 +       
19479 +       function change()
19480 +       {
19481 +               $this->pri = 'mod';
19482 +       }
19483 +}
19484 +
19485 +class baz extends bar
19486 +{
19487 +       private $pri = 'baz';
19488 +
19489 +       function __construct()
19490 +       {
19491 +               parent::__construct();
19492 +               $this->baz = true;
19493 +       }
19494 +}
19495 +
19496 +$baz = new baz;
19497 +var_dump($baz);
19498 +$baz->change();
19499 +var_dump($baz);
19500 +apc_store('baz', $baz);
19501 +unset($baz);
19502 +var_dump(apc_fetch('baz'));
19503 +
19504 +?>
19505 +===DONE===
19506 +<?php exit(0); ?>
19507 +--EXPECTF--
19508 +object(foo)#%d (0) {
19509 +}
19510 +object(foo)#%d (0) {
19511 +}
19512 +object(foo)#%d (1) {
19513 +  ["a"]=>
19514 +  bool(true)
19515 +}
19516 +object(baz)#%d (6) {
19517 +  ["pri":"baz":private]=>
19518 +  string(3) "baz"
19519 +  ["pub"]=>
19520 +  string(3) "bar"
19521 +  ["pro":protected]=>
19522 +  string(3) "bar"
19523 +  ["pri":"bar":private]=>
19524 +  string(3) "bar"
19525 +  ["bar"]=>
19526 +  bool(true)
19527 +  ["baz"]=>
19528 +  bool(true)
19529 +}
19530 +object(baz)#%d (6) {
19531 +  ["pri":"baz":private]=>
19532 +  string(3) "baz"
19533 +  ["pub"]=>
19534 +  string(3) "bar"
19535 +  ["pro":protected]=>
19536 +  string(3) "bar"
19537 +  ["pri":"bar":private]=>
19538 +  string(3) "mod"
19539 +  ["bar"]=>
19540 +  bool(true)
19541 +  ["baz"]=>
19542 +  bool(true)
19543 +}
19544 +object(baz)#%d (6) {
19545 +  ["pri":"baz":private]=>
19546 +  string(3) "baz"
19547 +  ["pub"]=>
19548 +  string(3) "bar"
19549 +  ["pro":protected]=>
19550 +  string(3) "bar"
19551 +  ["pri":"bar":private]=>
19552 +  string(3) "mod"
19553 +  ["bar"]=>
19554 +  bool(true)
19555 +  ["baz"]=>
19556 +  bool(true)
19557 +}
19558 +===DONE===
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
19562 @@ -0,0 +1,117 @@
19563 +--TEST--
19564 +APC: apc_store/fetch with objects (php pre-5.3)
19565 +--SKIPIF--
19566 +<?php
19567 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
19568 +    if(version_compare(zend_version(), '2.3.0') >= 0) {
19569 +               echo "skip\n";
19570 +       }
19571 +?>
19572 +--INI--
19573 +apc.enabled=1
19574 +apc.enable_cli=1
19575 +apc.file_update_protection=0
19576 +--FILE--
19577 +<?php
19578 +
19579 +class foo { }
19580 +$foo = new foo;
19581 +var_dump($foo);
19582 +apc_store('foo',$foo);
19583 +unset($foo);
19584 +$bar = apc_fetch('foo');
19585 +var_dump($bar);
19586 +$bar->a = true;
19587 +var_dump($bar);
19588 +
19589 +class bar extends foo
19590 +{
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
19594 +       
19595 +       function __construct()
19596 +       {
19597 +               $this->bar = true;
19598 +       }
19599 +       
19600 +       function change()
19601 +       {
19602 +               $this->pri = 'mod';
19603 +       }
19604 +}
19605 +
19606 +class baz extends bar
19607 +{
19608 +       private $pri = 'baz';
19609 +
19610 +       function __construct()
19611 +       {
19612 +               parent::__construct();
19613 +               $this->baz = true;
19614 +       }
19615 +}
19616 +
19617 +$baz = new baz;
19618 +var_dump($baz);
19619 +$baz->change();
19620 +var_dump($baz);
19621 +apc_store('baz', $baz);
19622 +unset($baz);
19623 +var_dump(apc_fetch('baz'));
19624 +
19625 +?>
19626 +===DONE===
19627 +<?php exit(0); ?>
19628 +--EXPECTF--
19629 +object(foo)#%d (0) {
19630 +}
19631 +object(foo)#%d (0) {
19632 +}
19633 +object(foo)#%d (1) {
19634 +  ["a"]=>
19635 +  bool(true)
19636 +}
19637 +object(baz)#%d (6) {
19638 +  ["pri:private"]=>
19639 +  string(3) "baz"
19640 +  ["pub"]=>
19641 +  string(3) "bar"
19642 +  ["pro:protected"]=>
19643 +  string(3) "bar"
19644 +  ["pri:private"]=>
19645 +  string(3) "bar"
19646 +  ["bar"]=>
19647 +  bool(true)
19648 +  ["baz"]=>
19649 +  bool(true)
19650 +}
19651 +object(baz)#%d (6) {
19652 +  ["pri:private"]=>
19653 +  string(3) "baz"
19654 +  ["pub"]=>
19655 +  string(3) "bar"
19656 +  ["pro:protected"]=>
19657 +  string(3) "bar"
19658 +  ["pri:private"]=>
19659 +  string(3) "mod"
19660 +  ["bar"]=>
19661 +  bool(true)
19662 +  ["baz"]=>
19663 +  bool(true)
19664 +}
19665 +object(baz)#%d (6) {
19666 +  ["pri:private"]=>
19667 +  string(3) "baz"
19668 +  ["pub"]=>
19669 +  string(3) "bar"
19670 +  ["pro:protected"]=>
19671 +  string(3) "bar"
19672 +  ["pri:private"]=>
19673 +  string(3) "mod"
19674 +  ["bar"]=>
19675 +  bool(true)
19676 +  ["baz"]=>
19677 +  bool(true)
19678 +}
19679 +===DONE===
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
19683 @@ -0,0 +1,38 @@
19684 +--TEST--
19685 +APC: apc_store/fetch with bools 
19686 +--SKIPIF--
19687 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19688 +--INI--
19689 +apc.enabled=1
19690 +apc.enable_cli=1
19691 +apc.file_update_protection=0
19692 +--FILE--
19693 +<?php
19694 +
19695 +$foo = false;
19696 +var_dump($foo);     /* false */
19697 +apc_store('foo',$foo);
19698 +//$success = "some string";
19699 +
19700 +$bar = apc_fetch('foo', $success);
19701 +var_dump($foo);     /* false */
19702 +var_dump($bar);     /* false */
19703 +var_dump($success); /* true  */
19704 +
19705 +$bar = apc_fetch('not foo', $success);
19706 +var_dump($foo);     /* false */
19707 +var_dump($bar);     /* false */
19708 +var_dump($success); /* false */
19709 +
19710 +?>
19711 +===DONE===
19712 +<?php exit(0); ?>
19713 +--EXPECTF--
19714 +bool(false)
19715 +bool(false)
19716 +bool(false)
19717 +bool(true)
19718 +bool(false)
19719 +bool(false)
19720 +bool(false)
19721 +===DONE===
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
19725 @@ -0,0 +1,50 @@
19726 +--TEST--
19727 +APC: apc_store/fetch with arrays of objects 
19728 +--SKIPIF--
19729 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19730 +--INI--
19731 +apc.enabled=1
19732 +apc.enable_cli=1
19733 +apc.file_update_protection=0
19734 +--FILE--
19735 +<?php
19736 +
19737 +$foo = array(new stdclass(), new stdclass());
19738 +
19739 +var_dump($foo);
19740 +
19741 +apc_store('foo',$foo);
19742 +
19743 +$bar = apc_fetch('foo');
19744 +var_dump($foo);
19745 +var_dump($bar);
19746 +
19747 +?>
19748 +===DONE===
19749 +<?php exit(0); ?>
19750 +--EXPECTF--
19751 +array(2) {
19752 +  [0]=>
19753 +  object(stdClass)#1 (0) {
19754 +  }
19755 +  [1]=>
19756 +  object(stdClass)#2 (0) {
19757 +  }
19758 +}
19759 +array(2) {
19760 +  [0]=>
19761 +  object(stdClass)#1 (0) {
19762 +  }
19763 +  [1]=>
19764 +  object(stdClass)#2 (0) {
19765 +  }
19766 +}
19767 +array(2) {
19768 +  [0]=>
19769 +  object(stdClass)#3 (0) {
19770 +  }
19771 +  [1]=>
19772 +  object(stdClass)#4 (0) {
19773 +  }
19774 +}
19775 +===DONE===
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
19779 @@ -0,0 +1,73 @@
19780 +--TEST--
19781 +APC: apc_store/fetch reference test
19782 +--SKIPIF--
19783 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19784 +--INI--
19785 +apc.enabled=1
19786 +apc.enable_cli=1
19787 +apc.file_update_protection=0
19788 +apc.serializer=default
19789 +report_memleaks=0
19790 +--FILE--
19791 +<?php
19792 +
19793 +$a = 'a';
19794 +$b = array($a);
19795 +$c = array('c');
19796 +$b[] = &$c;
19797 +$b[] = &$c;
19798 +$d = 'd';
19799 +$b[] = &$d;
19800 +$b[] = &$d;
19801 +$b[] = &$d;
19802 +$e = 'e';
19803 +$b[] = $e;
19804 +$b[] = $e;
19805 +$f = array('f');
19806 +$f[] = &$f;
19807 +$b[] = &$f;
19808 +apc_store('test', $b);
19809 +$x = apc_fetch('test');
19810 +debug_zval_dump($x);
19811 +
19812 +?>
19813 +===DONE===
19814 +<?php exit(0); ?>
19815 +--EXPECTF--
19816 +array(9) refcount(2){
19817 +  [0]=>
19818 +  string(1) "a" refcount(1)
19819 +  [1]=>
19820 +  &array(1) refcount(2){
19821 +    [0]=>
19822 +    string(1) "c" refcount(1)
19823 +  }
19824 +  [2]=>
19825 +  &array(1) refcount(2){
19826 +    [0]=>
19827 +    string(1) "c" refcount(1)
19828 +  }
19829 +  [3]=>
19830 +  &string(1) "d" refcount(3)
19831 +  [4]=>
19832 +  &string(1) "d" refcount(3)
19833 +  [5]=>
19834 +  &string(1) "d" refcount(3)
19835 +  [6]=>
19836 +  string(1) "e" refcount(2)
19837 +  [7]=>
19838 +  string(1) "e" refcount(2)
19839 +  [8]=>
19840 +  &array(2) refcount(2){
19841 +    [0]=>
19842 +    string(1) "f" refcount(1)
19843 +    [1]=>
19844 +    &array(2) refcount(2){
19845 +      [0]=>
19846 +      string(1) "f" refcount(1)
19847 +      [1]=>
19848 +      *RECURSION*
19849 +    }
19850 +  }
19851 +}
19852 +===DONE===
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
19856 @@ -0,0 +1,46 @@
19857 +--TEST--
19858 +APC: apc_inc/apc_dec test
19859 +--SKIPIF--
19860 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19861 +--INI--
19862 +apc.enabled=1
19863 +apc.enable_cli=1
19864 +apc.file_update_protection=0
19865 +--FILE--
19866 +<?php
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";
19871 +
19872 +echo "\$foobar -= 1 = ".apc_dec('foobar')."\n";
19873 +echo "\$foobar -= 10 = ".apc_dec('foobar',10)."\n";
19874 +
19875 +echo "\$f__bar += 1 = ".(apc_inc('f__bar')?"ok":"fail")."\n";
19876 +
19877 +apc_store('perfection', "xyz");
19878 +echo "\$perfection -= 1 = ".(apc_inc('perfection')?"ok":"epic fail")."\n";
19879 +
19880 +$success = false;
19881 +
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";
19886 +
19887 +?>
19888 +===DONE===
19889 +<?php exit(0); ?>
19890 +--EXPECTF--
19891 +$foobar = 2 
19892 +$foobar += 1 = 3
19893 +$foobar += 10 = 13
19894 +$foobar -= 1 = 12
19895 +$foobar -= 10 = 2
19896 +$f__bar += 1 = fail
19897 +$perfection -= 1 = epic fail
19898 +$foobar += 1 = 3
19899 +pass by ref success 1
19900 +$foobar -= 1 = 2
19901 +pass by ref success 1
19902 +===DONE===
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
19906 @@ -0,0 +1,34 @@
19907 +--TEST--
19908 +APC: apc_cas test
19909 +--SKIPIF--
19910 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19911 +--INI--
19912 +apc.enabled=1
19913 +apc.enable_cli=1
19914 +apc.file_update_protection=0
19915 +--FILE--
19916 +<?php
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";
19922 +
19923 +echo "\$f__bar == 1 ? 2 : 1 = ".(apc_cas('f__bar', 1, 2)?"ok":"fail")."\n";
19924 +
19925 +apc_store('perfection', "xyz");
19926 +echo "\$perfection == 2 ? 1 : 2 = ".(apc_cas('perfection', 2, 1)?"ok":"epic fail")."\n";
19927 +
19928 +echo "\$foobar = ".apc_fetch("foobar")."\n";
19929 +?>
19930 +===DONE===
19931 +<?php exit(0); ?>
19932 +--EXPECTF--
19933 +$foobar = 2
19934 +$foobar == 1 ? 2 : 1 = fail
19935 +$foobar == 2 ? 1 : 2 = ok
19936 +$foobar = 1
19937 +$f__bar == 1 ? 2 : 1 = fail
19938 +$perfection == 2 ? 1 : 2 = epic fail
19939 +$foobar = 1
19940 +===DONE===
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
19944 @@ -0,0 +1,97 @@
19945 +--TEST--
19946 +APC: apc_delete_file test
19947 +--SKIPIF--
19948 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
19949 +--INI--
19950 +apc.enabled=1
19951 +apc.enable_cli=1
19952 +apc.file_update_protection=0
19953 +apc.stat=On
19954 +report_memleaks=0
19955 +--FILE--
19956 +<?php
19957 +
19958 +$files = array( 'apc_009.php',
19959 +                'apc_009-1.php',
19960 +                'apc_009-2.php',
19961 +                'nofile.php',
19962 +              );
19963 +
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!');
19966 +
19967 +apc_compile_file($files[0]);
19968 +check_file($files[0]);
19969 +apc_delete_file($files[0]);
19970 +check_file($files[0]);
19971 +
19972 +apc_compile_file($files[0]);
19973 +apc_delete_file(array($files[0]));
19974 +check_file($files[0]);
19975 +
19976 +apc_compile_file($files[0]);
19977 +$it = new APCIterator('file');
19978 +apc_delete_file($it);
19979 +check_file($files[0]);
19980 +
19981 +var_dump(apc_compile_file(array($files[0], $files[1])));
19982 +check_file(array($files[0], $files[1]));
19983 +
19984 +var_dump(apc_compile_file($files));
19985 +check_file($files);
19986 +
19987 +function check_file($files) {
19988 +
19989 +  if (!is_array($files)) {
19990 +    $files = array($files);
19991 +  }
19992 +
19993 +  $info = apc_cache_info('file');
19994 +
19995 +  foreach ($files as $file) {
19996 +    $match = 0;
19997 +    foreach($info['cache_list'] as $cached_file) {
19998 +      if (stristr($cached_file['filename'], $file)) $match = 1;
19999 +    }
20000 +    if ($match) {
20001 +      echo "$file Found File\n";
20002 +    } else {
20003 +      echo "$file Not Found\n";
20004 +    }
20005 +  }
20006 +}
20007 +
20008 +?>
20009 +===DONE===
20010 +<?php exit(0); ?>
20011 +--CLEAN--
20012 +<?php
20013 +unlink('apc_009-1.php');
20014 +unlink('apc_009-2.php');
20015 +?>
20016 +--EXPECTF--
20017 +apc_009.php Found File
20018 +apc_009.php Not Found
20019 +apc_009.php Not Found
20020 +apc_009.php Not Found
20021 +array(0) {
20022 +}
20023 +apc_009.php Found File
20024 +apc_009-1.php Found File
20025 +
20026 +Parse error: syntax error, unexpected '!' in %s/apc_009-2.php on line 1
20027 +
20028 +Warning: apc_compile_file(): Error compiling apc_009-2.php in apc_compile_file. in %s/apc_009.php on line 29
20029 +
20030 +Warning: apc_compile_file(): Error compiling nofile.php in apc_compile_file. in %s/apc_009.php on line 29
20031 +array(2) {
20032 +  ["apc_009-2.php"]=>
20033 +  int(-1)
20034 +  ["nofile.php"]=>
20035 +  int(-1)
20036 +}
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
20041 +===DONE===
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
20045 @@ -0,0 +1,83 @@
20046 +--TEST--
20047 +APC: apc_store/fetch/add with array of key/value pairs.
20048 +--SKIPIF--
20049 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20050 +--INI--
20051 +apc.enabled=1
20052 +apc.enable_cli=1
20053 +apc.file_update_protection=0
20054 +--FILE--
20055 +<?php
20056 +
20057 +$entries = array();
20058 +$entries['key1'] = 'value1';
20059 +$entries['key2'] = 'value2';
20060 +$entries['key3'] = array('value3a','value3b');
20061 +$entries['key4'] = 4;
20062 +
20063 +var_dump(apc_store($entries));
20064 +$cached_values = apc_fetch(array_keys($entries));
20065 +var_dump($cached_values);
20066 +
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);
20074 +
20075 +?>
20076 +===DONE===
20077 +<?php exit(0); ?>
20078 +--EXPECTF--
20079 +array(0) {
20080 +}
20081 +array(4) {
20082 +  ["key1"]=>
20083 +  string(6) "value1"
20084 +  ["key2"]=>
20085 +  string(6) "value2"
20086 +  ["key3"]=>
20087 +  array(2) {
20088 +    [0]=>
20089 +    string(7) "value3a"
20090 +    [1]=>
20091 +    string(7) "value3b"
20092 +  }
20093 +  ["key4"]=>
20094 +  int(4)
20095 +}
20096 +array(2) {
20097 +  ["key1"]=>
20098 +  string(6) "value1"
20099 +  ["key3"]=>
20100 +  array(2) {
20101 +    [0]=>
20102 +    string(7) "value3a"
20103 +    [1]=>
20104 +    string(7) "value3b"
20105 +  }
20106 +}
20107 +array(2) {
20108 +  ["key1"]=>
20109 +  int(-1)
20110 +  ["key3"]=>
20111 +  int(-1)
20112 +}
20113 +array(4) {
20114 +  ["key1"]=>
20115 +  string(6) "value1"
20116 +  ["key2"]=>
20117 +  string(6) "value2"
20118 +  ["key3"]=>
20119 +  array(2) {
20120 +    [0]=>
20121 +    string(7) "value3a"
20122 +    [1]=>
20123 +    string(7) "value3b"
20124 +  }
20125 +  ["key4"]=>
20126 +  int(4)
20127 +}
20128 +===DONE===
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
20132 @@ -0,0 +1,33 @@
20133 +--TEST--
20134 +APC: classes with namespaces (php 5.3)
20135 +--SKIPIF--
20136 +<?php
20137 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
20138 +    if(version_compare(zend_version(), '2.3.0') < 0) {
20139 +               echo "skip\n";
20140 +       }
20141 +?>
20142 +--INI--
20143 +apc.enabled=1
20144 +apc.enable_cli=1
20145 +apc.file_update_protection=0
20146 +--FILE--
20147 +<?php
20148 +
20149 +require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
20150 +
20151 +$a = new Foo\Bar\Baz();
20152 +var_dump($a);
20153 +?>
20154 +===DONE===
20155 +<?php exit(0); ?>
20156 +--EXPECTF--
20157 +object(Foo\Bar\Baz)#1 (3) {
20158 +  ["i"]=>
20159 +  int(1)
20160 +  ["f":protected]=>
20161 +  float(3.14)
20162 +  ["s":"Foo\Bar\Baz":private]=>
20163 +  string(11) "hello world"
20164 +}
20165 +===DONE===
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
20169 @@ -0,0 +1,47 @@
20170 +--TEST--
20171 +APC: global spaces (php 5.3)
20172 +--SKIPIF--
20173 +<?php
20174 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
20175 +    if(version_compare(zend_version(), '2.3.0') < 0) {
20176 +               echo "skip\n";
20177 +       }
20178 +?>
20179 +--INI--
20180 +apc.enabled=1
20181 +apc.enable_cli=1
20182 +apc.file_update_protection=0
20183 +--FILE--
20184 +<?php
20185 +
20186 +require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
20187 +
20188 +$a = new Foo\Bar\Baz();
20189 +$a->foo();
20190 +var_dump(Foo\Bar\sort());
20191 +?>
20192 +===DONE===
20193 +<?php exit(0); ?>
20194 +--EXPECTF--
20195 +array(4) {
20196 +  [0]=>
20197 +  int(1)
20198 +  [1]=>
20199 +  int(2)
20200 +  [2]=>
20201 +  int(3)
20202 +  [3]=>
20203 +  int(4)
20204 +}
20205 +array(4) {
20206 +  [0]=>
20207 +  int(1)
20208 +  [1]=>
20209 +  int(2)
20210 +  [2]=>
20211 +  int(3)
20212 +  [3]=>
20213 +  int(4)
20214 +}
20215 +string(8) "IT WORKS"
20216 +===DONE===
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
20220 @@ -0,0 +1,31 @@
20221 +--TEST--
20222 +APC: anonymous functions (php 5.3)
20223 +--SKIPIF--
20224 +<?php
20225 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
20226 +    if(version_compare(zend_version(), '2.3.0') < 0) {
20227 +               echo "skip\n";
20228 +       }
20229 +?>
20230 +--INI--
20231 +apc.enabled=1
20232 +apc.enable_cli=1
20233 +apc.file_update_protection=0
20234 +--FILE--
20235 +<?php
20236 +
20237 +$greet = function($name)
20238 +{
20239 +    printf("Hello %s\r\n", $name);
20240 +};
20241 +
20242 +$greet('World');
20243 +$greet('PHP');
20244 +
20245 +?>
20246 +===DONE===
20247 +<?php exit(0); ?>
20248 +--EXPECTF--
20249 +Hello World
20250 +Hello PHP
20251 +===DONE===
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
20255 @@ -0,0 +1,33 @@
20256 +--TEST--
20257 +APC: closures (php 5.3)
20258 +--SKIPIF--
20259 +<?php
20260 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
20261 +    if(version_compare(zend_version(), '2.3.0') < 0) {
20262 +               echo "skip\n";
20263 +       }
20264 +?>
20265 +--INI--
20266 +apc.enabled=1
20267 +apc.enable_cli=1
20268 +apc.file_update_protection=0
20269 +--FILE--
20270 +<?php
20271 +function multiplier($n) {
20272 +       return function($i) use ($n) {
20273 +               return $n * $i;
20274 +       };
20275 +}
20276 +
20277 +$doubler = multiplier(2);
20278 +$tripler = multiplier(3);
20279 +
20280 +echo "double of 9 is ".$doubler(9)."\n";
20281 +echo "triple of 4 is ".$tripler(4)."\n";
20282 +?>
20283 +===DONE===
20284 +<?php exit(0); ?>
20285 +--EXPECTF--
20286 +double of 9 is 18
20287 +triple of 4 is 12
20288 +===DONE===
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
20292 @@ -0,0 +1,35 @@
20293 +--TEST--
20294 +APC: goto (php 5.3)
20295 +--SKIPIF--
20296 +<?php
20297 +    require_once(dirname(__FILE__) . '/skipif.inc'); 
20298 +    if(version_compare(zend_version(), '2.3.0') < 0) {
20299 +               echo "skip\n";
20300 +       }
20301 +?>
20302 +--INI--
20303 +apc.enabled=1
20304 +apc.enable_cli=1
20305 +apc.file_update_protection=0
20306 +--FILE--
20307 +<?php
20308 +
20309 +$i = 0;
20310 +a: 
20311 +$i++;
20312 +if($i % 3 == 0) goto b;
20313 +echo "$i\n";
20314 +b:
20315 +if($i < 10) goto a;
20316 +?>
20317 +===DONE===
20318 +<?php exit(0); ?>
20319 +--EXPECTF--
20320 +1
20321 +2
20322 +4
20323 +5
20324 +7
20325 +8
20326 +10
20327 +===DONE===
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
20331 @@ -0,0 +1,24 @@
20332 +--TEST--
20333 +APC: bindump user cache
20334 +--SKIPIF--
20335 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20336 +--INI--
20337 +apc.enabled=1
20338 +apc.enable_cli=1
20339 +--FILE--
20340 +<?php
20341 +apc_clear_cache('file');
20342 +apc_store('testkey','testvalue');
20343 +apc_bin_dump();
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'));
20349 +?>
20350 +===DONE===
20351 +<?php exit(0); ?>
20352 +--EXPECTF--
20353 +bool(false)
20354 +string(9) "testvalue"
20355 +===DONE===
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
20359 @@ -0,0 +1,42 @@
20360 +<?php
20361 +
20362 +$my_class = New my_class();
20363 +$my_i_class = New my_i_class();
20364 +
20365 +echo "apc bindump 002 test\n";
20366 +echo "\n";
20367 +echo "global scope execution:            Success\n";
20368 +echo "\n";
20369 +echo "function execution:                ".my_function()."\n";
20370 +echo "\n";
20371 +
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";
20377 +echo "\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";
20383 +echo "\n";
20384 +
20385 +
20386 +
20387 +function my_function() { return "Success"; }
20388 +
20389 +
20390 +class my_class {
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"; }
20396 +}
20397 +
20398 +class my_i_class extends my_class {
20399 +  function dummy() { return 1; }
20400 +}
20401 +
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
20405 @@ -0,0 +1,5 @@
20406 +<?php
20407 +
20408 +echo "Failed to use cached version!\n";
20409 +
20410 +?>
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
20414 @@ -0,0 +1,53 @@
20415 +--TEST--
20416 +APC: bindump file cache part 1
20417 +--SKIPIF--
20418 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20419 +--INI--
20420 +apc.enabled=1
20421 +apc.enable_cli=1
20422 +apc.stat=0
20423 +apc.cache_by_default=1
20424 +apc.filters=
20425 +report_memleaks = Off
20426 +--FILE--
20427 +<?php
20428 +
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');
20432 +
20433 +copy(filename1, filename);
20434 +apc_compile_file(filename);
20435 +$data = apc_bin_dump(NULL, NULL);
20436 +
20437 +apc_clear_cache();
20438 +
20439 +copy(filename2, filename);
20440 +apc_bin_load($data, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
20441 +include(filename);
20442 +
20443 +unlink(filename);
20444 +
20445 +?>
20446 +===DONE===
20447 +<?  php exit(0); ?>
20448 +--EXPECTF--
20449 +apc bindump 002 test
20450 +
20451 +global scope execution:            Success
20452 +
20453 +function execution:                Success
20454 +
20455 +class static method:               Success
20456 +class dynamic method:              Success
20457 +class static property:             Success
20458 +class dynamic property:            Success
20459 +class constant:                    Success
20460 +
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
20466 +
20467 +===DONE===
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
20471 @@ -0,0 +1,110 @@
20472 +--TEST--
20473 +APC: APCIterator general
20474 +--SKIPIF--
20475 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20476 +--INI--
20477 +apc.enabled=1
20478 +apc.enable_cli=1
20479 +apc.file_update_protection=0
20480 +--FILE--
20481 +<?php
20482 +
20483 +$it = new APCIterator('user');
20484 +for($i = 0; $i < 41; $i++) {
20485 +  apc_store("key$i", "value$i");
20486 +}
20487 +foreach($it as $key=>$value) {
20488 +  $vals[$key] = $value['key'];
20489 +}
20490 +ksort($vals);
20491 +var_dump($vals);
20492 +
20493 +?>
20494 +===DONE===
20495 +<?php exit(0); ?>
20496 +--EXPECT--
20497 +array(41) {
20498 +  ["key0"]=>
20499 +  string(4) "key0"
20500 +  ["key1"]=>
20501 +  string(4) "key1"
20502 +  ["key10"]=>
20503 +  string(5) "key10"
20504 +  ["key11"]=>
20505 +  string(5) "key11"
20506 +  ["key12"]=>
20507 +  string(5) "key12"
20508 +  ["key13"]=>
20509 +  string(5) "key13"
20510 +  ["key14"]=>
20511 +  string(5) "key14"
20512 +  ["key15"]=>
20513 +  string(5) "key15"
20514 +  ["key16"]=>
20515 +  string(5) "key16"
20516 +  ["key17"]=>
20517 +  string(5) "key17"
20518 +  ["key18"]=>
20519 +  string(5) "key18"
20520 +  ["key19"]=>
20521 +  string(5) "key19"
20522 +  ["key2"]=>
20523 +  string(4) "key2"
20524 +  ["key20"]=>
20525 +  string(5) "key20"
20526 +  ["key21"]=>
20527 +  string(5) "key21"
20528 +  ["key22"]=>
20529 +  string(5) "key22"
20530 +  ["key23"]=>
20531 +  string(5) "key23"
20532 +  ["key24"]=>
20533 +  string(5) "key24"
20534 +  ["key25"]=>
20535 +  string(5) "key25"
20536 +  ["key26"]=>
20537 +  string(5) "key26"
20538 +  ["key27"]=>
20539 +  string(5) "key27"
20540 +  ["key28"]=>
20541 +  string(5) "key28"
20542 +  ["key29"]=>
20543 +  string(5) "key29"
20544 +  ["key3"]=>
20545 +  string(4) "key3"
20546 +  ["key30"]=>
20547 +  string(5) "key30"
20548 +  ["key31"]=>
20549 +  string(5) "key31"
20550 +  ["key32"]=>
20551 +  string(5) "key32"
20552 +  ["key33"]=>
20553 +  string(5) "key33"
20554 +  ["key34"]=>
20555 +  string(5) "key34"
20556 +  ["key35"]=>
20557 +  string(5) "key35"
20558 +  ["key36"]=>
20559 +  string(5) "key36"
20560 +  ["key37"]=>
20561 +  string(5) "key37"
20562 +  ["key38"]=>
20563 +  string(5) "key38"
20564 +  ["key39"]=>
20565 +  string(5) "key39"
20566 +  ["key4"]=>
20567 +  string(4) "key4"
20568 +  ["key40"]=>
20569 +  string(5) "key40"
20570 +  ["key5"]=>
20571 +  string(4) "key5"
20572 +  ["key6"]=>
20573 +  string(4) "key6"
20574 +  ["key7"]=>
20575 +  string(4) "key7"
20576 +  ["key8"]=>
20577 +  string(4) "key8"
20578 +  ["key9"]=>
20579 +  string(4) "key9"
20580 +}
20581 +===DONE===
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
20585 @@ -0,0 +1,36 @@
20586 +--TEST--
20587 +APC: APCIterator regex
20588 +--SKIPIF--
20589 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20590 +--INI--
20591 +apc.enabled=1
20592 +apc.enable_cli=1
20593 +apc.file_update_protection=0
20594 +--FILE--
20595 +<?php
20596 +
20597 +$it = new APCIterator('user', '/key[0-9]0/');
20598 +for($i = 0; $i < 41; $i++) {
20599 +  apc_store("key$i", "value$i");
20600 +}
20601 +foreach($it as $key=>$value) {
20602 +  $vals[$key] = $value['key'];
20603 +}
20604 +ksort($vals);
20605 +var_dump($vals);
20606 +
20607 +?>
20608 +===DONE===
20609 +<?php exit(0); ?>
20610 +--EXPECT--
20611 +array(4) {
20612 +  ["key10"]=>
20613 +  string(5) "key10"
20614 +  ["key20"]=>
20615 +  string(5) "key20"
20616 +  ["key30"]=>
20617 +  string(5) "key30"
20618 +  ["key40"]=>
20619 +  string(5) "key40"
20620 +}
20621 +===DONE===
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
20625 @@ -0,0 +1,110 @@
20626 +--TEST--
20627 +APC: APCIterator chunk size
20628 +--SKIPIF--
20629 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20630 +--INI--
20631 +apc.enabled=1
20632 +apc.enable_cli=1
20633 +apc.file_update_protection=0
20634 +--FILE--
20635 +<?php
20636 +
20637 +$it = new APCIterator('user', NULL, APC_ITER_ALL, 10);
20638 +for($i = 0; $i < 41; $i++) {
20639 +  apc_store("key$i", "value$i");
20640 +}
20641 +foreach($it as $key=>$value) {
20642 +  $vals[$key] = $value['key'];
20643 +}
20644 +ksort($vals);
20645 +var_dump($vals);
20646 +
20647 +?>
20648 +===DONE===
20649 +<?php exit(0); ?>
20650 +--EXPECT--
20651 +array(41) {
20652 +  ["key0"]=>
20653 +  string(4) "key0"
20654 +  ["key1"]=>
20655 +  string(4) "key1"
20656 +  ["key10"]=>
20657 +  string(5) "key10"
20658 +  ["key11"]=>
20659 +  string(5) "key11"
20660 +  ["key12"]=>
20661 +  string(5) "key12"
20662 +  ["key13"]=>
20663 +  string(5) "key13"
20664 +  ["key14"]=>
20665 +  string(5) "key14"
20666 +  ["key15"]=>
20667 +  string(5) "key15"
20668 +  ["key16"]=>
20669 +  string(5) "key16"
20670 +  ["key17"]=>
20671 +  string(5) "key17"
20672 +  ["key18"]=>
20673 +  string(5) "key18"
20674 +  ["key19"]=>
20675 +  string(5) "key19"
20676 +  ["key2"]=>
20677 +  string(4) "key2"
20678 +  ["key20"]=>
20679 +  string(5) "key20"
20680 +  ["key21"]=>
20681 +  string(5) "key21"
20682 +  ["key22"]=>
20683 +  string(5) "key22"
20684 +  ["key23"]=>
20685 +  string(5) "key23"
20686 +  ["key24"]=>
20687 +  string(5) "key24"
20688 +  ["key25"]=>
20689 +  string(5) "key25"
20690 +  ["key26"]=>
20691 +  string(5) "key26"
20692 +  ["key27"]=>
20693 +  string(5) "key27"
20694 +  ["key28"]=>
20695 +  string(5) "key28"
20696 +  ["key29"]=>
20697 +  string(5) "key29"
20698 +  ["key3"]=>
20699 +  string(4) "key3"
20700 +  ["key30"]=>
20701 +  string(5) "key30"
20702 +  ["key31"]=>
20703 +  string(5) "key31"
20704 +  ["key32"]=>
20705 +  string(5) "key32"
20706 +  ["key33"]=>
20707 +  string(5) "key33"
20708 +  ["key34"]=>
20709 +  string(5) "key34"
20710 +  ["key35"]=>
20711 +  string(5) "key35"
20712 +  ["key36"]=>
20713 +  string(5) "key36"
20714 +  ["key37"]=>
20715 +  string(5) "key37"
20716 +  ["key38"]=>
20717 +  string(5) "key38"
20718 +  ["key39"]=>
20719 +  string(5) "key39"
20720 +  ["key4"]=>
20721 +  string(4) "key4"
20722 +  ["key40"]=>
20723 +  string(5) "key40"
20724 +  ["key5"]=>
20725 +  string(4) "key5"
20726 +  ["key6"]=>
20727 +  string(4) "key6"
20728 +  ["key7"]=>
20729 +  string(4) "key7"
20730 +  ["key8"]=>
20731 +  string(4) "key8"
20732 +  ["key9"]=>
20733 +  string(4) "key9"
20734 +}
20735 +===DONE===
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
20739 @@ -0,0 +1,36 @@
20740 +--TEST--
20741 +APC: APCIterator regex & chunk size & list
20742 +--SKIPIF--
20743 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20744 +--INI--
20745 +apc.enabled=1
20746 +apc.enable_cli=1
20747 +apc.file_update_protection=0
20748 +--FILE--
20749 +<?php
20750 +
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");
20754 +}
20755 +foreach($it as $key=>$value) {
20756 +  $vals[$key] = $value['key'];
20757 +}
20758 +ksort($vals);
20759 +var_dump($vals);
20760 +
20761 +?>
20762 +===DONE===
20763 +<?php exit(0); ?>
20764 +--EXPECT--
20765 +array(4) {
20766 +  ["key10"]=>
20767 +  string(5) "key10"
20768 +  ["key20"]=>
20769 +  string(5) "key20"
20770 +  ["key30"]=>
20771 +  string(5) "key30"
20772 +  ["key40"]=>
20773 +  string(5) "key40"
20774 +}
20775 +===DONE===
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
20779 @@ -0,0 +1,112 @@
20780 +--TEST--
20781 +APC: APCIterator delete
20782 +--SKIPIF--
20783 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20784 +--INI--
20785 +apc.enabled=1
20786 +apc.enable_cli=1
20787 +apc.file_update_protection=0
20788 +--FILE--
20789 +<?php
20790 +
20791 +$vals = array();
20792 +$vals2 = array();
20793 +$it = new APCIterator('user', '/key[0-9]0/');
20794 +for($i = 0; $i < 41; $i++) {
20795 +  apc_store("key$i", "value$i");
20796 +}
20797 +apc_delete($it);
20798 +$it2 = new APCIterator('user');
20799 +foreach($it as $key=>$value) {
20800 +  $vals[$key] = $value['key'];
20801 +}
20802 +foreach($it2 as $key=>$value) {
20803 +  $vals2[$key] = $value['key'];
20804 +}
20805 +ksort($vals2);
20806 +var_dump($vals);
20807 +var_dump($vals2);
20808 +
20809 +?>
20810 +===DONE===
20811 +<?php exit(0); ?>
20812 +--EXPECT--
20813 +array(0) {
20814 +}
20815 +array(37) {
20816 +  ["key0"]=>
20817 +  string(4) "key0"
20818 +  ["key1"]=>
20819 +  string(4) "key1"
20820 +  ["key11"]=>
20821 +  string(5) "key11"
20822 +  ["key12"]=>
20823 +  string(5) "key12"
20824 +  ["key13"]=>
20825 +  string(5) "key13"
20826 +  ["key14"]=>
20827 +  string(5) "key14"
20828 +  ["key15"]=>
20829 +  string(5) "key15"
20830 +  ["key16"]=>
20831 +  string(5) "key16"
20832 +  ["key17"]=>
20833 +  string(5) "key17"
20834 +  ["key18"]=>
20835 +  string(5) "key18"
20836 +  ["key19"]=>
20837 +  string(5) "key19"
20838 +  ["key2"]=>
20839 +  string(4) "key2"
20840 +  ["key21"]=>
20841 +  string(5) "key21"
20842 +  ["key22"]=>
20843 +  string(5) "key22"
20844 +  ["key23"]=>
20845 +  string(5) "key23"
20846 +  ["key24"]=>
20847 +  string(5) "key24"
20848 +  ["key25"]=>
20849 +  string(5) "key25"
20850 +  ["key26"]=>
20851 +  string(5) "key26"
20852 +  ["key27"]=>
20853 +  string(5) "key27"
20854 +  ["key28"]=>
20855 +  string(5) "key28"
20856 +  ["key29"]=>
20857 +  string(5) "key29"
20858 +  ["key3"]=>
20859 +  string(4) "key3"
20860 +  ["key31"]=>
20861 +  string(5) "key31"
20862 +  ["key32"]=>
20863 +  string(5) "key32"
20864 +  ["key33"]=>
20865 +  string(5) "key33"
20866 +  ["key34"]=>
20867 +  string(5) "key34"
20868 +  ["key35"]=>
20869 +  string(5) "key35"
20870 +  ["key36"]=>
20871 +  string(5) "key36"
20872 +  ["key37"]=>
20873 +  string(5) "key37"
20874 +  ["key38"]=>
20875 +  string(5) "key38"
20876 +  ["key39"]=>
20877 +  string(5) "key39"
20878 +  ["key4"]=>
20879 +  string(4) "key4"
20880 +  ["key5"]=>
20881 +  string(4) "key5"
20882 +  ["key6"]=>
20883 +  string(4) "key6"
20884 +  ["key7"]=>
20885 +  string(4) "key7"
20886 +  ["key8"]=>
20887 +  string(4) "key8"
20888 +  ["key9"]=>
20889 +  string(4) "key9"
20890 +}
20891 +===DONE===
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
20895 @@ -0,0 +1,1536 @@
20896 +--TEST--
20897 +APC: APCIterator formats 
20898 +--SKIPIF--
20899 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
20900 +--INI--
20901 +apc.enabled=1
20902 +apc.enable_cli=1
20903 +apc.file_update_protection=0
20904 +apc.user_entries_hint=4096
20905 +--FILE--
20906 +<?php
20907 +
20908 +$formats = array( 
20909 +                  APC_ITER_TYPE,
20910 +                  APC_ITER_KEY,
20911 +                  APC_ITER_FILENAME,
20912 +                  APC_ITER_DEVICE,
20913 +                  APC_ITER_INODE,
20914 +                  APC_ITER_VALUE,
20915 +                  APC_ITER_MD5,
20916 +                  APC_ITER_NUM_HITS,
20917 +                  APC_ITER_MTIME,
20918 +                  APC_ITER_CTIME,
20919 +                  APC_ITER_DTIME,
20920 +                  APC_ITER_ATIME,
20921 +                  APC_ITER_REFCOUNT,
20922 +                  APC_ITER_MEM_SIZE,
20923 +                  APC_ITER_TTL,
20924 +                  APC_ITER_NONE,
20925 +                  APC_ITER_ALL,
20926 +                  APC_ITER_ALL & ~APC_ITER_TTL,
20927 +                  APC_ITER_KEY | APC_ITER_NUM_HITS | APC_ITER_MEM_SIZE,
20928 +                );
20929 +
20930 +$it_array = array();
20931 +
20932 +foreach ($formats as $idx => $format) {
20933 +  $it_array[$idx] = new APCIterator('user', NULL, $format);
20934 +}
20935 +
20936 +for($i = 0; $i < 11; $i++) {
20937 +  apc_store("key$i", "value$i");
20938 +}
20939 +
20940 +foreach ($it_array as $idx => $it) {
20941 +  print_it($it, $idx);
20942 +}
20943 +
20944 +function print_it($it, $idx) {
20945 +  echo "IT #$idx\n";
20946 +  echo "============================\n";
20947 +  foreach ($it as $key=>$value) {
20948 +    var_dump($key);
20949 +    var_dump($value);
20950 +  }
20951 +  echo "============================\n\n";
20952 +}
20953 +
20954 +?>
20955 +===DONE===
20956 +<?php exit(0); ?>
20957 +--EXPECTF--
20958 +IT #0
20959 +============================
20960 +string(5) "key10"
20961 +array(1) {
20962 +  ["type"]=>
20963 +  string(4) "user"
20964 +}
20965 +string(4) "key0"
20966 +array(1) {
20967 +  ["type"]=>
20968 +  string(4) "user"
20969 +}
20970 +string(4) "key1"
20971 +array(1) {
20972 +  ["type"]=>
20973 +  string(4) "user"
20974 +}
20975 +string(4) "key2"
20976 +array(1) {
20977 +  ["type"]=>
20978 +  string(4) "user"
20979 +}
20980 +string(4) "key3"
20981 +array(1) {
20982 +  ["type"]=>
20983 +  string(4) "user"
20984 +}
20985 +string(4) "key4"
20986 +array(1) {
20987 +  ["type"]=>
20988 +  string(4) "user"
20989 +}
20990 +string(4) "key5"
20991 +array(1) {
20992 +  ["type"]=>
20993 +  string(4) "user"
20994 +}
20995 +string(4) "key6"
20996 +array(1) {
20997 +  ["type"]=>
20998 +  string(4) "user"
20999 +}
21000 +string(4) "key7"
21001 +array(1) {
21002 +  ["type"]=>
21003 +  string(4) "user"
21004 +}
21005 +string(4) "key8"
21006 +array(1) {
21007 +  ["type"]=>
21008 +  string(4) "user"
21009 +}
21010 +string(4) "key9"
21011 +array(1) {
21012 +  ["type"]=>
21013 +  string(4) "user"
21014 +}
21015 +============================
21016 +
21017 +IT #1
21018 +============================
21019 +string(5) "key10"
21020 +array(1) {
21021 +  ["key"]=>
21022 +  string(5) "key10"
21023 +}
21024 +string(4) "key0"
21025 +array(1) {
21026 +  ["key"]=>
21027 +  string(4) "key0"
21028 +}
21029 +string(4) "key1"
21030 +array(1) {
21031 +  ["key"]=>
21032 +  string(4) "key1"
21033 +}
21034 +string(4) "key2"
21035 +array(1) {
21036 +  ["key"]=>
21037 +  string(4) "key2"
21038 +}
21039 +string(4) "key3"
21040 +array(1) {
21041 +  ["key"]=>
21042 +  string(4) "key3"
21043 +}
21044 +string(4) "key4"
21045 +array(1) {
21046 +  ["key"]=>
21047 +  string(4) "key4"
21048 +}
21049 +string(4) "key5"
21050 +array(1) {
21051 +  ["key"]=>
21052 +  string(4) "key5"
21053 +}
21054 +string(4) "key6"
21055 +array(1) {
21056 +  ["key"]=>
21057 +  string(4) "key6"
21058 +}
21059 +string(4) "key7"
21060 +array(1) {
21061 +  ["key"]=>
21062 +  string(4) "key7"
21063 +}
21064 +string(4) "key8"
21065 +array(1) {
21066 +  ["key"]=>
21067 +  string(4) "key8"
21068 +}
21069 +string(4) "key9"
21070 +array(1) {
21071 +  ["key"]=>
21072 +  string(4) "key9"
21073 +}
21074 +============================
21075 +
21076 +IT #2
21077 +============================
21078 +string(5) "key10"
21079 +array(0) {
21080 +}
21081 +string(4) "key0"
21082 +array(0) {
21083 +}
21084 +string(4) "key1"
21085 +array(0) {
21086 +}
21087 +string(4) "key2"
21088 +array(0) {
21089 +}
21090 +string(4) "key3"
21091 +array(0) {
21092 +}
21093 +string(4) "key4"
21094 +array(0) {
21095 +}
21096 +string(4) "key5"
21097 +array(0) {
21098 +}
21099 +string(4) "key6"
21100 +array(0) {
21101 +}
21102 +string(4) "key7"
21103 +array(0) {
21104 +}
21105 +string(4) "key8"
21106 +array(0) {
21107 +}
21108 +string(4) "key9"
21109 +array(0) {
21110 +}
21111 +============================
21112 +
21113 +IT #3
21114 +============================
21115 +string(5) "key10"
21116 +array(0) {
21117 +}
21118 +string(4) "key0"
21119 +array(0) {
21120 +}
21121 +string(4) "key1"
21122 +array(0) {
21123 +}
21124 +string(4) "key2"
21125 +array(0) {
21126 +}
21127 +string(4) "key3"
21128 +array(0) {
21129 +}
21130 +string(4) "key4"
21131 +array(0) {
21132 +}
21133 +string(4) "key5"
21134 +array(0) {
21135 +}
21136 +string(4) "key6"
21137 +array(0) {
21138 +}
21139 +string(4) "key7"
21140 +array(0) {
21141 +}
21142 +string(4) "key8"
21143 +array(0) {
21144 +}
21145 +string(4) "key9"
21146 +array(0) {
21147 +}
21148 +============================
21149 +
21150 +IT #4
21151 +============================
21152 +string(5) "key10"
21153 +array(0) {
21154 +}
21155 +string(4) "key0"
21156 +array(0) {
21157 +}
21158 +string(4) "key1"
21159 +array(0) {
21160 +}
21161 +string(4) "key2"
21162 +array(0) {
21163 +}
21164 +string(4) "key3"
21165 +array(0) {
21166 +}
21167 +string(4) "key4"
21168 +array(0) {
21169 +}
21170 +string(4) "key5"
21171 +array(0) {
21172 +}
21173 +string(4) "key6"
21174 +array(0) {
21175 +}
21176 +string(4) "key7"
21177 +array(0) {
21178 +}
21179 +string(4) "key8"
21180 +array(0) {
21181 +}
21182 +string(4) "key9"
21183 +array(0) {
21184 +}
21185 +============================
21186 +
21187 +IT #5
21188 +============================
21189 +string(5) "key10"
21190 +array(1) {
21191 +  ["value"]=>
21192 +  string(7) "value10"
21193 +}
21194 +string(4) "key0"
21195 +array(1) {
21196 +  ["value"]=>
21197 +  string(6) "value0"
21198 +}
21199 +string(4) "key1"
21200 +array(1) {
21201 +  ["value"]=>
21202 +  string(6) "value1"
21203 +}
21204 +string(4) "key2"
21205 +array(1) {
21206 +  ["value"]=>
21207 +  string(6) "value2"
21208 +}
21209 +string(4) "key3"
21210 +array(1) {
21211 +  ["value"]=>
21212 +  string(6) "value3"
21213 +}
21214 +string(4) "key4"
21215 +array(1) {
21216 +  ["value"]=>
21217 +  string(6) "value4"
21218 +}
21219 +string(4) "key5"
21220 +array(1) {
21221 +  ["value"]=>
21222 +  string(6) "value5"
21223 +}
21224 +string(4) "key6"
21225 +array(1) {
21226 +  ["value"]=>
21227 +  string(6) "value6"
21228 +}
21229 +string(4) "key7"
21230 +array(1) {
21231 +  ["value"]=>
21232 +  string(6) "value7"
21233 +}
21234 +string(4) "key8"
21235 +array(1) {
21236 +  ["value"]=>
21237 +  string(6) "value8"
21238 +}
21239 +string(4) "key9"
21240 +array(1) {
21241 +  ["value"]=>
21242 +  string(6) "value9"
21243 +}
21244 +============================
21245 +
21246 +IT #6
21247 +============================
21248 +string(5) "key10"
21249 +array(0) {
21250 +}
21251 +string(4) "key0"
21252 +array(0) {
21253 +}
21254 +string(4) "key1"
21255 +array(0) {
21256 +}
21257 +string(4) "key2"
21258 +array(0) {
21259 +}
21260 +string(4) "key3"
21261 +array(0) {
21262 +}
21263 +string(4) "key4"
21264 +array(0) {
21265 +}
21266 +string(4) "key5"
21267 +array(0) {
21268 +}
21269 +string(4) "key6"
21270 +array(0) {
21271 +}
21272 +string(4) "key7"
21273 +array(0) {
21274 +}
21275 +string(4) "key8"
21276 +array(0) {
21277 +}
21278 +string(4) "key9"
21279 +array(0) {
21280 +}
21281 +============================
21282 +
21283 +IT #7
21284 +============================
21285 +string(5) "key10"
21286 +array(1) {
21287 +  ["num_hits"]=>
21288 +  int(0)
21289 +}
21290 +string(4) "key0"
21291 +array(1) {
21292 +  ["num_hits"]=>
21293 +  int(0)
21294 +}
21295 +string(4) "key1"
21296 +array(1) {
21297 +  ["num_hits"]=>
21298 +  int(0)
21299 +}
21300 +string(4) "key2"
21301 +array(1) {
21302 +  ["num_hits"]=>
21303 +  int(0)
21304 +}
21305 +string(4) "key3"
21306 +array(1) {
21307 +  ["num_hits"]=>
21308 +  int(0)
21309 +}
21310 +string(4) "key4"
21311 +array(1) {
21312 +  ["num_hits"]=>
21313 +  int(0)
21314 +}
21315 +string(4) "key5"
21316 +array(1) {
21317 +  ["num_hits"]=>
21318 +  int(0)
21319 +}
21320 +string(4) "key6"
21321 +array(1) {
21322 +  ["num_hits"]=>
21323 +  int(0)
21324 +}
21325 +string(4) "key7"
21326 +array(1) {
21327 +  ["num_hits"]=>
21328 +  int(0)
21329 +}
21330 +string(4) "key8"
21331 +array(1) {
21332 +  ["num_hits"]=>
21333 +  int(0)
21334 +}
21335 +string(4) "key9"
21336 +array(1) {
21337 +  ["num_hits"]=>
21338 +  int(0)
21339 +}
21340 +============================
21341 +
21342 +IT #8
21343 +============================
21344 +string(5) "key10"
21345 +array(1) {
21346 +  ["mtime"]=>
21347 +  int(%d)
21348 +}
21349 +string(4) "key0"
21350 +array(1) {
21351 +  ["mtime"]=>
21352 +  int(%d)
21353 +}
21354 +string(4) "key1"
21355 +array(1) {
21356 +  ["mtime"]=>
21357 +  int(%d)
21358 +}
21359 +string(4) "key2"
21360 +array(1) {
21361 +  ["mtime"]=>
21362 +  int(%d)
21363 +}
21364 +string(4) "key3"
21365 +array(1) {
21366 +  ["mtime"]=>
21367 +  int(%d)
21368 +}
21369 +string(4) "key4"
21370 +array(1) {
21371 +  ["mtime"]=>
21372 +  int(%d)
21373 +}
21374 +string(4) "key5"
21375 +array(1) {
21376 +  ["mtime"]=>
21377 +  int(%d)
21378 +}
21379 +string(4) "key6"
21380 +array(1) {
21381 +  ["mtime"]=>
21382 +  int(%d)
21383 +}
21384 +string(4) "key7"
21385 +array(1) {
21386 +  ["mtime"]=>
21387 +  int(%d)
21388 +}
21389 +string(4) "key8"
21390 +array(1) {
21391 +  ["mtime"]=>
21392 +  int(%d)
21393 +}
21394 +string(4) "key9"
21395 +array(1) {
21396 +  ["mtime"]=>
21397 +  int(%d)
21398 +}
21399 +============================
21400 +
21401 +IT #9
21402 +============================
21403 +string(5) "key10"
21404 +array(1) {
21405 +  ["creation_time"]=>
21406 +  int(%d)
21407 +}
21408 +string(4) "key0"
21409 +array(1) {
21410 +  ["creation_time"]=>
21411 +  int(%d)
21412 +}
21413 +string(4) "key1"
21414 +array(1) {
21415 +  ["creation_time"]=>
21416 +  int(%d)
21417 +}
21418 +string(4) "key2"
21419 +array(1) {
21420 +  ["creation_time"]=>
21421 +  int(%d)
21422 +}
21423 +string(4) "key3"
21424 +array(1) {
21425 +  ["creation_time"]=>
21426 +  int(%d)
21427 +}
21428 +string(4) "key4"
21429 +array(1) {
21430 +  ["creation_time"]=>
21431 +  int(%d)
21432 +}
21433 +string(4) "key5"
21434 +array(1) {
21435 +  ["creation_time"]=>
21436 +  int(%d)
21437 +}
21438 +string(4) "key6"
21439 +array(1) {
21440 +  ["creation_time"]=>
21441 +  int(%d)
21442 +}
21443 +string(4) "key7"
21444 +array(1) {
21445 +  ["creation_time"]=>
21446 +  int(%d)
21447 +}
21448 +string(4) "key8"
21449 +array(1) {
21450 +  ["creation_time"]=>
21451 +  int(%d)
21452 +}
21453 +string(4) "key9"
21454 +array(1) {
21455 +  ["creation_time"]=>
21456 +  int(%d)
21457 +}
21458 +============================
21459 +
21460 +IT #10
21461 +============================
21462 +string(5) "key10"
21463 +array(1) {
21464 +  ["deletion_time"]=>
21465 +  int(0)
21466 +}
21467 +string(4) "key0"
21468 +array(1) {
21469 +  ["deletion_time"]=>
21470 +  int(0)
21471 +}
21472 +string(4) "key1"
21473 +array(1) {
21474 +  ["deletion_time"]=>
21475 +  int(0)
21476 +}
21477 +string(4) "key2"
21478 +array(1) {
21479 +  ["deletion_time"]=>
21480 +  int(0)
21481 +}
21482 +string(4) "key3"
21483 +array(1) {
21484 +  ["deletion_time"]=>
21485 +  int(0)
21486 +}
21487 +string(4) "key4"
21488 +array(1) {
21489 +  ["deletion_time"]=>
21490 +  int(0)
21491 +}
21492 +string(4) "key5"
21493 +array(1) {
21494 +  ["deletion_time"]=>
21495 +  int(0)
21496 +}
21497 +string(4) "key6"
21498 +array(1) {
21499 +  ["deletion_time"]=>
21500 +  int(0)
21501 +}
21502 +string(4) "key7"
21503 +array(1) {
21504 +  ["deletion_time"]=>
21505 +  int(0)
21506 +}
21507 +string(4) "key8"
21508 +array(1) {
21509 +  ["deletion_time"]=>
21510 +  int(0)
21511 +}
21512 +string(4) "key9"
21513 +array(1) {
21514 +  ["deletion_time"]=>
21515 +  int(0)
21516 +}
21517 +============================
21518 +
21519 +IT #11
21520 +============================
21521 +string(5) "key10"
21522 +array(1) {
21523 +  ["access_time"]=>
21524 +  int(%d)
21525 +}
21526 +string(4) "key0"
21527 +array(1) {
21528 +  ["access_time"]=>
21529 +  int(%d)
21530 +}
21531 +string(4) "key1"
21532 +array(1) {
21533 +  ["access_time"]=>
21534 +  int(%d)
21535 +}
21536 +string(4) "key2"
21537 +array(1) {
21538 +  ["access_time"]=>
21539 +  int(%d)
21540 +}
21541 +string(4) "key3"
21542 +array(1) {
21543 +  ["access_time"]=>
21544 +  int(%d)
21545 +}
21546 +string(4) "key4"
21547 +array(1) {
21548 +  ["access_time"]=>
21549 +  int(%d)
21550 +}
21551 +string(4) "key5"
21552 +array(1) {
21553 +  ["access_time"]=>
21554 +  int(%d)
21555 +}
21556 +string(4) "key6"
21557 +array(1) {
21558 +  ["access_time"]=>
21559 +  int(%d)
21560 +}
21561 +string(4) "key7"
21562 +array(1) {
21563 +  ["access_time"]=>
21564 +  int(%d)
21565 +}
21566 +string(4) "key8"
21567 +array(1) {
21568 +  ["access_time"]=>
21569 +  int(%d)
21570 +}
21571 +string(4) "key9"
21572 +array(1) {
21573 +  ["access_time"]=>
21574 +  int(%d)
21575 +}
21576 +============================
21577 +
21578 +IT #12
21579 +============================
21580 +string(5) "key10"
21581 +array(1) {
21582 +  ["ref_count"]=>
21583 +  int(0)
21584 +}
21585 +string(4) "key0"
21586 +array(1) {
21587 +  ["ref_count"]=>
21588 +  int(0)
21589 +}
21590 +string(4) "key1"
21591 +array(1) {
21592 +  ["ref_count"]=>
21593 +  int(0)
21594 +}
21595 +string(4) "key2"
21596 +array(1) {
21597 +  ["ref_count"]=>
21598 +  int(0)
21599 +}
21600 +string(4) "key3"
21601 +array(1) {
21602 +  ["ref_count"]=>
21603 +  int(0)
21604 +}
21605 +string(4) "key4"
21606 +array(1) {
21607 +  ["ref_count"]=>
21608 +  int(0)
21609 +}
21610 +string(4) "key5"
21611 +array(1) {
21612 +  ["ref_count"]=>
21613 +  int(0)
21614 +}
21615 +string(4) "key6"
21616 +array(1) {
21617 +  ["ref_count"]=>
21618 +  int(0)
21619 +}
21620 +string(4) "key7"
21621 +array(1) {
21622 +  ["ref_count"]=>
21623 +  int(0)
21624 +}
21625 +string(4) "key8"
21626 +array(1) {
21627 +  ["ref_count"]=>
21628 +  int(0)
21629 +}
21630 +string(4) "key9"
21631 +array(1) {
21632 +  ["ref_count"]=>
21633 +  int(0)
21634 +}
21635 +============================
21636 +
21637 +IT #13
21638 +============================
21639 +string(5) "key10"
21640 +array(1) {
21641 +  ["mem_size"]=>
21642 +  int(%d)
21643 +}
21644 +string(4) "key0"
21645 +array(1) {
21646 +  ["mem_size"]=>
21647 +  int(%d)
21648 +}
21649 +string(4) "key1"
21650 +array(1) {
21651 +  ["mem_size"]=>
21652 +  int(%d)
21653 +}
21654 +string(4) "key2"
21655 +array(1) {
21656 +  ["mem_size"]=>
21657 +  int(%d)
21658 +}
21659 +string(4) "key3"
21660 +array(1) {
21661 +  ["mem_size"]=>
21662 +  int(%d)
21663 +}
21664 +string(4) "key4"
21665 +array(1) {
21666 +  ["mem_size"]=>
21667 +  int(%d)
21668 +}
21669 +string(4) "key5"
21670 +array(1) {
21671 +  ["mem_size"]=>
21672 +  int(%d)
21673 +}
21674 +string(4) "key6"
21675 +array(1) {
21676 +  ["mem_size"]=>
21677 +  int(%d)
21678 +}
21679 +string(4) "key7"
21680 +array(1) {
21681 +  ["mem_size"]=>
21682 +  int(%d)
21683 +}
21684 +string(4) "key8"
21685 +array(1) {
21686 +  ["mem_size"]=>
21687 +  int(%d)
21688 +}
21689 +string(4) "key9"
21690 +array(1) {
21691 +  ["mem_size"]=>
21692 +  int(%d)
21693 +}
21694 +============================
21695 +
21696 +IT #14
21697 +============================
21698 +string(5) "key10"
21699 +array(1) {
21700 +  ["ttl"]=>
21701 +  int(0)
21702 +}
21703 +string(4) "key0"
21704 +array(1) {
21705 +  ["ttl"]=>
21706 +  int(0)
21707 +}
21708 +string(4) "key1"
21709 +array(1) {
21710 +  ["ttl"]=>
21711 +  int(0)
21712 +}
21713 +string(4) "key2"
21714 +array(1) {
21715 +  ["ttl"]=>
21716 +  int(0)
21717 +}
21718 +string(4) "key3"
21719 +array(1) {
21720 +  ["ttl"]=>
21721 +  int(0)
21722 +}
21723 +string(4) "key4"
21724 +array(1) {
21725 +  ["ttl"]=>
21726 +  int(0)
21727 +}
21728 +string(4) "key5"
21729 +array(1) {
21730 +  ["ttl"]=>
21731 +  int(0)
21732 +}
21733 +string(4) "key6"
21734 +array(1) {
21735 +  ["ttl"]=>
21736 +  int(0)
21737 +}
21738 +string(4) "key7"
21739 +array(1) {
21740 +  ["ttl"]=>
21741 +  int(0)
21742 +}
21743 +string(4) "key8"
21744 +array(1) {
21745 +  ["ttl"]=>
21746 +  int(0)
21747 +}
21748 +string(4) "key9"
21749 +array(1) {
21750 +  ["ttl"]=>
21751 +  int(0)
21752 +}
21753 +============================
21754 +
21755 +IT #15
21756 +============================
21757 +string(5) "key10"
21758 +array(0) {
21759 +}
21760 +string(4) "key0"
21761 +array(0) {
21762 +}
21763 +string(4) "key1"
21764 +array(0) {
21765 +}
21766 +string(4) "key2"
21767 +array(0) {
21768 +}
21769 +string(4) "key3"
21770 +array(0) {
21771 +}
21772 +string(4) "key4"
21773 +array(0) {
21774 +}
21775 +string(4) "key5"
21776 +array(0) {
21777 +}
21778 +string(4) "key6"
21779 +array(0) {
21780 +}
21781 +string(4) "key7"
21782 +array(0) {
21783 +}
21784 +string(4) "key8"
21785 +array(0) {
21786 +}
21787 +string(4) "key9"
21788 +array(0) {
21789 +}
21790 +============================
21791 +
21792 +IT #16
21793 +============================
21794 +string(5) "key10"
21795 +array(11) {
21796 +  ["type"]=>
21797 +  string(4) "user"
21798 +  ["key"]=>
21799 +  string(5) "key10"
21800 +  ["value"]=>
21801 +  string(7) "value10"
21802 +  ["num_hits"]=>
21803 +  int(0)
21804 +  ["mtime"]=>
21805 +  int(%d)
21806 +  ["creation_time"]=>
21807 +  int(%d)
21808 +  ["deletion_time"]=>
21809 +  int(0)
21810 +  ["access_time"]=>
21811 +  int(%d)
21812 +  ["ref_count"]=>
21813 +  int(0)
21814 +  ["mem_size"]=>
21815 +  int(%d)
21816 +  ["ttl"]=>
21817 +  int(0)
21818 +}
21819 +string(4) "key0"
21820 +array(11) {
21821 +  ["type"]=>
21822 +  string(4) "user"
21823 +  ["key"]=>
21824 +  string(4) "key0"
21825 +  ["value"]=>
21826 +  string(6) "value0"
21827 +  ["num_hits"]=>
21828 +  int(0)
21829 +  ["mtime"]=>
21830 +  int(%d)
21831 +  ["creation_time"]=>
21832 +  int(%d)
21833 +  ["deletion_time"]=>
21834 +  int(0)
21835 +  ["access_time"]=>
21836 +  int(%d)
21837 +  ["ref_count"]=>
21838 +  int(0)
21839 +  ["mem_size"]=>
21840 +  int(%d)
21841 +  ["ttl"]=>
21842 +  int(0)
21843 +}
21844 +string(4) "key1"
21845 +array(11) {
21846 +  ["type"]=>
21847 +  string(4) "user"
21848 +  ["key"]=>
21849 +  string(4) "key1"
21850 +  ["value"]=>
21851 +  string(6) "value1"
21852 +  ["num_hits"]=>
21853 +  int(0)
21854 +  ["mtime"]=>
21855 +  int(%d)
21856 +  ["creation_time"]=>
21857 +  int(%d)
21858 +  ["deletion_time"]=>
21859 +  int(0)
21860 +  ["access_time"]=>
21861 +  int(%d)
21862 +  ["ref_count"]=>
21863 +  int(0)
21864 +  ["mem_size"]=>
21865 +  int(%d)
21866 +  ["ttl"]=>
21867 +  int(0)
21868 +}
21869 +string(4) "key2"
21870 +array(11) {
21871 +  ["type"]=>
21872 +  string(4) "user"
21873 +  ["key"]=>
21874 +  string(4) "key2"
21875 +  ["value"]=>
21876 +  string(6) "value2"
21877 +  ["num_hits"]=>
21878 +  int(0)
21879 +  ["mtime"]=>
21880 +  int(%d)
21881 +  ["creation_time"]=>
21882 +  int(%d)
21883 +  ["deletion_time"]=>
21884 +  int(0)
21885 +  ["access_time"]=>
21886 +  int(%d)
21887 +  ["ref_count"]=>
21888 +  int(0)
21889 +  ["mem_size"]=>
21890 +  int(%d)
21891 +  ["ttl"]=>
21892 +  int(0)
21893 +}
21894 +string(4) "key3"
21895 +array(11) {
21896 +  ["type"]=>
21897 +  string(4) "user"
21898 +  ["key"]=>
21899 +  string(4) "key3"
21900 +  ["value"]=>
21901 +  string(6) "value3"
21902 +  ["num_hits"]=>
21903 +  int(0)
21904 +  ["mtime"]=>
21905 +  int(%d)
21906 +  ["creation_time"]=>
21907 +  int(%d)
21908 +  ["deletion_time"]=>
21909 +  int(0)
21910 +  ["access_time"]=>
21911 +  int(%d)
21912 +  ["ref_count"]=>
21913 +  int(0)
21914 +  ["mem_size"]=>
21915 +  int(%d)
21916 +  ["ttl"]=>
21917 +  int(0)
21918 +}
21919 +string(4) "key4"
21920 +array(11) {
21921 +  ["type"]=>
21922 +  string(4) "user"
21923 +  ["key"]=>
21924 +  string(4) "key4"
21925 +  ["value"]=>
21926 +  string(6) "value4"
21927 +  ["num_hits"]=>
21928 +  int(0)
21929 +  ["mtime"]=>
21930 +  int(%d)
21931 +  ["creation_time"]=>
21932 +  int(%d)
21933 +  ["deletion_time"]=>
21934 +  int(0)
21935 +  ["access_time"]=>
21936 +  int(%d)
21937 +  ["ref_count"]=>
21938 +  int(0)
21939 +  ["mem_size"]=>
21940 +  int(%d)
21941 +  ["ttl"]=>
21942 +  int(0)
21943 +}
21944 +string(4) "key5"
21945 +array(11) {
21946 +  ["type"]=>
21947 +  string(4) "user"
21948 +  ["key"]=>
21949 +  string(4) "key5"
21950 +  ["value"]=>
21951 +  string(6) "value5"
21952 +  ["num_hits"]=>
21953 +  int(0)
21954 +  ["mtime"]=>
21955 +  int(%d)
21956 +  ["creation_time"]=>
21957 +  int(%d)
21958 +  ["deletion_time"]=>
21959 +  int(0)
21960 +  ["access_time"]=>
21961 +  int(%d)
21962 +  ["ref_count"]=>
21963 +  int(0)
21964 +  ["mem_size"]=>
21965 +  int(%d)
21966 +  ["ttl"]=>
21967 +  int(0)
21968 +}
21969 +string(4) "key6"
21970 +array(11) {
21971 +  ["type"]=>
21972 +  string(4) "user"
21973 +  ["key"]=>
21974 +  string(4) "key6"
21975 +  ["value"]=>
21976 +  string(6) "value6"
21977 +  ["num_hits"]=>
21978 +  int(0)
21979 +  ["mtime"]=>
21980 +  int(%d)
21981 +  ["creation_time"]=>
21982 +  int(%d)
21983 +  ["deletion_time"]=>
21984 +  int(0)
21985 +  ["access_time"]=>
21986 +  int(%d)
21987 +  ["ref_count"]=>
21988 +  int(0)
21989 +  ["mem_size"]=>
21990 +  int(%d)
21991 +  ["ttl"]=>
21992 +  int(0)
21993 +}
21994 +string(4) "key7"
21995 +array(11) {
21996 +  ["type"]=>
21997 +  string(4) "user"
21998 +  ["key"]=>
21999 +  string(4) "key7"
22000 +  ["value"]=>
22001 +  string(6) "value7"
22002 +  ["num_hits"]=>
22003 +  int(0)
22004 +  ["mtime"]=>
22005 +  int(%d)
22006 +  ["creation_time"]=>
22007 +  int(%d)
22008 +  ["deletion_time"]=>
22009 +  int(0)
22010 +  ["access_time"]=>
22011 +  int(%d)
22012 +  ["ref_count"]=>
22013 +  int(0)
22014 +  ["mem_size"]=>
22015 +  int(%d)
22016 +  ["ttl"]=>
22017 +  int(0)
22018 +}
22019 +string(4) "key8"
22020 +array(11) {
22021 +  ["type"]=>
22022 +  string(4) "user"
22023 +  ["key"]=>
22024 +  string(4) "key8"
22025 +  ["value"]=>
22026 +  string(6) "value8"
22027 +  ["num_hits"]=>
22028 +  int(0)
22029 +  ["mtime"]=>
22030 +  int(%d)
22031 +  ["creation_time"]=>
22032 +  int(%d)
22033 +  ["deletion_time"]=>
22034 +  int(0)
22035 +  ["access_time"]=>
22036 +  int(%d)
22037 +  ["ref_count"]=>
22038 +  int(0)
22039 +  ["mem_size"]=>
22040 +  int(%d)
22041 +  ["ttl"]=>
22042 +  int(0)
22043 +}
22044 +string(4) "key9"
22045 +array(11) {
22046 +  ["type"]=>
22047 +  string(4) "user"
22048 +  ["key"]=>
22049 +  string(4) "key9"
22050 +  ["value"]=>
22051 +  string(6) "value9"
22052 +  ["num_hits"]=>
22053 +  int(0)
22054 +  ["mtime"]=>
22055 +  int(%d)
22056 +  ["creation_time"]=>
22057 +  int(%d)
22058 +  ["deletion_time"]=>
22059 +  int(0)
22060 +  ["access_time"]=>
22061 +  int(%d)
22062 +  ["ref_count"]=>
22063 +  int(0)
22064 +  ["mem_size"]=>
22065 +  int(%d)
22066 +  ["ttl"]=>
22067 +  int(0)
22068 +}
22069 +============================
22070 +
22071 +IT #17
22072 +============================
22073 +string(5) "key10"
22074 +array(10) {
22075 +  ["type"]=>
22076 +  string(4) "user"
22077 +  ["key"]=>
22078 +  string(5) "key10"
22079 +  ["value"]=>
22080 +  string(7) "value10"
22081 +  ["num_hits"]=>
22082 +  int(0)
22083 +  ["mtime"]=>
22084 +  int(%d)
22085 +  ["creation_time"]=>
22086 +  int(%d)
22087 +  ["deletion_time"]=>
22088 +  int(0)
22089 +  ["access_time"]=>
22090 +  int(%d)
22091 +  ["ref_count"]=>
22092 +  int(0)
22093 +  ["mem_size"]=>
22094 +  int(%d)
22095 +}
22096 +string(4) "key0"
22097 +array(10) {
22098 +  ["type"]=>
22099 +  string(4) "user"
22100 +  ["key"]=>
22101 +  string(4) "key0"
22102 +  ["value"]=>
22103 +  string(6) "value0"
22104 +  ["num_hits"]=>
22105 +  int(0)
22106 +  ["mtime"]=>
22107 +  int(%d)
22108 +  ["creation_time"]=>
22109 +  int(%d)
22110 +  ["deletion_time"]=>
22111 +  int(0)
22112 +  ["access_time"]=>
22113 +  int(%d)
22114 +  ["ref_count"]=>
22115 +  int(0)
22116 +  ["mem_size"]=>
22117 +  int(%d)
22118 +}
22119 +string(4) "key1"
22120 +array(10) {
22121 +  ["type"]=>
22122 +  string(4) "user"
22123 +  ["key"]=>
22124 +  string(4) "key1"
22125 +  ["value"]=>
22126 +  string(6) "value1"
22127 +  ["num_hits"]=>
22128 +  int(0)
22129 +  ["mtime"]=>
22130 +  int(%d)
22131 +  ["creation_time"]=>
22132 +  int(%d)
22133 +  ["deletion_time"]=>
22134 +  int(0)
22135 +  ["access_time"]=>
22136 +  int(%d)
22137 +  ["ref_count"]=>
22138 +  int(0)
22139 +  ["mem_size"]=>
22140 +  int(%d)
22141 +}
22142 +string(4) "key2"
22143 +array(10) {
22144 +  ["type"]=>
22145 +  string(4) "user"
22146 +  ["key"]=>
22147 +  string(4) "key2"
22148 +  ["value"]=>
22149 +  string(6) "value2"
22150 +  ["num_hits"]=>
22151 +  int(0)
22152 +  ["mtime"]=>
22153 +  int(%d)
22154 +  ["creation_time"]=>
22155 +  int(%d)
22156 +  ["deletion_time"]=>
22157 +  int(0)
22158 +  ["access_time"]=>
22159 +  int(%d)
22160 +  ["ref_count"]=>
22161 +  int(0)
22162 +  ["mem_size"]=>
22163 +  int(%d)
22164 +}
22165 +string(4) "key3"
22166 +array(10) {
22167 +  ["type"]=>
22168 +  string(4) "user"
22169 +  ["key"]=>
22170 +  string(4) "key3"
22171 +  ["value"]=>
22172 +  string(6) "value3"
22173 +  ["num_hits"]=>
22174 +  int(0)
22175 +  ["mtime"]=>
22176 +  int(%d)
22177 +  ["creation_time"]=>
22178 +  int(%d)
22179 +  ["deletion_time"]=>
22180 +  int(0)
22181 +  ["access_time"]=>
22182 +  int(%d)
22183 +  ["ref_count"]=>
22184 +  int(0)
22185 +  ["mem_size"]=>
22186 +  int(%d)
22187 +}
22188 +string(4) "key4"
22189 +array(10) {
22190 +  ["type"]=>
22191 +  string(4) "user"
22192 +  ["key"]=>
22193 +  string(4) "key4"
22194 +  ["value"]=>
22195 +  string(6) "value4"
22196 +  ["num_hits"]=>
22197 +  int(0)
22198 +  ["mtime"]=>
22199 +  int(%d)
22200 +  ["creation_time"]=>
22201 +  int(%d)
22202 +  ["deletion_time"]=>
22203 +  int(0)
22204 +  ["access_time"]=>
22205 +  int(%d)
22206 +  ["ref_count"]=>
22207 +  int(0)
22208 +  ["mem_size"]=>
22209 +  int(%d)
22210 +}
22211 +string(4) "key5"
22212 +array(10) {
22213 +  ["type"]=>
22214 +  string(4) "user"
22215 +  ["key"]=>
22216 +  string(4) "key5"
22217 +  ["value"]=>
22218 +  string(6) "value5"
22219 +  ["num_hits"]=>
22220 +  int(0)
22221 +  ["mtime"]=>
22222 +  int(%d)
22223 +  ["creation_time"]=>
22224 +  int(%d)
22225 +  ["deletion_time"]=>
22226 +  int(0)
22227 +  ["access_time"]=>
22228 +  int(%d)
22229 +  ["ref_count"]=>
22230 +  int(0)
22231 +  ["mem_size"]=>
22232 +  int(%d)
22233 +}
22234 +string(4) "key6"
22235 +array(10) {
22236 +  ["type"]=>
22237 +  string(4) "user"
22238 +  ["key"]=>
22239 +  string(4) "key6"
22240 +  ["value"]=>
22241 +  string(6) "value6"
22242 +  ["num_hits"]=>
22243 +  int(0)
22244 +  ["mtime"]=>
22245 +  int(%d)
22246 +  ["creation_time"]=>
22247 +  int(%d)
22248 +  ["deletion_time"]=>
22249 +  int(0)
22250 +  ["access_time"]=>
22251 +  int(%d)
22252 +  ["ref_count"]=>
22253 +  int(0)
22254 +  ["mem_size"]=>
22255 +  int(%d)
22256 +}
22257 +string(4) "key7"
22258 +array(10) {
22259 +  ["type"]=>
22260 +  string(4) "user"
22261 +  ["key"]=>
22262 +  string(4) "key7"
22263 +  ["value"]=>
22264 +  string(6) "value7"
22265 +  ["num_hits"]=>
22266 +  int(0)
22267 +  ["mtime"]=>
22268 +  int(%d)
22269 +  ["creation_time"]=>
22270 +  int(%d)
22271 +  ["deletion_time"]=>
22272 +  int(0)
22273 +  ["access_time"]=>
22274 +  int(%d)
22275 +  ["ref_count"]=>
22276 +  int(0)
22277 +  ["mem_size"]=>
22278 +  int(%d)
22279 +}
22280 +string(4) "key8"
22281 +array(10) {
22282 +  ["type"]=>
22283 +  string(4) "user"
22284 +  ["key"]=>
22285 +  string(4) "key8"
22286 +  ["value"]=>
22287 +  string(6) "value8"
22288 +  ["num_hits"]=>
22289 +  int(0)
22290 +  ["mtime"]=>
22291 +  int(%d)
22292 +  ["creation_time"]=>
22293 +  int(%d)
22294 +  ["deletion_time"]=>
22295 +  int(0)
22296 +  ["access_time"]=>
22297 +  int(%d)
22298 +  ["ref_count"]=>
22299 +  int(0)
22300 +  ["mem_size"]=>
22301 +  int(%d)
22302 +}
22303 +string(4) "key9"
22304 +array(10) {
22305 +  ["type"]=>
22306 +  string(4) "user"
22307 +  ["key"]=>
22308 +  string(4) "key9"
22309 +  ["value"]=>
22310 +  string(6) "value9"
22311 +  ["num_hits"]=>
22312 +  int(0)
22313 +  ["mtime"]=>
22314 +  int(%d)
22315 +  ["creation_time"]=>
22316 +  int(%d)
22317 +  ["deletion_time"]=>
22318 +  int(0)
22319 +  ["access_time"]=>
22320 +  int(%d)
22321 +  ["ref_count"]=>
22322 +  int(0)
22323 +  ["mem_size"]=>
22324 +  int(%d)
22325 +}
22326 +============================
22327 +
22328 +IT #18
22329 +============================
22330 +string(5) "key10"
22331 +array(3) {
22332 +  ["key"]=>
22333 +  string(5) "key10"
22334 +  ["num_hits"]=>
22335 +  int(0)
22336 +  ["mem_size"]=>
22337 +  int(%d)
22338 +}
22339 +string(4) "key0"
22340 +array(3) {
22341 +  ["key"]=>
22342 +  string(4) "key0"
22343 +  ["num_hits"]=>
22344 +  int(0)
22345 +  ["mem_size"]=>
22346 +  int(%d)
22347 +}
22348 +string(4) "key1"
22349 +array(3) {
22350 +  ["key"]=>
22351 +  string(4) "key1"
22352 +  ["num_hits"]=>
22353 +  int(0)
22354 +  ["mem_size"]=>
22355 +  int(%d)
22356 +}
22357 +string(4) "key2"
22358 +array(3) {
22359 +  ["key"]=>
22360 +  string(4) "key2"
22361 +  ["num_hits"]=>
22362 +  int(0)
22363 +  ["mem_size"]=>
22364 +  int(%d)
22365 +}
22366 +string(4) "key3"
22367 +array(3) {
22368 +  ["key"]=>
22369 +  string(4) "key3"
22370 +  ["num_hits"]=>
22371 +  int(0)
22372 +  ["mem_size"]=>
22373 +  int(%d)
22374 +}
22375 +string(4) "key4"
22376 +array(3) {
22377 +  ["key"]=>
22378 +  string(4) "key4"
22379 +  ["num_hits"]=>
22380 +  int(0)
22381 +  ["mem_size"]=>
22382 +  int(%d)
22383 +}
22384 +string(4) "key5"
22385 +array(3) {
22386 +  ["key"]=>
22387 +  string(4) "key5"
22388 +  ["num_hits"]=>
22389 +  int(0)
22390 +  ["mem_size"]=>
22391 +  int(%d)
22392 +}
22393 +string(4) "key6"
22394 +array(3) {
22395 +  ["key"]=>
22396 +  string(4) "key6"
22397 +  ["num_hits"]=>
22398 +  int(0)
22399 +  ["mem_size"]=>
22400 +  int(%d)
22401 +}
22402 +string(4) "key7"
22403 +array(3) {
22404 +  ["key"]=>
22405 +  string(4) "key7"
22406 +  ["num_hits"]=>
22407 +  int(0)
22408 +  ["mem_size"]=>
22409 +  int(%d)
22410 +}
22411 +string(4) "key8"
22412 +array(3) {
22413 +  ["key"]=>
22414 +  string(4) "key8"
22415 +  ["num_hits"]=>
22416 +  int(0)
22417 +  ["mem_size"]=>
22418 +  int(%d)
22419 +}
22420 +string(4) "key9"
22421 +array(3) {
22422 +  ["key"]=>
22423 +  string(4) "key9"
22424 +  ["num_hits"]=>
22425 +  int(0)
22426 +  ["mem_size"]=>
22427 +  int(%d)
22428 +}
22429 +============================
22430 +
22431 +===DONE===
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
22435 @@ -0,0 +1,36 @@
22436 +--TEST--
22437 +APC: APCIterator Overwriting the ctor
22438 +--SKIPIF--
22439 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
22440 +--INI--
22441 +apc.enabled=1
22442 +apc.enable_cli=1
22443 +--FILE--
22444 +<?php
22445 +class foobar extends APCIterator {
22446 +       public function __construct() {}
22447 +}
22448 +$obj = new foobar;
22449 +var_dump(
22450 +       $obj->rewind(),
22451 +       $obj->current(),
22452 +       $obj->key(),
22453 +       $obj->next(),
22454 +       $obj->valid(),
22455 +       $obj->getTotalHits(),
22456 +       $obj->getTotalSize(),
22457 +       $obj->getTotalCount(),
22458 +       apc_delete($obj)
22459 +);
22460 +?>
22461 +--EXPECTF--
22462 +bool(false)
22463 +bool(false)
22464 +bool(false)
22465 +bool(false)
22466 +bool(false)
22467 +bool(false)
22468 +bool(false)
22469 +bool(false)
22470 +bool(false)
22471 +
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
22475 @@ -0,0 +1,18 @@
22476 +<?php
22477 +namespace Foo\Bar;
22478 +
22479 +function sort() {
22480 +       $a = array(3,2,1,4);
22481 +       \sort($a);  // global scoping
22482 +       var_dump($a);
22483 +       return "IT WORKS";
22484 +}
22485 +class Baz {
22486 +       public $i = 1;
22487 +       protected $f = 3.14;
22488 +       private $s = "hello world";
22489 +
22490 +       public function foo() {
22491 +               sort();
22492 +       }
22493 +}
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
22497 @@ -0,0 +1,6 @@
22498 +<?php
22499 +
22500 +if (!extension_loaded("apc")) die("skip");
22501 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
22502 +
22503 +?>
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
22507 @@ -0,0 +1,35 @@
22508 +Known Bugs
22509
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.
22514 +
22515 +2.   apc_store() probably needs some checks to skip trying to store
22516 +     internal classes.  Something along the lines of:
22517 +
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");
22522 +            RETURN_FALSE;
22523 +        }
22524 +     }
22525 +
22526 +     in the apc_store() function in php_apc.c but I am wondering if it needs to do more
22527 +     than that.
22528 +
22529 +Windows
22530 +
22531 +1.   The following configurations (build arguments) have not been implemented yet
22532 +
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
22537 +
22538 +2.   Non-blocking locks is not supported either
22539 +
22540 +3.   Update fileinfo to support stat info in a more portable way (see PECL #17903)
22541 +
22542 +4.   Check whether the signal handling needs to be enabled, and if it makes sense on Windows
22543 \ Kein Zeilenumbruch am Dateiende.