8eb204e1c06e3a3d5ec7f7d10aec9f4d1d3bafbe
[packages.git] / lang / php5 / patches / 005-APC.patch
1 diff -ubrN php-5.2.5-orig/ext/apc/apc.c php-5.2.5/ext/apc/apc.c
2 --- php-5.2.5-orig/ext/apc/apc.c        1969-12-31 18:00:00.000000000 -0600
3 +++ php-5.2.5/ext/apc/apc.c     2007-12-26 16:51:32.000000000 -0600
4 @@ -0,0 +1,554 @@
5 +/*
6 +  +----------------------------------------------------------------------+
7 +  | APC                                                                  |
8 +  +----------------------------------------------------------------------+
9 +  | Copyright (c) 2006 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: Daniel Cowgill <dcowgill@communityconnect.com>              |
20 +  |          George Schlossnagle <george@omniti.com>                     |
21 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
22 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
23 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
24 +  +----------------------------------------------------------------------+
25 +
26 +   This software was contributed to PHP by Community Connect Inc. in 2002
27 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
28 +   Future revisions and derivatives of this source code must acknowledge
29 +   Community Connect Inc. as the original contributor of this module by
30 +   leaving this note intact in the source code.
31 +
32 +   All other licensing and usage conditions are those of the PHP Group.
33 +
34 + */
35 +
36 +/* $Id: apc.c,v 3.18 2007/11/29 22:15:53 shire Exp $ */
37 +
38 +#include "apc.h"
39 +#include <regex.h>      /* for POSIX regular expressions */
40 +#include "php.h"
41 +
42 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
43 +
44 +/* {{{ memory allocation wrappers */
45 +
46 +void* apc_emalloc(size_t n)
47 +{
48 +    void* p = malloc(n);
49 +    if (p == NULL) {
50 +        apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
51 +    }
52 +    return p;
53 +}
54 +
55 +void* apc_erealloc(void* p, size_t n)
56 +{
57 +    p = realloc(p, n);
58 +    if (p == NULL) {
59 +        apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
60 +    }
61 +    return p;
62 +}
63 +
64 +void apc_efree(void* p)
65 +{
66 +    if (p == NULL) {
67 +        apc_eprint("apc_efree: attempt to free null pointer");
68 +    }
69 +    free(p);
70 +}
71 +
72 +char* apc_estrdup(const char* s)
73 +{
74 +    int len;
75 +    char* dup;
76 +
77 +    if (s == NULL) {
78 +        return NULL;
79 +    }
80 +    len = strlen(s);
81 +    dup = (char*) malloc(len+1);
82 +    if (dup == NULL) {
83 +        apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
84 +    }
85 +    memcpy(dup, s, len);
86 +    dup[len] = '\0';
87 +    return dup;
88 +}
89 +
90 +void* apc_xstrdup(const char* s, apc_malloc_t f)
91 +{
92 +    return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
93 +}
94 +
95 +void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
96 +{
97 +    void* q;
98 +
99 +    if (p != NULL && (q = f(n)) != NULL) {
100 +        memcpy(q, p, n);
101 +        return q;
102 +    }
103 +    return NULL;
104 +}
105 +
106 +/* }}} */
107 +
108 +/* {{{ console display functions */
109 +
110 +static void my_log(int level, const char* fmt, va_list args)
111 +{
112 +    static const char* level_strings[] = {
113 +        "apc-debug",
114 +        "apc-notice",
115 +        "apc-warning",
116 +        "apc-error"
117 +    };
118 +    static const int num_levels = NELEMS(level_strings);
119 +
120 +    time_t now;
121 +    char* buf;          /* for ctime */
122 +
123 +    fflush(stdout);
124 +
125 +    if (level < 0)
126 +        level = 0;
127 +    else if (level >= num_levels)
128 +        level = num_levels-1;
129 +    
130 +    now = time(0);
131 +    buf = ctime(&now);  /* TODO: replace with reentrant impl */
132 +    buf[24] = '\0';
133 +
134 +    fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
135 +    vfprintf(stderr, fmt, args);
136 +
137 +    if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
138 +        fprintf(stderr, " %s", strerror(errno));
139 +    }
140 +    fprintf(stderr, "\n");
141 +
142 +    if (level == APC_ERROR) {
143 +        exit(2);
144 +    }
145 +}
146 +
147 +void apc_log(int level, const char* fmt, ...)
148 +{
149 +    va_list args;
150 +    va_start(args, fmt);
151 +    my_log(level, fmt, args);
152 +    va_end(args);
153 +}
154 +
155 +void apc_eprint(const char* fmt, ...)
156 +{
157 +    va_list args;
158 +    va_start(args, fmt);
159 +    my_log(APC_ERROR, fmt, args);
160 +    va_end(args);
161 +}
162 +
163 +void apc_wprint(const char* fmt, ...)
164 +{
165 +    va_list args;
166 +    va_start(args, fmt);
167 +    my_log(APC_WARNING, fmt, args);
168 +    va_end(args);
169 +}
170 +
171 +void apc_nprint(const char* fmt, ...)
172 +{
173 +    va_list args;
174 +    va_start(args, fmt);
175 +    my_log(APC_NOTICE, fmt, args);
176 +    va_end(args);
177 +}
178 +
179 +void apc_dprint(const char* fmt, ...)
180 +{
181 +#ifdef APC_DEBUG
182 +    va_list args;
183 +    va_start(args, fmt);
184 +    my_log(APC_DBG, fmt, args);
185 +    va_end(args);
186 +#endif
187 +}
188 +
189 +/* }}} */
190 +
191 +/* {{{ string and text manipulation */
192 +
193 +char* apc_append(const char* s, const char* t)
194 +{
195 +    int slen;
196 +    int tlen;
197 +    char* p;
198 +
199 +    slen = strlen(s);
200 +    tlen = strlen(t);
201 +
202 +    p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
203 +    memcpy(p, s, slen);
204 +    memcpy(p + slen, t, tlen + 1);
205 +
206 +    return p;
207 +}
208 +
209 +char* apc_substr(const char* s, int start, int length)
210 +{
211 +    char* substr;
212 +    int src_len = strlen(s);
213 +
214 +    /* bring start into range */
215 +    if (start < 0) {
216 +        start = 0;
217 +    }
218 +    else if (start >= src_len) {
219 +        start = src_len - 1;
220 +    }
221 +
222 +    /* bring length into range */
223 +    if (length < 0 || src_len - start < length) {
224 +        length = src_len - start;
225 +    }
226 +
227 +    /* create the substring */
228 +    substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
229 +    substr[length] = '\0';
230 +    return substr;
231 +}
232 +
233 +char** apc_tokenize(const char* s, char delim)
234 +{
235 +    char** tokens;      /* array of tokens, NULL terminated */
236 +    int size;           /* size of tokens array */
237 +    int n;              /* index of next token in tokens array */
238 +    int cur;            /* current position in input string */
239 +    int end;            /* final legal position in input string */
240 +    int next;           /* position of next delimiter in input */
241 +    
242 +    if (!s) {
243 +        return NULL;
244 +    }
245 +
246 +    size = 2;
247 +    n    = 0;
248 +    cur  = 0;
249 +    end  = strlen(s) - 1;
250 +    
251 +    tokens = (char**) apc_emalloc(size * sizeof(char*));
252 +    tokens[n] = NULL;
253 +
254 +    while (cur <= end) {
255 +        /* search for the next delimiter */
256 +        char* p = strchr(s + cur, delim);
257 +        next = p ? p-s : end+1;
258 +
259 +        /* resize token array if necessary */
260 +        if (n == size-1) {
261 +            size *= 2;
262 +            tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
263 +        }
264 +
265 +        /* save the current token */
266 +        tokens[n] = apc_substr(s, cur, next-cur);
267 +
268 +        tokens[++n] = NULL;
269 +        cur = next + 1;
270 +    }
271 +
272 +    return tokens;
273 +}
274 +
275 +/* }}} */
276 +
277 +/* {{{ filesystem functions */
278 +
279 +#ifdef PHP_WIN32
280 +int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
281 +{
282 +    char rpath[MAXPATHLEN];
283 +    BY_HANDLE_FILE_INFORMATION fi;
284 +    HANDLE f;
285 +    
286 +    if (VCWD_STAT(path, buf)) {
287 +        return -1;
288 +    }
289 +
290 +    VCWD_REALPATH(path, rpath);
291 +    f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
292 +    GetFileInformationByHandle(f, &fi);
293 +    buf->st_ino = (ino_t)fi.nFileIndexLow;
294 +    CloseHandle (f);
295 +    return 0;
296 +}
297 +#endif
298 +
299 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
300 +{
301 +    char** paths;
302 +    char *exec_fname;
303 +    int exec_fname_length;
304 +    int found = 0;
305 +    int i;
306 +    TSRMLS_FETCH();
307 +
308 +    assert(filename && fileinfo);
309 +
310 +    if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
311 +        strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
312 +        return 0;
313 +    }
314 +
315 +    paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
316 +    if (!paths)
317 +        return -1;
318 +
319 +    /* for each directory in paths, look for filename inside */
320 +    for (i = 0; paths[i]; i++) {
321 +        snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
322 +        if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
323 +            found = 1;
324 +            break;
325 +        }
326 +    }
327 +
328 +    /* check in path of the calling scripts' current working directory */
329 +    /* modified from main/streams/plain_wrapper.c */
330 +    if(!found && zend_is_executing(TSRMLS_C)) {
331 +        exec_fname = zend_get_executed_filename(TSRMLS_C);
332 +        exec_fname_length = strlen(exec_fname);
333 +        while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
334 +        if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
335 +            /* not: [no active file] or no path */
336 +            memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
337 +            fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
338 +            strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
339 +            /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
340 +            if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
341 +                found = 1;
342 +            }
343 +        }
344 +    }
345 +    
346 +    /* free the value returned by apc_tokenize */
347 +    for (i = 0; paths[i]; i++) {
348 +        apc_efree(paths[i]);
349 +    }
350 +    apc_efree(paths);
351 +
352 +    return found ? 0 : -1;
353 +}
354 +
355 +/* }}} */
356 +
357 +/* {{{ regular expression wrapper functions */
358 +
359 +typedef struct {
360 +    regex_t *reg;
361 +    unsigned char type;
362 +} apc_regex;
363 +
364 +void* apc_regex_compile_array(char* patterns[])
365 +{
366 +    apc_regex** regs;
367 +    int npat;
368 +    int i;
369 +
370 +    if (!patterns)
371 +        return NULL;
372 +
373 +    /* count the number of patterns in patterns */
374 +    for (npat = 0; patterns[npat] != NULL; npat++) {}
375 +
376 +    if (npat == 0)
377 +        return NULL;
378 +
379 +    /* allocate the array of compiled expressions */
380 +    regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
381 +    for (i = 0; i <= npat; i++) {
382 +        regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
383 +        regs[i]->reg = NULL;
384 +        regs[i]->type = APC_NEGATIVE_MATCH;
385 +    }
386 +
387 +    /* compile the expressions */
388 +    for (i = 0; i < npat; i++) {
389 +        char *pattern = patterns[i];
390 +        if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
391 +        else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
392 +
393 +        regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
394 +
395 +        if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
396 +            apc_wprint("apc_regex_compile_array: invalid expression '%s'",
397 +                       pattern);
398 +
399 +            apc_regex_destroy_array(regs);
400 +
401 +            return NULL;
402 +        }
403 +    }
404 +
405 +    return (void*) regs;
406 +}
407 +
408 +void apc_regex_destroy_array(void* p)
409 +{
410 +    if (p != NULL) {
411 +        apc_regex** regs = (apc_regex**) p;
412 +        int i;
413 +
414 +        for (i = 0; regs[i]->reg != NULL; i++) {
415 +            regfree(regs[i]->reg);
416 +            apc_efree(regs[i]->reg);
417 +            apc_efree(regs[i]);
418 +        }
419 +        apc_efree(regs);
420 +    }
421 +}
422 +
423 +int apc_regex_match_array(void* p, const char* input)
424 +{
425 +    apc_regex** regs;
426 +    int i;
427 +
428 +    if (!p)
429 +        return 0;
430 +
431 +    regs = (apc_regex**) p;
432 +    for (i = 0; regs[i]->reg != NULL; i++)
433 +        if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
434 +            return (int)(regs[i]->type);
435 +
436 +    return 0;
437 +}
438 +
439 +/* }}} */
440 +
441 +/* {{{ crc32 implementation */
442 +
443 +/* this table was generated by crc32gen() */
444 +static unsigned int crc32tab[] = {
445 +    /*   0 */  0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd, 
446 +    /*   4 */  0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1, 
447 +    /*   8 */  0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4, 
448 +    /*  12 */  0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8, 
449 +    /*  16 */  0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef, 
450 +    /*  20 */  0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3, 
451 +    /*  24 */  0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6, 
452 +    /*  28 */  0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da, 
453 +    /*  32 */  0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9, 
454 +    /*  36 */  0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995, 
455 +    /*  40 */  0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0, 
456 +    /*  44 */  0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c, 
457 +    /*  48 */  0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b, 
458 +    /*  52 */  0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7, 
459 +    /*  56 */  0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492, 
460 +    /*  60 */  0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be, 
461 +    /*  64 */  0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815, 
462 +    /*  68 */  0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939, 
463 +    /*  72 */  0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c, 
464 +    /*  76 */  0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20, 
465 +    /*  80 */  0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027, 
466 +    /*  84 */  0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b, 
467 +    /*  88 */  0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e, 
468 +    /*  92 */  0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512, 
469 +    /*  96 */  0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871, 
470 +    /* 100 */  0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d, 
471 +    /* 104 */  0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68, 
472 +    /* 108 */  0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44, 
473 +    /* 112 */  0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043, 
474 +    /* 116 */  0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f, 
475 +    /* 120 */  0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a, 
476 +    /* 124 */  0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576, 
477 +    /* 128 */  0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d, 
478 +    /* 132 */  0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861, 
479 +    /* 136 */  0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54, 
480 +    /* 140 */  0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78, 
481 +    /* 144 */  0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f, 
482 +    /* 148 */  0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053, 
483 +    /* 152 */  0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566, 
484 +    /* 156 */  0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a, 
485 +    /* 160 */  0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929, 
486 +    /* 164 */  0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805, 
487 +    /* 168 */  0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30, 
488 +    /* 172 */  0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c, 
489 +    /* 176 */  0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b, 
490 +    /* 180 */  0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037, 
491 +    /* 184 */  0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502, 
492 +    /* 188 */  0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e, 
493 +    /* 192 */  0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985, 
494 +    /* 196 */  0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9, 
495 +    /* 200 */  0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c, 
496 +    /* 204 */  0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0, 
497 +    /* 208 */  0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7, 
498 +    /* 212 */  0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b, 
499 +    /* 216 */  0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae, 
500 +    /* 220 */  0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482, 
501 +    /* 224 */  0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1, 
502 +    /* 228 */  0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd, 
503 +    /* 232 */  0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8, 
504 +    /* 236 */  0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4, 
505 +    /* 240 */  0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3, 
506 +    /* 244 */  0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff, 
507 +    /* 248 */  0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca, 
508 +    /* 252 */  0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6, 
509 +};
510 +
511 +unsigned int apc_crc32(const char* buf, int len)
512 +{
513 +    int i;
514 +    int k;
515 +    unsigned int crc;
516 +
517 +    /* preconditioning */
518 +    crc = 0xFFFFFFFF;
519 +    
520 +    for (i = 0; i < len; i++) {
521 +        k = (crc ^ buf[i]) & 0x000000FF;
522 +        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
523 +    }
524 +
525 +    /* postconditioning */
526 +    return ~crc;
527 +}
528 +
529 +/* crc32gen: generate the nth (0..255) crc32 table value */
530 +#if 0
531 +static unsigned long crc32gen(int n)
532 +{
533 +    int i;
534 +    unsigned long crc;
535 +    
536 +    crc = n;
537 +    for (i = 8; i >= 0; i--) {
538 +        if (crc & 1) {
539 +            crc = (crc >> 1) ^ 0xEDB88320;
540 +        }
541 +        else {
542 +            crc >>= 1;
543 +        }
544 +    }
545 +    return crc;
546 +}
547 +#endif
548 +
549 +/* }}} */
550 +
551 +/*
552 + * Local variables:
553 + * tab-width: 4
554 + * c-basic-offset: 4
555 + * End:
556 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
557 + * vim<600: expandtab sw=4 ts=4 sts=4
558 + */
559 diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.c php-5.2.5/ext/apc/apc_cache.c
560 --- php-5.2.5-orig/ext/apc/apc_cache.c  1969-12-31 18:00:00.000000000 -0600
561 +++ php-5.2.5/ext/apc/apc_cache.c       2007-12-26 16:51:32.000000000 -0600
562 @@ -0,0 +1,1343 @@
563 +/*
564 +  +----------------------------------------------------------------------+
565 +  | APC                                                                  |
566 +  +----------------------------------------------------------------------+
567 +  | Copyright (c) 2006 The PHP Group                                     |
568 +  +----------------------------------------------------------------------+
569 +  | This source file is subject to version 3.01 of the PHP license,      |
570 +  | that is bundled with this package in the file LICENSE, and is        |
571 +  | available through the world-wide-web at the following url:           |
572 +  | http://www.php.net/license/3_01.txt                                  |
573 +  | If you did not receive a copy of the PHP license and are unable to   |
574 +  | obtain it through the world-wide-web, please send a note to          |
575 +  | license@php.net so we can mail you a copy immediately.               |
576 +  +----------------------------------------------------------------------+
577 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
578 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
579 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
580 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
581 +  +----------------------------------------------------------------------+
582 +
583 +   This software was contributed to PHP by Community Connect Inc. in 2002
584 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
585 +   Future revisions and derivatives of this source code must acknowledge
586 +   Community Connect Inc. as the original contributor of this module by
587 +   leaving this note intact in the source code.
588 +
589 +   All other licensing and usage conditions are those of the PHP Group.
590 +
591 + */
592 +
593 +/* $Id: apc_cache.c,v 3.145 2007/10/05 23:06:56 gopalv Exp $ */
594 +
595 +#include "apc_cache.h"
596 +#include "apc_lock.h"
597 +#include "apc_sma.h"
598 +#include "apc_globals.h"
599 +#include "SAPI.h"
600 +#include "ext/standard/php_var.h"
601 +#include "ext/standard/php_smart_str.h"
602 +
603 +/* TODO: rehash when load factor exceeds threshold */
604 +
605 +#define CHECK(p) { if ((p) == NULL) return NULL; }
606 +
607 +/* {{{ locking macros */
608 +#define CREATE_LOCK(lock)     apc_lck_create(NULL, 0, 1, lock)
609 +#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
610 +#define LOCK(c)         { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
611 +#define RDLOCK(c)       { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
612 +#define UNLOCK(c)       { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
613 +/* }}} */
614 +
615 +/* {{{ struct definition: slot_t */
616 +typedef struct slot_t slot_t;
617 +struct slot_t {
618 +    apc_cache_key_t key;        /* slot key */
619 +    apc_cache_entry_t* value;   /* slot value */
620 +    slot_t* next;               /* next slot in linked list */
621 +    int num_hits;               /* number of hits to this bucket */
622 +    time_t creation_time;       /* time slot was initialized */
623 +    time_t deletion_time;       /* time slot was removed from cache */
624 +    time_t access_time;         /* time slot was last accessed */
625 +};
626 +/* }}} */
627 +
628 +/* {{{ struct definition: header_t
629 +   Any values that must be shared among processes should go in here. */
630 +typedef struct header_t header_t;
631 +struct header_t {
632 +    apc_lck_t lock;              /* read/write lock (exclusive blocking cache lock) */
633 +    apc_lck_t wrlock;           /* write lock (non-blocking used to prevent cache slams) */
634 +    int num_hits;               /* total successful hits in cache */
635 +    int num_misses;             /* total unsuccessful hits in cache */
636 +    int num_inserts;            /* total successful inserts in cache */
637 +    slot_t* deleted_list;       /* linked list of to-be-deleted slots */
638 +    time_t start_time;          /* time the above counters were reset */
639 +    int expunges;               /* total number of expunges */
640 +    zend_bool busy;             /* Flag to tell clients when we are busy cleaning the cache */
641 +    int num_entries;            /* Statistic on the number of entries */
642 +    size_t mem_size;            /* Statistic on the memory size used by this cache */
643 +};
644 +/* }}} */
645 +
646 +/* {{{ struct definition: apc_cache_t */
647 +struct apc_cache_t {
648 +    void* shmaddr;              /* process (local) address of shared cache */
649 +    header_t* header;           /* cache header (stored in SHM) */
650 +    slot_t** slots;             /* array of cache slots (stored in SHM) */
651 +    int num_slots;              /* number of slots in cache */
652 +    int gc_ttl;                 /* maximum time on GC list for a slot */
653 +    int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
654 +};
655 +/* }}} */
656 +
657 +/* {{{ struct definition local_slot_t */
658 +typedef struct local_slot_t local_slot_t;
659 +struct local_slot_t {
660 +    slot_t *original;           /* the original slot in shm */
661 +    int num_hits;               /* number of hits */
662 +    time_t creation_time;       /* creation time */
663 +    apc_cache_entry_t *value;   /* shallow copy of slot->value */
664 +    local_slot_t *next;         /* only for dead list */
665 +};
666 +/* }}} */
667 +/* {{{ struct definition apc_local_cache_t */
668 +struct apc_local_cache_t {
669 +    apc_cache_t* shmcache;      /* the real cache in shm */
670 +    local_slot_t* slots;        /* process (local) cache of objects */
671 +    local_slot_t* dead_list;    /* list of objects pending removal */
672 +    int num_slots;              /* number of slots in cache */
673 +    int ttl;                    /* time to live */
674 +    int num_hits;               /* number of hits */
675 +    int generation;             /* every generation lives between expunges */
676 +};
677 +/* }}} */
678 +
679 +/* {{{ key_equals */
680 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
681 +/* }}} */
682 +
683 +/* {{{ hash */
684 +static unsigned int hash(apc_cache_key_t key)
685 +{
686 +    return key.data.file.device + key.data.file.inode;
687 +}
688 +/* }}} */
689 +
690 +/* {{{ string_nhash_8 */
691 +static unsigned int string_nhash_8(const char *s, size_t len)
692 +{
693 +    register const unsigned int *iv = (const unsigned int *)s;
694 +    register unsigned int h = 0;
695 +    register const unsigned int *e  = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
696 +
697 +    for(;iv<e;iv++) {
698 +        h += *iv;
699 +        h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
700 +    }
701 +    s = (const char *)iv;
702 +    for(len %= sizeof(unsigned int);len;len--) {
703 +        h += *(s++);
704 +    }
705 +    h ^= (h >> 13);
706 +    h ^= (h >> 7);
707 +    return h;
708 +}
709 +/* }}} */
710 +
711 +/* {{{ make_slot */
712 +slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
713 +{
714 +    slot_t* p = apc_sma_malloc(sizeof(slot_t));
715 +    if (!p) return NULL;
716 +
717 +    if(value->type == APC_CACHE_ENTRY_USER) {
718 +        char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
719 +        if (!identifier) {
720 +            apc_sma_free(p);
721 +            return NULL;
722 +        }
723 +        key.data.user.identifier = identifier;
724 +    } else if(key.type == APC_CACHE_KEY_FPFILE) {
725 +        char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
726 +        if (!fullpath) {
727 +            apc_sma_free(p);
728 +            return NULL;
729 +        }
730 +        key.data.fpfile.fullpath = fullpath;
731 +    }
732 +    p->key = key;
733 +    p->value = value;
734 +    p->next = next;
735 +    p->num_hits = 0;
736 +    p->creation_time = t;
737 +    p->access_time = t;
738 +    p->deletion_time = 0;
739 +    return p;
740 +}
741 +/* }}} */
742 +
743 +/* {{{ free_slot */
744 +static void free_slot(slot_t* slot)
745 +{
746 +    if(slot->value->type == APC_CACHE_ENTRY_USER) {
747 +        apc_sma_free((char *)slot->key.data.user.identifier);
748 +    } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
749 +        apc_sma_free((char *)slot->key.data.fpfile.fullpath);
750 +    }
751 +    apc_cache_free_entry(slot->value);
752 +    apc_sma_free(slot);
753 +}
754 +/* }}} */
755 +
756 +/* {{{ remove_slot */
757 +static void remove_slot(apc_cache_t* cache, slot_t** slot)
758 +{
759 +    slot_t* dead = *slot;
760 +    *slot = (*slot)->next;
761 +
762 +    cache->header->mem_size -= dead->value->mem_size;
763 +    cache->header->num_entries--;
764 +    if (dead->value->ref_count <= 0) {
765 +        free_slot(dead);
766 +    }
767 +    else {
768 +        dead->next = cache->header->deleted_list;
769 +        dead->deletion_time = time(0);
770 +        cache->header->deleted_list = dead;
771 +    }
772 +}
773 +/* }}} */
774 +
775 +/* {{{ process_pending_removals */
776 +static void process_pending_removals(apc_cache_t* cache)
777 +{
778 +    slot_t** slot;
779 +    time_t now;
780 +
781 +    /* This function scans the list of removed cache entries and deletes any
782 +     * entry whose reference count is zero (indicating that it is no longer
783 +     * being executed) or that has been on the pending list for more than
784 +     * cache->gc_ttl seconds (we issue a warning in the latter case).
785 +     */
786 +
787 +    if (!cache->header->deleted_list)
788 +        return;
789 +
790 +    slot = &cache->header->deleted_list;
791 +    now = time(0);
792 +
793 +    while (*slot != NULL) {
794 +        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
795 +
796 +        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
797 +            slot_t* dead = *slot;
798 +
799 +            if (dead->value->ref_count > 0) {
800 +                switch(dead->value->type) {
801 +                    case APC_CACHE_ENTRY_FILE:
802 +                        apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
803 +                            "was on gc-list for %d seconds", dead->value->data.file.filename,
804 +                            dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
805 +                        break;
806 +                    case APC_CACHE_ENTRY_USER:
807 +                        apc_log(APC_WARNING, "GC cache entry '%s' "
808 +                            "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
809 +                        break;
810 +                }
811 +            }
812 +            *slot = dead->next;
813 +            free_slot(dead);
814 +        }
815 +        else {
816 +            slot = &(*slot)->next;
817 +        }
818 +    }
819 +}
820 +/* }}} */
821 +
822 +/* {{{ prevent_garbage_collection */
823 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
824 +{
825 +    /* set reference counts on zend objects to an arbitrarily high value to
826 +     * prevent garbage collection after execution */
827 +
828 +    enum { BIG_VALUE = 1000 };
829 +
830 +    if(entry->data.file.op_array) {
831 +        entry->data.file.op_array->refcount[0] = BIG_VALUE;
832 +    }
833 +    if (entry->data.file.functions) {
834 +        int i;
835 +        apc_function_t* fns = entry->data.file.functions;
836 +        for (i=0; fns[i].function != NULL; i++) {
837 +#ifdef ZEND_ENGINE_2            
838 +            *(fns[i].function->op_array.refcount) = BIG_VALUE;
839 +#else            
840 +            fns[i].function->op_array.refcount[0] = BIG_VALUE;
841 +#endif            
842 +        }
843 +    }
844 +    if (entry->data.file.classes) {
845 +        int i;
846 +        apc_class_t* classes = entry->data.file.classes;
847 +        for (i=0; classes[i].class_entry != NULL; i++) {
848 +#ifdef ZEND_ENGINE_2            
849 +            classes[i].class_entry->refcount = BIG_VALUE;
850 +#else            
851 +            classes[i].class_entry->refcount[0] = BIG_VALUE;
852 +#endif
853 +        }
854 +    }
855 +}
856 +/* }}} */
857 +
858 +/* {{{ apc_cache_create */
859 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
860 +{
861 +    apc_cache_t* cache;
862 +    int cache_size;
863 +    int num_slots;
864 +    int i;
865 +
866 +    num_slots = size_hint > 0 ? size_hint*2 : 2000;
867 +
868 +    cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
869 +    cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
870 +
871 +    cache->shmaddr = apc_sma_malloc(cache_size);
872 +    if(!cache->shmaddr) {
873 +        apc_eprint("Unable to allocate shared memory for cache structures.  (Perhaps your shared memory size isn't large enough?). ");
874 +    }
875 +    memset(cache->shmaddr, 0, cache_size);
876 +
877 +    cache->header = (header_t*) cache->shmaddr;
878 +    cache->header->num_hits = 0;
879 +    cache->header->num_misses = 0;
880 +    cache->header->deleted_list = NULL;
881 +    cache->header->start_time = time(NULL);
882 +    cache->header->expunges = 0;
883 +    cache->header->busy = 0;
884 +
885 +    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
886 +    cache->num_slots = num_slots;
887 +    cache->gc_ttl = gc_ttl;
888 +    cache->ttl = ttl;
889 +    CREATE_LOCK(cache->header->lock);
890 +#if NONBLOCKING_LOCK_AVAILABLE
891 +    CREATE_LOCK(cache->header->wrlock);
892 +#endif
893 +    for (i = 0; i < num_slots; i++) {
894 +        cache->slots[i] = NULL;
895 +    }
896 +
897 +    return cache;
898 +}
899 +/* }}} */
900 +
901 +/* {{{ apc_cache_destroy */
902 +void apc_cache_destroy(apc_cache_t* cache)
903 +{
904 +    DESTROY_LOCK(cache);
905 +    apc_efree(cache);
906 +}
907 +/* }}} */
908 +
909 +/* {{{ apc_cache_clear */
910 +void apc_cache_clear(apc_cache_t* cache)
911 +{
912 +    int i;
913 +
914 +    if(!cache) return;
915 +
916 +    LOCK(cache);
917 +    cache->header->busy = 1;
918 +    cache->header->num_hits = 0;
919 +    cache->header->num_misses = 0;
920 +    cache->header->start_time = time(NULL);
921 +    cache->header->expunges = 0;
922 +
923 +    for (i = 0; i < cache->num_slots; i++) {
924 +        slot_t* p = cache->slots[i];
925 +        while (p) {
926 +            remove_slot(cache, &p);
927 +        }
928 +        cache->slots[i] = NULL;
929 +    }
930 +    
931 +    cache->header->busy = 0;
932 +    UNLOCK(cache);
933 +}
934 +/* }}} */
935 +
936 +/* {{{ apc_cache_expunge */
937 +void apc_cache_expunge(apc_cache_t* cache, time_t t)
938 +{
939 +    int i;
940 +
941 +    if(!cache) return;
942 +
943 +    if(!cache->ttl) {
944 +        /* 
945 +         * If cache->ttl is not set, we wipe out the entire cache when
946 +         * we run out of space. 
947 +         */
948 +        LOCK(cache);
949 +        cache->header->busy = 1;
950 +        cache->header->expunges++;
951 +        for (i = 0; i < cache->num_slots; i++) {
952 +            slot_t* p = cache->slots[i];
953 +            while (p) {
954 +                remove_slot(cache, &p);
955 +            }
956 +            cache->slots[i] = NULL;
957 +        }
958 +        cache->header->busy = 0;
959 +        UNLOCK(cache);
960 +    } else {
961 +        slot_t **p;
962 +
963 +        /*
964 +         * If the ttl for the cache is set we walk through and delete stale 
965 +         * entries.  For the user cache that is slightly confusing since
966 +         * we have the individual entry ttl's we can look at, but that would be
967 +         * too much work.  So if you want the user cache expunged, set a high
968 +         * default apc.user_ttl and still provide a specific ttl for each entry
969 +         * on insert
970 +         */
971 +
972 +        LOCK(cache);
973 +        cache->header->busy = 1;
974 +        cache->header->expunges++;
975 +        for (i = 0; i < cache->num_slots; i++) {
976 +            p = &cache->slots[i];
977 +            while(*p) {
978 +                /* 
979 +                 * For the user cache we look at the individual entry ttl values
980 +                 * and if not set fall back to the default ttl for the user cache
981 +                 */
982 +                if((*p)->value->type == APC_CACHE_ENTRY_USER) {
983 +                    if((*p)->value->data.user.ttl) {
984 +                        if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
985 +                            remove_slot(cache, p);
986 +                            continue;
987 +                        }
988 +                    } else if(cache->ttl) {
989 +                        if((*p)->creation_time + cache->ttl < t) {
990 +                            remove_slot(cache, p);
991 +                            continue;
992 +                        }
993 +                    }
994 +                } else if((*p)->access_time < (t - cache->ttl)) {
995 +                    remove_slot(cache, p);
996 +                    continue;
997 +                }
998 +                p = &(*p)->next;
999 +            }
1000 +        }
1001 +        cache->header->busy = 0;
1002 +        UNLOCK(cache);
1003 +    }
1004 +}
1005 +/* }}} */
1006 +
1007 +/* {{{ apc_cache_insert */
1008 +int apc_cache_insert(apc_cache_t* cache,
1009 +                     apc_cache_key_t key,
1010 +                     apc_cache_entry_t* value,
1011 +                     time_t t)
1012 +{
1013 +    slot_t** slot;
1014 +
1015 +    if (!value) {
1016 +        return 0;
1017 +    }
1018 +
1019 +#ifdef __DEBUG_APC__
1020 +    fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
1021 +#endif
1022 +
1023 +    LOCK(cache);
1024 +    process_pending_removals(cache);
1025 +
1026 +    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1027 +    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1028 +
1029 +    while(*slot) {
1030 +      if(key.type == (*slot)->key.type) {
1031 +        if(key.type == APC_CACHE_KEY_FILE) {
1032 +            if(key_equals((*slot)->key.data.file, key.data.file)) {
1033 +                /* If existing slot for the same device+inode is different, remove it and insert the new version */
1034 +                if ((*slot)->key.mtime != key.mtime) {
1035 +                    remove_slot(cache, slot);
1036 +                    break;
1037 +                }
1038 +                UNLOCK(cache);
1039 +                return 0;
1040 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1041 +                remove_slot(cache, slot);
1042 +                continue;
1043 +            }
1044 +        } else {   /* APC_CACHE_KEY_FPFILE */
1045 +                if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1046 +                /* Hrm.. it's already here, remove it and insert new one */
1047 +                remove_slot(cache, slot);
1048 +                break;
1049 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1050 +                remove_slot(cache, slot);
1051 +                continue;
1052 +            }
1053 +        }
1054 +      }
1055 +      slot = &(*slot)->next;
1056 +    }
1057 +
1058 +    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1059 +        UNLOCK(cache);
1060 +        return -1;
1061 +    }
1062 +   
1063 +    cache->header->mem_size += value->mem_size;
1064 +    cache->header->num_entries++;
1065 +    cache->header->num_inserts++;
1066 +    
1067 +    UNLOCK(cache);
1068 +    return 1;
1069 +}
1070 +/* }}} */
1071 +
1072 +/* {{{ apc_cache_user_insert */
1073 +int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC)
1074 +{
1075 +    slot_t** slot;
1076 +    size_t* mem_size_ptr = NULL;
1077 +
1078 +    if (!value) {
1079 +        return 0;
1080 +    }
1081 +
1082 +    LOCK(cache);
1083 +    process_pending_removals(cache);
1084 +
1085 +    slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
1086 +
1087 +    if (APCG(mem_size_ptr) != NULL) {
1088 +        mem_size_ptr = APCG(mem_size_ptr);
1089 +        APCG(mem_size_ptr) = NULL;
1090 +    }
1091 +
1092 +    while (*slot) {
1093 +        if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
1094 +            /* 
1095 +             * At this point we have found the user cache entry.  If we are doing 
1096 +             * an exclusive insert (apc_add) we are going to bail right away if
1097 +             * the user entry already exists and it has no ttl, or
1098 +             * there is a ttl and the entry has not timed out yet.
1099 +             */
1100 +            if(exclusive && (  !(*slot)->value->data.user.ttl ||
1101 +                              ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) 
1102 +                            ) ) {
1103 +                UNLOCK(cache);
1104 +                return 0;
1105 +            }
1106 +            remove_slot(cache, slot);
1107 +            break;
1108 +        } else 
1109 +        /* 
1110 +         * This is a bit nasty.  The idea here is to do runtime cleanup of the linked list of
1111 +         * slot entries so we don't always have to skip past a bunch of stale entries.  We check
1112 +         * for staleness here and get rid of them by first checking to see if the cache has a global
1113 +         * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
1114 +         * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
1115 +         */
1116 +        if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || 
1117 +           ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
1118 +            remove_slot(cache, slot);
1119 +            continue;
1120 +        }
1121 +        slot = &(*slot)->next;
1122 +    }
1123 +
1124 +    if (mem_size_ptr != NULL) {
1125 +        APCG(mem_size_ptr) = mem_size_ptr;
1126 +    }
1127 +
1128 +    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1129 +        UNLOCK(cache);
1130 +        return 0;
1131 +    }
1132 +    if (APCG(mem_size_ptr) != NULL) {
1133 +        value->mem_size = *APCG(mem_size_ptr);
1134 +        cache->header->mem_size += *APCG(mem_size_ptr);
1135 +    }
1136 +    cache->header->num_entries++;
1137 +    cache->header->num_inserts++;
1138 +
1139 +    UNLOCK(cache);
1140 +    return 1;
1141 +}
1142 +/* }}} */
1143 +
1144 +/* {{{ apc_cache_find_slot */
1145 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1146 +{
1147 +    slot_t** slot;
1148 +    volatile slot_t* retval = NULL;
1149 +
1150 +    LOCK(cache);
1151 +    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1152 +    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1153 +
1154 +    while (*slot) {
1155 +      if(key.type == (*slot)->key.type) {
1156 +        if(key.type == APC_CACHE_KEY_FILE) {
1157 +            if(key_equals((*slot)->key.data.file, key.data.file)) {
1158 +                if((*slot)->key.mtime != key.mtime) {
1159 +                    remove_slot(cache, slot);
1160 +                    cache->header->num_misses++;
1161 +                    UNLOCK(cache);
1162 +                    return NULL;
1163 +                }
1164 +                (*slot)->num_hits++;
1165 +                (*slot)->value->ref_count++;
1166 +                (*slot)->access_time = t;
1167 +                prevent_garbage_collection((*slot)->value);
1168 +                cache->header->num_hits++;
1169 +                retval = *slot;
1170 +                UNLOCK(cache);
1171 +                return (slot_t*)retval;
1172 +            }
1173 +        } else {  /* APC_CACHE_KEY_FPFILE */
1174 +            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1175 +                /* TTL Check ? */
1176 +                (*slot)->num_hits++;
1177 +                (*slot)->value->ref_count++;
1178 +                (*slot)->access_time = t;
1179 +                prevent_garbage_collection((*slot)->value);
1180 +                cache->header->num_hits++;
1181 +                retval = *slot;
1182 +                UNLOCK(cache);
1183 +                return (slot_t*)retval;
1184 +            }
1185 +        }
1186 +      }
1187 +      slot = &(*slot)->next;
1188 +    }
1189 +    cache->header->num_misses++;
1190 +    UNLOCK(cache);
1191 +    return NULL;
1192 +}
1193 +/* }}} */
1194 +
1195 +/* {{{ apc_cache_find */
1196 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1197 +{
1198 +    slot_t * slot = apc_cache_find_slot(cache, key, t);
1199 +    return (slot) ? slot->value : NULL;
1200 +}
1201 +/* }}} */
1202 +
1203 +/* {{{ apc_cache_user_find */
1204 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
1205 +{
1206 +    slot_t** slot;
1207 +    volatile apc_cache_entry_t* value = NULL;
1208 +
1209 +    LOCK(cache);
1210 +
1211 +    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1212 +
1213 +    while (*slot) {
1214 +        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1215 +            /* Check to make sure this entry isn't expired by a hard TTL */
1216 +            if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
1217 +                remove_slot(cache, slot);
1218 +                UNLOCK(cache);
1219 +                return NULL;
1220 +            }
1221 +            /* Otherwise we are fine, increase counters and return the cache entry */
1222 +            (*slot)->num_hits++;
1223 +            (*slot)->value->ref_count++;
1224 +            (*slot)->access_time = t;
1225 +
1226 +            cache->header->num_hits++;
1227 +            value = (*slot)->value;
1228 +            UNLOCK(cache);
1229 +            return (apc_cache_entry_t*)value;
1230 +        }
1231 +        slot = &(*slot)->next;
1232 +    }
1233
1234 +    UNLOCK(cache);
1235 +    return NULL;
1236 +}
1237 +/* }}} */
1238 +
1239 +/* {{{ apc_cache_user_delete */
1240 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
1241 +{
1242 +    slot_t** slot;
1243 +
1244 +    LOCK(cache);
1245 +
1246 +    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1247 +
1248 +    while (*slot) {
1249 +        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1250 +            remove_slot(cache, slot);
1251 +            UNLOCK(cache);
1252 +            return 1;
1253 +        }
1254 +        slot = &(*slot)->next;
1255 +    }
1256 +
1257 +    UNLOCK(cache);
1258 +    return 0;
1259 +}
1260 +/* }}} */
1261 +
1262 +/* {{{ apc_cache_release */
1263 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
1264 +{
1265 +    /* local cache refcount-- is done in apc_local_cache_cleanup */
1266 +    if(entry->local) return;
1267 +
1268 +    LOCK(cache);
1269 +    entry->ref_count--;
1270 +    UNLOCK(cache);
1271 +}
1272 +/* }}} */
1273 +
1274 +/* {{{ apc_cache_make_file_key */
1275 +int apc_cache_make_file_key(apc_cache_key_t* key,
1276 +                       const char* filename,
1277 +                       const char* include_path,
1278 +                       time_t t
1279 +                                          TSRMLS_DC)
1280 +{
1281 +    struct stat *tmp_buf=NULL;
1282 +    struct apc_fileinfo_t fileinfo = { {0}, };
1283 +    int len;
1284 +
1285 +    assert(key != NULL);
1286 +
1287 +    if (!filename || !SG(request_info).path_translated) {
1288 +#ifdef __DEBUG_APC__
1289 +        fprintf(stderr,"No filename and no path_translated - bailing\n");
1290 +#endif
1291 +        return 0;
1292 +       }
1293 +
1294 +    len = strlen(filename);
1295 +    if(APCG(fpstat)==0) {
1296 +        if(IS_ABSOLUTE_PATH(filename,len)) {
1297 +            key->data.fpfile.fullpath = filename;
1298 +            key->data.fpfile.fullpath_len = len;
1299 +            key->mtime = t;
1300 +            key->type = APC_CACHE_KEY_FPFILE;
1301 +        } else {
1302 +            if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1303 +                apc_wprint("apc failed to locate %s - bailing", filename);
1304 +                return 0;
1305 +            }
1306 +
1307 +            if(!realpath(fileinfo.fullpath, APCG(canon_path))) {
1308 +                apc_wprint("realpath failed to canonicalize %s - bailing", filename);
1309 +                return 0;
1310 +            }
1311 +
1312 +            key->data.fpfile.fullpath = APCG(canon_path);
1313 +            key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
1314 +            key->mtime = t;
1315 +            key->type = APC_CACHE_KEY_FPFILE;
1316 +        }
1317 +        return 1;
1318 +    } 
1319 +
1320 +    if(!strcmp(SG(request_info).path_translated, filename)) {
1321 +        tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
1322 +    }
1323 +    if(tmp_buf) { 
1324 +               fileinfo.st_buf = *tmp_buf;
1325 +    } else {
1326 +        if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1327 +#ifdef __DEBUG_APC__
1328 +            fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
1329 +#endif
1330 +            return 0;
1331 +        }
1332 +    }
1333 +
1334 +    if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
1335 +#ifdef __DEBUG_APC__
1336 +        fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
1337 +#endif
1338 +        return 0;
1339 +    }
1340 +
1341 +    /*
1342 +     * This is a bit of a hack.
1343 +     *
1344 +     * Here I am checking to see if the file is at least 2 seconds old.  
1345 +     * The idea is that if the file is currently being written to then its
1346 +     * mtime is going to match or at most be 1 second off of the current
1347 +     * request time and we want to avoid caching files that have not been
1348 +     * completely written.  Of course, people should be using atomic 
1349 +     * mechanisms to push files onto live web servers, but adding this
1350 +     * tiny safety is easier than educating the world.  This is now
1351 +     * configurable, but the default is still 2 seconds.
1352 +     */
1353 +    if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) { 
1354 +#ifdef __DEBUG_APC__
1355 +        fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
1356 +#endif
1357 +        return 0;
1358 +    }
1359 +
1360 +    key->data.file.device = fileinfo.st_buf.st_dev;
1361 +    key->data.file.inode  = fileinfo.st_buf.st_ino;
1362 +    /* 
1363 +     * If working with content management systems that like to munge the mtime, 
1364 +     * it might be appropriate to key off of the ctime to be immune to systems
1365 +     * that try to backdate a template.  If the mtime is set to something older
1366 +     * than the previous mtime of a template we will obviously never see this
1367 +     * "older" template.  At some point the Smarty templating system did this.
1368 +     * I generally disagree with using the ctime here because you lose the 
1369 +     * ability to warm up new content by saving it to a temporary file, hitting
1370 +     * it once to cache it and then renaming it into its permanent location so
1371 +     * set the apc.stat_ctime=true to enable this check.
1372 +     */
1373 +    if(APCG(stat_ctime)) {
1374 +        key->mtime  = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime; 
1375 +    } else {
1376 +        key->mtime = fileinfo.st_buf.st_mtime;
1377 +    }
1378 +    key->type = APC_CACHE_KEY_FILE;
1379 +    return 1;
1380 +}
1381 +/* }}} */
1382 +
1383 +/* {{{ apc_cache_make_user_key */
1384 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
1385 +{
1386 +    assert(key != NULL);
1387 +
1388 +    if (!identifier)
1389 +        return 0;
1390 +
1391 +    key->data.user.identifier = identifier;
1392 +    key->data.user.identifier_len = identifier_len;
1393 +    key->mtime = t;
1394 +    key->type = APC_CACHE_KEY_USER;
1395 +    return 1;
1396 +}
1397 +/* }}} */
1398 +
1399 +/* {{{ apc_cache_make_file_entry */
1400 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
1401 +                                        zend_op_array* op_array,
1402 +                                        apc_function_t* functions,
1403 +                                        apc_class_t* classes)
1404 +{
1405 +    apc_cache_entry_t* entry;
1406 +
1407 +    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1408 +    if (!entry) return NULL;
1409 +
1410 +    entry->data.file.filename  = apc_xstrdup(filename, apc_sma_malloc);
1411 +    if(!entry->data.file.filename) {
1412 +#ifdef __DEBUG_APC__
1413 +        fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
1414 +#endif
1415 +        apc_sma_free(entry);
1416 +        return NULL;
1417 +    }
1418 +#ifdef __DEBUG_APC__
1419 +    fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
1420 +#endif
1421 +    entry->data.file.op_array  = op_array;
1422 +    entry->data.file.functions = functions;
1423 +    entry->data.file.classes   = classes;
1424 +    entry->type = APC_CACHE_ENTRY_FILE;
1425 +    entry->ref_count = 0;
1426 +    entry->mem_size = 0;
1427 +    entry->local = 0;
1428 +    return entry;
1429 +}
1430 +/* }}} */
1431 +
1432 +/* {{{ apc_cache_store_zval */
1433 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1434 +{
1435 +    smart_str buf = {0};
1436 +    php_serialize_data_t var_hash;
1437 +    TSRMLS_FETCH();
1438 +
1439 +    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1440 +        if(!dst) {
1441 +            CHECK(dst = (zval*) allocate(sizeof(zval)));
1442 +        }
1443 +               
1444 +        PHP_VAR_SERIALIZE_INIT(var_hash);
1445 +        php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
1446 +        PHP_VAR_SERIALIZE_DESTROY(var_hash);
1447 +               
1448 +        dst->type = IS_NULL; /* in case we fail */
1449 +        if(buf.c) {
1450 +            dst->type = src->type & ~IS_CONSTANT_INDEX;
1451 +            dst->value.str.len = buf.len;
1452 +            CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
1453 +            dst->type = src->type;
1454 +            smart_str_free(&buf);
1455 +        }
1456 +        return dst; 
1457 +    } else {
1458 +        
1459 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1460 +        HashTable *old = APCG(copied_zvals);
1461 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1462 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1463 +        
1464 +        dst = apc_copy_zval(dst, src, allocate, deallocate);
1465 +
1466 +        if(APCG(copied_zvals)) {
1467 +            zend_hash_destroy(APCG(copied_zvals));
1468 +            efree(APCG(copied_zvals));
1469 +        }
1470 +
1471 +        APCG(copied_zvals) = old;
1472 +
1473 +        return dst;
1474 +    }
1475 +}
1476 +/* }}} */
1477 +
1478 +/* {{{ apc_cache_fetch_zval */
1479 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1480 +{
1481 +    TSRMLS_FETCH();
1482 +    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1483 +        php_unserialize_data_t var_hash;
1484 +        const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
1485 +
1486 +        PHP_VAR_UNSERIALIZE_INIT(var_hash);
1487 +        if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
1488 +            PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1489 +            zval_dtor(dst);
1490 +            php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
1491 +            dst->type = IS_NULL;
1492 +        }
1493 +        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);         
1494 +        return dst; 
1495 +    } else {
1496 +    
1497 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1498 +        HashTable *old = APCG(copied_zvals);
1499 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1500 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1501 +        
1502 +        dst = apc_copy_zval(dst, src, allocate, deallocate);
1503 +
1504 +        if(APCG(copied_zvals)) {
1505 +            zend_hash_destroy(APCG(copied_zvals));
1506 +            efree(APCG(copied_zvals));
1507 +        }
1508 +
1509 +        APCG(copied_zvals) = old;
1510 +
1511 +        return dst;
1512 +    }
1513 +}
1514 +/* }}} */
1515 +
1516 +/* {{{ apc_cache_free_zval */
1517 +void apc_cache_free_zval(zval* src, apc_free_t deallocate)
1518 +{
1519 +    TSRMLS_FETCH();
1520 +    if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1521 +        if (src->value.str.val) {
1522 +               deallocate(src->value.str.val);
1523 +        }
1524 +        deallocate(src);
1525 +    } else {
1526 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1527 +        HashTable *old = APCG(copied_zvals);
1528 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1529 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1530 +        
1531 +        apc_free_zval(src, deallocate);
1532 +
1533 +        if(APCG(copied_zvals)) {
1534 +            zend_hash_destroy(APCG(copied_zvals));
1535 +            efree(APCG(copied_zvals));
1536 +        }
1537 +
1538 +        APCG(copied_zvals) = old;
1539 +    }
1540 +}
1541 +/* }}} */
1542 +
1543 +/* {{{ apc_cache_make_user_entry */
1544 +apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
1545 +{
1546 +    apc_cache_entry_t* entry;
1547 +
1548 +    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1549 +    if (!entry) return NULL;
1550 +
1551 +    entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
1552 +    entry->data.user.info_len = info_len;
1553 +    if(!entry->data.user.info) {
1554 +        apc_sma_free(entry);
1555 +        return NULL;
1556 +    }
1557 +    entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
1558 +    if(!entry->data.user.val) {
1559 +        apc_sma_free(entry->data.user.info);
1560 +        apc_sma_free(entry);
1561 +        return NULL;
1562 +    }
1563 +    INIT_PZVAL(entry->data.user.val);
1564 +    entry->data.user.ttl = ttl;
1565 +    entry->type = APC_CACHE_ENTRY_USER;
1566 +    entry->ref_count = 0;
1567 +    entry->mem_size = 0;
1568 +    entry->local = 0;
1569 +    return entry;
1570 +}
1571 +/* }}} */
1572 +
1573 +/* {{{ apc_cache_free_entry */
1574 +void apc_cache_free_entry(apc_cache_entry_t* entry)
1575 +{
1576 +    if (entry != NULL) {
1577 +        assert(entry->ref_count == 0);
1578 +        switch(entry->type) {
1579 +            case APC_CACHE_ENTRY_FILE:
1580 +                apc_sma_free(entry->data.file.filename);
1581 +                apc_free_op_array(entry->data.file.op_array, apc_sma_free);
1582 +                apc_free_functions(entry->data.file.functions, apc_sma_free);
1583 +                apc_free_classes(entry->data.file.classes, apc_sma_free);
1584 +                break;
1585 +            case APC_CACHE_ENTRY_USER:
1586 +                apc_sma_free(entry->data.user.info);
1587 +                apc_cache_free_zval(entry->data.user.val, apc_sma_free);
1588 +                break;
1589 +        }
1590 +        apc_sma_free(entry);
1591 +    }
1592 +}
1593 +/* }}} */
1594 +
1595 +/* {{{ apc_cache_info */
1596 +apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
1597 +{
1598 +    apc_cache_info_t* info;
1599 +    slot_t* p;
1600 +    int i;
1601 +
1602 +    if(!cache) return NULL;
1603 +
1604 +    LOCK(cache);
1605 +
1606 +    info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
1607 +    if(!info) {
1608 +        UNLOCK(cache);
1609 +        return NULL;
1610 +    }
1611 +    info->num_slots = cache->num_slots;
1612 +    info->ttl = cache->ttl;
1613 +    info->num_hits = cache->header->num_hits;
1614 +    info->num_misses = cache->header->num_misses;
1615 +    info->list = NULL;
1616 +    info->deleted_list = NULL;
1617 +    info->start_time = cache->header->start_time;
1618 +    info->expunges = cache->header->expunges;
1619 +    info->mem_size = cache->header->mem_size;
1620 +    info->num_entries = cache->header->num_entries;
1621 +    info->num_inserts = cache->header->num_inserts;
1622 +
1623 +    if(!limited) {
1624 +        /* For each hashtable slot */
1625 +        for (i = 0; i < info->num_slots; i++) {
1626 +            p = cache->slots[i];
1627 +            for (; p != NULL; p = p->next) {
1628 +                apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1629 +
1630 +                if(p->value->type == APC_CACHE_ENTRY_FILE) {
1631 +                    link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1632 +                    link->data.file.device = p->key.data.file.device;
1633 +                    link->data.file.inode = p->key.data.file.inode;
1634 +                    link->type = APC_CACHE_ENTRY_FILE;
1635 +                } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1636 +                    link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1637 +                    link->data.user.ttl = p->value->data.user.ttl;
1638 +                    link->type = APC_CACHE_ENTRY_USER;
1639 +                }
1640 +                link->num_hits = p->num_hits;
1641 +                link->mtime = p->key.mtime;
1642 +                link->creation_time = p->creation_time;
1643 +                link->deletion_time = p->deletion_time;
1644 +                link->access_time = p->access_time;
1645 +                link->ref_count = p->value->ref_count;
1646 +                link->mem_size = p->value->mem_size;
1647 +                link->next = info->list;
1648 +                info->list = link;
1649 +            }
1650 +        }
1651 +
1652 +        /* For each slot pending deletion */
1653 +        for (p = cache->header->deleted_list; p != NULL; p = p->next) {
1654 +            apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1655 +
1656 +            if(p->value->type == APC_CACHE_ENTRY_FILE) {
1657 +                link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1658 +                if(p->key.type == APC_CACHE_KEY_FILE) {
1659 +                    link->data.file.device = p->key.data.file.device;
1660 +                    link->data.file.inode = p->key.data.file.inode;
1661 +                } else { /* This is a no-stat fullpath file entry */
1662 +                    link->data.file.device = 0;
1663 +                    link->data.file.inode = 0;
1664 +                }
1665 +                link->type = APC_CACHE_ENTRY_FILE;
1666 +            } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1667 +                link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1668 +                link->data.user.ttl = p->value->data.user.ttl;
1669 +                link->type = APC_CACHE_ENTRY_USER;
1670 +            }
1671 +            link->num_hits = p->num_hits;
1672 +            link->mtime = p->key.mtime;
1673 +            link->creation_time = p->creation_time;
1674 +            link->deletion_time = p->deletion_time;
1675 +            link->access_time = p->access_time;
1676 +            link->ref_count = p->value->ref_count;
1677 +            link->mem_size = p->value->mem_size;
1678 +            link->next = info->deleted_list;
1679 +            info->deleted_list = link;
1680 +        }
1681 +    }
1682 +
1683 +    UNLOCK(cache);
1684 +    return info;
1685 +}
1686 +/* }}} */
1687 +
1688 +/* {{{ apc_cache_free_info */
1689 +void apc_cache_free_info(apc_cache_info_t* info)
1690 +{
1691 +    apc_cache_link_t* p = info->list;
1692 +    apc_cache_link_t* q = NULL;
1693 +    while (p != NULL) {
1694 +        q = p;
1695 +        p = p->next;
1696 +        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1697 +        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1698 +        apc_efree(q);
1699 +    }
1700 +    p = info->deleted_list;
1701 +    while (p != NULL) {
1702 +        q = p;
1703 +        p = p->next;
1704 +        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1705 +        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1706 +        apc_efree(q);
1707 +    }
1708 +    apc_efree(info);
1709 +}
1710 +/* }}} */
1711 +
1712 +/* {{{ apc_cache_unlock */
1713 +void apc_cache_unlock(apc_cache_t* cache)
1714 +{
1715 +    UNLOCK(cache);
1716 +}
1717 +/* }}} */
1718 +
1719 +/* {{{ apc_cache_busy */
1720 +zend_bool apc_cache_busy(apc_cache_t* cache)
1721 +{
1722 +    return cache->header->busy;
1723 +}
1724 +/* }}} */
1725 +
1726 +#if NONBLOCKING_LOCK_AVAILABLE
1727 +/* {{{ apc_cache_write_lock */
1728 +zend_bool apc_cache_write_lock(apc_cache_t* cache)
1729 +{
1730 +    return apc_lck_nb_lock(cache->header->wrlock);
1731 +}
1732 +/* }}} */
1733 +
1734 +/* {{{ apc_cache_write_unlock */
1735 +void apc_cache_write_unlock(apc_cache_t* cache)
1736 +{
1737 +    apc_lck_unlock(cache->header->wrlock);
1738 +}
1739 +/* }}} */
1740 +#endif
1741 +
1742 +/* {{{ make_local_slot */
1743 +static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot, time_t t) 
1744 +{
1745 +    apc_cache_entry_t* value;
1746 +
1747 +    value = apc_emalloc(sizeof(apc_cache_entry_t));
1748 +    memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
1749 +    value->local = 1;
1750 +
1751 +    lslot->original = slot;
1752 +    lslot->value = value;
1753 +    lslot->num_hits = 0;
1754 +    lslot->creation_time = t;
1755 +
1756 +    return lslot; /* for what joy ? ... consistency */
1757 +}
1758 +/* }}} */
1759 +
1760 +/* {{{ free_local_slot */
1761 +static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot) 
1762 +{
1763 +    local_slot_t * dead = NULL;
1764 +    if(!lslot->original) return;
1765 +
1766 +    /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
1767 +    dead = apc_emalloc(sizeof(local_slot_t));
1768 +    memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
1769 +
1770 +    lslot->original = NULL;
1771 +    lslot->value = NULL;
1772 +
1773 +    dead->next = cache->dead_list;
1774 +    cache->dead_list = dead;
1775 +}
1776 +/* }}} */
1777 +
1778 +/* {{{ apc_local_cache_create */
1779 +apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
1780 +{
1781 +    apc_local_cache_t* cache = NULL;
1782 +
1783 +    cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
1784 +
1785 +    cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
1786 +    memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
1787 +
1788 +    cache->shmcache = shmcache;
1789 +    cache->num_slots = num_slots;
1790 +    cache->ttl = ttl;
1791 +    cache->num_hits = 0;
1792 +    cache->generation = shmcache->header->expunges;
1793 +    cache->dead_list = NULL;
1794 +
1795 +    return cache;
1796 +}
1797 +/* }}} */
1798 +
1799 +/* {{{ apc_local_cache_cleanup */
1800 +void apc_local_cache_cleanup(apc_local_cache_t* cache) {
1801 +    local_slot_t * lslot;
1802 +    time_t t = time(0);
1803 +    
1804 +    int i;
1805 +    for(i = 0; i < cache->num_slots; i++) {
1806 +        lslot = &cache->slots[i];
1807 +        /* every slot lives for exactly TTL seconds */
1808 +        if((lslot->original && lslot->creation_time < (t - cache->ttl)) ||
1809 +                cache->generation != cache->shmcache->header->expunges) {
1810 +            free_local_slot(cache, lslot);
1811 +        }
1812 +    }
1813 +
1814 +    LOCK(cache->shmcache);
1815 +    for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
1816 +        lslot->original->num_hits += lslot->num_hits;
1817 +        lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
1818 +        apc_efree(lslot->value);
1819 +    }
1820 +    UNLOCK(cache->shmcache);
1821 +
1822 +    cache->dead_list = NULL;
1823 +}
1824 +/* }}} */
1825 +
1826 +/* {{{ apc_local_cache_destroy */
1827 +void apc_local_cache_destroy(apc_local_cache_t* cache)
1828 +{
1829 +    int i;
1830 +    for(i = 0; i < cache->num_slots; i++) {
1831 +        free_local_slot(cache, &cache->slots[i]);
1832 +    }
1833 +
1834 +    apc_local_cache_cleanup(cache);
1835 +
1836 +    LOCK(cache->shmcache);
1837 +    cache->shmcache->header->num_hits += cache->num_hits;
1838 +    UNLOCK(cache->shmcache);
1839 +
1840 +    apc_efree(cache->slots);
1841 +    apc_efree(cache);
1842 +}
1843 +/* }}} */
1844 +
1845 +/* {{{ apc_local_cache_find */
1846 +apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
1847 +{
1848 +    slot_t* slot;
1849 +    local_slot_t* lslot; 
1850 +
1851 +    if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
1852 +    else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1853 +
1854 +    slot = lslot->original;
1855 +
1856 +    if(slot && key.type == slot->key.type) {
1857 +        if(slot->access_time < (t - cache->ttl)) {
1858 +            goto not_found;
1859 +        }
1860 +        if(key.type == APC_CACHE_KEY_FILE && 
1861 +           key_equals(slot->key.data.file, key.data.file)) {
1862 +            if(slot->key.mtime != key.mtime) {
1863 +                free_local_slot(cache, lslot);
1864 +                goto not_found;
1865 +            }
1866 +            cache->num_hits++;
1867 +            lslot->num_hits++;
1868 +            lslot->original->access_time = t; /* unlocked write, but last write wins */
1869 +            return lslot->value;
1870 +        } else if(key.type == APC_CACHE_KEY_FPFILE) {
1871 +            if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1872 +                cache->num_hits++;
1873 +                lslot->num_hits++;
1874 +                lslot->original->access_time = t; /* unlocked write, but last write wins */
1875 +                return lslot->value;
1876 +            }
1877 +        }
1878 +    }
1879 +not_found:
1880 +    if(apc_cache_busy(cache->shmcache)) {
1881 +        return NULL;
1882 +    }
1883 +
1884 +    slot = apc_cache_find_slot(cache->shmcache, key, t);
1885 +
1886 +    if(!slot) return NULL;
1887 +   
1888 +    /* i.e maintain a sort of top list */
1889 +    if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits)  < slot->num_hits) {
1890 +        free_local_slot(cache, lslot);
1891 +        make_local_slot(cache, lslot, slot, t); 
1892 +        return lslot->value;
1893 +    }
1894 +    return slot->value;
1895 +}
1896 +/* }}} */
1897 +
1898 +/*
1899 + * Local variables:
1900 + * tab-width: 4
1901 + * c-basic-offset: 4
1902 + * End:
1903 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1904 + * vim<600: expandtab sw=4 ts=4 sts=4
1905 + */
1906 diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.h php-5.2.5/ext/apc/apc_cache.h
1907 --- php-5.2.5-orig/ext/apc/apc_cache.h  1969-12-31 18:00:00.000000000 -0600
1908 +++ php-5.2.5/ext/apc/apc_cache.h       2007-12-26 16:51:32.000000000 -0600
1909 @@ -0,0 +1,312 @@
1910 +/*
1911 +  +----------------------------------------------------------------------+
1912 +  | APC                                                                  |
1913 +  +----------------------------------------------------------------------+
1914 +  | Copyright (c) 2006 The PHP Group                                     |
1915 +  +----------------------------------------------------------------------+
1916 +  | This source file is subject to version 3.01 of the PHP license,      |
1917 +  | that is bundled with this package in the file LICENSE, and is        |
1918 +  | available through the world-wide-web at the following url:           |
1919 +  | http://www.php.net/license/3_01.txt.                                 |
1920 +  | If you did not receive a copy of the PHP license and are unable to   |
1921 +  | obtain it through the world-wide-web, please send a note to          |
1922 +  | license@php.net so we can mail you a copy immediately.               |
1923 +  +----------------------------------------------------------------------+
1924 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
1925 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
1926 +  +----------------------------------------------------------------------+
1927 +
1928 +   This software was contributed to PHP by Community Connect Inc. in 2002
1929 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1930 +   Future revisions and derivatives of this source code must acknowledge
1931 +   Community Connect Inc. as the original contributor of this module by
1932 +   leaving this note intact in the source code.
1933 +
1934 +   All other licensing and usage conditions are those of the PHP Group.
1935 +
1936 + */
1937 +
1938 +/* $Id: apc_cache.h,v 3.46 2007/10/05 23:06:56 gopalv Exp $ */
1939 +
1940 +#ifndef APC_CACHE_H
1941 +#define APC_CACHE_H
1942 +
1943 +/*
1944 + * This module defines the shared memory file cache. Basically all of the
1945 + * logic for storing and retrieving cache entries lives here.
1946 + */
1947 +
1948 +#include "apc.h"
1949 +#include "apc_compile.h"
1950 +
1951 +#define APC_CACHE_ENTRY_FILE   1
1952 +#define APC_CACHE_ENTRY_USER   2
1953 +
1954 +#define APC_CACHE_KEY_FILE     1
1955 +#define APC_CACHE_KEY_USER     2
1956 +#define APC_CACHE_KEY_FPFILE   3
1957 +
1958 +/* {{{ struct definition: apc_cache_key_t */
1959 +#define T apc_cache_t*
1960 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
1961 +
1962 +typedef union _apc_cache_key_data_t {
1963 +    struct {
1964 +        dev_t device;             /* the filesystem device */
1965 +        ino_t inode;              /* the filesystem inode */
1966 +    } file;
1967 +    struct {
1968 +        const char *identifier;
1969 +        int identifier_len;
1970 +    } user;
1971 +    struct {
1972 +        const char *fullpath;
1973 +        int fullpath_len;
1974 +    } fpfile;
1975 +} apc_cache_key_data_t;
1976 +
1977 +typedef struct apc_cache_key_t apc_cache_key_t;
1978 +struct apc_cache_key_t {
1979 +    apc_cache_key_data_t data;
1980 +    time_t mtime;                 /* the mtime of this cached entry */
1981 +    unsigned char type;
1982 +};
1983 +/* }}} */
1984 +
1985 +/* {{{ struct definition: apc_cache_entry_t */
1986 +typedef union _apc_cache_entry_value_t {
1987 +    struct {
1988 +        char *filename;             /* absolute path to source file */
1989 +        zend_op_array* op_array;    /* op_array allocated in shared memory */
1990 +        apc_function_t* functions;  /* array of apc_function_t's */
1991 +        apc_class_t* classes;       /* array of apc_class_t's */
1992 +    } file;
1993 +    struct {
1994 +        char *info; 
1995 +        int info_len; 
1996 +        zval *val;
1997 +        unsigned int ttl;
1998 +    } user;
1999 +} apc_cache_entry_value_t;
2000 +
2001 +typedef struct apc_cache_entry_t apc_cache_entry_t;
2002 +struct apc_cache_entry_t {
2003 +    apc_cache_entry_value_t data;
2004 +    unsigned char type;
2005 +    unsigned char local;
2006 +    int ref_count;
2007 +    size_t mem_size;
2008 +};
2009 +/* }}} */
2010 +
2011 +/*
2012 + * apc_cache_create creates the shared memory compiler cache. This function
2013 + * should be called just once (ideally in the web server parent process, e.g.
2014 + * in apache), otherwise you will end up with multiple caches (which won't
2015 + * necessarily break anything). Returns a pointer to the cache object.
2016 + *
2017 + * size_hint is a "hint" at the total number of source files that will be
2018 + * cached. It determines the physical size of the hash table. Passing 0 for
2019 + * this argument will use a reasonable default value.
2020 + *
2021 + * gc_ttl is the maximum time a cache entry may speed on the garbage
2022 + * collection list. This is basically a work around for the inherent
2023 + * unreliability of our reference counting mechanism (see apc_cache_release).
2024 + *
2025 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
2026 + * is needed.  This helps in cleaning up the cache and ensuring that entries 
2027 + * hit frequently stay cached and ones not hit very often eventually disappear.
2028 + */
2029 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
2030 +
2031 +/*
2032 + * apc_cache_destroy releases any OS resources associated with a cache object.
2033 + * Under apache, this function can be safely called by the child processes
2034 + * when they exit.
2035 + */
2036 +extern void apc_cache_destroy(T cache);
2037 +
2038 +/*
2039 + * apc_cache_clear empties a cache. This can safely be called at any time,
2040 + * even while other server processes are executing cached source files.
2041 + */
2042 +extern void apc_cache_clear(T cache);
2043 +
2044 +/*
2045 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
2046 + * Internally, the filename is translated to a canonical representation, so
2047 + * that relative and absolute filenames will map to a single key. Returns
2048 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
2049 + * returned, the caller must free the cache entry by calling
2050 + * apc_cache_free_entry (see below).
2051 + *
2052 + * key is the value created by apc_cache_make_file_key for file keys.
2053 + *
2054 + * value is a cache entry returned by apc_cache_make_entry (see below).
2055 + */
2056 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
2057 +                            apc_cache_entry_t* value, time_t t);
2058 +
2059 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
2060 +                            apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
2061 +
2062 +/*
2063 + * apc_cache_find searches for a cache entry by filename, and returns a
2064 + * pointer to the entry if found, NULL otherwise.
2065 + *
2066 + * key is a value created by apc_cache_make_file_key for file keys.
2067 + */
2068 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
2069 +
2070 +/*
2071 + * apc_cache_user_find searches for a cache entry by its hashed identifier, 
2072 + * and returns a pointer to the entry if found, NULL otherwise.
2073 + *
2074 + */
2075 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
2076 +
2077 +/*
2078 + * apc_cache_user_delete finds an entry in the user cache and deletes it.
2079 + */
2080 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
2081 +
2082 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
2083 + * zval from it.
2084 + *
2085 + */
2086 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
2087 +
2088 +/*
2089 + * apc_cache_release decrements the reference count associated with a cache
2090 + * entry. Calling apc_cache_find automatically increments the reference count,
2091 + * and this function must be called post-execution to return the count to its
2092 + * original value. Failing to do so will prevent the entry from being
2093 + * garbage-collected.
2094 + *
2095 + * entry is the cache entry whose ref count you want to decrement.
2096 + */
2097 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
2098 +
2099 +/*
2100 + * apc_cache_make_file_key creates a key object given a relative or absolute
2101 + * filename and an optional list of auxillary paths to search. include_path is
2102 + * searched if the filename cannot be found relative to the current working
2103 + * directory.
2104 + *
2105 + * key points to caller-allocated storage (must not be null).
2106 + *
2107 + * filename is the path to the source file.
2108 + *
2109 + * include_path is a colon-separated list of directories to search.
2110 + *
2111 + * and finally we pass in the current request time so we can avoid
2112 + * caching files with a current mtime which tends to indicate that
2113 + * they are still being written to.
2114 + */
2115 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
2116 +                                   const char* filename,
2117 +                                   const char* include_path,
2118 +                                   time_t t
2119 +                                                              TSRMLS_DC);
2120 +
2121 +/*
2122 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
2123 + * and the compilation results returned by the PHP compiler.
2124 + */
2125 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2126 +                                                    zend_op_array* op_array,
2127 +                                                    apc_function_t* functions,
2128 +                                                    apc_class_t* classes);
2129 +/*
2130 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
2131 + * and the zval to be stored.
2132 + */
2133 +extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
2134 +
2135 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
2136 +
2137 +/*
2138 + * Frees all memory associated with an object returned by apc_cache_make_entry
2139 + * (see above).
2140 + */
2141 +extern void apc_cache_free_entry(apc_cache_entry_t* entry);
2142 +
2143 +/* {{{ struct definition: apc_cache_link_data_t */
2144 +typedef union _apc_cache_link_data_t {
2145 +    struct {
2146 +        char *filename;
2147 +        dev_t device;
2148 +        ino_t inode;
2149 +    } file;
2150 +    struct {
2151 +        char *info;
2152 +        unsigned int ttl;
2153 +    } user;
2154 +} apc_cache_link_data_t;
2155 +/* }}} */
2156 +
2157 +/* {{{ struct definition: apc_cache_link_t */
2158 +typedef struct apc_cache_link_t apc_cache_link_t;
2159 +struct apc_cache_link_t {
2160 +    apc_cache_link_data_t data;
2161 +    unsigned char type;
2162 +    int num_hits;
2163 +    time_t mtime;
2164 +    time_t creation_time;
2165 +    time_t deletion_time;
2166 +    time_t access_time;
2167 +    int ref_count;
2168 +    size_t mem_size;
2169 +    apc_cache_link_t* next;
2170 +};
2171 +/* }}} */
2172 +
2173 +/* {{{ struct definition: apc_cache_info_t */
2174 +typedef struct apc_cache_info_t apc_cache_info_t;
2175 +struct apc_cache_info_t {
2176 +    int num_slots;
2177 +    int num_hits;
2178 +    int num_misses;
2179 +    int ttl;
2180 +    apc_cache_link_t* list;
2181 +    apc_cache_link_t* deleted_list;
2182 +    time_t start_time;
2183 +    int expunges;
2184 +    int num_entries;
2185 +    int num_inserts;
2186 +    size_t mem_size;
2187 +};
2188 +/* }}} */
2189 +
2190 +extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
2191 +extern void apc_cache_free_info(apc_cache_info_t* info);
2192 +extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
2193 +extern void apc_cache_unlock(apc_cache_t* cache);
2194 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
2195 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
2196 +extern void apc_cache_write_unlock(apc_cache_t* cache);
2197 +
2198 +/* 
2199 + * Process local cache, which keeps a refcount hungry version of the slots
2200 + * for quick access without a lock - as long as the entry exists in local
2201 + * cache, the refcount of the shm version will be +1 more than required.
2202 + * It holds no data, only a shallow copy of apc_cache_entry.
2203 + */
2204 +typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */ 
2205 +
2206 +extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
2207 +extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
2208 +extern void apc_local_cache_destroy(apc_local_cache_t* cache);
2209 +extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
2210 +
2211 +#undef T
2212 +#endif
2213 +
2214 +/*
2215 + * Local variables:
2216 + * tab-width: 4
2217 + * c-basic-offset: 4
2218 + * End:
2219 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
2220 + * vim<600: expandtab sw=4 ts=4 sts=4
2221 + */
2222 diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.c php-5.2.5/ext/apc/apc_compile.c
2223 --- php-5.2.5-orig/ext/apc/apc_compile.c        1969-12-31 18:00:00.000000000 -0600
2224 +++ php-5.2.5/ext/apc/apc_compile.c     2007-12-26 16:51:32.000000000 -0600
2225 @@ -0,0 +1,2529 @@
2226 +/*
2227 +  +----------------------------------------------------------------------+
2228 +  | APC                                                                  |
2229 +  +----------------------------------------------------------------------+
2230 +  | Copyright (c) 2006 The PHP Group                                     |
2231 +  +----------------------------------------------------------------------+
2232 +  | This source file is subject to version 3.01 of the PHP license,      |
2233 +  | that is bundled with this package in the file LICENSE, and is        |
2234 +  | available through the world-wide-web at the following url:           |
2235 +  | http://www.php.net/license/3_01.txt.                                 |
2236 +  | If you did not receive a copy of the PHP license and are unable to   |
2237 +  | obtain it through the world-wide-web, please send a note to          |
2238 +  | license@php.net so we can mail you a copy immediately.               |
2239 +  +----------------------------------------------------------------------+
2240 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
2241 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
2242 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
2243 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
2244 +  +----------------------------------------------------------------------+
2245 +
2246 +   This software was contributed to PHP by Community Connect Inc. in 2002
2247 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
2248 +   Future revisions and derivatives of this source code must acknowledge
2249 +   Community Connect Inc. as the original contributor of this module by
2250 +   leaving this note intact in the source code.
2251 +
2252 +   All other licensing and usage conditions are those of the PHP Group.
2253 +
2254 + */
2255 +
2256 +/* $Id: apc_compile.c,v 3.87 2007/08/25 13:09:13 gopalv Exp $ */
2257 +
2258 +#include "apc_compile.h"
2259 +#include "apc_globals.h"
2260 +#include "apc_zend.h"
2261 +
2262 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
2263 +typedef void  (*ht_free_fun_t)(void*, apc_free_t);
2264 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
2265 +
2266 +#ifdef ZEND_ENGINE_2
2267 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
2268 +#endif
2269 +
2270 +#define CHECK(p) { if ((p) == NULL) return NULL; }
2271 +
2272 +/* {{{ internal function declarations */
2273 +
2274 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
2275 +
2276 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
2277 +
2278 +/*
2279 + * The "copy" functions perform deep-copies on a particular data structure
2280 + * (passed as the second argument). They also optionally allocate space for
2281 + * the destination data structure if the first argument is null.
2282 + */
2283 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
2284 +static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
2285 +static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
2286 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
2287 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
2288 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
2289 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
2290 +static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, ht_free_fun_t, int, apc_malloc_t, apc_free_t, ht_check_copy_fun_t, ...);
2291 +#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
2292 +    my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
2293 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
2294 +#ifdef ZEND_ENGINE_2
2295 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
2296 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
2297 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
2298 +#endif
2299 +/*
2300 + * The "destroy" functions free the memory associated with a particular data
2301 + * structure but do not free the pointer to the data structure.
2302 + *
2303 + * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
2304 + * the zval* has other references elsewhere 
2305 + */
2306 +static int  my_destroy_zval(zval*, apc_free_t); 
2307 +static void my_destroy_zval_ptr(zval**, apc_free_t);
2308 +static void my_destroy_zend_op(zend_op*, apc_free_t);
2309 +static void my_destroy_znode(znode*, apc_free_t);
2310 +static void my_destroy_function(zend_function*, apc_free_t);
2311 +static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
2312 +static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
2313 +static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2314 +static void my_destroy_op_array(zend_op_array*, apc_free_t);
2315 +#ifdef ZEND_ENGINE_2
2316 +static void my_destroy_property_info(zend_property_info*, apc_free_t);
2317 +static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
2318 +static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
2319 +#endif
2320 +
2321 +/*
2322 + * The "free" functions work exactly like their "destroy" counterparts (see
2323 + * above) but also free the pointer to the data structure.
2324 + */
2325 +static void my_free_zval_ptr(zval**, apc_free_t);
2326 +static void my_free_function(zend_function*, apc_free_t);
2327 +static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2328 +#ifdef ZEND_ENGINE_2
2329 +static void my_free_property_info(zend_property_info* src, apc_free_t);
2330 +static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
2331 +static void my_free_arg_info(zend_arg_info*, apc_free_t);
2332 +#endif
2333 +
2334 +/*
2335 + * The "fixup" functions need for ZEND_ENGINE_2
2336 + */
2337 +#ifdef ZEND_ENGINE_2
2338 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2339 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
2340 +/* my_fixup_function_for_execution is the same as my_fixup_function
2341 + * but named differently for clarity
2342 + */
2343 +#define my_fixup_function_for_execution my_fixup_function
2344 +
2345 +#ifdef ZEND_ENGINE_2_2
2346 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2347 +#define my_fixup_property_info_for_execution my_fixup_property_info
2348 +#endif
2349 +
2350 +#endif
2351 +
2352 +/*
2353 + * These functions return "1" if the member/function is
2354 + * defined/overridden in the 'current' class and not inherited.
2355 + */
2356 +static int my_check_copy_function(Bucket* src, va_list args);
2357 +static int my_check_copy_default_property(Bucket* p, va_list args);
2358 +#ifdef ZEND_ENGINE_2
2359 +static int my_check_copy_property_info(Bucket* src, va_list args);
2360 +static int my_check_copy_static_member(Bucket* src, va_list args);
2361 +#endif
2362 +
2363 +/* }}} */
2364 +
2365 +/* {{{ check_op_array_integrity */
2366 +#if 0
2367 +static void check_op_array_integrity(zend_op_array* src)
2368 +{
2369 +    int i, j;
2370 +
2371 +    /* These sorts of checks really aren't particularly effective, but they
2372 +     * can provide a welcome sanity check when debugging. Just don't enable
2373 +     * for production use!  */
2374 +
2375 +    assert(src->refcount != NULL);
2376 +    assert(src->opcodes != NULL);
2377 +    assert(src->last > 0);
2378 +
2379 +    for (i = 0; i < src->last; i++) {
2380 +        zend_op* op = &src->opcodes[i];
2381 +        znode* nodes[] = { &op->result, &op->op1, &op->op2 };
2382 +        for (j = 0; j < 3; j++) {
2383 +            assert(nodes[j]->op_type == IS_CONST ||
2384 +                   nodes[j]->op_type == IS_VAR ||
2385 +                   nodes[j]->op_type == IS_TMP_VAR ||
2386 +                   nodes[j]->op_type == IS_UNUSED);
2387 +
2388 +            if (nodes[j]->op_type == IS_CONST) {
2389 +                int type = nodes[j]->u.constant.type;
2390 +                assert(type == IS_RESOURCE ||
2391 +                       type == IS_BOOL ||
2392 +                       type == IS_LONG ||
2393 +                       type == IS_DOUBLE ||
2394 +                       type == IS_NULL ||
2395 +                       type == IS_CONSTANT ||
2396 +                       type == IS_STRING ||
2397 +                       type == FLAG_IS_BC ||
2398 +                       type == IS_ARRAY ||
2399 +                       type == IS_CONSTANT_ARRAY ||
2400 +                       type == IS_OBJECT);
2401 +            }
2402 +        }
2403 +    }
2404 +}
2405 +#endif
2406 +/* }}} */
2407 +
2408 +/* {{{ is_derived_class */
2409 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
2410 +{
2411 +    int i;
2412 +
2413 +    /*
2414 +     * Scan the op_array for execution-time class declarations of derived
2415 +     * classes. If we find one whose key matches our current class key, we
2416 +     * know the current class is a derived class.
2417 +     *
2418 +     * This check is exceedingly inefficient (fortunately it only has to occur
2419 +     * once, when the source file is first compiled and cached), but the
2420 +     * compiler should save this information for us -- definitely a candidate
2421 +     * for a Zend Engine patch.
2422 +     *
2423 +     * XXX checking for derived classes provides a minimal (albeit measurable)
2424 +     * speed up. It may not be worth the added complexity -- considere
2425 +     * removing this optimization.
2426 +     */
2427 +
2428 +    for (i = 0; i < op_array->last; i++) {
2429 +        zend_op* op = &op_array->opcodes[i];
2430 +
2431 +#ifdef ZEND_ENGINE_2        
2432 +        if (op->opcode == ZEND_DECLARE_CLASS &&
2433 +            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2434 +#else            
2435 +        if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
2436 +            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2437 +#endif            
2438 +        {
2439 +            if (op->op1.u.constant.value.str.len == key_size &&
2440 +                !memcmp(op->op1.u.constant.value.str.val, key, key_size))
2441 +            {
2442 +                return 1;
2443 +            }
2444 +        }
2445 +    }
2446 +
2447 +    return 0;
2448 +}
2449 +/* }}} */
2450 +
2451 +/* {{{ my_bitwise_copy_function */
2452 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
2453 +{
2454 +    assert(src != NULL);
2455 +
2456 +    if (!dst) {
2457 +        CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
2458 +    }
2459 +
2460 +    /* We only need to do a bitwise copy */
2461 +    memcpy(dst, src, sizeof(src[0]));
2462 +
2463 +    return dst;
2464 +}
2465 +/* }}} */
2466 +
2467 +/* {{{ my_copy_zval_ptr */
2468 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
2469 +{
2470 +    int local_dst_alloc = 0;
2471 +    zval* dst_new;
2472 +    
2473 +    assert(src != NULL);
2474 +
2475 +    if (!dst) {
2476 +        CHECK(dst = (zval**) allocate(sizeof(zval*)));
2477 +        local_dst_alloc = 1;
2478 +    }
2479 +
2480 +    if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
2481 +        if(local_dst_alloc) deallocate(dst);
2482 +        return NULL;
2483 +    }
2484 +    dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
2485 +    if(dst_new != *dst) {
2486 +        deallocate(*dst);
2487 +        *dst = dst_new;
2488 +    }
2489 +
2490 +    (*dst)->refcount = (*src)->refcount;
2491 +    (*dst)->is_ref = (*src)->is_ref;
2492 +    
2493 +    return dst;
2494 +}
2495 +/* }}} */
2496 +
2497 +/* {{{ my_copy_zval */
2498 +static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
2499 +{
2500 +    zval **tmp;
2501 +    TSRMLS_FETCH();
2502 +    
2503 +    assert(dst != NULL);
2504 +    assert(src != NULL);
2505 +
2506 +    memcpy(dst, src, sizeof(src[0]));
2507 +
2508 +    switch (src->type & ~IS_CONSTANT_INDEX) {
2509 +    case IS_RESOURCE:
2510 +    case IS_BOOL:
2511 +    case IS_LONG:
2512 +    case IS_DOUBLE:
2513 +    case IS_NULL:
2514 +        break;
2515 +
2516 +    case IS_CONSTANT:
2517 +    case IS_STRING:
2518 +#ifndef ZEND_ENGINE_2        
2519 +    case FLAG_IS_BC:
2520 +#endif        
2521 +        if (src->value.str.val) {
2522 +            CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
2523 +                                                   src->value.str.len+1,
2524 +                                                   allocate));
2525 +        }
2526 +        break;
2527 +    
2528 +    case IS_ARRAY:
2529 +
2530 +        if(APCG(copied_zvals)) {
2531 +            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
2532 +                (*tmp)->refcount++;
2533 +                return *tmp;
2534 +            }
2535 +        
2536 +            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
2537 +        }
2538 +        /* fall through */
2539
2540 +    case IS_CONSTANT_ARRAY:
2541 +
2542 +        CHECK(dst->value.ht =
2543 +            my_copy_hashtable(NULL,
2544 +                              src->value.ht,
2545 +                              (ht_copy_fun_t) my_copy_zval_ptr,
2546 +                              (ht_free_fun_t) my_free_zval_ptr,
2547 +                              1,
2548 +                              allocate, deallocate));
2549 +        break;
2550 +
2551 +    case IS_OBJECT:
2552 +#ifndef ZEND_ENGINE_2        
2553 +        CHECK(dst->value.obj.ce =
2554 +            my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
2555 +
2556 +        if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
2557 +                              src->value.obj.properties,
2558 +                              (ht_copy_fun_t) my_copy_zval_ptr,
2559 +                              (ht_free_fun_t) my_free_zval_ptr,
2560 +                              1,
2561 +                              allocate, deallocate))) {
2562 +            my_destroy_class_entry(dst->value.obj.ce, deallocate);
2563 +            return NULL;
2564 +        }
2565 +        break;
2566 +#else
2567 +       dst->type = IS_NULL;
2568 +#endif        
2569 +        break;
2570 +
2571 +    default:
2572 +        assert(0);
2573 +    }
2574 +
2575 +    return dst;
2576 +}
2577 +/* }}} */
2578 +
2579 +/* {{{ my_copy_znode */
2580 +static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
2581 +{
2582 +    assert(dst != NULL);
2583 +    assert(src != NULL);
2584 +
2585 +    memcpy(dst, src, sizeof(src[0]));
2586 +
2587 +#ifdef IS_CV
2588 +    assert(dst ->op_type == IS_CONST ||
2589 +           dst ->op_type == IS_VAR ||
2590 +           dst ->op_type == IS_CV ||
2591 +           dst ->op_type == IS_TMP_VAR ||
2592 +           dst ->op_type == IS_UNUSED);
2593 +#else
2594 +    assert(dst ->op_type == IS_CONST ||
2595 +           dst ->op_type == IS_VAR ||
2596 +           dst ->op_type == IS_TMP_VAR ||
2597 +           dst ->op_type == IS_UNUSED);
2598 +#endif
2599 +
2600 +    if (src->op_type == IS_CONST) {
2601 +        if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
2602 +            return NULL;
2603 +        }
2604 +    }
2605 +
2606 +    return dst;
2607 +}
2608 +/* }}} */
2609 +
2610 +/* {{{ my_copy_zend_op */
2611 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
2612 +{
2613 +    assert(dst != NULL);
2614 +    assert(src != NULL);
2615 +
2616 +    memcpy(dst, src, sizeof(src[0]));
2617 +
2618 +    if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL 
2619 +            || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
2620 +            || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
2621 +    {
2622 +        return NULL;
2623 +    }
2624 +
2625 +    return dst;
2626 +}
2627 +/* }}} */
2628 +
2629 +/* {{{ my_copy_function */
2630 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
2631 +{
2632 +    int local_dst_alloc = 0;
2633 +       TSRMLS_FETCH();
2634 +
2635 +    assert(src != NULL);
2636 +
2637 +    if(!dst) local_dst_alloc = 1;
2638 +    CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
2639 +
2640 +    switch (src->type) {
2641 +    case ZEND_INTERNAL_FUNCTION:
2642 +    case ZEND_OVERLOADED_FUNCTION:
2643 +        /* shallow copy because op_array is internal */
2644 +        dst->op_array = src->op_array;
2645 +        break;
2646 +        
2647 +    case ZEND_USER_FUNCTION:
2648 +    case ZEND_EVAL_CODE:
2649 +        if(!apc_copy_op_array(&dst->op_array,
2650 +                                &src->op_array,
2651 +                                allocate, deallocate TSRMLS_CC)) {
2652 +            if(local_dst_alloc) deallocate(dst);
2653 +            return NULL;
2654 +        }
2655 +        break;
2656 +
2657 +    default:
2658 +        assert(0);
2659 +    }
2660 +#ifdef ZEND_ENGINE_2
2661 +    /* 
2662 +     * op_array bitwise copying overwrites what ever you modified
2663 +     * before apc_copy_op_array - which is why this code is outside 
2664 +     * my_bitwise_copy_function. 
2665 +     */
2666 +
2667 +    /* zend_do_inheritance will re-look this up, because the pointers
2668 +     * in prototype are from a function table of another class. It just
2669 +     * helps if that one is from EG(class_table).
2670 +     */
2671 +    dst->common.prototype = NULL; 
2672 +
2673 +    /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
2674 +     * have to carry around a prototype. Thankfully zend_do_inheritance
2675 +     * sets this properly as well
2676 +     */
2677 +    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
2678 +#endif
2679 +
2680 +
2681 +    return dst;
2682 +}
2683 +/* }}} */
2684 +
2685 +/* {{{ my_copy_function_entry */
2686 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2687 +{
2688 +    int local_dst_alloc = 0;
2689 +    assert(src != NULL);
2690 +
2691 +    if (!dst) {
2692 +        CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
2693 +        local_dst_alloc = 1;
2694 +    }
2695 +
2696 +    /* Start with a bitwise copy */
2697 +    memcpy(dst, src, sizeof(src[0]));
2698 +
2699 +    dst->fname = NULL;
2700 +#ifdef ZEND_ENGINE_2
2701 +    dst->arg_info = NULL;
2702 +#else
2703 +    dst->func_arg_types = NULL;
2704 +#endif
2705 +
2706 +    if (src->fname) {
2707 +        if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
2708 +            goto cleanup;
2709 +        }
2710 +    }
2711 +
2712 +#ifdef ZEND_ENGINE_2    
2713 +    if (src->arg_info) {
2714 +        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
2715 +                                                src->arg_info,
2716 +                                                src->num_args,
2717 +                                                allocate,
2718 +                                                deallocate))) {
2719 +            goto cleanup;
2720 +        }
2721 +    }
2722 +#else    
2723 +    if (src->func_arg_types) {
2724 +        if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
2725 +                                                src->func_arg_types[0]+1,
2726 +                                                allocate))) {
2727 +            goto cleanup;
2728 +        }
2729 +    }
2730 +#endif
2731 +
2732 +    return dst;
2733 +
2734 +cleanup:
2735 +    if(dst->fname) deallocate(dst->fname);
2736 +    if(local_dst_alloc) deallocate(dst);
2737 +    return NULL;
2738 +}
2739 +/* }}} */
2740 +
2741 +#ifdef ZEND_ENGINE_2
2742 +/* {{{ my_copy_property_info */
2743 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2744 +{
2745 +    int local_dst_alloc = 0;
2746 +    
2747 +    assert(src != NULL);
2748 +
2749 +    if (!dst) {
2750 +        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2751 +        local_dst_alloc = 1;
2752 +    }
2753 +
2754 +    /* Start with a bitwise copy */
2755 +    memcpy(dst, src, sizeof(*src));
2756 +
2757 +    dst->name = NULL;
2758 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2759 +    dst->doc_comment = NULL;
2760 +#endif
2761 +
2762 +    if (src->name) {
2763 +        /* private members are stored inside property_info as a mangled
2764 +         * string of the form:
2765 +         *      \0<classname>\0<membername>\0
2766 +         */
2767 +        if(!(dst->name = 
2768 +                    apc_xmemcpy(src->name, src->name_length+1, allocate))) {
2769 +            goto cleanup;
2770 +        }
2771 +    }
2772 +
2773 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2774 +    if (src->doc_comment) {
2775 +        if( !(dst->doc_comment =
2776 +                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
2777 +            goto cleanup;
2778 +        }
2779 +    }
2780 +#endif
2781 +
2782 +    return dst;
2783 +
2784 +cleanup:
2785 +    if(dst->name) deallocate(dst->name);
2786 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2787 +    if(dst->doc_comment) deallocate(dst->doc_comment);
2788 +#endif
2789 +    if(local_dst_alloc) deallocate(dst);
2790 +    return NULL;
2791 +}
2792 +/* }}} */
2793 +
2794 +/* {{{ my_copy_property_info_for_execution */
2795 +static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2796 +{
2797 +    int local_dst_alloc = 0;
2798 +    
2799 +    assert(src != NULL);
2800 +
2801 +    if (!dst) {
2802 +        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2803 +        local_dst_alloc = 1;
2804 +    }
2805 +
2806 +    /* We need only a shallow copy */
2807 +    memcpy(dst, src, sizeof(*src));
2808 +
2809 +    return dst;
2810 +}
2811 +/* }}} */
2812 +
2813 +/* {{{ my_copy_arg_info_array */
2814 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, zend_arg_info* src, uint num_args, apc_malloc_t allocate, apc_free_t deallocate)
2815 +{
2816 +    int local_dst_alloc = 0;
2817 +    int i = 0;
2818 +
2819 +    
2820 +    if (!dst) {
2821 +        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
2822 +        local_dst_alloc = 1;
2823 +    }
2824 +
2825 +    /* Start with a bitwise copy */
2826 +    memcpy(dst, src, sizeof(*src)*num_args);
2827 +
2828 +    for(i=0; i < num_args; i++) {
2829 +        if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {            
2830 +            if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
2831 +            if(local_dst_alloc) deallocate(dst);
2832 +            return NULL;
2833 +        }
2834 +    }
2835 +
2836 +    return dst;    
2837 +}
2838 +/* }}} */
2839 +
2840 +/* {{{ my_copy_arg_info */
2841 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2842 +{
2843 +    int local_dst_alloc = 0;
2844 +    
2845 +    assert(src != NULL);
2846 +
2847 +    if (!dst) {
2848 +        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
2849 +        local_dst_alloc = 1;
2850 +    }
2851 +
2852 +    /* Start with a bitwise copy */
2853 +    memcpy(dst, src, sizeof(*src));
2854 +
2855 +    dst->name = NULL;
2856 +    dst->class_name = NULL;
2857 +
2858 +    if (src->name) {
2859 +        if(!(dst->name = 
2860 +                    apc_xmemcpy(src->name, src->name_len+1, allocate))) {
2861 +            goto cleanup;
2862 +        }
2863 +    }
2864 +
2865 +    if (src->class_name) {
2866 +        if(!(dst->class_name = 
2867 +                    apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
2868 +            goto cleanup;
2869 +        }
2870 +    }
2871 +
2872 +    return dst;
2873 +
2874 +cleanup:
2875 +    if(dst->name) deallocate(dst->name);
2876 +    if(dst->class_name) deallocate(dst->name);
2877 +    if(local_dst_alloc) deallocate(dst);
2878 +    return NULL;
2879 +}
2880 +/* }}} */
2881 +#endif
2882 +
2883 +/* {{{ my_copy_class_entry */
2884 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2885 +{
2886 +    int local_dst_alloc = 0;
2887 +    int i = 0;
2888 +
2889 +    assert(src != NULL);
2890 +
2891 +    if (!dst) {
2892 +        CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
2893 +        local_dst_alloc = 1;
2894 +    }
2895 +
2896 +    /* Start with a bitwise copy */
2897 +    memcpy(dst, src, sizeof(*src));
2898 +
2899 +    dst->name = NULL;
2900 +    dst->builtin_functions = NULL;
2901 +    memset(&dst->function_table, 0, sizeof(dst->function_table));
2902 +    memset(&dst->default_properties, 0, sizeof(dst->default_properties));
2903 +#ifndef ZEND_ENGINE_2
2904 +    dst->refcount = NULL;
2905 +#else
2906 +    dst->static_members = NULL;
2907 +    dst->doc_comment = NULL;
2908 +    dst->filename = NULL;
2909 +    memset(&dst->properties_info, 0, sizeof(dst->properties_info));
2910 +    memset(&dst->constants_table, 0, sizeof(dst->constants_table));
2911 +    memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
2912 +#endif
2913 +
2914 +    if (src->name) {
2915 +        if(!(dst->name = apc_xstrdup(src->name, allocate))) {
2916 +            goto cleanup;
2917 +        }
2918 +    }
2919 +
2920 +#ifndef ZEND_ENGINE_2    
2921 +    if(!(dst->refcount = apc_xmemcpy(src->refcount,
2922 +                                      sizeof(src->refcount[0]),
2923 +                                      allocate))) {
2924 +        goto cleanup;
2925 +    }
2926 +#endif        
2927 +
2928 +    if(!(my_copy_hashtable_ex(&dst->function_table,
2929 +                            &src->function_table,
2930 +                            (ht_copy_fun_t) my_copy_function,
2931 +                            (ht_free_fun_t) my_free_function,
2932 +                            0,
2933 +                            allocate, deallocate,
2934 +                            (ht_check_copy_fun_t) my_check_copy_function,
2935 +                            src))) {
2936 +        goto cleanup;
2937 +    }
2938 +
2939 +#ifdef ZEND_ENGINE_2
2940 +
2941 +    /* the interfaces are populated at runtime using ADD_INTERFACE */
2942 +    dst->interfaces = NULL; 
2943 +
2944 +    /* the current count includes inherited interfaces as well,
2945 +       the real dynamic ones are the first <n> which are zero'd
2946 +       out in zend_do_end_class_declaration */
2947 +    for(i = 0 ; i < src->num_interfaces ; i++) {
2948 +        if(src->interfaces[i])
2949 +        {
2950 +            dst->num_interfaces = i;
2951 +            break;
2952 +        }
2953 +    }
2954 +
2955 +    /* these will either be set inside my_fixup_hashtable or 
2956 +     * they will be copied out from parent inside zend_do_inheritance 
2957 +     */
2958 +    dst->constructor =  NULL;
2959 +    dst->destructor = NULL;
2960 +    dst->clone = NULL;
2961 +    dst->__get = NULL;
2962 +    dst->__set = NULL;
2963 +    dst->__unset = NULL;
2964 +    dst->__isset = NULL;
2965 +    dst->__call = NULL;
2966 +#ifdef ZEND_ENGINE_2_2
2967 +    dst->__tostring = NULL;
2968 +#endif
2969 +
2970 +    /* unset function proxies */
2971 +    dst->serialize_func = NULL;
2972 +    dst->unserialize_func = NULL;
2973 +    
2974 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
2975 +#endif
2976 +
2977 +    if(!(my_copy_hashtable_ex(&dst->default_properties,
2978 +                            &src->default_properties,
2979 +                            (ht_copy_fun_t) my_copy_zval_ptr,
2980 +                            (ht_free_fun_t) my_free_zval_ptr,
2981 +                            1,
2982 +                            allocate,deallocate,
2983 +                            (ht_check_copy_fun_t) my_check_copy_default_property,
2984 +                            src))) {
2985 +        goto cleanup;
2986 +    }
2987 +
2988 +#ifdef ZEND_ENGINE_2
2989 +    
2990 +    if(!(my_copy_hashtable_ex(&dst->properties_info,
2991 +                            &src->properties_info,
2992 +                            (ht_copy_fun_t) my_copy_property_info,
2993 +                            (ht_free_fun_t) my_free_property_info,
2994 +                            0,
2995 +                            allocate, deallocate,
2996 +                            (ht_check_copy_fun_t) my_check_copy_property_info,
2997 +                            src))) {
2998 +        goto cleanup;
2999 +    }
3000 +
3001 +#ifdef ZEND_ENGINE_2_2
3002 +    /* php5.2 introduced a scope attribute for property info */
3003 +    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
3004 +#endif
3005 +    
3006 +    if(!my_copy_hashtable_ex(&dst->default_static_members,
3007 +                            &src->default_static_members,
3008 +                            (ht_copy_fun_t) my_copy_zval_ptr,
3009 +                            (ht_free_fun_t) my_free_zval_ptr,
3010 +                            1,
3011 +                            allocate, deallocate,
3012 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
3013 +                            src,
3014 +                            &src->default_static_members)) {
3015 +        goto cleanup;
3016 +    }
3017 +    if(src->static_members != &src->default_static_members)
3018 +    {
3019 +        if(!(dst->static_members = my_copy_hashtable_ex(NULL,
3020 +                            src->static_members,
3021 +                            (ht_copy_fun_t) my_copy_zval_ptr,
3022 +                            (ht_free_fun_t) my_free_zval_ptr,
3023 +                            1,
3024 +                            allocate, deallocate,
3025 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
3026 +                            src,
3027 +                            src->static_members))) {
3028 +            goto cleanup;
3029 +        }
3030 +    }
3031 +    else
3032 +    {
3033 +        dst->static_members = &dst->default_static_members;
3034 +    }
3035 +
3036 +    if(!(my_copy_hashtable(&dst->constants_table,
3037 +                            &src->constants_table,
3038 +                            (ht_copy_fun_t) my_copy_zval_ptr,
3039 +                            (ht_free_fun_t) my_free_zval_ptr,
3040 +                            1,
3041 +                            allocate, deallocate))) {
3042 +        goto cleanup;
3043 +    }
3044 +
3045 +    if (src->doc_comment) {
3046 +        if(!(dst->doc_comment =
3047 +                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3048 +            goto cleanup;
3049 +        }
3050 +    }
3051 +#endif
3052 +    
3053 +    if (src->builtin_functions) {
3054 +        int i, n;
3055 +
3056 +        for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
3057 +
3058 +        if(!(dst->builtin_functions =
3059 +            (zend_function_entry*)
3060 +                allocate((n + 1) * sizeof(zend_function_entry)))) {
3061 +            goto cleanup;
3062 +        }
3063 +
3064 +
3065 +        for (i = 0; i < n; i++) {
3066 +            if(!my_copy_function_entry(&dst->builtin_functions[i],
3067 +                                   &src->builtin_functions[i],
3068 +                                   allocate, deallocate)) {
3069 +                int ii;
3070 +
3071 +                for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
3072 +                goto cleanup;
3073 +            }
3074 +        }
3075 +        dst->builtin_functions[n].fname = NULL;
3076 +    }
3077 +
3078 +#ifdef ZEND_ENGINE_2
3079 +    if (src->filename) {
3080 +        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3081 +            goto cleanup;
3082 +        }
3083 +    }
3084 +#endif
3085 +   
3086 +    return dst;
3087 +
3088 +
3089 +cleanup:
3090 +    if(dst->name) deallocate(dst->name);
3091 +#ifdef ZEND_ENGINE_2
3092 +    if(dst->doc_comment) deallocate(dst->doc_comment);
3093 +    if(dst->filename) deallocate(dst->filename);
3094 +#else
3095 +    if(dst->refcount) deallocate(dst->refcount);
3096 +#endif
3097 +    
3098 +    if(dst->builtin_functions) deallocate(dst->builtin_functions);
3099 +    if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
3100 +    if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3101 +
3102 +#ifdef ZEND_ENGINE_2
3103 +    if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
3104 +    if(dst->default_static_members.arBuckets)
3105 +    {
3106 +        my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3107 +    }
3108 +    if(dst->static_members && dst->static_members != &(dst->default_static_members))
3109 +    {
3110 +        my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3111 +        deallocate(dst->static_members);
3112 +    }
3113 +    if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3114 +#endif
3115 +    if(local_dst_alloc) deallocate(dst);
3116 +
3117 +    return NULL;
3118 +}
3119 +/* }}} */
3120 +
3121 +/* {{{ my_copy_hashtable */
3122 +static HashTable* my_copy_hashtable_ex(HashTable* dst,
3123 +                                    HashTable* src,
3124 +                                    ht_copy_fun_t copy_fn,
3125 +                                    ht_free_fun_t free_fn,
3126 +                                    int holds_ptrs,
3127 +                                    apc_malloc_t allocate, 
3128 +                                    apc_free_t deallocate,
3129 +                                    ht_check_copy_fun_t check_fn,
3130 +                                    ...)
3131 +{
3132 +    Bucket* curr = NULL;
3133 +    Bucket* prev = NULL;
3134 +    Bucket* newp = NULL;
3135 +    int first = 1;
3136 +    int local_dst_alloc = 0;
3137 +    int index = 0;
3138 +
3139 +    assert(src != NULL);
3140 +
3141 +    if (!dst) {
3142 +        CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
3143 +        local_dst_alloc = 1;
3144 +    }
3145 +
3146 +    memcpy(dst, src, sizeof(src[0]));
3147 +
3148 +    /* allocate buckets for the new hashtable */
3149 +    if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
3150 +        if(local_dst_alloc) deallocate(dst);
3151 +        return NULL;
3152 +    }
3153 +
3154 +    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
3155 +    dst->pInternalPointer = NULL;
3156 +    dst->pListHead = NULL;
3157 +    
3158 +    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
3159 +        int n = curr->h % dst->nTableSize;
3160 +
3161 +        if(check_fn) {
3162 +            va_list args;
3163 +            va_start(args, check_fn);
3164 +
3165 +            /* Call the check_fn to see if the current bucket 
3166 +             * needs to be copied out
3167 +             */
3168 +            if(!check_fn(curr, args)) {
3169 +                dst->nNumOfElements--;
3170 +                continue;
3171 +            }
3172 +
3173 +            va_end(args);
3174 +        }
3175 +
3176 +        /* create a copy of the bucket 'curr' */
3177 +        if(!(newp =
3178 +            (Bucket*) apc_xmemcpy(curr,
3179 +                                  sizeof(Bucket) + curr->nKeyLength - 1,
3180 +                                  allocate))) {
3181 +            goto cleanup;
3182 +        }
3183 +
3184 +        /* insert 'newp' into the linked list at its hashed index */
3185 +        if (dst->arBuckets[n]) {
3186 +            newp->pNext = dst->arBuckets[n];
3187 +            newp->pLast = NULL;
3188 +            newp->pNext->pLast = newp;
3189 +        }
3190 +        else {
3191 +            newp->pNext = newp->pLast = NULL;
3192 +        }
3193 +
3194 +        dst->arBuckets[n] = newp;
3195 +
3196 +        /* copy the bucket data using our 'copy_fn' callback function */
3197 +        if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
3198 +            goto cleanup;
3199 +        }
3200 +
3201 +        if (holds_ptrs) {
3202 +            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
3203 +        }
3204 +        else {
3205 +            newp->pDataPtr = NULL;
3206 +        }
3207 +
3208 +        /* insert 'newp' into the table-thread linked list */
3209 +        newp->pListLast = prev;
3210 +        newp->pListNext = NULL;
3211 +
3212 +        if (prev) {
3213 +            prev->pListNext = newp;
3214 +        }
3215 +
3216 +        if (first) {
3217 +            dst->pListHead = newp;
3218 +            first = 0;
3219 +        }
3220 +
3221 +        prev = newp;
3222 +    }
3223 +
3224 +    dst->pListTail = newp;
3225 +
3226 +    return dst;
3227 +    
3228 +    cleanup:
3229 +    for(index = 0; index < dst->nTableSize; index++)
3230 +    {
3231 +        curr = dst->arBuckets[index];
3232 +        while(curr != NULL)
3233 +        {
3234 +            Bucket * tmp = curr;
3235 +            if(curr->pData && free_fn)
3236 +            {
3237 +                free_fn(curr->pData, deallocate);
3238 +            }
3239 +            curr = curr->pNext;
3240 +            deallocate(tmp);
3241 +        }
3242 +    }   
3243 +    deallocate(dst->arBuckets);
3244 +    if(local_dst_alloc) deallocate(dst);
3245 +    else dst->arBuckets = NULL;
3246 +
3247 +    return NULL;
3248 +}
3249 +/* }}} */
3250 +
3251 +/* {{{ my_copy_static_variables */
3252 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
3253 +{ 
3254 +    if (src->static_variables == NULL) {
3255 +        return NULL;
3256 +    }
3257 +
3258 +    return my_copy_hashtable(NULL,
3259 +                             src->static_variables,
3260 +                             (ht_copy_fun_t) my_copy_zval_ptr,
3261 +                             (ht_free_fun_t) my_free_zval_ptr,
3262 +                             1,
3263 +                             allocate, deallocate);
3264 +}
3265 +/* }}} */
3266 +
3267 +/* {{{ apc_copy_zval */
3268 +zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
3269 +{
3270 +    int local_dst_alloc = 0;
3271 +    assert(src != NULL);
3272 +
3273 +    if (!dst) {
3274 +        CHECK(dst = (zval*) allocate(sizeof(zval)));
3275 +        local_dst_alloc = 1;
3276 +    }
3277 +
3278 +    dst = my_copy_zval(dst, src, allocate, deallocate);
3279 +    if(!dst) {
3280 +        if(local_dst_alloc) deallocate(dst);
3281 +        return NULL;
3282 +    }
3283 +    return dst; 
3284 +}
3285 +/* }}} */
3286 +
3287 +#ifdef ZEND_ENGINE_2
3288 +/* {{{ apc_fixup_op_array_jumps */
3289 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
3290 +{
3291 +    int i;
3292 +
3293 +    for (i=0; i < dst->last; ++i) {
3294 +        zend_op *zo = &(dst->opcodes[i]);
3295 +        /*convert opline number to jump address*/
3296 +        switch (zo->opcode) {
3297 +            case ZEND_JMP:
3298 +                /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
3299 +                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
3300 +                break;
3301 +            case ZEND_JMPZ:
3302 +            case ZEND_JMPNZ:
3303 +            case ZEND_JMPZ_EX:
3304 +            case ZEND_JMPNZ_EX:
3305 +                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
3306 +                break;
3307 +            default:
3308 +                break;
3309 +        }
3310 +    }
3311 +}
3312 +/* }}} */
3313 +#endif
3314 +
3315 +/* {{{ apc_copy_op_array */
3316 +zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3317 +{
3318 +    int i;
3319 +    int local_dst_alloc = 0;
3320 +    apc_fileinfo_t fileinfo;
3321 +    char canon_path[MAXPATHLEN];
3322 +    char *fullpath = NULL;
3323 +#ifdef ZEND_ENGINE_2
3324 +    apc_opflags_t * flags = NULL;
3325 +#endif
3326 +
3327 +    assert(src != NULL);
3328 +
3329 +    if (!dst) {
3330 +        CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
3331 +        local_dst_alloc = 1;
3332 +    }
3333 +
3334 +    if(APCG(apc_optimize_function)) {
3335 +        APCG(apc_optimize_function)(src TSRMLS_CC);
3336 +    }
3337 +    
3338 +    /* start with a bitwise copy of the array */
3339 +    memcpy(dst, src, sizeof(src[0]));
3340 +
3341 +    dst->function_name = NULL;
3342 +    dst->filename = NULL;
3343 +    dst->refcount = NULL;
3344 +    dst->opcodes = NULL;
3345 +    dst->brk_cont_array = NULL;
3346 +    dst->static_variables = NULL;
3347 +#ifdef ZEND_ENGINE_2
3348 +    dst->try_catch_array = NULL;
3349 +    dst->arg_info = NULL;
3350 +    dst->doc_comment = NULL;
3351 +#else
3352 +    dst->arg_types = NULL;
3353 +#endif
3354 +#ifdef ZEND_ENGINE_2_1
3355 +    dst->vars = NULL;
3356 +#endif
3357 +
3358 +    /* copy the arg types array (if set) */
3359 +#ifdef ZEND_ENGINE_2
3360 +    if (src->arg_info) {
3361 +        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
3362 +                                                src->arg_info,
3363 +                                                src->num_args,
3364 +                                                allocate,
3365 +                                                deallocate))) {
3366 +            goto cleanup;
3367 +        }
3368 +    }
3369 +#else    
3370 +    if (src->arg_types) {
3371 +        if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
3372 +                        sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
3373 +                        allocate))) {
3374 +            goto cleanup;
3375 +        }
3376 +    }
3377 +#endif
3378 +
3379 +    if (src->function_name) {
3380 +        if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
3381 +            goto cleanup;
3382 +        }
3383 +    }
3384 +    if (src->filename) {
3385 +        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3386 +            goto cleanup;
3387 +        }
3388 +    }
3389 +
3390 +    if(!(dst->refcount = apc_xmemcpy(src->refcount,
3391 +                                      sizeof(src->refcount[0]),
3392 +                                      allocate))) {
3393 +        goto cleanup;
3394 +    }
3395 +
3396 +    /* deep-copy the opcodes */
3397 +    if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
3398 +        goto cleanup;
3399 +    }
3400 +
3401 +#ifdef ZEND_ENGINE_2
3402 +    if(APCG(reserved_offset) != -1) {
3403 +        /* Insanity alert: the void* pointer is cast into an apc_opflags_t 
3404 +         * struct. apc_zend_init() checks to ensure that it fits in a void* */
3405 +        flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
3406 +        memset(flags, 0, sizeof(apc_opflags_t));
3407 +        /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
3408 +    }
3409 +#endif
3410 +    
3411 +    for (i = 0; i < src->last; i++) {
3412 +#ifdef ZEND_ENGINE_2
3413 +        zend_op *zo = &(src->opcodes[i]);
3414 +        /* a lot of files are merely constant arrays with no jumps */
3415 +        switch (zo->opcode) {
3416 +            case ZEND_JMP:
3417 +            case ZEND_JMPZ:
3418 +            case ZEND_JMPNZ:
3419 +            case ZEND_JMPZ_EX:
3420 +            case ZEND_JMPNZ_EX:
3421 +                if(flags != NULL) {
3422 +                    flags->has_jumps = 1;
3423 +                }
3424 +                break;
3425 +#ifdef ZEND_ENGINE_2
3426 +            /* auto_globals_jit was not in php-4.3.* */
3427 +            case ZEND_FETCH_R:
3428 +            case ZEND_FETCH_W:
3429 +            case ZEND_FETCH_IS:
3430 +            case ZEND_FETCH_FUNC_ARG:
3431 +                if(PG(auto_globals_jit) && flags != NULL)
3432 +                {
3433 +                     /* The fetch is only required if auto_globals_jit=1  */
3434 +                    if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
3435 +                            zo->op1.op_type == IS_CONST && 
3436 +                            zo->op1.u.constant.type == IS_STRING) {
3437 +                        znode * varname = &zo->op1;
3438 +                        if (varname->u.constant.value.str.val[0] == '_') {
3439 +#define SET_IF_AUTOGLOBAL(member) \
3440 +    if(!strcmp(varname->u.constant.value.str.val, #member)) \
3441 +        flags->member = 1 /* no ';' here */
3442 +                            SET_IF_AUTOGLOBAL(_GET);
3443 +                            else SET_IF_AUTOGLOBAL(_POST);
3444 +                            else SET_IF_AUTOGLOBAL(_COOKIE);
3445 +                            else SET_IF_AUTOGLOBAL(_SERVER);
3446 +                            else SET_IF_AUTOGLOBAL(_ENV);
3447 +                            else SET_IF_AUTOGLOBAL(_FILES);
3448 +                            else SET_IF_AUTOGLOBAL(_REQUEST);
3449 +                            else if(zend_is_auto_global(
3450 +                                            varname->u.constant.value.str.val,
3451 +                                            varname->u.constant.value.str.len
3452 +                                            TSRMLS_CC))
3453 +                            {
3454 +                                flags->unknown_global = 1;
3455 +                            }
3456 +                        }
3457 +                    }
3458 +                }
3459 +                break;
3460 +#endif
3461 +            case ZEND_RECV_INIT:
3462 +                if(zo->op2.op_type == IS_CONST &&
3463 +                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
3464 +                    if(flags != NULL) {
3465 +                        flags->deep_copy = 1;
3466 +                    }
3467 +                }
3468 +                break;
3469 +            default:
3470 +                if((zo->op1.op_type == IS_CONST &&
3471 +                    zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
3472 +                    (zo->op2.op_type == IS_CONST &&
3473 +                        zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
3474 +                    if(flags != NULL) {
3475 +                        flags->deep_copy = 1;
3476 +                    }
3477 +                }
3478 +                break;
3479 +        }
3480 +#endif
3481 +        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
3482 +            int ii;
3483 +            for(ii = i-1; ii>=0; ii--) {
3484 +                my_destroy_zend_op(dst->opcodes+ii, deallocate);
3485 +            }
3486 +            goto  cleanup;
3487 +        }
3488 +#ifdef ZEND_ENGINE_2
3489 +/* This code breaks apc's rule#1 - cache what you compile */
3490 +        if(APCG(fpstat)==0) {
3491 +            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
3492 +                (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
3493 +                /* constant includes */
3494 +                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) { 
3495 +                    if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
3496 +                        if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
3497 +                            /* everything has to go through a realpath() */
3498 +                            zend_op *dzo = &(dst->opcodes[i]);
3499 +                            deallocate(dzo->op1.u.constant.value.str.val);
3500 +                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
3501 +                            dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
3502 +                        }
3503 +                    }
3504 +                }
3505 +            }
3506 +        }
3507 +#endif 
3508 +    }
3509 +
3510 +#ifdef ZEND_ENGINE_2
3511 +    if(flags == NULL || flags->has_jumps) {
3512 +        apc_fixup_op_array_jumps(dst,src);
3513 +    }
3514 +#endif
3515 +
3516 +    /* copy the break-continue array */
3517 +    if (src->brk_cont_array) {
3518 +        if(!(dst->brk_cont_array =
3519 +            apc_xmemcpy(src->brk_cont_array,
3520 +                        sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
3521 +                        allocate))) {
3522 +            goto cleanup_opcodes;
3523 +        }
3524 +    }
3525 +
3526 +    /* copy the table of static variables */
3527 +    if (src->static_variables) {
3528 +        if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
3529 +            goto cleanup_opcodes;
3530 +        }
3531 +    }
3532 +    
3533 +#ifdef ZEND_ENGINE_2
3534 +    if (src->try_catch_array) {
3535 +        if(!(dst->try_catch_array = 
3536 +                apc_xmemcpy(src->try_catch_array,
3537 +                        sizeof(src->try_catch_array[0]) * src->last_try_catch,
3538 +                        allocate))) {
3539 +            goto cleanup_opcodes;
3540 +        }
3541 +    }
3542 +#endif
3543 +
3544 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
3545 +    if (src->vars) {
3546 +        if(!(dst->vars = apc_xmemcpy(src->vars,
3547 +                            sizeof(src->vars[0]) * src->last_var,
3548 +                            allocate))) {
3549 +            goto cleanup_opcodes;
3550 +        }
3551 +        
3552 +        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
3553 +        
3554 +        for(i = 0; i <  src->last_var; i++) {
3555 +            if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
3556 +                                src->vars[i].name_len + 1,
3557 +                                allocate))) {
3558 +                dst->last_var = i;
3559 +                goto cleanup_opcodes;
3560 +            }
3561 +        }
3562 +    }
3563 +#endif
3564 +
3565 +#ifdef ZEND_ENGINE_2
3566 +    if (src->doc_comment) {
3567 +        if (!(dst->doc_comment 
3568 +                = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3569 +            goto cleanup_opcodes;
3570 +        }
3571 +    }
3572 +#endif
3573 +
3574 +    return dst;
3575 +
3576 +cleanup_opcodes:
3577 +    if(dst->opcodes) {
3578 +        for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
3579 +    }
3580 +cleanup:
3581 +    if(dst->function_name) deallocate(dst->function_name);
3582 +    if(dst->refcount) deallocate(dst->refcount);
3583 +    if(dst->filename) deallocate(dst->filename);
3584 +#ifdef ZEND_ENGINE_2
3585 +    if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
3586 +    if(dst->try_catch_array) deallocate(dst->try_catch_array);
3587 +    if(dst->doc_comment) deallocate(dst->doc_comment);
3588 +#else
3589 +    if(dst->arg_types) deallocate(dst->arg_types);
3590 +#endif
3591 +    if(dst->opcodes) deallocate(dst->opcodes);
3592 +    if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
3593 +    if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
3594 +#ifdef ZEND_ENGINE_2_1
3595 +    if (dst->vars) {
3596 +       for(i=0; i < dst->last_var; i++) {
3597 +            if(dst->vars[i].name) deallocate(dst->vars[i].name);    
3598 +        }
3599 +        deallocate(dst->vars);
3600 +    }
3601 +#endif
3602 +    if(local_dst_alloc) deallocate(dst);
3603 +    return NULL;
3604 +}
3605 +/* }}} */
3606 +
3607 +/* {{{ apc_copy_new_functions */
3608 +apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3609 +{
3610 +    apc_function_t* array;
3611 +    int new_count;              /* number of new functions in table */
3612 +    int i;
3613 +
3614 +    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
3615 +    assert(new_count >= 0);
3616 +
3617 +    CHECK(array =
3618 +        (apc_function_t*)
3619 +            allocate(sizeof(apc_function_t) * (new_count+1)));
3620 +
3621 +    if (new_count == 0) {
3622 +        array[0].function = NULL;
3623 +        return array;
3624 +    }
3625 +    
3626 +    /* Skip the first `old_count` functions in the table */
3627 +    zend_hash_internal_pointer_reset(CG(function_table));
3628 +    for (i = 0; i < old_count; i++) {
3629 +        zend_hash_move_forward(CG(function_table));
3630 +    }
3631 +
3632 +    /* Add the next `new_count` functions to our array */
3633 +    for (i = 0; i < new_count; i++) {
3634 +        char* key;
3635 +        uint key_size;
3636 +        zend_function* fun;
3637 +
3638 +        zend_hash_get_current_key_ex(CG(function_table),
3639 +                                     &key,
3640 +                                     &key_size,
3641 +                                     NULL,
3642 +                                     0,
3643 +                                     NULL);
3644 +
3645 +        zend_hash_get_current_data(CG(function_table), (void**) &fun);
3646 +
3647 +        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3648 +            int ii;
3649 +            for(ii=i-1; ii>=0; ii--) {
3650 +                deallocate(array[ii].name);
3651 +                my_free_function(array[ii].function, deallocate);
3652 +            }
3653 +            deallocate(array);
3654 +            return NULL;
3655 +        }
3656 +        array[i].name_len = (int) key_size-1;
3657 +        if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
3658 +            int ii;
3659 +            deallocate(array[i].name);
3660 +            for(ii=i-1; ii>=0; ii--) {
3661 +                deallocate(array[ii].name);
3662 +                my_free_function(array[ii].function, deallocate);
3663 +            }
3664 +            deallocate(array);
3665 +            return NULL;
3666 +        }
3667 +        zend_hash_move_forward(CG(function_table));
3668 +    }
3669 +
3670 +    array[i].function = NULL;
3671 +    return array;
3672 +}
3673 +/* }}} */
3674 +
3675 +/* {{{ apc_copy_new_classes */
3676 +apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3677 +{
3678 +    apc_class_t* array;
3679 +    int new_count;              /* number of new classes in table */
3680 +    int i;
3681 +    
3682 +    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
3683 +    assert(new_count >= 0);
3684 +
3685 +    CHECK(array =
3686 +        (apc_class_t*)
3687 +            allocate(sizeof(apc_class_t)*(new_count+1)));
3688 +    
3689 +    if (new_count == 0) {
3690 +        array[0].class_entry = NULL;
3691 +        return array;
3692 +    }
3693 +
3694 +    /* Skip the first `old_count` classes in the table */
3695 +    zend_hash_internal_pointer_reset(CG(class_table));
3696 +    for (i = 0; i < old_count; i++) {
3697 +        zend_hash_move_forward(CG(class_table));
3698 +    }
3699 +
3700 +    /* Add the next `new_count` classes to our array */
3701 +    for (i = 0; i < new_count; i++) {
3702 +        char* key;
3703 +        uint key_size;
3704 +        zend_class_entry* elem = NULL;
3705 +
3706 +        array[i].class_entry = NULL;
3707 +
3708 +        zend_hash_get_current_key_ex(CG(class_table),
3709 +                                     &key,
3710 +                                     &key_size,
3711 +                                     NULL,
3712 +                                     0,
3713 +                                     NULL);
3714 +
3715 +       zend_hash_get_current_data(CG(class_table), (void**) &elem);
3716 +  
3717 +        
3718 +#ifdef ZEND_ENGINE_2
3719 +               elem = *((zend_class_entry**)elem);
3720 +#endif
3721 +        
3722 +        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3723 +            int ii;
3724 +
3725 +            for(ii=i-1; ii>=0; ii--) {
3726 +                deallocate(array[ii].name);
3727 +                my_destroy_class_entry(array[ii].class_entry, deallocate);
3728 +                deallocate(array[ii].class_entry);
3729 +            }
3730 +            deallocate(array);
3731 +            return NULL;
3732 +        }
3733 +        array[i].name_len = (int) key_size-1;
3734 +        if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
3735 +            int ii;
3736 +            
3737 +            deallocate(array[i].name);
3738 +            for(ii=i-1; ii>=0; ii--) {
3739 +                deallocate(array[ii].name);
3740 +                my_destroy_class_entry(array[ii].class_entry, deallocate);
3741 +                deallocate(array[ii].class_entry);
3742 +            }
3743 +            deallocate(array);
3744 +            return NULL;
3745 +        }
3746 +
3747 +        /*
3748 +         * If the class has a pointer to its parent class, save the parent
3749 +         * name so that we can enable compile-time inheritance when we reload
3750 +         * the child class; otherwise, set the parent name to null and scan
3751 +         * the op_array to determine if this class inherits from some base
3752 +         * class at execution-time.
3753 +         */
3754 +
3755 +        if (elem->parent) {
3756 +            if(!(array[i].parent_name =
3757 +                apc_xstrdup(elem->parent->name, allocate))) {
3758 +                int ii;
3759 +                 
3760 +                for(ii=i; ii>=0; ii--) {
3761 +                    deallocate(array[ii].name);
3762 +                    my_destroy_class_entry(array[ii].class_entry, deallocate);
3763 +                    deallocate(array[ii].class_entry);
3764 +                    if(ii==i) continue;
3765 +                    if(array[ii].parent_name) deallocate(array[ii].parent_name);
3766 +                }
3767 +                deallocate(array);
3768 +                return NULL;
3769 +            }
3770 +            array[i].is_derived = 1;
3771 +        }
3772 +        else {
3773 +            array[i].parent_name = NULL;
3774 +            array[i].is_derived = is_derived_class(op_array, key, key_size);
3775 +        }
3776 +
3777 +        zend_hash_move_forward(CG(class_table));
3778 +    }
3779 +
3780 +    array[i].class_entry = NULL;
3781 +    return array;
3782 +}
3783 +/* }}} */
3784 +
3785 +/* {{{ my_destroy_zval_ptr */
3786 +static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
3787 +{
3788 +    assert(src != NULL);
3789 +    if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
3790 +        deallocate(src[0]);
3791 +    }
3792 +}
3793 +/* }}} */
3794 +
3795 +/* {{{ my_destroy_zval */
3796 +static int my_destroy_zval(zval* src, apc_free_t deallocate)
3797 +{
3798 +    zval **tmp;
3799 +    TSRMLS_FETCH();
3800 +
3801 +    switch (src->type & ~IS_CONSTANT_INDEX) {
3802 +    case IS_RESOURCE:
3803 +    case IS_BOOL:
3804 +    case IS_LONG:
3805 +    case IS_DOUBLE:
3806 +    case IS_NULL:
3807 +        break;
3808 +
3809 +    case IS_CONSTANT:
3810 +    case IS_STRING:
3811 +#ifndef ZEND_ENGINE_2        
3812 +    case FLAG_IS_BC:
3813 +#endif        
3814 +        deallocate(src->value.str.val);
3815 +        break;
3816 +    
3817 +    case IS_ARRAY:
3818 +    
3819 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
3820 +        if(APCG(copied_zvals)) {
3821 +            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3822 +                (*tmp)->refcount--;
3823 +                return FAILURE;
3824 +            } 
3825 +            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
3826 +        }
3827 +        /* fall through */
3828 +
3829 +    case IS_CONSTANT_ARRAY:
3830 +        my_free_hashtable(src->value.ht,
3831 +                          (ht_free_fun_t) my_free_zval_ptr,
3832 +                          deallocate);
3833 +        break;
3834 +
3835 +    case IS_OBJECT:
3836 +#ifndef ZEND_ENGINE_2        
3837 +        my_destroy_class_entry(src->value.obj.ce, deallocate);
3838 +        deallocate(src->value.obj.ce);
3839 +        my_free_hashtable(src->value.obj.properties,
3840 +                          (ht_free_fun_t) my_free_zval_ptr,
3841 +                          deallocate);
3842 +#endif        
3843 +        break;
3844 +
3845 +    default:
3846 +        assert(0);
3847 +    }
3848 +
3849 +    return SUCCESS;
3850 +}
3851 +/* }}} */
3852 +
3853 +/* {{{ my_destroy_znode */
3854 +static void my_destroy_znode(znode* src, apc_free_t deallocate)
3855 +{
3856 +    if (src->op_type == IS_CONST) {
3857 +        my_destroy_zval(&src->u.constant, deallocate);
3858 +    }
3859 +}
3860 +/* }}} */
3861 +
3862 +/* {{{ my_destroy_zend_op */
3863 +static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
3864 +{
3865 +    my_destroy_znode(&src->result, deallocate);
3866 +    my_destroy_znode(&src->op1, deallocate);
3867 +    my_destroy_znode(&src->op2, deallocate);
3868 +}
3869 +/* }}} */
3870 +
3871 +/* {{{ my_destroy_function */
3872 +static void my_destroy_function(zend_function* src, apc_free_t deallocate)
3873 +{
3874 +    assert(src != NULL);
3875 +
3876 +    switch (src->type) {
3877 +    case ZEND_INTERNAL_FUNCTION:
3878 +    case ZEND_OVERLOADED_FUNCTION:
3879 +        break;
3880 +        
3881 +    case ZEND_USER_FUNCTION:
3882 +    case ZEND_EVAL_CODE:
3883 +        my_destroy_op_array(&src->op_array, deallocate);
3884 +        break;
3885 +
3886 +    default:
3887 +        assert(0);
3888 +    }
3889 +}
3890 +/* }}} */
3891 +
3892 +/* {{{ my_destroy_function_entry */
3893 +static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
3894 +{
3895 +    assert(src != NULL);
3896 +
3897 +    deallocate(src->fname);
3898 +#ifdef ZEND_ENGINE_2    
3899 +    if (src->arg_info) {
3900 +            my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
3901 +    }
3902 +#else
3903 +    if (src->func_arg_types) {
3904 +        deallocate(src->func_arg_types);
3905 +    }
3906 +#endif    
3907 +}
3908 +/* }}} */
3909 +
3910 +#ifdef ZEND_ENGINE_2    
3911 +/* {{{ my_destroy_property_info*/
3912 +static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
3913 +{
3914 +    assert(src != NULL);
3915 +
3916 +    deallocate(src->name);
3917 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
3918 +    if(src->doc_comment) deallocate(src->doc_comment);
3919 +#endif
3920 +}
3921 +/* }}} */
3922 +
3923 +/* {{{ my_destroy_arg_info_array */
3924 +static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
3925 +{
3926 +    int i = 0;
3927 +    
3928 +    assert(src != NULL);
3929 +
3930 +    for(i=0; i < num_args; i++) {
3931 +        my_destroy_arg_info(&src[i], deallocate);
3932 +    }
3933 +}
3934 +/* }}} */
3935 +
3936 +/* {{{ my_destroy_arg_info */
3937 +static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
3938 +{
3939 +    assert(src != NULL);
3940 +
3941 +    deallocate(src->name);
3942 +    deallocate(src->class_name);
3943 +}
3944 +/* }}} */
3945 +#endif    
3946 +
3947 +/* {{{ my_destroy_class_entry */
3948 +static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
3949 +{
3950 +    uint i;
3951 +
3952 +    assert(src != NULL);
3953 +
3954 +    deallocate(src->name);
3955 +#ifndef ZEND_ENGINE_2    
3956 +    deallocate(src->refcount);
3957 +#else
3958 +    if(src->doc_comment) deallocate(src->doc_comment);
3959 +    if(src->filename) deallocate(src->filename);
3960 +#endif
3961 +
3962 +    my_destroy_hashtable(&src->function_table,
3963 +                         (ht_free_fun_t) my_free_function,
3964 +                         deallocate);
3965 +
3966 +    my_destroy_hashtable(&src->default_properties,
3967 +                         (ht_free_fun_t) my_free_zval_ptr,
3968 +                         deallocate);
3969 +
3970 +#ifdef ZEND_ENGINE_2
3971 +    my_destroy_hashtable(&src->properties_info, 
3972 +                            (ht_free_fun_t) my_free_property_info,
3973 +                            deallocate);
3974 +    if(src->static_members) 
3975 +    {
3976 +        my_destroy_hashtable(src->static_members,
3977 +                         (ht_free_fun_t) my_free_zval_ptr,
3978 +                         deallocate);
3979 +        if(src->static_members != &(src->default_static_members))
3980 +        {
3981 +            deallocate(src->static_members);
3982 +        }
3983 +    }
3984 +
3985 +    my_destroy_hashtable(&src->constants_table, 
3986 +                            (ht_free_fun_t) my_free_zval_ptr,
3987 +                            deallocate);
3988 +#endif
3989 +
3990 +    if (src->builtin_functions) {
3991 +        for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
3992 +            my_destroy_function_entry(&src->builtin_functions[i], deallocate);
3993 +        }
3994 +        deallocate(src->builtin_functions);
3995 +    }
3996 +}
3997 +/* }}} */
3998 +
3999 +/* {{{ my_destroy_hashtable */
4000 +static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4001 +{
4002 +    int i;
4003 +
4004 +    assert(src != NULL);
4005 +
4006 +    for (i = 0; i < src->nTableSize; i++) {
4007 +        Bucket* p = src->arBuckets[i];
4008 +        while (p != NULL) {
4009 +            Bucket* q = p;
4010 +            p = p->pNext;
4011 +            free_fn(q->pData, deallocate);
4012 +            deallocate(q);
4013 +        }
4014 +    }
4015 +
4016 +    deallocate(src->arBuckets);
4017 +}
4018 +/* }}} */
4019 +
4020 +/* {{{ my_destroy_op_array */
4021 +static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
4022 +{
4023 +    int i;
4024 +
4025 +    assert(src != NULL);
4026 +
4027 +#ifdef ZEND_ENGINE_2
4028 +    if (src->arg_info) {
4029 +        my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
4030 +    }
4031 +#else    
4032 +    if (src->arg_types) {
4033 +        deallocate(src->arg_types);
4034 +    }
4035 +#endif
4036 +
4037 +    deallocate(src->function_name);
4038 +    deallocate(src->filename);
4039 +    deallocate(src->refcount);
4040 +
4041 +    for (i = 0; i < src->last; i++) {
4042 +        my_destroy_zend_op(src->opcodes + i, deallocate);
4043 +    }
4044 +    deallocate(src->opcodes);
4045 +
4046 +    if (src->brk_cont_array) {
4047 +        deallocate(src->brk_cont_array);
4048 +    }
4049 +
4050 +    if (src->static_variables) {
4051 +        my_free_hashtable(src->static_variables,
4052 +                          (ht_free_fun_t) my_free_zval_ptr,
4053 +                          deallocate);
4054 +    }
4055 +    
4056 +#ifdef ZEND_ENGINE_2_1
4057 +    if (src->vars) {
4058 +       for(i=0; i < src->last_var; i++) {
4059 +            if(src->vars[i].name) deallocate(src->vars[i].name);    
4060 +        }
4061 +        deallocate(src->vars);
4062 +    }
4063 +#endif
4064 +#ifdef ZEND_ENGINE_2
4065 +    if(src->try_catch_array) {
4066 +        deallocate(src->try_catch_array);
4067 +    }
4068 +    if (src->doc_comment) {
4069 +        deallocate(src->doc_comment);
4070 +    }
4071 +#endif
4072 +}
4073 +/* }}} */
4074 +
4075 +/* {{{ my_free_zval_ptr */
4076 +static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
4077 +{
4078 +    my_destroy_zval_ptr(src, deallocate);
4079 +    deallocate(src);
4080 +}
4081 +/* }}} */
4082 +
4083 +#ifdef ZEND_ENGINE_2
4084 +/* {{{ my_free_property_info */
4085 +static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
4086 +{
4087 +    my_destroy_property_info(src, deallocate);
4088 +    deallocate(src);
4089 +}
4090 +/* }}} */
4091 +
4092 +/* {{{ my_free_arg_info_array */
4093 +static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
4094 +{
4095 +    my_destroy_arg_info_array(src, num_args, deallocate);
4096 +    deallocate(src);
4097 +}
4098 +/* }}} */
4099 +
4100 +/* {{{ my_free_arg_info */
4101 +static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
4102 +{
4103 +    my_destroy_arg_info(src, deallocate);
4104 +    deallocate(src);
4105 +}
4106 +/* }}} */
4107 +#endif
4108 +
4109 +/* {{{ my_free_function */
4110 +static void my_free_function(zend_function* src, apc_free_t deallocate)
4111 +{
4112 +    my_destroy_function(src, deallocate);
4113 +    deallocate(src);
4114 +}
4115 +/* }}} */
4116 +
4117 +/* {{{ my_free_hashtable */
4118 +static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4119 +{
4120 +    my_destroy_hashtable(src, free_fn, deallocate);
4121 +    deallocate(src);
4122 +}
4123 +/* }}} */
4124 +
4125 +/* {{{ apc_free_op_array */
4126 +void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
4127 +{
4128 +    if (src != NULL) {
4129 +        my_destroy_op_array(src, deallocate);
4130 +        deallocate(src);
4131 +    }
4132 +}
4133 +/* }}} */
4134 +
4135 +/* {{{ apc_free_functions */
4136 +void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
4137 +{
4138 +    int i;
4139 +
4140 +    if (src != NULL) {
4141 +        for (i = 0; src[i].function != NULL; i++) {
4142 +            deallocate(src[i].name);
4143 +            my_destroy_function(src[i].function, deallocate);
4144 +            deallocate(src[i].function);
4145 +        }   
4146 +        deallocate(src);
4147 +    }   
4148 +}
4149 +/* }}} */
4150 +
4151 +/* {{{ apc_free_classes */
4152 +void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
4153 +{
4154 +    int i;
4155 +
4156 +    if (src != NULL) {
4157 +        for (i = 0; src[i].class_entry != NULL; i++) {
4158 +            deallocate(src[i].name);
4159 +            deallocate(src[i].parent_name);
4160 +            my_destroy_class_entry(src[i].class_entry, deallocate);
4161 +            deallocate(src[i].class_entry);
4162 +        }   
4163 +        deallocate(src);
4164 +    }   
4165 +}
4166 +/* }}} */
4167 +
4168 +/* {{{ apc_free_zval */
4169 +void apc_free_zval(zval* src, apc_free_t deallocate)
4170 +{
4171 +    if (src != NULL) {
4172 +        if(my_destroy_zval(src, deallocate) == SUCCESS) {
4173 +            deallocate(src);
4174 +        }
4175 +    }
4176 +}
4177 +/* }}} */
4178 +
4179 +
4180 +/* Used only by my_prepare_op_array_for_execution */
4181 +#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                                \
4182 +                         /* The fetch is only required if auto_globals_jit=1  */                \
4183 +                        if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&                            \
4184 +                            zo->op1.op_type == IS_CONST &&                                      \
4185 +                            zo->op1.u.constant.type == IS_STRING &&                             \
4186 +                            zo->op1.u.constant.value.str.val[0] == '_') {                       \
4187 +                                                                                                \
4188 +                            znode* varname = &zo->op1;                                          \
4189 +                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
4190 +                                                          varname->u.constant.value.str.len     \
4191 +                                                          TSRMLS_CC);                           \
4192 +                        }                                                                       \
4193 +
4194 +/* {{{ my_prepare_op_array_for_execution */
4195 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC) 
4196 +{
4197 +    /* combine my_fetch_global_vars and my_copy_data_exceptions.
4198 +     *   - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4199 +     *   - If the opcode stream contain mutable data, ensure a copy.
4200 +     *   - Fixup array jumps in the same loop.
4201 +     */
4202 +    int i=src->last;
4203 +    zend_op *zo;
4204 +    zend_op *dzo;
4205 +#ifdef ZEND_ENGINE_2
4206 +    apc_opflags_t * flags = APCG(reserved_offset) != -1 ? 
4207 +                                (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
4208 +    int needcopy = flags ? flags->deep_copy : 1;
4209 +    /* auto_globals_jit was not in php4 */
4210 +    int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
4211 +
4212 +#define FETCH_AUTOGLOBAL(member) do { \
4213 +    if(flags && flags->member == 1) { \
4214 +        zend_is_auto_global(#member,\
4215 +                            (sizeof(#member) - 1)\
4216 +                            TSRMLS_CC);\
4217 +    } \
4218 +}while(0); 
4219 +            
4220 +    FETCH_AUTOGLOBAL(_GET);
4221 +    FETCH_AUTOGLOBAL(_POST);
4222 +    FETCH_AUTOGLOBAL(_COOKIE);
4223 +    FETCH_AUTOGLOBAL(_SERVER);
4224 +    FETCH_AUTOGLOBAL(_ENV);
4225 +    FETCH_AUTOGLOBAL(_FILES);
4226 +    FETCH_AUTOGLOBAL(_REQUEST);
4227 +
4228 +#else
4229 +    int needcopy = 0;
4230 +    int do_prepare_fetch_global = 0;
4231 +    int j = 0;
4232 +
4233 +    for(j = 0; j < src->last; j++) {
4234 +        zo = &src->opcodes[j];
4235 +        
4236 +        if( ((zo->op1.op_type == IS_CONST &&
4237 +              zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
4238 +            ((zo->op2.op_type == IS_CONST &&
4239 +              zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4240 +            needcopy = 1;
4241 +        }
4242 +    }
4243 +#endif
4244 +    
4245 +    if(needcopy) {
4246 +
4247 +        dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes, 
4248 +                                    sizeof(zend_op) * src->last,
4249 +                                    apc_php_malloc);
4250 +        zo = src->opcodes;
4251 +        dzo = dst->opcodes;
4252 +        while(i > 0) {
4253 +
4254 +            if( ((zo->op1.op_type == IS_CONST &&
4255 +                  zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
4256 +                ((zo->op2.op_type == IS_CONST &&
4257 +                  zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4258 +
4259 +                if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
4260 +                    assert(0); /* emalloc failed or a bad constant array */
4261 +                }
4262 +            }
4263 +            
4264 +#ifdef ZEND_ENGINE_2
4265 +            switch(zo->opcode) {
4266 +                case ZEND_JMP:
4267 +                    dzo->op1.u.jmp_addr = dst->opcodes + 
4268 +                                            (zo->op1.u.jmp_addr - src->opcodes);
4269 +                    break;
4270 +                case ZEND_JMPZ:
4271 +                case ZEND_JMPNZ:
4272 +                case ZEND_JMPZ_EX:
4273 +                case ZEND_JMPNZ_EX:
4274 +                    dzo->op2.u.jmp_addr = dst->opcodes + 
4275 +                                            (zo->op2.u.jmp_addr - src->opcodes);
4276 +                    break;
4277 +                case ZEND_FETCH_R:
4278 +                case ZEND_FETCH_W:
4279 +                case ZEND_FETCH_IS:
4280 +                case ZEND_FETCH_FUNC_ARG:
4281 +                    if(do_prepare_fetch_global)
4282 +                    {
4283 +                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4284 +                    }
4285 +                    break;
4286 +                default:
4287 +                    break;
4288 +            }
4289 +#endif
4290 +            i--;
4291 +            zo++;
4292 +            dzo++;
4293 +        }
4294 +#ifdef ZEND_ENGINE_2
4295 +    } else {  /* !needcopy */
4296 +        /* The fetch is only required if auto_globals_jit=1  */
4297 +        if(do_prepare_fetch_global)
4298 +        {
4299 +            zo = src->opcodes;
4300 +            while(i > 0) {
4301 +
4302 +                if(zo->opcode == ZEND_FETCH_R || 
4303 +                   zo->opcode == ZEND_FETCH_W ||
4304 +                   zo->opcode == ZEND_FETCH_IS ||
4305 +                   zo->opcode == ZEND_FETCH_FUNC_ARG 
4306 +                  ) {
4307 +                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4308 +                }
4309 +
4310 +                i--;
4311 +                zo++;
4312 +            }
4313 +        }
4314 +#endif
4315 +    }
4316 +    return 1;
4317 +}
4318 +/* }}} */
4319 +
4320 +/* {{{ apc_copy_op_array_for_execution */
4321 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4322 +{
4323 +    if(dst == NULL) {
4324 +        dst = (zend_op_array*) emalloc(sizeof(src[0]));
4325 +    }
4326 +    memcpy(dst, src, sizeof(src[0]));
4327 +    dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
4328 +
4329 +    dst->refcount = apc_xmemcpy(src->refcount,
4330 +                                      sizeof(src->refcount[0]),
4331 +                                      apc_php_malloc);
4332 +    
4333 +    my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
4334 +
4335 +    return dst;
4336 +}
4337 +/* }}} */
4338 +
4339 +/* {{{ apc_copy_function_for_execution */
4340 +zend_function* apc_copy_function_for_execution(zend_function* src)
4341 +{
4342 +    zend_function* dst;
4343 +    TSRMLS_FETCH();
4344 +
4345 +    dst = (zend_function*) emalloc(sizeof(src[0]));
4346 +    memcpy(dst, src, sizeof(src[0]));
4347 +    apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
4348 +    return dst;
4349 +}
4350 +/* }}} */
4351 +
4352 +/* {{{ apc_copy_function_for_execution_ex */
4353 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
4354 +{
4355 +    if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
4356 +    return apc_copy_function_for_execution(src);
4357 +}
4358 +/* }}} */
4359 +
4360 +/* {{{ apc_copy_class_entry_for_execution */
4361 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
4362 +{
4363 +    zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
4364 +    memcpy(dst, src, sizeof(src[0]));
4365 +
4366 +#ifdef ZEND_ENGINE_2
4367 +    if(src->num_interfaces)
4368 +    {
4369 +        /* These are slots to be populated later by ADD_INTERFACE insns */
4370 +        dst->interfaces = apc_php_malloc(
4371 +                            sizeof(zend_class_entry*) * src->num_interfaces);
4372 +        memset(dst->interfaces, 0, 
4373 +                            sizeof(zend_class_entry*) * src->num_interfaces);
4374 +    }
4375 +    else
4376 +    {
4377 +        /* assert(dst->interfaces == NULL); */
4378 +    }
4379 +#endif
4380 +
4381 +#ifndef ZEND_ENGINE_2    
4382 +    dst->refcount = apc_xmemcpy(src->refcount,
4383 +                                      sizeof(src->refcount[0]),
4384 +                                      apc_php_malloc);
4385 +#endif        
4386 +
4387 +    /* Deep-copy the class properties, because they will be modified */
4388 +
4389 +    my_copy_hashtable(&dst->default_properties,
4390 +                      &src->default_properties,
4391 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4392 +                      (ht_free_fun_t) my_free_zval_ptr,
4393 +                      1,
4394 +                      apc_php_malloc, apc_php_free);
4395 +
4396 +    /* For derived classes, we must also copy the function hashtable (although
4397 +     * we can merely bitwise copy the functions it contains) */
4398 +
4399 +    my_copy_hashtable(&dst->function_table,
4400 +                      &src->function_table,
4401 +                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
4402 +                      NULL,
4403 +                      0,
4404 +                      apc_php_malloc, apc_php_free);
4405 +#ifdef ZEND_ENGINE_2
4406 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
4407 +
4408 +    /* zend_do_inheritance merges properties_info.
4409 +     * Need only shallow copying as it doesn't hold the pointers.
4410 +     */
4411 +    my_copy_hashtable(&dst->properties_info,
4412 +                      &src->properties_info,
4413 +                      (ht_copy_fun_t) my_copy_property_info_for_execution,
4414 +                      NULL,
4415 +                      0,
4416 +                      apc_php_malloc, apc_php_free);
4417 +
4418 +#ifdef ZEND_ENGINE_2_2
4419 +    /* php5.2 introduced a scope attribute for property info */
4420 +    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4421 +#endif
4422 +
4423 +    /* if inheritance results in a hash_del, it might result in
4424 +     * a pefree() of the pointers here. Deep copying required. 
4425 +     */
4426 +
4427 +    my_copy_hashtable(&dst->constants_table,
4428 +                      &src->constants_table,
4429 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4430 +                      NULL,
4431 +                      1,
4432 +                      apc_php_malloc, apc_php_free);
4433 +
4434 +    my_copy_hashtable(&dst->default_static_members,
4435 +                      &src->default_static_members,
4436 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4437 +                      (ht_free_fun_t) my_free_zval_ptr,
4438 +                      1,
4439 +                      apc_php_malloc, apc_php_free);
4440 +
4441 +    if(src->static_members != &(src->default_static_members))
4442 +    {
4443 +        dst->static_members = my_copy_hashtable(NULL,
4444 +                          src->static_members,
4445 +                          (ht_copy_fun_t) my_copy_zval_ptr,
4446 +                          (ht_free_fun_t) my_free_zval_ptr,
4447 +                          1,
4448 +                          apc_php_malloc, apc_php_free);
4449 +    }
4450 +    else 
4451 +    {
4452 +        dst->static_members = &(dst->default_static_members);
4453 +    }
4454 +
4455 +#endif
4456 +
4457 +    return dst;
4458 +}
4459 +/* }}} */
4460 +
4461 +/* {{{ apc_free_class_entry_after_execution */
4462 +void apc_free_class_entry_after_execution(zend_class_entry* src)
4463 +{
4464 +#ifdef ZEND_ENGINE_2
4465 +    if(src->num_interfaces > 0 && src->interfaces) {
4466 +        apc_php_free(src->interfaces);
4467 +        src->interfaces = NULL;
4468 +        src->num_interfaces = 0;
4469 +    }
4470 +    /* my_destroy_hashtable() does not play nice with refcounts */
4471 +
4472 +    zend_hash_clean(&src->default_static_members);
4473 +    if(src->static_members != &(src->default_static_members))
4474 +    {
4475 +        zend_hash_destroy(src->static_members);
4476 +        apc_php_free(src->static_members);
4477 +        src->static_members = NULL;
4478 +    }
4479 +    else
4480 +    {
4481 +        src->static_members = NULL;
4482 +    }
4483 +    zend_hash_clean(&src->default_properties);
4484 +    zend_hash_clean(&src->constants_table);
4485 +#endif
4486 +
4487 +    /* TODO: more cleanup */
4488 +}
4489 +/* }}} */
4490 +
4491 +#ifdef ZEND_ENGINE_2
4492 +
4493 +/* {{{ my_fixup_function */
4494 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4495 +{
4496 +    zend_function* zf = p->pData;
4497 +
4498 +    #define SET_IF_SAME_NAME(member) \
4499 +    do { \
4500 +        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
4501 +            dst->member = zf; \
4502 +        } \
4503 +    } \
4504 +    while(0)
4505 +
4506 +    if(zf->common.scope == src)
4507 +    {
4508 +    
4509 +        /* Fixing up the default functions for objects here since
4510 +         * we need to compare with the newly allocated functions
4511 +         *
4512 +         * caveat: a sub-class method can have the same name as the
4513 +         * parent's constructor and create problems.
4514 +         */
4515 +        
4516 +        if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
4517 +        else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
4518 +        else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
4519 +        else
4520 +        {
4521 +            SET_IF_SAME_NAME(__get);
4522 +            SET_IF_SAME_NAME(__set);
4523 +            SET_IF_SAME_NAME(__unset);
4524 +            SET_IF_SAME_NAME(__isset);
4525 +            SET_IF_SAME_NAME(__call);
4526 +#ifdef ZEND_ENGINE_2_2
4527 +            SET_IF_SAME_NAME(__tostring);
4528 +#endif
4529 +        }
4530 +        zf->common.scope = dst;
4531 +    }
4532 +    else
4533 +    {
4534 +        /* no other function should reach here */
4535 +        assert(0);
4536 +    }
4537 +
4538 +    #undef SET_IF_SAME_NAME
4539 +}
4540 +/* }}} */
4541 +
4542 +#ifdef ZEND_ENGINE_2_2
4543 +/* {{{ my_fixup_property_info */
4544 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4545 +{
4546 +    zend_property_info* property_info = (zend_property_info*)p->pData;
4547 +
4548 +    if(property_info->ce == src)
4549 +    {
4550 +        property_info->ce = dst;
4551 +    }
4552 +    else
4553 +    {
4554 +        assert(0); /* should never happen */
4555 +    }
4556 +}
4557 +/* }}} */
4558 +#endif
4559 +
4560 +/* {{{ my_fixup_hashtable */
4561 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
4562 +{
4563 +    Bucket *p;
4564 +    
4565 +       uint i;
4566 +    
4567 +       for (i = 0; i < ht->nTableSize; i++) {
4568 +               if(!ht->arBuckets) break;
4569 +        p = ht->arBuckets[i];
4570 +               while (p != NULL) {
4571 +            fixup(p, src, dst);
4572 +                       p = p->pNext;
4573 +               }
4574 +       }
4575 +}
4576 +/* }}} */
4577 +
4578 +#endif
4579 +
4580 +/* {{{ my_check_copy_function */
4581 +static int my_check_copy_function(Bucket* p, va_list args)
4582 +{
4583 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4584 +    zend_function* zf = (zend_function*)p->pData;
4585 +#ifndef ZEND_ENGINE_2
4586 +    zend_class_entry* parent = src->parent;
4587 +    zend_function* parent_fn = NULL;
4588 +#endif
4589 +
4590 +#ifdef ZEND_ENGINE_2
4591 +    return (zf->common.scope == src);
4592 +#else
4593 +       if (parent &&
4594 +        zend_hash_quick_find(&parent->function_table, p->arKey, 
4595 +            p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
4596 +        
4597 +        if((parent_fn && zf) && 
4598 +                (parent_fn->op_array.refcount == zf->op_array.refcount))
4599 +        {
4600 +            return 0;
4601 +        }
4602 +    }
4603 +    return 1;
4604 +#endif 
4605 +}
4606 +/* }}} */
4607 +
4608 +/* {{{ my_check_copy_default_property */
4609 +static int my_check_copy_default_property(Bucket* p, va_list args)
4610 +{
4611 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4612 +    zend_class_entry* parent = src->parent;
4613 +    zval ** child_prop = (zval**)p->pData;
4614 +    zval ** parent_prop = NULL;
4615 +
4616 +       if (parent &&
4617 +        zend_hash_quick_find(&parent->default_properties, p->arKey, 
4618 +            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
4619 +
4620 +        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
4621 +        {
4622 +            return 0;
4623 +        }
4624 +    }
4625 +    
4626 +    /* possibly not in the parent */
4627 +    return 1;
4628 +}
4629 +/* }}} */
4630 +
4631 +#ifdef ZEND_ENGINE_2
4632 +
4633 +/* {{{ my_check_copy_property_info */
4634 +static int my_check_copy_property_info(Bucket* p, va_list args)
4635 +{
4636 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4637 +    zend_class_entry* parent = src->parent;
4638 +    zend_property_info* child_info = (zend_property_info*)p->pData;
4639 +    zend_property_info* parent_info = NULL;
4640 +
4641 +#ifdef ZEND_ENGINE_2_2
4642 +    /* so much easier */
4643 +    return (child_info->ce == src);
4644 +#endif
4645 +
4646 +       if (parent &&
4647 +        zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength, 
4648 +            p->h, (void **) &parent_info)==SUCCESS) {
4649 +        if(parent_info->flags & ZEND_ACC_PRIVATE)
4650 +        {
4651 +            return 1;
4652 +        }
4653 +        if((parent_info->flags & ZEND_ACC_PPP_MASK) != 
4654 +            (child_info->flags & ZEND_ACC_PPP_MASK))
4655 +        {
4656 +            /* TODO: figure out whether ACC_CHANGED is more appropriate
4657 +             * here */
4658 +            return 1;
4659 +        }
4660 +        return 0;
4661 +    }
4662 +    
4663 +    /* property doesn't exist in parent, copy into cached child */
4664 +    return 1;
4665 +}
4666 +/* }}} */
4667 +
4668 +/* {{{ my_check_copy_static_member */
4669 +static int my_check_copy_static_member(Bucket* p, va_list args)
4670 +{
4671 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4672 +    HashTable * ht = va_arg(args, HashTable*);
4673 +    zend_class_entry* parent = src->parent;
4674 +    HashTable * parent_ht = NULL;
4675 +    char * member_name;
4676 +    char * class_name = NULL;
4677 +
4678 +    zend_property_info *parent_info = NULL;
4679 +    zend_property_info *child_info = NULL;
4680 +    zval ** parent_prop = NULL;
4681 +    zval ** child_prop = (zval**)(p->pData);
4682 +
4683 +    if(!parent) {
4684 +        return 1;
4685 +    }
4686 +
4687 +    /* these do not need free'ing */
4688 +#ifdef ZEND_ENGINE_2_2
4689 +    zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
4690 +#else
4691 +    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
4692 +#endif
4693 +
4694 +    /* please refer do_inherit_property_access_check in zend_compile.c
4695 +     * to understand why we lookup in properties_info.
4696 +     */
4697 +    if((zend_hash_find(&parent->properties_info, member_name, 
4698 +                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
4699 +        &&
4700 +        (zend_hash_find(&src->properties_info, member_name,
4701 +                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
4702 +    {
4703 +        if(child_info->flags & ZEND_ACC_STATIC &&    
4704 +            (parent_info->flags & ZEND_ACC_PROTECTED &&
4705 +            child_info->flags & ZEND_ACC_PUBLIC))
4706 +        {
4707 +            /* Do not copy into static_members. zend_do_inheritance
4708 +             * will automatically insert a NULL value.
4709 +             * TODO: decrement refcount or fixup when copying out for exec ? 
4710 +             */ 
4711 +            return 0;
4712 +        }
4713 +        if(ht == &(src->default_static_members))
4714 +        {
4715 +            parent_ht = &parent->default_static_members;
4716 +        }
4717 +        else
4718 +        {
4719 +            parent_ht = parent->static_members;
4720 +        }
4721 +
4722 +        if(zend_hash_quick_find(parent_ht, p->arKey,
4723 +                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
4724 +        {
4725 +            /* they point to the same zval */
4726 +            if(*parent_prop == *child_prop)
4727 +            {
4728 +                return 0;
4729 +            }
4730 +        }
4731 +    }
4732 +    
4733 +    return 1;
4734 +}
4735 +/* }}} */
4736 +#endif
4737 +
4738 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
4739 + *      register a optimizer callback function, returns the previous callback
4740 + */
4741 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
4742 +    apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
4743 +    APCG(apc_optimize_function) = optimizer;
4744 +    return old_optimizer;
4745 +}
4746 +
4747 +/*
4748 + * Local variables:
4749 + * tab-width: 4
4750 + * c-basic-offset: 4
4751 + * End:
4752 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4753 + * vim<600: expandtab sw=4 ts=4 sts=4
4754 + */
4755 diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.h php-5.2.5/ext/apc/apc_compile.h
4756 --- php-5.2.5-orig/ext/apc/apc_compile.h        1969-12-31 18:00:00.000000000 -0600
4757 +++ php-5.2.5/ext/apc/apc_compile.h     2007-12-26 16:51:32.000000000 -0600
4758 @@ -0,0 +1,134 @@
4759 +/*
4760 +  +----------------------------------------------------------------------+
4761 +  | APC                                                                  |
4762 +  +----------------------------------------------------------------------+
4763 +  | Copyright (c) 2006 The PHP Group                                     |
4764 +  +----------------------------------------------------------------------+
4765 +  | This source file is subject to version 3.01 of the PHP license,      |
4766 +  | that is bundled with this package in the file LICENSE, and is        |
4767 +  | available through the world-wide-web at the following url:           |
4768 +  | http://www.php.net/license/3_01.txt                                  |
4769 +  | If you did not receive a copy of the PHP license and are unable to   |
4770 +  | obtain it through the world-wide-web, please send a note to          |
4771 +  | license@php.net so we can mail you a copy immediately.               |
4772 +  +----------------------------------------------------------------------+
4773 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
4774 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
4775 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
4776 +  +----------------------------------------------------------------------+
4777 +
4778 +   This software was contributed to PHP by Community Connect Inc. in 2002
4779 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4780 +   Future revisions and derivatives of this source code must acknowledge
4781 +   Community Connect Inc. as the original contributor of this module by
4782 +   leaving this note intact in the source code.
4783 +
4784 +   All other licensing and usage conditions are those of the PHP Group.
4785 +
4786 + */
4787 +
4788 +/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
4789 +
4790 +#ifndef APC_COMPILE_H
4791 +#define APC_COMPILE_H
4792 +
4793 +/*
4794 + * This module encapsulates most of the complexity involved in deep-copying
4795 + * the Zend compiler data structures. The routines are allocator-agnostic, so
4796 + * the same function can be used for copying to and from shared memory.
4797 + */
4798 +
4799 +#include "apc.h"
4800 +#include "apc_php.h"
4801 +
4802 +/* {{{ struct definition: apc_function_t */
4803 +typedef struct apc_function_t apc_function_t;
4804 +struct apc_function_t {
4805 +    char* name;                 /* the function name */
4806 +    int name_len;               /* length of name */
4807 +    zend_function* function;    /* the zend function data structure */
4808 +};
4809 +/* }}} */
4810 +
4811 +/* {{{ struct definition: apc_class_t */
4812 +typedef struct apc_class_t apc_class_t;
4813 +struct apc_class_t {
4814 +    char* name;                     /* the class name */
4815 +    int name_len;                   /* length of name */
4816 +    int is_derived;                 /* true if this is a derived class */
4817 +    char* parent_name;              /* the parent class name */
4818 +    zend_class_entry* class_entry;  /* the zend class data structure */
4819 +};
4820 +/* }}} */
4821 +
4822 +/* {{{ struct definition: apc_opflags_t */
4823 +typedef struct apc_opflags_t apc_opflags_t;
4824 +struct apc_opflags_t {
4825 +    unsigned int has_jumps      : 1; /* has jump offsets */
4826 +    unsigned int deep_copy      : 1; /* needs deep copy */
4827 +
4828 +    /* autoglobal bits */
4829 +    unsigned int _POST          : 1;
4830 +    unsigned int _GET           : 1;
4831 +    unsigned int _COOKIE        : 1;
4832 +    unsigned int _SERVER        : 1;
4833 +    unsigned int _ENV           : 1;
4834 +    unsigned int _FILES         : 1;
4835 +    unsigned int _REQUEST       : 1;
4836 +    unsigned int unknown_global : 1;
4837 +};
4838 +/* }}} */
4839 +
4840 +/*
4841 + * These are the top-level copy functions.
4842 + */
4843 +
4844 +extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4845 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
4846 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4847 +extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4848 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
4849 +
4850 +/*
4851 + * Deallocation functions corresponding to the copy functions above.
4852 + */
4853 +
4854 +extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
4855 +extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
4856 +extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
4857 +extern void apc_free_zval(zval* src, apc_free_t deallocate);
4858 +
4859 +/*
4860 + * These "copy-for-execution" functions must be called after retrieving an
4861 + * object from the shared cache. They do the minimal amount of work necessary
4862 + * to allow multiple processes to concurrently execute the same VM data
4863 + * structures.
4864 + */
4865 +
4866 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
4867 +extern zend_function* apc_copy_function_for_execution(zend_function* src);
4868 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
4869 +
4870 +/*
4871 + * The "free-after-execution" function performs a cursory clean up of the class data
4872 + * This is required to minimize memory leak warnings and to ensure correct destructor
4873 + * ordering of some variables.
4874 + */
4875 +extern void apc_free_class_entry_after_execution(zend_class_entry* src);
4876 +
4877 +/*
4878 + * Optimization callback definition and registration function. 
4879 + */
4880 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
4881 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
4882 +
4883 +#endif
4884 +
4885 +/*
4886 + * Local variables:
4887 + * tab-width: 4
4888 + * c-basic-offset: 4
4889 + * End:
4890 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4891 + * vim<600: expandtab sw=4 ts=4 sts=4
4892 + */
4893 diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.c php-5.2.5/ext/apc/apc_debug.c
4894 --- php-5.2.5-orig/ext/apc/apc_debug.c  1969-12-31 18:00:00.000000000 -0600
4895 +++ php-5.2.5/ext/apc/apc_debug.c       2007-12-26 16:51:32.000000000 -0600
4896 @@ -0,0 +1,57 @@
4897 +/*
4898 +  +----------------------------------------------------------------------+
4899 +  | APC                                                                  |
4900 +  +----------------------------------------------------------------------+
4901 +  | Copyright (c) 2006 The PHP Group                                     |
4902 +  +----------------------------------------------------------------------+
4903 +  | This source file is subject to version 3.01 of the PHP license,      |
4904 +  | that is bundled with this package in the file LICENSE, and is        |
4905 +  | available through the world-wide-web at the following url:           |
4906 +  | http://www.php.net/license/3_01.txt                                  |
4907 +  | If you did not receive a copy of the PHP license and are unable to   |
4908 +  | obtain it through the world-wide-web, please send a note to          |
4909 +  | license@php.net so we can mail you a copy immediately.               |
4910 +  +----------------------------------------------------------------------+
4911 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
4912 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
4913 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
4914 +  +----------------------------------------------------------------------+
4915 +
4916 +   This software was contributed to PHP by Community Connect Inc. in 2002
4917 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4918 +   Future revisions and derivatives of this source code must acknowledge
4919 +   Community Connect Inc. as the original contributor of this module by
4920 +   leaving this note intact in the source code.
4921 +
4922 +   All other licensing and usage conditions are those of the PHP Group.
4923 +*/
4924 +
4925 +/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
4926 +#include "apc.h"
4927 +#include <stdio.h>
4928 +#include "zend_compile.h"
4929 +
4930 +#ifdef __DEBUG_APC__
4931 +
4932 +#include <dlfcn.h>
4933 +
4934 +/* keep track of vld_dump_oparray() signature */
4935 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
4936 +
4937 +#endif
4938 +
4939 +void dump(zend_op_array *op_array TSRMLS_DC)
4940 +{
4941 +#ifdef __DEBUG_APC__
4942 +       vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
4943 +
4944 +       if(dump_op_array)
4945 +       {
4946 +               dump_op_array(op_array TSRMLS_CC); 
4947 +       }
4948 +       else
4949 +       {
4950 +               apc_wprint("vld is not installed or something even worse.");
4951 +       }
4952 +#endif
4953 +}
4954 diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.h php-5.2.5/ext/apc/apc_debug.h
4955 --- php-5.2.5-orig/ext/apc/apc_debug.h  1969-12-31 18:00:00.000000000 -0600
4956 +++ php-5.2.5/ext/apc/apc_debug.h       2007-12-26 16:51:32.000000000 -0600
4957 @@ -0,0 +1 @@
4958 +void dump(zend_op_array * TSRMLS_DC);
4959 diff -ubrN php-5.2.5-orig/ext/apc/apc.dsp php-5.2.5/ext/apc/apc.dsp
4960 --- php-5.2.5-orig/ext/apc/apc.dsp      1969-12-31 18:00:00.000000000 -0600
4961 +++ php-5.2.5/ext/apc/apc.dsp   2007-12-26 16:51:32.000000000 -0600
4962 @@ -0,0 +1,207 @@
4963 +# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>\r
4964 +# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
4965 +# ** DO NOT EDIT **\r
4966 +\r
4967 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
4968 +\r
4969 +CFG=apc - Win32 Debug_TS\r
4970 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
4971 +!MESSAGE use the Export Makefile command and run\r
4972 +!MESSAGE \r
4973 +!MESSAGE NMAKE /f "apc.mak".\r
4974 +!MESSAGE \r
4975 +!MESSAGE You can specify a configuration when running NMAKE\r
4976 +!MESSAGE by defining the macro CFG on the command line. For example:\r
4977 +!MESSAGE \r
4978 +!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"\r
4979 +!MESSAGE \r
4980 +!MESSAGE Possible choices for configuration are:\r
4981 +!MESSAGE \r
4982 +!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
4983 +!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
4984 +!MESSAGE \r
4985 +\r
4986 +# Begin Project\r
4987 +# PROP AllowPerConfigDependencies 0\r
4988 +# PROP Scc_ProjName ""\r
4989 +# PROP Scc_LocalPath ""\r
4990 +CPP=cl.exe\r
4991 +MTL=midl.exe\r
4992 +RSC=rc.exe\r
4993 +\r
4994 +!IF  "$(CFG)" == "apc - Win32 Debug_TS"\r
4995 +\r
4996 +# PROP BASE Use_MFC 0\r
4997 +# PROP BASE Use_Debug_Libraries 1\r
4998 +# PROP BASE Output_Dir "Debug_TS"\r
4999 +# PROP BASE Intermediate_Dir "Debug_TS"\r
5000 +# PROP BASE Target_Dir ""\r
5001 +# PROP Use_MFC 0\r
5002 +# PROP Use_Debug_Libraries 1\r
5003 +# PROP Output_Dir "Debug_TS"\r
5004 +# PROP Intermediate_Dir "Debug_TS"\r
5005 +# PROP Ignore_Export_Lib 0\r
5006 +# PROP Target_Dir ""\r
5007 +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c\r
5008 +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=1 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c\r
5009 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
5010 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
5011 +# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
5012 +# ADD RSC /l 0x409 /d "_DEBUG"\r
5013 +BSC32=bscmake.exe\r
5014 +# ADD BASE BSC32 /nologo\r
5015 +# ADD BSC32 /nologo\r
5016 +LINK32=link.exe\r
5017 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
5018 +# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug_TS/php_apc.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS"\r
5019 +\r
5020 +!ELSEIF  "$(CFG)" == "apc - Win32 Release_TS"\r
5021 +\r
5022 +# PROP BASE Use_MFC 0\r
5023 +# PROP BASE Use_Debug_Libraries 0\r
5024 +# PROP BASE Output_Dir "Release_TS"\r
5025 +# PROP BASE Intermediate_Dir "Release_TS"\r
5026 +# PROP BASE Target_Dir ""\r
5027 +# PROP Use_MFC 0\r
5028 +# PROP Use_Debug_Libraries 0\r
5029 +# PROP Output_Dir "Release_TS"\r
5030 +# PROP Intermediate_Dir "Release_TS"\r
5031 +# PROP Ignore_Export_Lib 0\r
5032 +# PROP Target_Dir ""\r
5033 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c\r
5034 +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=0 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c\r
5035 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
5036 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
5037 +# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
5038 +# ADD RSC /l 0x409 /d "NDEBUG"\r
5039 +BSC32=bscmake.exe\r
5040 +# ADD BASE BSC32 /nologo\r
5041 +# ADD BSC32 /nologo\r
5042 +LINK32=link.exe\r
5043 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
5044 +# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Release_TS/php_apc.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"\r
5045 +\r
5046 +!ENDIF \r
5047 +\r
5048 +# Begin Target\r
5049 +\r
5050 +# Name "apc - Win32 Debug_TS"\r
5051 +# Name "apc - Win32 Release_TS"\r
5052 +# Begin Group "Source Files"\r
5053 +\r
5054 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
5055 +# Begin Source File\r
5056 +\r
5057 +SOURCE=.\apc.c\r
5058 +# End Source File\r
5059 +# Begin Source File\r
5060 +\r
5061 +SOURCE=.\apc_cache.c\r
5062 +# End Source File\r
5063 +# Begin Source File\r
5064 +\r
5065 +SOURCE=.\apc_compile.c\r
5066 +# End Source File\r
5067 +# Begin Source File\r
5068 +\r
5069 +SOURCE=.\apc_debug.c\r
5070 +# End Source File\r
5071 +# Begin Source File\r
5072 +\r
5073 +SOURCE=.\apc_fcntl_win32.c\r
5074 +# End Source File\r
5075 +# Begin Source File\r
5076 +\r
5077 +SOURCE=.\apc_main.c\r
5078 +# End Source File\r
5079 +# Begin Source File\r
5080 +\r
5081 +SOURCE=.\apc_rfc1867.c\r
5082 +# End Source File\r
5083 +# Begin Source File\r
5084 +\r
5085 +SOURCE=.\apc_shm.c\r
5086 +# End Source File\r
5087 +# Begin Source File\r
5088 +\r
5089 +SOURCE=.\apc_sma.c\r
5090 +# End Source File\r
5091 +# Begin Source File\r
5092 +\r
5093 +SOURCE=.\apc_stack.c\r
5094 +# End Source File\r
5095 +# Begin Source File\r
5096 +\r
5097 +SOURCE=.\apc_zend.c\r
5098 +# End Source File\r
5099 +# Begin Source File\r
5100 +\r
5101 +SOURCE=.\php_apc.c\r
5102 +# End Source File\r
5103 +# End Group\r
5104 +# Begin Group "Header Files"\r
5105 +\r
5106 +# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
5107 +# Begin Source File\r
5108 +\r
5109 +SOURCE=.\apc.h\r
5110 +# End Source File\r
5111 +# Begin Source File\r
5112 +\r
5113 +SOURCE=.\apc_cache.h\r
5114 +# End Source File\r
5115 +# Begin Source File\r
5116 +\r
5117 +SOURCE=.\apc_compile.h\r
5118 +# End Source File\r
5119 +# Begin Source File\r
5120 +\r
5121 +SOURCE=.\apc_debug.h\r
5122 +# End Source File\r
5123 +# Begin Source File\r
5124 +\r
5125 +SOURCE=.\apc_fcntl.h\r
5126 +# End Source File\r
5127 +# Begin Source File\r
5128 +\r
5129 +SOURCE=.\apc_globals.h\r
5130 +# End Source File\r
5131 +# Begin Source File\r
5132 +\r
5133 +SOURCE=.\apc_lock.h\r
5134 +# End Source File\r
5135 +# Begin Source File\r
5136 +\r
5137 +SOURCE=.\apc_main.h\r
5138 +# End Source File\r
5139 +# Begin Source File\r
5140 +\r
5141 +SOURCE=.\apc_php.h\r
5142 +# End Source File\r
5143 +# Begin Source File\r
5144 +\r
5145 +SOURCE=.\apc_shm.h\r
5146 +# End Source File\r
5147 +# Begin Source File\r
5148 +\r
5149 +SOURCE=.\apc_sma.h\r
5150 +# End Source File\r
5151 +# Begin Source File\r
5152 +\r
5153 +SOURCE=.\apc_stack.h\r
5154 +# End Source File\r
5155 +# Begin Source File\r
5156 +\r
5157 +SOURCE=.\apc_zend.h\r
5158 +# End Source File\r
5159 +# Begin Source File\r
5160 +\r
5161 +SOURCE=.\php_apc.h\r
5162 +# End Source File\r
5163 +# End Group\r
5164 +# Begin Group "Resource Files"\r
5165 +\r
5166 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
5167 +# End Group\r
5168 +# End Target\r
5169 +# End Project\r
5170 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.c php-5.2.5/ext/apc/apc_fcntl.c
5171 --- php-5.2.5-orig/ext/apc/apc_fcntl.c  1969-12-31 18:00:00.000000000 -0600
5172 +++ php-5.2.5/ext/apc/apc_fcntl.c       2007-12-26 16:51:32.000000000 -0600
5173 @@ -0,0 +1,118 @@
5174 +/*
5175 +  +----------------------------------------------------------------------+
5176 +  | APC                                                                  |
5177 +  +----------------------------------------------------------------------+
5178 +  | Copyright (c) 2006 The PHP Group                                     |
5179 +  +----------------------------------------------------------------------+
5180 +  | This source file is subject to version 3.01 of the PHP license,      |
5181 +  | that is bundled with this package in the file LICENSE, and is        |
5182 +  | available through the world-wide-web at the following url:           |
5183 +  | http://www.php.net/license/3_01.txt                                  |
5184 +  | If you did not receive a copy of the PHP license and are unable to   |
5185 +  | obtain it through the world-wide-web, please send a note to          |
5186 +  | license@php.net so we can mail you a copy immediately.               |
5187 +  +----------------------------------------------------------------------+
5188 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5189 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5190 +  +----------------------------------------------------------------------+
5191 +
5192 +   This software was contributed to PHP by Community Connect Inc. in 2002
5193 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5194 +   Future revisions and derivatives of this source code must acknowledge
5195 +   Community Connect Inc. as the original contributor of this module by
5196 +   leaving this note intact in the source code.
5197 +
5198 +   All other licensing and usage conditions are those of the PHP Group.
5199 +
5200 + */
5201 +
5202 +/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
5203 +
5204 +#include "apc_fcntl.h"
5205 +#include "apc.h"
5206 +#include <unistd.h>
5207 +#include <fcntl.h>
5208 +
5209 +int apc_fcntl_create(const char* pathname)
5210 +{
5211 +    int fd;
5212 +    if(pathname == NULL) {
5213 +        char lock_path[] = "/tmp/.apc.XXXXXX";
5214 +        mktemp(lock_path);
5215 +        fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5216 +        if(fd > 0 ) {
5217 +            unlink(lock_path);
5218 +            return fd;
5219 +        } else {
5220 +            apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
5221 +            return -1;
5222 +        }
5223 +    }
5224 +    fd = open(pathname, O_RDWR|O_CREAT, 0666);
5225 +    if(fd > 0 ) {
5226 +        unlink(pathname);
5227 +        return fd;
5228 +    }
5229 +    apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
5230 +    return -1;
5231 +}
5232 +
5233 +void apc_fcntl_destroy(int fd)
5234 +{
5235 +    close(fd);
5236 +}
5237 +
5238 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5239 +{
5240 +  int ret;
5241 +  struct flock lock;
5242 +
5243 +  lock.l_type = type;
5244 +  lock.l_start = offset;
5245 +  lock.l_whence = whence;
5246 +  lock.l_len = len;
5247 +  lock.l_pid = 0;
5248 +
5249 +  do { ret = fcntl(fd, cmd, &lock) ; }
5250 +  while(ret < 0 && errno == EINTR);
5251 +  return(ret);
5252 +}
5253 +
5254 +void apc_fcntl_lock(int fd)
5255 +{
5256 +    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5257 +        apc_eprint("apc_fcntl_lock failed:");
5258 +    }
5259 +}
5260 +
5261 +void apc_fcntl_rdlock(int fd)
5262 +{
5263 +    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
5264 +        apc_eprint("apc_fcntl_rdlock failed:");
5265 +    }
5266 +}
5267 +
5268 +zend_bool apc_fcntl_nonblocking_lock(int fd)
5269 +{
5270 +    if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5271 +        if(errno==EACCES||errno==EAGAIN) return 0;
5272 +        else apc_eprint("apc_fcntl_lock failed:");
5273 +    }
5274 +    return 1;
5275 +}
5276 +
5277 +void apc_fcntl_unlock(int fd)
5278 +{
5279 +    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
5280 +        apc_eprint("apc_fcntl_unlock failed:");
5281 +    }
5282 +}
5283 +
5284 +/*
5285 + * Local variables:
5286 + * tab-width: 4
5287 + * c-basic-offset: 4
5288 + * End:
5289 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5290 + * vim<600: expandtab sw=4 ts=4 sts=4
5291 + */
5292 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.h php-5.2.5/ext/apc/apc_fcntl.h
5293 --- php-5.2.5-orig/ext/apc/apc_fcntl.h  1969-12-31 18:00:00.000000000 -0600
5294 +++ php-5.2.5/ext/apc/apc_fcntl.h       2007-12-26 16:51:32.000000000 -0600
5295 @@ -0,0 +1,50 @@
5296 +/*
5297 +  +----------------------------------------------------------------------+
5298 +  | APC                                                                  |
5299 +  +----------------------------------------------------------------------+
5300 +  | Copyright (c) 2006 The PHP Group                                     |
5301 +  +----------------------------------------------------------------------+
5302 +  | This source file is subject to version 3.01 of the PHP license,      |
5303 +  | that is bundled with this package in the file LICENSE, and is        |
5304 +  | available through the world-wide-web at the following url:           |
5305 +  | http://www.php.net/license/3_01.txt.                                 |
5306 +  | If you did not receive a copy of the PHP license and are unable to   |
5307 +  | obtain it through the world-wide-web, please send a note to          |
5308 +  | license@php.net so we can mail you a copy immediately.               |
5309 +  +----------------------------------------------------------------------+
5310 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5311 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5312 +  +----------------------------------------------------------------------+
5313 +
5314 +   This software was contributed to PHP by Community Connect Inc. in 2002
5315 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5316 +   Future revisions and derivatives of this source code must acknowledge
5317 +   Community Connect Inc. as the original contributor of this module by
5318 +   leaving this note intact in the source code.
5319 +
5320 +   All other licensing and usage conditions are those of the PHP Group.
5321 +
5322 + */
5323 +
5324 +/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
5325 +
5326 +#ifndef APC_FCNTL_H
5327 +#define APC_FCNTL_H
5328 +
5329 +
5330 +extern int apc_fcntl_create(const char* pathname);
5331 +extern void apc_fcntl_destroy(int fd);
5332 +extern void apc_fcntl_lock(int fd);
5333 +extern void apc_fcntl_rdlock(int fd);
5334 +extern void apc_fcntl_unlock(int fd);
5335 +extern unsigned char apc_fcntl_nonblocking_lock(int fd);
5336 +#endif
5337 +
5338 +/*
5339 + * Local variables:
5340 + * tab-width: 4
5341 + * c-basic-offset: 4
5342 + * End:
5343 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5344 + * vim<600: expandtab sw=4 ts=4 sts=4
5345 + */
5346 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl_win32.c php-5.2.5/ext/apc/apc_fcntl_win32.c
5347 --- php-5.2.5-orig/ext/apc/apc_fcntl_win32.c    1969-12-31 18:00:00.000000000 -0600
5348 +++ php-5.2.5/ext/apc/apc_fcntl_win32.c 2007-12-26 16:51:32.000000000 -0600
5349 @@ -0,0 +1,117 @@
5350 +/*
5351 +  +----------------------------------------------------------------------+
5352 +  | APC                                                                  |
5353 +  +----------------------------------------------------------------------+
5354 +  | Copyright (c) 2006 The PHP Group                                     |
5355 +  +----------------------------------------------------------------------+
5356 +  | This source file is subject to version 3.01 of the PHP license,      |
5357 +  | that is bundled with this package in the file LICENSE, and is        |
5358 +  | available through the world-wide-web at the following url:           |
5359 +  | http://www.php.net/license/3_01.txt                                  |
5360 +  | If you did not receive a copy of the PHP license and are unable to   |
5361 +  | obtain it through the world-wide-web, please send a note to          |
5362 +  | license@php.net so we can mail you a copy immediately.               |
5363 +  +----------------------------------------------------------------------+
5364 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5365 +  |          Edin Kadribasic <edink@php.net>                             |
5366 +  +----------------------------------------------------------------------+
5367 +
5368 +   This software was contributed to PHP by Community Connect Inc. in 2002
5369 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5370 +   Future revisions and derivatives of this source code must acknowledge
5371 +   Community Connect Inc. as the original contributor of this module by
5372 +   leaving this note intact in the source code.
5373 +
5374 +   All other licensing and usage conditions are those of the PHP Group.
5375 +
5376 + */
5377 +
5378 +/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
5379 +
5380 +#include "apc_fcntl.h"
5381 +#include "apc.h"
5382 +#include <php.h>
5383 +#include <win32/flock.h>
5384 +#include <io.h>
5385 +#include <fcntl.h>
5386 +#include <sys/types.h>
5387 +#include <sys/stat.h>
5388 +
5389 +int apc_fcntl_create(const char* pathname)
5390 +{
5391 +       char *lock_file = emalloc(MAXPATHLEN);
5392 +       HANDLE fd;
5393 +       DWORD tmplen;
5394 +       static int i=0;
5395 +       
5396 +       tmplen = GetTempPath(MAXPATHLEN, lock_file);
5397 +       if (!tmplen) {
5398 +               efree(lock_file);
5399 +               return -1;
5400 +       }
5401 +
5402 +       snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
5403 +       
5404 +       fd = CreateFile(lock_file,
5405 +        GENERIC_READ | GENERIC_WRITE,
5406 +        FILE_SHARE_READ | FILE_SHARE_WRITE,
5407 +        NULL,
5408 +        OPEN_ALWAYS,
5409 +        FILE_ATTRIBUTE_NORMAL,
5410 +        NULL);
5411 +        
5412 +
5413 +       if (fd == INVALID_HANDLE_VALUE) {
5414 +               apc_eprint("apc_fcntl_create: could not open %s", lock_file);
5415 +               efree(lock_file);
5416 +               return -1;
5417 +       }
5418 +       
5419 +       efree(lock_file);
5420 +       return (int)fd;
5421 +}
5422 +
5423 +void apc_fcntl_destroy(int fd)
5424 +{
5425 +       CloseHandle((HANDLE)fd);
5426 +}
5427 +
5428 +void apc_fcntl_lock(int fd)
5429 +{
5430 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5431 +       
5432 +       if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
5433 +               apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
5434 +       }
5435 +}
5436 +
5437 +void apc_fcntl_rdlock(int fd)
5438 +{
5439 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5440 +       
5441 +       if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
5442 +               apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
5443 +       }
5444 +}
5445 +
5446 +void apc_fcntl_unlock(int fd)
5447 +{
5448 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5449 +
5450 +       if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
5451 +               DWORD error_code = GetLastError();
5452 +               /* Ignore already unlocked error */
5453 +               if (error_code != ERROR_NOT_LOCKED) {
5454 +                       apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
5455 +               }
5456 +       }
5457 +}
5458 +
5459 +/*
5460 + * Local variables:
5461 + * tab-width: 4
5462 + * c-basic-offset: 4
5463 + * End:
5464 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5465 + * vim<600: expandtab sw=4 ts=4 sts=4
5466 + */
5467 diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
5468 --- php-5.2.5-orig/ext/apc/apc_futex.c  1969-12-31 18:00:00.000000000 -0600
5469 +++ php-5.2.5/ext/apc/apc_futex.c       2007-12-26 16:51:32.000000000 -0600
5470 @@ -0,0 +1,116 @@
5471 +/*
5472 +  +----------------------------------------------------------------------+
5473 +  | APC                                                                  |
5474 +  +----------------------------------------------------------------------+
5475 +  | Copyright (c) 2006 The PHP Group                                     |
5476 +  +----------------------------------------------------------------------+
5477 +  | This source file is subject to version 3.01 of the PHP license,      |
5478 +  | that is bundled with this package in the file LICENSE, and is        |
5479 +  | available through the world-wide-web at the following url:           |
5480 +  | http://www.php.net/license/3_01.txt                                  |
5481 +  | If you did not receive a copy of the PHP license and are unable to   |
5482 +  | obtain it through the world-wide-web, please send a note to          |
5483 +  | license@php.net so we can mail you a copy immediately.               |
5484 +  +----------------------------------------------------------------------+
5485 +  | Authors: Brian Shire <shire@php.net>                                 |
5486 +  +----------------------------------------------------------------------+
5487 +
5488 + */
5489 +
5490 +/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5491 +
5492 +/***************************************************************************
5493 +* Futex (Fast Userspace Mutex) support for APC
5494 +* 
5495 +* Futex support provides user space locking with system calls only
5496 +* for the contended cases.  Some required reading for this functionality is:
5497 +*
5498 +* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux' 
5499 +*  by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
5500 +*   http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
5501 +*
5502 +* 'Futexes are Tricky' by Ulrich Drepper 
5503 +*    http://people.redhat.com/drepper/futex.pdf
5504 +*
5505 +* 
5506 +* This implementation is optimized and designed for the i386 and x86_64 
5507 +* architectures.  Other architectures may require additional design 
5508 +* to efficiently and safely implement this functionality. 
5509 +*
5510 +* Lock values are:
5511 +* 0 = Unlocked
5512 +* 1 = Locked without any waiting processes
5513 +* 2 = Locked with an unknown number of waiting processes
5514 +*
5515 +***************************************************************************/
5516 +
5517 +#include "apc.h"
5518 +#include "apc_futex.h"
5519 +
5520 +#ifdef APC_FUTEX_LOCKS
5521 +
5522 +
5523 +inline int apc_futex_create()
5524 +{
5525 +    return 0;
5526 +}
5527 +
5528 +inline void apc_futex_destroy(volatile int* lock)
5529 +{
5530 +    return;
5531 +}
5532 +
5533 +void apc_futex_lock(volatile int* lock)
5534 +{
5535 +    int c;
5536 +  
5537 +    /*  Attempt to obtain a lock if not currently locked.  If the previous
5538 +     *  value was not 0 then we did not obtain the lock, and must wait.
5539 +     *  If the previous value was 1 (has no waiting processes) then we
5540 +     *  set the lock to 2 before blocking on the futex wait operation.  
5541 +     *  This implementation suffers from the possible difficulty of 
5542 +     *  efficently implementing the atomic xchg operation on some
5543 +     *  architectures, and could also cause unecessary wake operations by
5544 +     *  setting the lock to 2 when there are no additional waiters.
5545 +     */ 
5546 +    if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
5547 +        if(c != 2) {
5548 +            c = apc_xchg(lock, 2);
5549 +        }
5550 +        while(c != 0) {
5551 +            apc_futex_wait(lock, 2);
5552 +            c = apc_xchg(lock, 2);
5553 +        }
5554 +    }
5555 +    
5556 +}
5557 +
5558 +/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
5559 +inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
5560 +{
5561 +    return apc_cmpxchg(lock, 0, 1) == 0;
5562 +}
5563 +
5564 +
5565 +inline void apc_futex_unlock(volatile int* lock)
5566 +{
5567 +    /* set the lock to 0, if it's previous values was not 1 (no waiters)
5568 +     * then perform a wake operation on one process letting it know the lock 
5569 +     * is available.  This is an optimization to save wake calls if there
5570 +     * are no waiting processes for the lock 
5571 +     */
5572 +    if(apc_xchg(lock,0) != 1) {
5573 +        apc_futex_wake(lock, 1);
5574 +    }
5575 +}
5576 +
5577 +#endif
5578 +
5579 +/*
5580 + * Local variables:
5581 + * tab-width: 4
5582 + * c-basic-offset: 4
5583 + * End:
5584 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5585 + * vim<600: expandtab sw=4 ts=4 sts=4
5586 + */
5587 diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.h php-5.2.5/ext/apc/apc_futex.h
5588 --- php-5.2.5-orig/ext/apc/apc_futex.h  1969-12-31 18:00:00.000000000 -0600
5589 +++ php-5.2.5/ext/apc/apc_futex.h       2007-12-26 16:51:32.000000000 -0600
5590 @@ -0,0 +1,55 @@
5591 +/*
5592 +  +----------------------------------------------------------------------+
5593 +  | APC                                                                  |
5594 +  +----------------------------------------------------------------------+
5595 +  | Copyright (c) 2006 The PHP Group                                     |
5596 +  +----------------------------------------------------------------------+
5597 +  | This source file is subject to version 3.01 of the PHP license,      |
5598 +  | that is bundled with this package in the file LICENSE, and is        |
5599 +  | available through the world-wide-web at the following url:           |
5600 +  | http://www.php.net/license/3_01.txt                                  |
5601 +  | If you did not receive a copy of the PHP license and are unable to   |
5602 +  | obtain it through the world-wide-web, please send a note to          |
5603 +  | license@php.net so we can mail you a copy immediately.               |
5604 +  +----------------------------------------------------------------------+
5605 +  | Authors: Brian Shire <shire@php.net>                                 |
5606 +  +----------------------------------------------------------------------+
5607 +
5608 + */
5609 +
5610 +/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5611 +
5612 +#ifndef APC_FUTEX_H
5613 +#define APC_FUTEX_H
5614 +
5615 +#include "apc.h"
5616 +
5617 +#ifdef APC_FUTEX_LOCKS 
5618 +
5619 +#include <asm/types.h>
5620 +#include <unistd.h>
5621 +#include <linux/futex.h>
5622 +
5623 +#include "arch/atomic.h"
5624 +
5625 +#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
5626 +#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
5627 +#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
5628 +
5629 +int apc_futex_create();
5630 +void apc_futex_destroy(volatile int* lock);
5631 +void apc_futex_lock(volatile int* lock);
5632 +void apc_futex_unlock(volatile int* lock);
5633 +
5634 +#endif
5635 +
5636 +#endif
5637 +
5638 +/*
5639 + * Local variables:
5640 + * tab-width: 4
5641 + * c-basic-offset: 4
5642 + * End:
5643 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5644 + * vim<600: expandtab sw=4 ts=4 sts=4
5645 + */
5646 diff -ubrN php-5.2.5-orig/ext/apc/apc_globals.h php-5.2.5/ext/apc/apc_globals.h
5647 --- php-5.2.5-orig/ext/apc/apc_globals.h        1969-12-31 18:00:00.000000000 -0600
5648 +++ php-5.2.5/ext/apc/apc_globals.h     2007-12-26 16:51:32.000000000 -0600
5649 @@ -0,0 +1,119 @@
5650 +/*
5651 +  +----------------------------------------------------------------------+
5652 +  | APC                                                                  |
5653 +  +----------------------------------------------------------------------+
5654 +  | Copyright (c) 2006 The PHP Group                                     |
5655 +  +----------------------------------------------------------------------+
5656 +  | This source file is subject to version 3.01 of the PHP license,      |
5657 +  | that is bundled with this package in the file LICENSE, and is        |
5658 +  | available through the world-wide-web at the following url:           |
5659 +  | http://www.php.net/license/3_01.txt.                                 |
5660 +  | If you did not receive a copy of the PHP license and are unable to   |
5661 +  | obtain it through the world-wide-web, please send a note to          |
5662 +  | license@php.net so we can mail you a copy immediately.               |
5663 +  +----------------------------------------------------------------------+
5664 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
5665 +  |          George Schlossnagle <george@omniti.com>                     |
5666 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5667 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
5668 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
5669 +  +----------------------------------------------------------------------+
5670 +
5671 +   This software was contributed to PHP by Community Connect Inc. in 2002
5672 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5673 +   Future revisions and derivatives of this source code must acknowledge
5674 +   Community Connect Inc. as the original contributor of this module by
5675 +   leaving this note intact in the source code.
5676 +
5677 +   All other licensing and usage conditions are those of the PHP Group.
5678 +
5679 + */
5680 +
5681 +/* $Id: apc_globals.h,v 3.70 2007/12/26 22:46:33 rasmus Exp $ */
5682 +
5683 +#ifndef APC_GLOBALS_H
5684 +#define APC_GLOBALS_H
5685 +
5686 +#define APC_VERSION "3.0.16"
5687 +
5688 +#include "apc_cache.h"
5689 +#include "apc_stack.h"
5690 +#include "apc_php.h"
5691 +
5692 +ZEND_BEGIN_MODULE_GLOBALS(apc)
5693 +    /* configuration parameters */
5694 +    zend_bool enabled;      /* if true, apc is enabled (defaults to true) */
5695 +    long shm_segments;      /* number of shared memory segments to use */
5696 +    long shm_size;          /* size of each shared memory segment (in MB) */
5697 +    long num_files_hint;    /* parameter to apc_cache_create */
5698 +    long user_entries_hint;
5699 +    long gc_ttl;            /* parameter to apc_cache_create */
5700 +    long ttl;               /* parameter to apc_cache_create */
5701 +    long user_ttl;
5702 +#if APC_MMAP
5703 +    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
5704 +#endif
5705 +    char** filters;         /* array of regex filters that prevent caching */
5706 +
5707 +    /* module variables */
5708 +    zend_bool initialized;       /* true if module was initialized */
5709 +    apc_stack_t* cache_stack;    /* the stack of cached executable code */
5710 +    zend_bool cache_by_default;  /* true if files should be cached unless filtered out */
5711 +                                 /* false if files should only be cached if filtered in */
5712 +    long slam_defense;           /* Probability of a process not caching an uncached file */
5713 +    size_t* mem_size_ptr;        /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
5714 +    long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
5715 +    zend_bool enable_cli;        /* Flag to override turning APC off for CLI */
5716 +    long max_file_size;                 /* Maximum size of file, in bytes that APC will be allowed to cache */
5717 +    long slam_rand;              /* A place to store the slam rand value for the request */
5718 +    zend_bool fpstat;            /* true if fullpath includes should be stat'ed */
5719 +    zend_bool stat_ctime;        /* true if ctime in addition to mtime should be checked */
5720 +    zend_bool write_lock;        /* true for a global write lock */
5721 +    zend_bool report_autofilter; /* true for auto-filter warnings */
5722 +    zend_bool include_once;         /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
5723 +    apc_optimize_function_t apc_optimize_function;   /* optimizer function callback */
5724 +#ifdef MULTIPART_EVENT_FORMDATA
5725 +    zend_bool rfc1867;           /* Flag to enable rfc1867 handler */
5726 +    char* rfc1867_prefix;        /* Key prefix */
5727 +    char* rfc1867_name;          /* Name of hidden field to activate upload progress/key suffix */
5728 +    double rfc1867_freq;         /* Update frequency as percentage or bytes */
5729 +#endif
5730 +    HashTable *copied_zvals;     /* my_copy recursion detection list */
5731 +#ifdef ZEND_ENGINE_2
5732 +    int reserved_offset;         /* offset for apc info in op_array->reserved[] */
5733 +#endif
5734 +    zend_bool localcache;        /* enable local cache */
5735 +    long localcache_size;        /* size of fast cache */
5736 +    apc_local_cache_t* lcache;   /* unlocked local cache */
5737 +    zend_bool force_file_update; /* force files to be updated during apc_compile_file */
5738 +    char canon_path[MAXPATHLEN]; /* canonical path for key data */
5739 +#if APC_FILEHITS
5740 +    zval *filehits;             /* Files that came from the cache for this request */
5741 +#endif
5742 +    zend_bool coredump_unmap;    /* Trap signals that coredump and unmap shared memory */
5743 +ZEND_END_MODULE_GLOBALS(apc)
5744 +
5745 +/* (the following declaration is defined in php_apc.c) */
5746 +ZEND_EXTERN_MODULE_GLOBALS(apc)
5747 +
5748 +#ifdef ZTS
5749 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
5750 +#else
5751 +# define APCG(v) (apc_globals.v)
5752 +#endif
5753 +
5754 +/* True globals */
5755 +extern apc_cache_t* apc_cache;       /* the global compiler cache */
5756 +extern apc_cache_t* apc_user_cache;  /* the global user content cache */
5757 +extern void* apc_compiled_filters;   /* compiled filters */
5758 +
5759 +#endif
5760 +
5761 +/*
5762 + * Local variables:
5763 + * tab-width: 4
5764 + * c-basic-offset: 4
5765 + * End:
5766 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5767 + * vim<600: expandtab sw=4 ts=4 sts=4
5768 + */
5769 diff -ubrN php-5.2.5-orig/ext/apc/apc.h php-5.2.5/ext/apc/apc.h
5770 --- php-5.2.5-orig/ext/apc/apc.h        1969-12-31 18:00:00.000000000 -0600
5771 +++ php-5.2.5/ext/apc/apc.h     2007-12-26 16:51:32.000000000 -0600
5772 @@ -0,0 +1,126 @@
5773 +/*
5774 +  +----------------------------------------------------------------------+
5775 +  | APC                                                                  |
5776 +  +----------------------------------------------------------------------+
5777 +  | Copyright (c) 2006 The PHP Group                                     |
5778 +  +----------------------------------------------------------------------+
5779 +  | This source file is subject to version 3.01 of the PHP license,      |
5780 +  | that is bundled with this package in the file LICENSE, and is        |
5781 +  | available through the world-wide-web at the following url:           |
5782 +  | http://www.php.net/license/3_01.txt                                  |
5783 +  | If you did not receive a copy of the PHP license and are unable to   |
5784 +  | obtain it through the world-wide-web, please send a note to          |
5785 +  | license@php.net so we can mail you a copy immediately.               |
5786 +  +----------------------------------------------------------------------+
5787 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
5788 +  |          George Schlossnagle <george@omniti.com>                     |
5789 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5790 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
5791 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
5792 +  +----------------------------------------------------------------------+
5793 +
5794 +   This software was contributed to PHP by Community Connect Inc. in 2002
5795 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5796 +   Future revisions and derivatives of this source code must acknowledge
5797 +   Community Connect Inc. as the original contributor of this module by
5798 +   leaving this note intact in the source code.
5799 +
5800 +   All other licensing and usage conditions are those of the PHP Group.
5801 +
5802 + */
5803 +
5804 +/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
5805 +
5806 +#ifndef APC_H
5807 +#define APC_H
5808 +
5809 +/*
5810 + * This module defines utilities and helper functions used elsewhere in APC.
5811 + */
5812 +
5813 +/* Commonly needed C library headers. */
5814 +#include <assert.h>
5815 +#include <errno.h>
5816 +#include <stdarg.h>
5817 +#include <stdio.h>
5818 +#include <stdlib.h>
5819 +#include <string.h>
5820 +#include <time.h>
5821 +
5822 +/* UNIX headers (needed for struct stat) */
5823 +#include <sys/types.h>
5824 +#include <sys/stat.h>
5825 +#ifndef PHP_WIN32
5826 +#include <unistd.h>
5827 +#endif
5828 +
5829 +#ifdef HAVE_CONFIG_H
5830 +#include <config.h>
5831 +#endif
5832 +
5833 +#include "php.h"
5834 +
5835 +/* log levels constants (see apc_log) */
5836 +enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
5837 +
5838 +/* typedefs for extensible memory allocators */
5839 +typedef void* (*apc_malloc_t)(size_t);
5840 +typedef void  (*apc_free_t)  (void*);
5841 +
5842 +/* wrappers for memory allocation routines */
5843 +extern void* apc_emalloc(size_t n);
5844 +extern void* apc_erealloc(void* p, size_t n);
5845 +extern void apc_efree(void* p);
5846 +extern char* apc_estrdup(const char* s);
5847 +extern void* apc_xstrdup(const char* s, apc_malloc_t f);
5848 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
5849 +
5850 +/* console display functions */
5851 +extern void apc_log(int level, const char* fmt, ...);
5852 +extern void apc_eprint(const char* fmt, ...);
5853 +extern void apc_wprint(const char* fmt, ...);
5854 +extern void apc_dprint(const char* fmt, ...);
5855 +extern void apc_nprint(const char* fmt, ...);
5856 +
5857 +/* string and text manipulation */
5858 +extern char* apc_append(const char* s, const char* t);
5859 +extern char* apc_substr(const char* s, int start, int length);
5860 +extern char** apc_tokenize(const char* s, char delim);
5861 +
5862 +/* filesystem functions */
5863 +
5864 +typedef struct apc_fileinfo_t 
5865 +{
5866 +    char fullpath[MAXPATHLEN+1];
5867 +    struct stat st_buf;
5868 +} apc_fileinfo_t;
5869 +
5870 +#ifndef PHP_WIN32
5871 +#define apc_stat(f, b) stat(f, b)
5872 +#else
5873 +#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
5874 +extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
5875 +#endif
5876 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
5877 +
5878 +/* regular expression wrapper functions */
5879 +extern void* apc_regex_compile_array(char* patterns[]);
5880 +extern void apc_regex_destroy_array(void* p);
5881 +extern int apc_regex_match_array(void* p, const char* input);
5882 +
5883 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
5884 +extern unsigned int apc_crc32(const char* buf, int len);
5885 +
5886 +#define APC_NEGATIVE_MATCH 1
5887 +#define APC_POSITIVE_MATCH 2
5888 +
5889 +#endif
5890 +
5891 +/*
5892 + * Local variables:
5893 + * tab-width: 4
5894 + * c-basic-offset: 4
5895 + * End:
5896 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5897 + * vim<600: expandtab sw=4 ts=4 sts=4
5898 + */
5899 diff -ubrN php-5.2.5-orig/ext/apc/apc_lock.h php-5.2.5/ext/apc/apc_lock.h
5900 --- php-5.2.5-orig/ext/apc/apc_lock.h   1969-12-31 18:00:00.000000000 -0600
5901 +++ php-5.2.5/ext/apc/apc_lock.h        2007-12-26 16:51:32.000000000 -0600
5902 @@ -0,0 +1,105 @@
5903 +/*
5904 +  +----------------------------------------------------------------------+
5905 +  | APC                                                                  |
5906 +  +----------------------------------------------------------------------+
5907 +  | Copyright (c) 2006 The PHP Group                                     |
5908 +  +----------------------------------------------------------------------+
5909 +  | This source file is subject to version 3.01 of the PHP license,      |
5910 +  | that is bundled with this package in the file LICENSE, and is        |
5911 +  | available through the world-wide-web at the following url:           |
5912 +  | http://www.php.net/license/3_01.txt                                  |
5913 +  | If you did not receive a copy of the PHP license and are unable to   |
5914 +  | obtain it through the world-wide-web, please send a note to          |
5915 +  | license@php.net so we can mail you a copy immediately.               |
5916 +  +----------------------------------------------------------------------+
5917 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5918 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5919 +  +----------------------------------------------------------------------+
5920 +
5921 +   This software was contributed to PHP by Community Connect Inc. in 2002
5922 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5923 +   Future revisions and derivatives of this source code must acknowledge
5924 +   Community Connect Inc. as the original contributor of this module by
5925 +   leaving this note intact in the source code.
5926 +
5927 +   All other licensing and usage conditions are those of the PHP Group.
5928 +
5929 + */
5930 +
5931 +/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
5932 +
5933 +#ifndef APC_LOCK
5934 +#define APC_LOCK
5935 +
5936 +#include "apc_sem.h"
5937 +#include "apc_fcntl.h"
5938 +#include "apc_pthreadmutex.h"
5939 +#include "apc_futex.h"
5940 +#include "apc_spin.h"
5941 +#ifdef HAVE_CONFIG_H
5942 +#include <config.h>
5943 +#endif
5944 +
5945 +#ifdef TSRM_LOCKS
5946 +#define RDLOCK_AVAILABLE 0
5947 +#define NONBLOCKING_LOCK_AVAILABLE 0
5948 +/* quick & dirty: use TSRM mutex locks for now */
5949 +#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
5950 +#define apc_lck_destroy(a)    tsrm_mutex_free((MUTEX_T)a)
5951 +#define apc_lck_lock(a)       tsrm_mutex_lock((MUTEX_T)a)
5952 +#define apc_lck_rdlock(a)     tsrm_mutex_lock((MUTEX_T)a)
5953 +#define apc_lck_unlock(a)     tsrm_mutex_unlock((MUTEX_T)a)
5954 +#elif defined(APC_SEM_LOCKS)
5955 +#define RDLOCK_AVAILABLE 0
5956 +#define NONBLOCKING_LOCK_AVAILABLE 0
5957 +#define apc_lck_t int
5958 +#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
5959 +#define apc_lck_destroy(a)    apc_sem_destroy(a)
5960 +#define apc_lck_lock(a)       apc_sem_lock(a)
5961 +#define apc_lck_rdlock(a)     apc_sem_lock(a)
5962 +#define apc_lck_unlock(a)     apc_sem_unlock(a)
5963 +#elif defined(APC_PTHREADMUTEX_LOCKS)
5964 +#define RDLOCK_AVAILABLE 0
5965 +#define NONBLOCKING_LOCK_AVAILABLE 1
5966 +#define apc_lck_t pthread_mutex_t 
5967 +#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
5968 +#define apc_lck_destroy(a)    apc_pthreadmutex_destroy(&a)
5969 +#define apc_lck_lock(a)       apc_pthreadmutex_lock(&a)
5970 +#define apc_lck_nb_lock(a)    apc_pthreadmutex_nonblocking_lock(&a)
5971 +#define apc_lck_rdlock(a)     apc_pthreadmutex_lock(&a)
5972 +#define apc_lck_unlock(a)     apc_pthreadmutex_unlock(&a)
5973 +#elif defined(APC_FUTEX_LOCKS)
5974 +#define NONBLOCKING_LOCK_AVAILABLE 1 
5975 +#define apc_lck_t int 
5976 +#define apc_lck_create(a,b,c,d) d=apc_futex_create()
5977 +#define apc_lck_destroy(a)    apc_futex_destroy(&a)
5978 +#define apc_lck_lock(a)       apc_futex_lock(&a)
5979 +#define apc_lck_nb_lock(a)    apc_futex_nonblocking_lock(&a)
5980 +#define apc_lck_rdlock(a)     apc_futex_lock(&a)
5981 +#define apc_lck_unlock(a)     apc_futex_unlock(&a)
5982 +#elif defined(APC_SPIN_LOCKS)
5983 +#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
5984 +#define apc_lck_t slock_t 
5985 +#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
5986 +#define apc_lck_destroy(a)    apc_slock_destroy(&a)
5987 +#define apc_lck_lock(a)       apc_slock_lock(&a)
5988 +#define apc_lck_nb_lock(a)    apc_slock_nonblocking_lock(&a)
5989 +#define apc_lck_rdlock(a)     apc_slock_lock(&a)
5990 +#define apc_lck_unlock(a)     apc_slock_unlock(&a)
5991 +#else
5992 +#define RDLOCK_AVAILABLE 1
5993 +#ifdef PHP_WIN32
5994 +#define NONBLOCKING_LOCK_AVAILABLE 0
5995 +#else
5996 +#define NONBLOCKING_LOCK_AVAILABLE 1
5997 +#endif
5998 +#define apc_lck_t int
5999 +#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
6000 +#define apc_lck_destroy(a)    apc_fcntl_destroy(a)
6001 +#define apc_lck_lock(a)       apc_fcntl_lock(a)
6002 +#define apc_lck_nb_lock(a)    apc_fcntl_nonblocking_lock(a)
6003 +#define apc_lck_rdlock(a)     apc_fcntl_rdlock(a)
6004 +#define apc_lck_unlock(a)     apc_fcntl_unlock(a)
6005 +#endif
6006 +
6007 +#endif
6008 diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
6009 --- php-5.2.5-orig/ext/apc/apc_main.c   1969-12-31 18:00:00.000000000 -0600
6010 +++ php-5.2.5/ext/apc/apc_main.c        2007-12-26 16:51:32.000000000 -0600
6011 @@ -0,0 +1,701 @@
6012 +/*
6013 +  +----------------------------------------------------------------------+
6014 +  | APC                                                                  |
6015 +  +----------------------------------------------------------------------+
6016 +  | Copyright (c) 2006 The PHP Group                                     |
6017 +  +----------------------------------------------------------------------+
6018 +  | This source file is subject to version 3.01 of the PHP license,      |
6019 +  | that is bundled with this package in the file LICENSE, and is        |
6020 +  | available through the world-wide-web at the following url:           |
6021 +  | http://www.php.net/license/3_01.txt                                  |
6022 +  | If you did not receive a copy of the PHP license and are unable to   |
6023 +  | obtain it through the world-wide-web, please send a note to          |
6024 +  | license@php.net so we can mail you a copy immediately.               |
6025 +  +----------------------------------------------------------------------+
6026 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
6027 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6028 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
6029 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
6030 +  +----------------------------------------------------------------------+
6031 +
6032 +   This software was contributed to PHP by Community Connect Inc. in 2002
6033 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6034 +   Future revisions and derivatives of this source code must acknowledge
6035 +   Community Connect Inc. as the original contributor of this module by
6036 +   leaving this note intact in the source code.
6037 +
6038 +   All other licensing and usage conditions are those of the PHP Group.
6039 +
6040 + */
6041 +
6042 +/* $Id: apc_main.c,v 3.103 2007/11/14 19:46:46 shire Exp $ */
6043 +
6044 +#include "apc_php.h"
6045 +#include "apc_main.h"
6046 +#include "apc.h"
6047 +#include "apc_lock.h"
6048 +#include "apc_cache.h"
6049 +#include "apc_compile.h"
6050 +#include "apc_globals.h"
6051 +#include "apc_sma.h"
6052 +#include "apc_stack.h"
6053 +#include "apc_zend.h"
6054 +#include "SAPI.h"
6055 +#if PHP_API_VERSION <= 20020918
6056 +#if HAVE_APACHE
6057 +#ifdef APC_PHP4_STAT
6058 +#undef XtOffsetOf
6059 +#include "httpd.h"
6060 +#endif
6061 +#endif
6062 +#endif
6063 +
6064 +/* {{{ module variables */
6065 +
6066 +/* pointer to the original Zend engine compile_file function */
6067 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
6068 +static zend_compile_t *old_compile_file;
6069 +
6070 +/* }}} */
6071 +
6072 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
6073 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
6074 +{
6075 +    zend_compile_t *retval = old_compile_file;
6076 +
6077 +    if (ptr != NULL) old_compile_file = ptr;
6078 +    return retval;
6079 +}
6080 +/* }}} */
6081 +
6082 +/* {{{ install_function */
6083 +static int install_function(apc_function_t fn TSRMLS_DC)
6084 +{
6085 +    int status =
6086 +        zend_hash_add(EG(function_table),
6087 +                      fn.name,
6088 +                      fn.name_len+1,
6089 +                      apc_copy_function_for_execution(fn.function),
6090 +                      sizeof(fn.function[0]),
6091 +                      NULL);
6092 +
6093 +    if (status == FAILURE) {
6094 +        /* apc_eprint("Cannot redeclare %s()", fn.name); */
6095 +    }
6096 +
6097 +    return status;
6098 +}
6099 +/* }}} */
6100 +
6101 +/* {{{ install_class */
6102 +static int install_class(apc_class_t cl TSRMLS_DC)
6103 +{
6104 +    zend_class_entry* class_entry = cl.class_entry;
6105 +    zend_class_entry* parent = NULL;
6106 +    int status;
6107 +#ifdef ZEND_ENGINE_2
6108 +    zend_class_entry** allocated_ce = NULL;
6109 +#endif
6110 +
6111 +
6112 +    /* Special case for mangled names. Mangled names are unique to a file.
6113 +     * There is no way two classes with the same mangled name will occur,
6114 +     * unless a file is included twice. And if in case, a file is included
6115 +     * twice, all mangled name conflicts can be ignored and the class redeclaration
6116 +     * error may be deferred till runtime of the corresponding DECLARE_CLASS
6117 +     * calls.
6118 +     */
6119 +
6120 +    if(cl.name_len != 0 && cl.name[0] == '\0') {
6121 +        if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
6122 +            return SUCCESS;
6123 +        }
6124 +    }
6125 +    
6126 +#ifdef ZEND_ENGINE_2    
6127 +    /*
6128 +     * XXX: We need to free this somewhere...
6129 +     */
6130 +    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));    
6131 +
6132 +    if(!allocated_ce) {
6133 +        return FAILURE;
6134 +    }
6135 +
6136 +    *allocated_ce = 
6137 +#endif        
6138 +    class_entry =
6139 +        apc_copy_class_entry_for_execution(cl.class_entry,
6140 +                                           cl.is_derived);
6141 +
6142 +
6143 +    /* restore parent class pointer for compile-time inheritance */
6144 +    if (cl.parent_name != NULL) {
6145 +#ifdef ZEND_ENGINE_2    
6146 +        zend_class_entry** parent_ptr = NULL;
6147 +        /*
6148 +         * zend_lookup_class has to be due to presence of __autoload, 
6149 +         * just looking up the EG(class_table) is not enough in php5!
6150 +         * Even more dangerously, thanks to __autoload and people using
6151 +         * class names as filepaths for inclusion, this has to be case
6152 +         * sensitive. zend_lookup_class automatically does a case_fold
6153 +         * internally, but passes the case preserved version to __autoload.
6154 +         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because 
6155 +         * zend_lookup_class does it internally anyway!
6156 +         */
6157 +        status = zend_lookup_class(cl.parent_name,
6158 +                                    strlen(cl.parent_name),
6159 +                                    &parent_ptr TSRMLS_CC);
6160 +#else
6161 +        status = zend_hash_find(EG(class_table),
6162 +                                cl.parent_name,
6163 +                                strlen(cl.parent_name)+1,
6164 +                                (void**) &parent);
6165 +#endif
6166 +        if (status == FAILURE) {
6167 +            if(APCG(report_autofilter)) {
6168 +                apc_wprint("Dynamic inheritance detected for class %s", cl.name);
6169 +            }
6170 +            class_entry->parent = NULL;
6171 +            return status;
6172 +        }
6173 +        else {
6174 +#ifdef ZEND_ENGINE_2            
6175 +            parent = *parent_ptr;
6176 +#endif 
6177 +            class_entry->parent = parent;
6178 +#ifdef ZEND_ENGINE_2
6179 +            zend_do_inheritance(class_entry, parent TSRMLS_CC);
6180 +#else
6181 +            zend_do_inheritance(class_entry, parent);
6182 +#endif
6183 +        }
6184 +
6185 +
6186 +    }
6187 +
6188 +#ifdef ZEND_ENGINE_2                           
6189 +    status = zend_hash_add(EG(class_table),
6190 +                           cl.name,
6191 +                           cl.name_len+1,
6192 +                           allocated_ce,
6193 +                           sizeof(zend_class_entry*),
6194 +                           NULL);
6195 +#else                           
6196 +    status = zend_hash_add(EG(class_table),
6197 +                           cl.name,
6198 +                           cl.name_len+1,
6199 +                           class_entry,
6200 +                           sizeof(zend_class_entry),
6201 +                           NULL);
6202 +#endif                           
6203 +
6204 +    if (status == FAILURE) {
6205 +        apc_eprint("Cannot redeclare class %s", cl.name);
6206 +    } 
6207 +    return status;
6208 +}
6209 +/* }}} */
6210 +
6211 +/* {{{ uninstall_class */
6212 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
6213 +{
6214 +    int status;
6215 +
6216 +#ifdef ZEND_ENGINE_2                           
6217 +    status = zend_hash_del(EG(class_table),
6218 +                           cl.name,
6219 +                           cl.name_len+1);
6220 +#else                           
6221 +    status = zend_hash_del(EG(class_table),
6222 +                           cl.name,
6223 +                           cl.name_len+1);
6224 +#endif                           
6225 +    if (status == FAILURE) {
6226 +        apc_eprint("Cannot delete class %s", cl.name);
6227 +    } 
6228 +    return status;
6229 +}
6230 +/* }}} */
6231 +
6232 +/* {{{ compare_file_handles */
6233 +static int compare_file_handles(void* a, void* b)
6234 +{
6235 +    zend_file_handle* fh1 = (zend_file_handle*)a;
6236 +    zend_file_handle* fh2 = (zend_file_handle*)b;
6237 +    return (fh1->type == fh2->type && 
6238 +            fh1->filename == fh2->filename &&
6239 +            fh1->opened_path == fh2->opened_path);
6240 +}
6241 +/* }}} */
6242 +
6243 +/* {{{ cached_compile */
6244 +static zend_op_array* cached_compile(zend_file_handle* h,
6245 +                                        int type TSRMLS_DC)
6246 +{
6247 +    apc_cache_entry_t* cache_entry;
6248 +    int i, ii;
6249 +
6250 +    cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
6251 +    assert(cache_entry != NULL);
6252 +
6253 +    if (cache_entry->data.file.classes) {
6254 +        for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6255 +            if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
6256 +                goto default_compile;
6257 +            }
6258 +        }
6259 +    }
6260 +
6261 +    if (cache_entry->data.file.functions) {
6262 +        for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6263 +            install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
6264 +        }
6265 +    }
6266 +
6267 +
6268 +    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
6269 +
6270 +default_compile:
6271 +
6272 +    if(APCG(report_autofilter)) {
6273 +        apc_wprint("Autofiltering %s", h->opened_path);
6274 +    }
6275 +
6276 +    if(cache_entry->data.file.classes) {
6277 +        for(ii = 0; ii < i ; ii++) {
6278 +            uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
6279 +        }
6280 +    }
6281 +    
6282 +    apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
6283 +    
6284 +    apc_cache_release(apc_cache, cache_entry);
6285 +
6286 +    /* cannot free up cache data yet, it maybe in use */
6287 +    
6288 +    zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
6289 +    
6290 +    h->type = ZEND_HANDLE_FILENAME;
6291 +
6292 +    return NULL;
6293 +}
6294 +/* }}} */
6295 +
6296 +/* {{{ my_compile_file
6297 +   Overrides zend_compile_file */
6298 +static zend_op_array* my_compile_file(zend_file_handle* h,
6299 +                                               int type TSRMLS_DC)
6300 +{
6301 +    apc_cache_key_t key;
6302 +    apc_cache_entry_t* cache_entry;
6303 +    zend_op_array* op_array;
6304 +    int num_functions, num_classes, ret;
6305 +    zend_op_array* alloc_op_array;
6306 +    apc_function_t* alloc_functions;
6307 +    apc_class_t* alloc_classes;
6308 +    time_t t;
6309 +    char *path;
6310 +    size_t mem_size;
6311 +
6312 +    if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
6313 +               return old_compile_file(h, type TSRMLS_CC);
6314 +       }
6315 +
6316 +    /* check our regular expression filters */
6317 +    if (APCG(filters) && apc_compiled_filters) {
6318 +        int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
6319 +        if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
6320 +            return old_compile_file(h, type TSRMLS_CC);
6321 +        }
6322 +    } else if(!APCG(cache_by_default)) {
6323 +        return old_compile_file(h, type TSRMLS_CC);
6324 +    }
6325 +
6326 +#if PHP_API_VERSION < 20041225
6327 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
6328 +    t = ((request_rec *)SG(server_context))->request_time;
6329 +#else 
6330 +    t = time(0);
6331 +#endif
6332 +#else 
6333 +    t = sapi_get_request_time(TSRMLS_C);
6334 +#endif
6335 +
6336 +#ifdef __DEBUG_APC__
6337 +    fprintf(stderr,"1. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6338 +#endif
6339 +
6340 +    /* try to create a cache key; if we fail, give up on caching */
6341 +    if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
6342 +        return old_compile_file(h, type TSRMLS_CC);
6343 +    }
6344 +
6345 +
6346 +    if(!APCG(force_file_update)) {
6347 +        if(APCG(localcache)) {
6348 +            /* search for the file in the local cache */
6349 +            cache_entry = apc_local_cache_find(APCG(lcache), key, t);
6350 +        } else {
6351 +            /* search for the file in the cache */
6352 +            cache_entry = apc_cache_find(apc_cache, key, t);
6353 +        }
6354 +    } else {
6355 +        cache_entry = NULL;
6356 +    }
6357 +
6358 +    if (cache_entry != NULL) {
6359 +        int dummy = 1;
6360 +        if (h->opened_path == NULL) {
6361 +            h->opened_path = estrdup(cache_entry->data.file.filename);
6362 +        }
6363 +        zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
6364 +        zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
6365 +        apc_stack_push(APCG(cache_stack), cache_entry);
6366 +        op_array = cached_compile(h, type TSRMLS_CC);
6367 +        if(op_array) {
6368 +#ifdef APC_FILEHITS
6369 +            /* If the file comes from the cache, add it to the global request file list */
6370 +            add_next_index_string(APCG(filehits), h->filename, 1);
6371 +#endif
6372 +            return op_array;
6373 +        }
6374 +        if(APCG(report_autofilter)) {
6375 +            apc_wprint("Recompiling %s", h->opened_path);
6376 +        }
6377 +        /* TODO: check what happens with EG(included_files) */
6378 +    }
6379 +    
6380 +    if(apc_cache_busy(apc_cache) && APCG(localcache)) {
6381 +        /* possibly local cache returned NULL because cache is busy */
6382 +               return old_compile_file(h, type TSRMLS_CC);
6383 +       }
6384 +
6385 +    /* remember how many functions and classes existed before compilation */
6386 +    num_functions = zend_hash_num_elements(CG(function_table));
6387 +    num_classes   = zend_hash_num_elements(CG(class_table));
6388 +    
6389 +    /* compile the file using the default compile function */
6390 +    op_array = old_compile_file(h, type TSRMLS_CC);
6391 +    if (op_array == NULL) {
6392 +        return NULL;
6393 +    }
6394 +    /*
6395 +     * Basically this will cause a file only to be cached on a percentage 
6396 +     * of the attempts.  This is to avoid cache slams when starting up a
6397 +     * very busy server or when modifying files on a very busy live server.
6398 +     * There is no point having many processes all trying to cache the same
6399 +     * file at the same time.  By introducing a chance of being cached
6400 +     * we theoretically cut the cache slam problem by the given percentage.
6401 +     * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
6402 +     * to cache an uncached file will be ignored.
6403 +     */
6404 +    if(APCG(slam_defense)) {
6405 +        if(APCG(slam_rand)==-1) {
6406 +            APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
6407 +        }
6408 +        if(APCG(slam_rand) < APCG(slam_defense)) {
6409 +            return op_array;
6410 +        }
6411 +    }
6412 +
6413 +    /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
6414 +    if(key.type == APC_CACHE_KEY_FPFILE) {
6415 +        apc_fileinfo_t fileinfo;
6416 +        struct stat *tmp_buf = NULL;
6417 +        if(!strcmp(SG(request_info).path_translated, h->filename)) {
6418 +            tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
6419 +        }
6420 +        if(tmp_buf) { 
6421 +            fileinfo.st_buf = *tmp_buf;
6422 +        } else {
6423 +            if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
6424 +#ifdef __DEBUG_APC__
6425 +                fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
6426 +#endif
6427 +                return op_array;
6428 +            }
6429 +        }
6430 +        key.mtime = fileinfo.st_buf.st_mtime;
6431 +    }
6432 +
6433 +    HANDLE_BLOCK_INTERRUPTIONS();
6434 +
6435 +#if NONBLOCKING_LOCK_AVAILABLE
6436 +    if(APCG(write_lock)) {
6437 +        if(!apc_cache_write_lock(apc_cache)) {
6438 +            HANDLE_UNBLOCK_INTERRUPTIONS();
6439 +            return op_array;
6440 +        }
6441 +    }
6442 +#endif
6443 +
6444 +    mem_size = 0;
6445 +    APCG(mem_size_ptr) = &mem_size;
6446 +    if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6447 +        apc_cache_expunge(apc_cache,t);
6448 +        apc_cache_expunge(apc_user_cache,t);
6449 +        APCG(mem_size_ptr) = NULL;
6450 +#if NONBLOCKING_LOCK_AVAILABLE
6451 +        if(APCG(write_lock)) {
6452 +            apc_cache_write_unlock(apc_cache);
6453 +        }
6454 +#endif
6455 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6456 +        return op_array;
6457 +    }
6458 +    
6459 +    if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6460 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6461 +        apc_cache_expunge(apc_cache,t);
6462 +        apc_cache_expunge(apc_user_cache,t);
6463 +        APCG(mem_size_ptr) = NULL;
6464 +#if NONBLOCKING_LOCK_AVAILABLE
6465 +        if(APCG(write_lock)) {
6466 +            apc_cache_write_unlock(apc_cache);
6467 +        }
6468 +#endif
6469 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6470 +        return op_array;
6471 +    }
6472 +    if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6473 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6474 +        apc_free_functions(alloc_functions, apc_sma_free);
6475 +        apc_cache_expunge(apc_cache,t);
6476 +        apc_cache_expunge(apc_user_cache,t);
6477 +        APCG(mem_size_ptr) = NULL;
6478 +#if NONBLOCKING_LOCK_AVAILABLE
6479 +        if(APCG(write_lock)) {
6480 +            apc_cache_write_unlock(apc_cache);
6481 +        }
6482 +#endif
6483 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6484 +        return op_array;
6485 +    }
6486 +
6487 +    path = h->opened_path;
6488 +    if(!path) path=h->filename;
6489 +
6490 +#ifdef __DEBUG_APC__
6491 +    fprintf(stderr,"2. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6492 +#endif
6493 +
6494 +    if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
6495 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6496 +        apc_free_functions(alloc_functions, apc_sma_free);
6497 +        apc_free_classes(alloc_classes, apc_sma_free);
6498 +        apc_cache_expunge(apc_cache,t);
6499 +        apc_cache_expunge(apc_user_cache,t);
6500 +        APCG(mem_size_ptr) = NULL;
6501 +#if NONBLOCKING_LOCK_AVAILABLE
6502 +        if(APCG(write_lock)) {
6503 +            apc_cache_write_unlock(apc_cache);
6504 +        }
6505 +#endif
6506 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6507 +        return op_array;
6508 +    }
6509 +    APCG(mem_size_ptr) = NULL;
6510 +    cache_entry->mem_size = mem_size;
6511 +
6512 +    if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
6513 +        apc_cache_free_entry(cache_entry);
6514 +        if(ret==-1) {
6515 +            apc_cache_expunge(apc_cache,t);
6516 +            apc_cache_expunge(apc_user_cache,t);
6517 +        }
6518 +    }
6519 +
6520 +#if NONBLOCKING_LOCK_AVAILABLE
6521 +    if(APCG(write_lock)) {
6522 +        apc_cache_write_unlock(apc_cache);
6523 +    }
6524 +#endif
6525 +    HANDLE_UNBLOCK_INTERRUPTIONS();
6526 +
6527 +    return op_array;
6528 +}
6529 +/* }}} */
6530 +
6531 +/* {{{ module init and shutdown */
6532 +
6533 +int apc_module_init(int module_number TSRMLS_DC)
6534 +{
6535 +    /* apc initialization */
6536 +#if APC_MMAP
6537 +    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
6538 +#else
6539 +    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
6540 +#endif
6541 +    apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
6542 +    apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
6543 +
6544 +    apc_compiled_filters = apc_regex_compile_array(APCG(filters));
6545 +
6546 +    /* override compilation */
6547 +    old_compile_file = zend_compile_file;
6548 +    zend_compile_file = my_compile_file;
6549 +    REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
6550 +
6551 +    APCG(initialized) = 1;
6552 +    return 0;
6553 +}
6554 +
6555 +int apc_module_shutdown(TSRMLS_D)
6556 +{
6557 +    if (!APCG(initialized))
6558 +        return 0;
6559 +
6560 +    /* restore compilation */
6561 +    zend_compile_file = old_compile_file;
6562 +
6563 +    /* 
6564 +     * In case we got interrupted by a SIGTERM or something else during execution
6565 +     * we may have cache entries left on the stack that we need to check to make
6566 +     * sure that any functions or classes these may have added to the global function
6567 +     * and class tables are removed before we blow away the memory that hold them.
6568 +     * 
6569 +     * This is merely to remove memory leak warnings - as the process is terminated
6570 +     * immediately after shutdown. The following while loop can be removed without
6571 +     * affecting anything else.
6572 +     */
6573 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
6574 +        int i;
6575 +        apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6576 +        if (cache_entry->data.file.functions) {
6577 +            for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6578 +                zend_hash_del(EG(function_table),
6579 +                    cache_entry->data.file.functions[i].name,
6580 +                    cache_entry->data.file.functions[i].name_len+1);
6581 +            }
6582 +        }
6583 +        if (cache_entry->data.file.classes) {
6584 +            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6585 +                zend_hash_del(EG(class_table),
6586 +                    cache_entry->data.file.classes[i].name,
6587 +                    cache_entry->data.file.classes[i].name_len+1);
6588 +            }
6589 +        }
6590 +        apc_cache_release(apc_cache, cache_entry);
6591 +    }
6592 +
6593 +    apc_cache_destroy(apc_cache);
6594 +    apc_cache_destroy(apc_user_cache);
6595 +    apc_sma_cleanup();
6596 +
6597 +    APCG(initialized) = 0;
6598 +    return 0;
6599 +}
6600 +
6601 +/* }}} */
6602 +
6603 +/* {{{ process init and shutdown */
6604 +int apc_process_init(int module_number TSRMLS_DC)
6605 +{
6606 +    int minttl = (APCG(gc_ttl) >  APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
6607 +    int size = APCG(localcache_size);
6608 +    if(APCG(initialized) && APCG(localcache)) {
6609 +        /* TTL is 2 mins by default */
6610 +        APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120); 
6611 +    }
6612 +    return 0;
6613 +}
6614 +
6615 +int apc_process_shutdown(TSRMLS_D)
6616 +{
6617 +    if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
6618 +        apc_local_cache_destroy(APCG(lcache));
6619 +        APCG(lcache) = NULL;
6620 +    }
6621 +       return 0;
6622 +}
6623 +/* }}} */
6624 +
6625 +/* {{{ request init and shutdown */
6626 +
6627 +int apc_request_init(TSRMLS_D)
6628 +{
6629 +    apc_stack_clear(APCG(cache_stack));
6630 +    APCG(slam_rand) = -1;
6631 +    APCG(copied_zvals) = NULL;
6632 +
6633 +#ifdef APC_FILEHITS
6634 +    ALLOC_INIT_ZVAL(APCG(filehits));
6635 +    array_init(APCG(filehits));
6636 +#endif
6637 +
6638 +    return 0;
6639 +}
6640 +
6641 +int apc_request_shutdown(TSRMLS_D)
6642 +{
6643 +    apc_deactivate(TSRMLS_C);
6644 +
6645 +#ifdef APC_FILEHITS
6646 +    zval_ptr_dtor(&APCG(filehits));
6647 +#endif
6648 +
6649 +    return 0;
6650 +}
6651 +
6652 +/* }}} */
6653 +
6654 +/* {{{ apc_deactivate */
6655 +void apc_deactivate(TSRMLS_D)
6656 +{
6657 +    /* The execution stack was unwound, which prevented us from decrementing
6658 +     * the reference counts on active cache entries in `my_execute`.
6659 +     */
6660 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
6661 +        int i;
6662 +        zend_class_entry* zce = NULL;
6663 +        void ** centry = (void*)(&zce);
6664 +#ifdef ZEND_ENGINE_2
6665 +        zend_class_entry** pzce = NULL;
6666 +#endif
6667 +        
6668 +        apc_cache_entry_t* cache_entry =
6669 +            (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6670 +
6671 +        if (cache_entry->data.file.classes) {
6672 +            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6673 +#ifdef ZEND_ENGINE_2
6674 +                centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
6675 +#endif
6676 +                if(zend_hash_find(EG(class_table), 
6677 +                    cache_entry->data.file.classes[i].name,
6678 +                    cache_entry->data.file.classes[i].name_len+1,
6679 +                    (void**)centry) == FAILURE)
6680 +                {
6681 +                    /* double inclusion of conditional classes ends up failing 
6682 +                     * this lookup the second time around.
6683 +                     */
6684 +                    continue;
6685 +                }
6686 +
6687 +#ifdef ZEND_ENGINE_2
6688 +                zce = *pzce;
6689 +#endif
6690 +                zend_hash_del(EG(class_table),
6691 +                    cache_entry->data.file.classes[i].name,
6692 +                    cache_entry->data.file.classes[i].name_len+1);
6693 +                
6694 +                apc_free_class_entry_after_execution(zce);
6695 +            }
6696 +        }
6697 +        apc_cache_release(apc_cache, cache_entry);
6698 +    }
6699 +    if(APCG(localcache)) {
6700 +        apc_local_cache_cleanup(APCG(lcache)); 
6701 +    }
6702 +}
6703 +/* }}} */
6704 +
6705 +/*
6706 + * Local variables:
6707 + * tab-width: 4
6708 + * c-basic-offset: 4
6709 + * End:
6710 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6711 + * vim<600: expandtab sw=4 ts=4 sts=4
6712 + */
6713 diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
6714 --- php-5.2.5-orig/ext/apc/apc_main.h   1969-12-31 18:00:00.000000000 -0600
6715 +++ php-5.2.5/ext/apc/apc_main.h        2007-12-26 16:51:32.000000000 -0600
6716 @@ -0,0 +1,67 @@
6717 +/*
6718 +  +----------------------------------------------------------------------+
6719 +  | APC                                                                  |
6720 +  +----------------------------------------------------------------------+
6721 +  | Copyright (c) 2006 The PHP Group                                     |
6722 +  +----------------------------------------------------------------------+
6723 +  | This source file is subject to version 3.01 of the PHP license,      |
6724 +  | that is bundled with this package in the file LICENSE, and is        |
6725 +  | available through the world-wide-web at the following url:           |
6726 +  | http://www.php.net/license/3_01.txt                                  |
6727 +  | If you did not receive a copy of the PHP license and are unable to   |
6728 +  | obtain it through the world-wide-web, please send a note to          |
6729 +  | license@php.net so we can mail you a copy immediately.               |
6730 +  +----------------------------------------------------------------------+
6731 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
6732 +  |          George Schlossnagle <george@omniti.com>                     |
6733 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6734 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
6735 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
6736 +  +----------------------------------------------------------------------+
6737 +
6738 +   This software was contributed to PHP by Community Connect Inc. in 2002
6739 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6740 +   Future revisions and derivatives of this source code must acknowledge
6741 +   Community Connect Inc. as the original contributor of this module by
6742 +   leaving this note intact in the source code.
6743 +
6744 +   All other licensing and usage conditions are those of the PHP Group.
6745 +
6746 + */
6747 +
6748 +/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
6749 +
6750 +#ifndef APC_MAIN_H
6751 +#define APC_MAIN_H
6752 +
6753 +/*
6754 + * This module provides the primary interface between PHP and APC.
6755 + */
6756 +
6757 +extern int apc_module_init(int module_number TSRMLS_DC);
6758 +extern int apc_module_shutdown(TSRMLS_D);
6759 +extern int apc_process_init(int module_number TSRMLS_DC);
6760 +extern int apc_process_shutdown(TSRMLS_D);
6761 +extern int apc_request_init(TSRMLS_D);
6762 +extern int apc_request_shutdown(TSRMLS_D);
6763 +
6764 +/*
6765 + * apc_deactivate is called by the PHP interpreter when an "exception" is
6766 + * raised (e.g., a call to the exit function) that unwinds the execution
6767 + * stack.
6768 + */
6769 +extern void apc_deactivate();
6770 +
6771 +
6772 +extern const char* apc_version();
6773 +
6774 +#endif
6775 +
6776 +/*
6777 + * Local variables:
6778 + * tab-width: 4
6779 + * c-basic-offset: 4
6780 + * End:
6781 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6782 + * vim<600: expandtab sw=4 ts=4 sts=4
6783 + */
6784 diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
6785 --- php-5.2.5-orig/ext/apc/apc_mmap.c   1969-12-31 18:00:00.000000000 -0600
6786 +++ php-5.2.5/ext/apc/apc_mmap.c        2007-12-26 16:51:32.000000000 -0600
6787 @@ -0,0 +1,139 @@
6788 +/*
6789 +  +----------------------------------------------------------------------+
6790 +  | APC                                                                  |
6791 +  +----------------------------------------------------------------------+
6792 +  | Copyright (c) 2006 The PHP Group                                     |
6793 +  +----------------------------------------------------------------------+
6794 +  | This source file is subject to version 3.01 of the PHP license,      |
6795 +  | that is bundled with this package in the file LICENSE, and is        |
6796 +  | available through the world-wide-web at the following url:           |
6797 +  | http://www.php.net/license/3_01.txt                                  |
6798 +  | If you did not receive a copy of the PHP license and are unable to   |
6799 +  | obtain it through the world-wide-web, please send a note to          |
6800 +  | license@php.net so we can mail you a copy immediately.               |
6801 +  +----------------------------------------------------------------------+
6802 +  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
6803 +  +----------------------------------------------------------------------+
6804 +
6805 +   This software was contributed to PHP by Community Connect Inc. in 2002
6806 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6807 +   Future revisions and derivatives of this source code must acknowledge
6808 +   Community Connect Inc. as the original contributor of this module by
6809 +   leaving this note intact in the source code.
6810 +
6811 +   All other licensing and usage conditions are those of the PHP Group.
6812 +
6813 + */
6814 +
6815 +/* $Id: apc_mmap.c,v 3.7 2007/12/20 23:00:51 shire Exp $ */
6816 +
6817 +#include "apc.h"
6818 +
6819 +#if APC_MMAP
6820 +
6821 +#include <fcntl.h>
6822 +#include <sys/types.h>
6823 +#include <sys/mman.h>
6824 +
6825 +/* 
6826 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
6827 + * tells whatever update daemons might be running to not flush dirty
6828 + * vm pages to disk unless absolutely necessary.  My guess is that
6829 + * most systems that don't have this probably default to only synching
6830 + * to disk when absolutely necessary.
6831 + */
6832 +#ifndef MAP_NOSYNC
6833 +#define MAP_NOSYNC 0
6834 +#endif
6835 +
6836 +void *apc_mmap(char *file_mask, size_t size)
6837 +{
6838 +    void* shmaddr;  /* the shared memory address */
6839 +
6840 +    /* If no filename was provided, do an anonymous mmap */
6841 +    if(!file_mask || (file_mask && !strlen(file_mask))) {
6842 +        shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
6843 +    } else {
6844 +        int fd;
6845 +
6846 +        /* 
6847 +         * If the filemask contains .shm we try to do a POSIX-compliant shared memory
6848 +         * backed mmap which should avoid synchs on some platforms.  At least on
6849 +         * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
6850 +         * a file in a mounted shmfs.  For this to work on Linux you need to make sure
6851 +         * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
6852 +         * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
6853 +         * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
6854 +         * path you want here.
6855 +         */
6856 +        if(strstr(file_mask,".shm")) {
6857 +            mktemp(file_mask);
6858 +            fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
6859 +            if(fd == -1) {
6860 +                apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
6861 +                return (void *)-1;
6862 +            }
6863 +            if (ftruncate(fd, size) < 0) {
6864 +                close(fd);
6865 +                shm_unlink(file_mask);
6866 +                apc_eprint("apc_mmap: ftruncate failed:");
6867 +                return (void *)-1;
6868 +            }
6869 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6870 +            shm_unlink(file_mask);
6871 +            close(fd);
6872 +        }
6873 +        /*
6874 +         * Support anonymous mmap through the /dev/zero interface as well
6875 +         */
6876 +        else if(!strcmp(file_mask,"/dev/zero")) {
6877 +            fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
6878 +            if(fd == -1) {
6879 +                apc_eprint("apc_mmap: open on /dev/zero failed:");
6880 +                return (void *)-1;
6881 +            }
6882 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6883 +            close(fd);
6884 +        }
6885 +        /* 
6886 +         * Otherwise we do a normal filesystem mmap
6887 +         */
6888 +        else {
6889 +            fd = mkstemp(file_mask);
6890 +            if(fd == -1) {
6891 +                apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
6892 +                return (void *)-1;
6893 +            }
6894 +            if (ftruncate(fd, size) < 0) {
6895 +                close(fd);
6896 +                unlink(file_mask);
6897 +                apc_eprint("apc_mmap: ftruncate failed:");
6898 +            }
6899 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
6900 +            close(fd);
6901 +            unlink(file_mask);
6902 +        }
6903 +    }
6904 +    if((int)shmaddr == -1) {
6905 +        apc_eprint("apc_mmap: mmap failed:");
6906 +    }
6907 +    return shmaddr;
6908 +}
6909 +
6910 +void apc_unmap(void* shmaddr, size_t size)
6911 +{
6912 +    if (munmap(shmaddr, size) < 0) {
6913 +        apc_wprint("apc_unmap: munmap failed:");
6914 +    }
6915 +}
6916 +
6917 +#endif
6918 +
6919 +/*
6920 + * Local variables:
6921 + * tab-width: 4
6922 + * c-basic-offset: 4
6923 + * End:
6924 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6925 + * vim<600: expandtab sw=4 ts=4 sts=4
6926 + */
6927 diff -ubrN php-5.2.5-orig/ext/apc/apc.php php-5.2.5/ext/apc/apc.php
6928 --- php-5.2.5-orig/ext/apc/apc.php      1969-12-31 18:00:00.000000000 -0600
6929 +++ php-5.2.5/ext/apc/apc.php   2007-12-26 16:51:32.000000000 -0600
6930 @@ -0,0 +1,1326 @@
6931 +<?php
6932 +/*
6933 +  +----------------------------------------------------------------------+
6934 +  | APC                                                                  |
6935 +  +----------------------------------------------------------------------+
6936 +  | Copyright (c) 2006 The PHP Group                                     |
6937 +  +----------------------------------------------------------------------+
6938 +  | This source file is subject to version 3.01 of the PHP license,      |
6939 +  | that is bundled with this package in the file LICENSE, and is        |
6940 +  | available through the world-wide-web at the following url:           |
6941 +  | http://www.php.net/license/3_01.txt                                  |
6942 +  | If you did not receive a copy of the PHP license and are unable to   |
6943 +  | obtain it through the world-wide-web, please send a note to          |
6944 +  | license@php.net so we can mail you a copy immediately.               |
6945 +  +----------------------------------------------------------------------+
6946 +  | Authors: Ralf Becker <beckerr@php.net>                               |
6947 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6948 +  |          Ilia Alshanetsky <ilia@prohost.org>                         |
6949 +  +----------------------------------------------------------------------+
6950 +
6951 +   All other licensing and usage conditions are those of the PHP Group.
6952 +
6953 + */
6954 +
6955 +$VERSION='$Id: apc.php,v 3.68 2007/07/22 00:25:48 gopalv Exp $';
6956 +
6957 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
6958 +if (file_exists("apc.conf.php")) include("apc.conf.php");
6959 +////////////////////////////////////////////////////////
6960 +
6961 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
6962 +
6963 +defaults('USE_AUTHENTICATION',1);                      // Use (internal) authentication - best choice if 
6964 +                                                                                       // no other authentication is available
6965 +                                                                                       // If set to 0:
6966 +                                                                                       //  There will be no further authentication. You 
6967 +                                                                                       //  will have to handle this by yourself!
6968 +                                                                                       // If set to 1:
6969 +                                                                                       //  You need to change ADMIN_PASSWORD to make
6970 +                                                                                       //  this work!
6971 +defaults('ADMIN_USERNAME','apc');                      // Admin Username
6972 +defaults('ADMIN_PASSWORD','password');         // Admin Password - CHANGE THIS TO ENABLE!!!
6973 +
6974 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
6975 +//           users generate a md5 or crypt password in a easy way to fill it in above
6976 +
6977 +//defaults('DATE_FORMAT', "d.m.Y H:i:s");      // German
6978 +defaults('DATE_FORMAT', 'Y/m/d H:i:s');        // US
6979 +
6980 +defaults('GRAPH_SIZE',200);                                    // Image size
6981 +
6982 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
6983 +
6984 +
6985 +// "define if not defined"
6986 +function defaults($d,$v) {
6987 +       if (!defined($d)) define($d,$v); // or just @define(...)
6988 +}
6989 +
6990 +// rewrite $PHP_SELF to block XSS attacks
6991 +//
6992 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES) : '';
6993 +$time = time();
6994 +$host = getenv('HOSTNAME');
6995 +if($host) { $host = '('.$host.')'; }
6996 +
6997 +// operation constants
6998 +define('OB_HOST_STATS',1);
6999 +define('OB_SYS_CACHE',2);
7000 +define('OB_USER_CACHE',3);
7001 +define('OB_SYS_CACHE_DIR',4);
7002 +define('OB_VERSION_CHECK',9);
7003 +
7004 +// check validity of input variables
7005 +$vardom=array(
7006 +       'OB'    => '/^\d+$/',                   // operational mode switch
7007 +       'CC'    => '/^[01]$/',                  // clear cache requested
7008 +       'DU'    => '/^.*$/',                    // Delete User Key
7009 +       'SH'    => '/^[a-z0-9]+$/',             // shared object description
7010 +
7011 +       'IMG'   => '/^[123]$/',                 // image to generate
7012 +       'LO'    => '/^1$/',                             // login requested
7013 +
7014 +       'COUNT' => '/^\d+$/',                   // number of line displayed in list
7015 +       'SCOPE' => '/^[AD]$/',                  // list view scope
7016 +       'SORT1' => '/^[AHSMCDTZ]$/',    // first sort key
7017 +       'SORT2' => '/^[DA]$/',                  // second sort key
7018 +       'AGGR'  => '/^\d+$/',                   // aggregation by dir level
7019 +       'SEARCH'        => '~^[a-zA-Z0-1/_.-]*$~'                       // aggregation by dir level
7020 +);
7021 +
7022 +// default cache mode
7023 +$cache_mode='opcode';
7024 +
7025 +// cache scope
7026 +$scope_list=array(
7027 +       'A' => 'cache_list',
7028 +       'D' => 'deleted_list'
7029 +);
7030 +
7031 +// handle POST and GET requests
7032 +if (empty($_REQUEST)) {
7033 +       if (!empty($_GET) && !empty($_POST)) {
7034 +               $_REQUEST = array_merge($_GET, $_POST);
7035 +       } else if (!empty($_GET)) {
7036 +               $_REQUEST = $_GET;
7037 +       } else if (!empty($_POST)) {
7038 +               $_REQUEST = $_POST;
7039 +       } else {
7040 +               $_REQUEST = array();
7041 +       }
7042 +}
7043 +
7044 +// check parameter syntax
7045 +foreach($vardom as $var => $dom) {
7046 +       if (!isset($_REQUEST[$var])) {
7047 +               $MYREQUEST[$var]=NULL;
7048 +       } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
7049 +               $MYREQUEST[$var]=$_REQUEST[$var];
7050 +       } else {
7051 +               $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
7052 +       }
7053 +}
7054 +
7055 +// check parameter sematics
7056 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
7057 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
7058 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
7059 +if (empty($MYREQUEST['OB']))   $MYREQUEST['OB']=OB_HOST_STATS;
7060 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
7061 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
7062 +
7063 +$MY_SELF=
7064 +       "$PHP_SELF".
7065 +       "?SCOPE=".$MYREQUEST['SCOPE'].
7066 +       "&SORT1=".$MYREQUEST['SORT1'].
7067 +       "&SORT2=".$MYREQUEST['SORT2'].
7068 +       "&COUNT=".$MYREQUEST['COUNT'];
7069 +$MY_SELF_WO_SORT=
7070 +       "$PHP_SELF".
7071 +       "?SCOPE=".$MYREQUEST['SCOPE'].
7072 +       "&COUNT=".$MYREQUEST['COUNT'];
7073 +
7074 +// authentication needed?
7075 +//
7076 +if (!USE_AUTHENTICATION) {
7077 +       $AUTHENTICATED=1;
7078 +} else {
7079 +       $AUTHENTICATED=0;
7080 +       if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
7081 +
7082 +               if (!isset($_SERVER['PHP_AUTH_USER']) ||
7083 +                       !isset($_SERVER['PHP_AUTH_PW']) ||
7084 +                       $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
7085 +                       $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
7086 +                       Header("WWW-Authenticate: Basic realm=\"APC Login\"");
7087 +                       Header("HTTP/1.0 401 Unauthorized");
7088 +
7089 +                       echo <<<EOB
7090 +                               <html><body>
7091 +                               <h1>Rejected!</h1>
7092 +                               <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
7093 +                               <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
7094 +                               </body></html>
7095 +EOB;
7096 +                       exit;
7097 +                       
7098 +               } else {
7099 +                       $AUTHENTICATED=1;
7100 +               }
7101 +       }
7102 +}
7103 +       
7104 +// select cache mode
7105 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
7106 +       $cache_mode='user';
7107 +}
7108 +// clear cache
7109 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
7110 +       apc_clear_cache($cache_mode);
7111 +}
7112 +
7113 +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
7114 +       apc_delete($MYREQUEST['DU']);
7115 +}
7116 +
7117 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
7118 +       echo "No cache info available.  APC does not appear to be running.";
7119 +  exit;
7120 +}
7121 +
7122 +$cache_user = apc_cache_info('user', 1);  
7123 +$mem=apc_sma_info();
7124 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
7125 +
7126 +// don't cache this page
7127 +//
7128 +header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
7129 +header("Cache-Control: post-check=0, pre-check=0", false);
7130 +header("Pragma: no-cache");                                    // HTTP/1.0
7131 +
7132 +function duration($ts) {
7133 +    global $time;
7134 +    $years = (int)((($time - $ts)/(7*86400))/52.177457);
7135 +    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
7136 +    $weeks = (int)(($rem)/(7*86400));
7137 +    $days = (int)(($rem)/86400) - $weeks*7;
7138 +    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
7139 +    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
7140 +    $str = '';
7141 +    if($years==1) $str .= "$years year, ";
7142 +    if($years>1) $str .= "$years years, ";
7143 +    if($weeks==1) $str .= "$weeks week, ";
7144 +    if($weeks>1) $str .= "$weeks weeks, ";
7145 +    if($days==1) $str .= "$days day,";
7146 +    if($days>1) $str .= "$days days,";
7147 +    if($hours == 1) $str .= " $hours hour and";
7148 +    if($hours>1) $str .= " $hours hours and";
7149 +    if($mins == 1) $str .= " 1 minute";
7150 +    else $str .= " $mins minutes";
7151 +    return $str;
7152 +}
7153 +
7154 +// create graphics
7155 +//
7156 +function graphics_avail() {
7157 +       return extension_loaded('gd');
7158 +}
7159 +if (isset($MYREQUEST['IMG']))
7160 +{
7161 +       if (!graphics_avail()) {
7162 +               exit(0);
7163 +       }
7164 +
7165 +       function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
7166 +               $r=$diameter/2;
7167 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
7168 +
7169 +               
7170 +               if (function_exists("imagefilledarc")) {
7171 +                       // exists only if GD 2.0.1 is avaliable
7172 +                       imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
7173 +                       imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
7174 +                       imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
7175 +               } else {
7176 +                       imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
7177 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7178 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7179 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
7180 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
7181 +                       imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
7182 +               }
7183 +               if ($text) {
7184 +                       if ($placeindex>0) {
7185 +                               imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7186 +                               imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
7187 +                               
7188 +                       } else {
7189 +                               imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7190 +                       }
7191 +               }
7192 +       } 
7193 +
7194 +       function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
7195 +               $r=$diameter/2;
7196 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
7197 +
7198 +               if ($placeindex>0) {
7199 +                       imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7200 +                       imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
7201 +                               
7202 +               } else {
7203 +                       imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7204 +               }
7205 +       } 
7206 +       
7207 +       function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
7208 +               global $col_black;
7209 +               $x1=$x+$w-1;
7210 +               $y1=$y+$h-1;
7211 +
7212 +               imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
7213 +               if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
7214 +               else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
7215 +               imagerectangle($im, $x, $y1, $x1, $y, $color1);
7216 +               if ($text) {
7217 +                       if ($placeindex>0) {
7218 +                       
7219 +                               if ($placeindex<16)
7220 +                               {
7221 +                                       $px=5;
7222 +                                       $py=$placeindex*12+6;
7223 +                                       imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
7224 +                                       imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
7225 +                                       imagestring($im,2,$px,$py-6,$text,$color1);     
7226 +                                       
7227 +                               } else {
7228 +                                       if ($placeindex<31) {
7229 +                                               $px=$x+40*2;
7230 +                                               $py=($placeindex-15)*12+6;
7231 +                                       } else {
7232 +                                               $px=$x+40*2+100*intval(($placeindex-15)/15);
7233 +                                               $py=($placeindex%15)*12+6;
7234 +                                       }
7235 +                                       imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
7236 +                                       imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
7237 +                                       imagestring($im,2,$px+2,$py-6,$text,$color1);   
7238 +                               }
7239 +                       } else {
7240 +                               imagestring($im,4,$x+5,$y1-16,$text,$color1);
7241 +                       }
7242 +               }
7243 +       }
7244 +
7245 +
7246 +       $size = GRAPH_SIZE; // image size
7247 +       if ($MYREQUEST['IMG']==3)
7248 +               $image = imagecreate(2*$size+150, $size+10);
7249 +       else
7250 +               $image = imagecreate($size+50, $size+10);
7251 +
7252 +       $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
7253 +       $col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
7254 +       $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
7255 +       $col_black = imagecolorallocate($image,   0,   0,   0);
7256 +       imagecolortransparent($image,$col_white);
7257 +
7258 +       switch ($MYREQUEST['IMG']) {
7259 +       
7260 +       case 1:
7261 +               $s=$mem['num_seg']*$mem['seg_size'];
7262 +               $a=$mem['avail_mem'];
7263 +               $x=$y=$size/2;
7264 +               $fuzz = 0.000001;
7265 +
7266 +               // This block of code creates the pie chart.  It is a lot more complex than you
7267 +               // would expect because we try to visualize any memory fragmentation as well.
7268 +               $angle_from = 0;
7269 +               $string_placement=array();
7270 +               for($i=0; $i<$mem['num_seg']; $i++) {   
7271 +                       $ptr = 0;
7272 +                       $free = $mem['block_lists'][$i];
7273 +                       foreach($free as $block) {
7274 +                               if($block['offset']!=$ptr) {       // Used block
7275 +                                       $angle_to = $angle_from+($block['offset']-$ptr)/$s;
7276 +                                       if(($angle_to+$fuzz)>1) $angle_to = 1;
7277 +                                       fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7278 +                                       if (($angle_to-$angle_from)>0.05) {
7279 +                                               array_push($string_placement, array($angle_from,$angle_to));
7280 +                                       }
7281 +                                       $angle_from = $angle_to;
7282 +                               }
7283 +                               $angle_to = $angle_from+($block['size'])/$s;
7284 +                               if(($angle_to+$fuzz)>1) $angle_to = 1;
7285 +                               fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
7286 +                               if (($angle_to-$angle_from)>0.05) {
7287 +                                       array_push($string_placement, array($angle_from,$angle_to));
7288 +                               }
7289 +                               $angle_from = $angle_to;
7290 +                               $ptr = $block['offset']+$block['size'];
7291 +                       }
7292 +                       if ($ptr < $mem['seg_size']) { // memory at the end 
7293 +                               $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
7294 +                               if(($angle_to+$fuzz)>1) $angle_to = 1;
7295 +                               fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7296 +                               if (($angle_to-$angle_from)>0.05) {
7297 +                                       array_push($string_placement, array($angle_from,$angle_to));
7298 +                               }
7299 +                       }
7300 +               }
7301 +               foreach ($string_placement as $angle) {
7302 +                       text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
7303 +               }
7304 +               break;
7305 +               
7306 +       case 2: 
7307 +               $s=$cache['num_hits']+$cache['num_misses'];
7308 +               $a=$cache['num_hits'];
7309 +               
7310 +               fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7311 +               fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7312 +               break;
7313 +               
7314 +       case 3:
7315 +               $s=$mem['num_seg']*$mem['seg_size'];
7316 +               $a=$mem['avail_mem'];
7317 +               $x=130;
7318 +               $y=1;
7319 +               $j=1;
7320 +
7321 +               // This block of code creates the bar chart.  It is a lot more complex than you
7322 +               // would expect because we try to visualize any memory fragmentation as well.
7323 +               for($i=0; $i<$mem['num_seg']; $i++) {   
7324 +                       $ptr = 0;
7325 +                       $free = $mem['block_lists'][$i];
7326 +                       foreach($free as $block) {
7327 +                               if($block['offset']!=$ptr) {       // Used block
7328 +                                       $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
7329 +                                       if ($h>0) {
7330 +                                                $j++;
7331 +                                               if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
7332 +                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
7333 +                                        }
7334 +                                       $y+=$h;
7335 +                               }
7336 +                               $h=(GRAPH_SIZE-5)*($block['size'])/$s;
7337 +                               if ($h>0) {
7338 +                                        $j++;
7339 +                                       if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
7340 +                                       else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
7341 +                                }
7342 +                               $y+=$h;
7343 +                               $ptr = $block['offset']+$block['size'];
7344 +                       }
7345 +                       if ($ptr < $mem['seg_size']) { // memory at the end 
7346 +                               $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
7347 +                               if ($h > 0) {
7348 +                                       fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
7349 +                               }
7350 +                       }
7351 +               }
7352 +               break;
7353 +       case 4: 
7354 +               $s=$cache['num_hits']+$cache['num_misses'];
7355 +               $a=$cache['num_hits'];
7356 +                       
7357 +               fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7358 +               fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7359 +               break;
7360 +       
7361 +       }
7362 +       header("Content-type: image/png");
7363 +       imagepng($image);
7364 +       exit;
7365 +}
7366 +
7367 +// pretty printer for byte values
7368 +//
7369 +function bsize($s) {
7370 +       foreach (array('','K','M','G') as $i => $k) {
7371 +               if ($s < 1024) break;
7372 +               $s/=1024;
7373 +       }
7374 +       return sprintf("%5.1f %sBytes",$s,$k);
7375 +}
7376 +
7377 +// sortable table header in "scripts for this host" view
7378 +function sortheader($key,$name,$extra='') {
7379 +       global $MYREQUEST, $MY_SELF_WO_SORT;
7380 +       
7381 +       if ($MYREQUEST['SORT1']==$key) {
7382 +               $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
7383 +       }
7384 +       return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
7385 +
7386 +}
7387 +
7388 +// create menu entry 
7389 +function menu_entry($ob,$title) {
7390 +       global $MYREQUEST,$MY_SELF;
7391 +       if ($MYREQUEST['OB']!=$ob) {
7392 +               return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7393 +       } else if (empty($MYREQUEST['SH'])) {
7394 +               return "<li><span class=active>$title</span></li>";
7395 +       } else {
7396 +               return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
7397 +       }
7398 +}
7399 +
7400 +function put_login_link($s="Login")
7401 +{
7402 +       global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
7403 +       // needs ADMIN_PASSWORD to be changed!
7404 +       //
7405 +       if (!USE_AUTHENTICATION) {
7406 +               return;
7407 +       } else if (ADMIN_PASSWORD=='password')
7408 +       {
7409 +               print <<<EOB
7410 +                       <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>
7411 +EOB;
7412 +       } else if ($AUTHENTICATED) {
7413 +               print <<<EOB
7414 +                       '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
7415 +EOB;
7416 +       } else{
7417 +               print <<<EOB
7418 +                       <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
7419 +EOB;
7420 +       }
7421 +}
7422 +
7423 +
7424 +?>
7425 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7426 +<html>
7427 +<head><title>APC INFO <?php echo $host ?></title>
7428 +<style><!--
7429 +body { background:white; font-size:100.01%; margin:0; padding:0; }
7430 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
7431 +* html body   {font-size:0.8em}
7432 +* html p      {font-size:0.8em}
7433 +* html td     {font-size:0.8em}
7434 +* html th     {font-size:0.8em}
7435 +* html input  {font-size:0.8em}
7436 +* html submit {font-size:0.8em}
7437 +td { vertical-align:top }
7438 +a { color:black; font-weight:none; text-decoration:none; }
7439 +a:hover { text-decoration:underline; }
7440 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
7441 +
7442 +
7443 +div.head div.login {
7444 +       position:absolute;
7445 +       right: 1em;
7446 +       top: 1.2em;
7447 +       color:white;
7448 +       width:6em;
7449 +       }
7450 +div.head div.login a {
7451 +       position:absolute;
7452 +       right: 0em;
7453 +       background:rgb(119,123,180);
7454 +       border:solid rgb(102,102,153) 2px;
7455 +       color:white;
7456 +       font-weight:bold;
7457 +       padding:0.1em 0.5em 0.1em 0.5em;
7458 +       text-decoration:none;
7459 +       }
7460 +div.head div.login a:hover {
7461 +       background:rgb(193,193,244);
7462 +       }
7463 +
7464 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
7465 +* html h1.apc { margin-bottom:-7px; }
7466 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
7467 +h1.apc div.logo span.logo {
7468 +       background:rgb(119,123,180);
7469 +       color:black;
7470 +       border-right: solid black 1px;
7471 +       border-bottom: solid black 1px;
7472 +       font-style:italic;
7473 +       font-size:1em;
7474 +       padding-left:1.2em;
7475 +       padding-right:1.2em;
7476 +       text-align:right;
7477 +       }
7478 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
7479 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
7480 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
7481 +hr.apc {
7482 +       background:white;
7483 +       border-bottom:solid rgb(102,102,153) 1px;
7484 +       border-style:none;
7485 +       border-top:solid rgb(102,102,153) 10px;
7486 +       height:12px;
7487 +       margin:0;
7488 +       margin-top:1px;
7489 +       padding:0;
7490 +}
7491 +
7492 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
7493 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
7494 +ol.menu a {
7495 +       background:rgb(153,153,204);
7496 +       border:solid rgb(102,102,153) 2px;
7497 +       color:white;
7498 +       font-weight:bold;
7499 +       margin-right:0em;
7500 +       padding:0.1em 0.5em 0.1em 0.5em;
7501 +       text-decoration:none;
7502 +       margin-left: 5px;
7503 +       }
7504 +ol.menu a.child_active {
7505 +       background:rgb(153,153,204);
7506 +       border:solid rgb(102,102,153) 2px;
7507 +       color:white;
7508 +       font-weight:bold;
7509 +       margin-right:0em;
7510 +       padding:0.1em 0.5em 0.1em 0.5em;
7511 +       text-decoration:none;
7512 +       border-left: solid black 5px;
7513 +       margin-left: 0px;
7514 +       }
7515 +ol.menu span.active {
7516 +       background:rgb(153,153,204);
7517 +       border:solid rgb(102,102,153) 2px;
7518 +       color:black;
7519 +       font-weight:bold;
7520 +       margin-right:0em;
7521 +       padding:0.1em 0.5em 0.1em 0.5em;
7522 +       text-decoration:none;
7523 +       border-left: solid black 5px;
7524 +       }
7525 +ol.menu span.inactive {
7526 +       background:rgb(193,193,244);
7527 +       border:solid rgb(182,182,233) 2px;
7528 +       color:white;
7529 +       font-weight:bold;
7530 +       margin-right:0em;
7531 +       padding:0.1em 0.5em 0.1em 0.5em;
7532 +       text-decoration:none;
7533 +       margin-left: 5px;
7534 +       }
7535 +ol.menu a:hover {
7536 +       background:rgb(193,193,244);
7537 +       text-decoration:none;
7538 +       }
7539 +       
7540 +       
7541 +div.info {
7542 +       background:rgb(204,204,204);
7543 +       border:solid rgb(204,204,204) 1px;
7544 +       margin-bottom:1em;
7545 +       }
7546 +div.info h2 {
7547 +       background:rgb(204,204,204);
7548 +       color:black;
7549 +       font-size:1em;
7550 +       margin:0;
7551 +       padding:0.1em 1em 0.1em 1em;
7552 +       }
7553 +div.info table {
7554 +       border:solid rgb(204,204,204) 1px;
7555 +       border-spacing:0;
7556 +       width:100%;
7557 +       }
7558 +div.info table th {
7559 +       background:rgb(204,204,204);
7560 +       color:white;
7561 +       margin:0;
7562 +       padding:0.1em 1em 0.1em 1em;
7563 +       }
7564 +div.info table th a.sortable { color:black; }
7565 +div.info table tr.tr-0 { background:rgb(238,238,238); }
7566 +div.info table tr.tr-1 { background:rgb(221,221,221); }
7567 +div.info table td { padding:0.3em 1em 0.3em 1em; }
7568 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
7569 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
7570 +div.info table td h3 {
7571 +       color:black;
7572 +       font-size:1.1em;
7573 +       margin-left:-0.3em;
7574 +       }
7575 +
7576 +div.graph { margin-bottom:1em }
7577 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
7578 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
7579 +div.graph table td.td-0 { background:rgb(238,238,238); }
7580 +div.graph table td.td-1 { background:rgb(221,221,221); }
7581 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
7582 +
7583 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
7584 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
7585 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
7586 +
7587 +div.sorting { margin:1.5em 0em 1.5em 2em }
7588 +.center { text-align:center }
7589 +.aright { position:absolute;right:1em }
7590 +.right { text-align:right }
7591 +.ok { color:rgb(0,200,0); font-weight:bold}
7592 +.failed { color:rgb(200,0,0); font-weight:bold}
7593 +
7594 +span.box {
7595 +       border: black solid 1px;
7596 +       border-right:solid black 2px;
7597 +       border-bottom:solid black 2px;
7598 +       padding:0 0.5em 0 0.5em;
7599 +       margin-right:1em;
7600 +}
7601 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
7602 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
7603 +
7604 +div.authneeded {
7605 +       background:rgb(238,238,238);
7606 +       border:solid rgb(204,204,204) 1px;
7607 +       color:rgb(200,0,0);
7608 +       font-size:1.2em;
7609 +       font-weight:bold;
7610 +       padding:2em;
7611 +       text-align:center;
7612 +       }
7613 +       
7614 +input {
7615 +       background:rgb(153,153,204);
7616 +       border:solid rgb(102,102,153) 2px;
7617 +       color:white;
7618 +       font-weight:bold;
7619 +       margin-right:1em;
7620 +       padding:0.1em 0.5em 0.1em 0.5em;
7621 +       }
7622 +//-->
7623 +</style>
7624 +</head>
7625 +<body>
7626 +<div class="head">
7627 +       <h1 class="apc">
7628 +               <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
7629 +               <div class="nameinfo">Opcode Cache</div>
7630 +       </h1>
7631 +       <div class="login">
7632 +       <?php put_login_link(); ?>
7633 +       </div>
7634 +       <hr class="apc">
7635 +</div>
7636 +<?php
7637 +
7638 +
7639 +// Display main Menu
7640 +echo <<<EOB
7641 +       <ol class=menu>
7642 +       <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
7643 +EOB;
7644 +echo
7645 +       menu_entry(1,'View Host Stats'),
7646 +       menu_entry(2,'System Cache Entries');
7647 +if ($AUTHENTICATED) {
7648 +       echo menu_entry(4,'Per-Directory Entries');
7649 +}
7650 +echo
7651 +       menu_entry(3,'User Cache Entries'),
7652 +       menu_entry(9,'Version Check');
7653 +       
7654 +if ($AUTHENTICATED) {
7655 +       echo <<<EOB
7656 +               <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
7657 +EOB;
7658 +}
7659 +echo <<<EOB
7660 +       </ol>
7661 +EOB;
7662 +
7663 +
7664 +// CONTENT
7665 +echo <<<EOB
7666 +       <div class=content>
7667 +EOB;
7668 +
7669 +// MAIN SWITCH STATEMENT 
7670 +
7671 +switch ($MYREQUEST['OB']) {
7672 +
7673 +
7674 +
7675 +
7676 +
7677 +// -----------------------------------------------
7678 +// Host Stats
7679 +// -----------------------------------------------
7680 +case OB_HOST_STATS:
7681 +       $mem_size = $mem['num_seg']*$mem['seg_size'];
7682 +       $mem_avail= $mem['avail_mem'];
7683 +       $mem_used = $mem_size-$mem_avail;
7684 +       $seg_size = bsize($mem['seg_size']);
7685 +       $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
7686 +       $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
7687 +       $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
7688 +       $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
7689 +       $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
7690 +       $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
7691 +       $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
7692 +       $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
7693 +       $apcversion = phpversion('apc');
7694 +       $phpversion = phpversion();
7695 +       $number_files = $cache['num_entries']; 
7696 +    $size_files = bsize($cache['mem_size']);
7697 +       $number_vars = $cache_user['num_entries'];
7698 +    $size_vars = bsize($cache_user['mem_size']);
7699 +       $i=0;
7700 +       echo <<< EOB
7701 +               <div class="info div1"><h2>General Cache Information</h2>
7702 +               <table cellspacing=0><tbody>
7703 +               <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
7704 +               <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
7705 +EOB;
7706 +
7707 +       if(!empty($_SERVER['SERVER_NAME']))
7708 +               echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
7709 +       if(!empty($_SERVER['SERVER_SOFTWARE']))
7710 +               echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
7711 +
7712 +       echo <<<EOB
7713 +               <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
7714 +    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
7715 +    </td></tr>
7716 +EOB;
7717 +       echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
7718 +       echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
7719 +       echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
7720 +       echo <<<EOB
7721 +               </tbody></table>
7722 +               </div>
7723 +
7724 +               <div class="info div1"><h2>File Cache Information</h2>
7725 +               <table cellspacing=0><tbody>
7726 +               <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
7727 +               <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
7728 +               <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
7729 +               <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
7730 +               <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
7731 +               <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
7732 +               <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
7733 +               <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
7734 +               </tbody></table>
7735 +               </div>
7736 +
7737 +               <div class="info div1"><h2>User Cache Information</h2>
7738 +               <table cellspacing=0><tbody>
7739 +    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
7740 +               <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
7741 +               <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
7742 +               <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
7743 +               <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
7744 +               <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
7745 +               <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
7746 +               <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
7747 +
7748 +               </tbody></table>
7749 +               </div>
7750 +
7751 +               <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
7752 +EOB;
7753 +
7754 +       $j = 0;
7755 +       foreach (ini_get_all('apc') as $k => $v) {
7756 +               echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
7757 +               $j = 1 - $j;
7758 +       }
7759 +
7760 +       if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
7761 +               $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
7762 +       else
7763 +               $mem_note = "Memory Usage";
7764 +
7765 +       echo <<< EOB
7766 +               </tbody></table>
7767 +               </div>
7768 +
7769 +               <div class="graph div3"><h2>Host Status Diagrams</h2>
7770 +               <table cellspacing=0><tbody>
7771 +EOB;
7772 +       $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
7773 +       echo <<<EOB
7774 +               <tr>
7775 +               <td class=td-0>$mem_note</td>
7776 +               <td class=td-1>Hits &amp; Misses</td>
7777 +               </tr>
7778 +EOB;
7779 +
7780 +       echo
7781 +               graphics_avail() ? 
7782 +                         '<tr>'.
7783 +                         "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
7784 +                         "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
7785 +                       : "",
7786 +               '<tr>',
7787 +               '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
7788 +               '<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",
7789 +               '</tr>',
7790 +               '<tr>',
7791 +               '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
7792 +               '<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";
7793 +       echo <<< EOB
7794 +               </tr>
7795 +               </tbody></table>
7796 +
7797 +               <br/>
7798 +               <h2>Detailed Memory Usage and Fragmentation</h2>
7799 +               <table cellspacing=0><tbody>
7800 +               <tr>
7801 +               <td class=td-0 colspan=2><br/>
7802 +EOB;
7803 +
7804 +       // Fragementation: (freeseg - 1) / total_seg
7805 +       $nseg = $freeseg = $fragsize = $freetotal = 0;
7806 +       for($i=0; $i<$mem['num_seg']; $i++) {
7807 +               $ptr = 0;
7808 +               foreach($mem['block_lists'][$i] as $block) {
7809 +                       if ($block['offset'] != $ptr) {
7810 +                               ++$nseg;
7811 +                       }
7812 +                       $ptr = $block['offset'] + $block['size'];
7813 +                        /* Only consider blocks <5M for the fragmentation % */
7814 +                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
7815 +                        $freetotal+=$block['size'];
7816 +               }
7817 +               $freeseg += count($mem['block_lists'][$i]);
7818 +       }
7819 +       
7820 +       if ($freeseg > 1) {
7821 +               $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
7822 +       } else {
7823 +               $frag = "0%";
7824 +       }
7825 +
7826 +       if (graphics_avail()) {
7827 +               $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
7828 +               echo <<<EOB
7829 +                       <img alt="" $size src="$PHP_SELF?IMG=3&$time">
7830 +EOB;
7831 +       }
7832 +       echo <<<EOB
7833 +               </br>Fragmentation: $frag
7834 +               </td>
7835 +               </tr>
7836 +EOB;
7837 +        if(isset($mem['adist'])) {
7838 +          foreach($mem['adist'] as $i=>$v) {
7839 +            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
7840 +            if($i==0) $range = "1";
7841 +            else $range = "$cur - $nxt";
7842 +            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
7843 +          }
7844 +        }
7845 +        echo <<<EOB
7846 +               </tbody></table>
7847 +               </div>
7848 +EOB;
7849 +               
7850 +       break;
7851 +
7852 +
7853 +// -----------------------------------------------
7854 +// User Cache Entries
7855 +// -----------------------------------------------
7856 +case OB_USER_CACHE:
7857 +       if (!$AUTHENTICATED) {
7858 +               echo '<div class="authneeded">You need to login to see the user values here!<br/>&nbsp;<br/>';
7859 +               put_login_link("Login now!");
7860 +               echo '</div>';
7861 +               break;
7862 +       }
7863 +       $fieldname='info';
7864 +       $fieldheading='User Entry Label';
7865 +       $fieldkey='info';
7866 +
7867 +// -----------------------------------------------
7868 +// System Cache Entries                
7869 +// -----------------------------------------------
7870 +case OB_SYS_CACHE:     
7871 +       if (!isset($fieldname))
7872 +       {
7873 +               $fieldname='filename';
7874 +               $fieldheading='Script Filename';
7875 +               if(ini_get("apc.stat")) $fieldkey='inode';
7876 +               else $fieldkey='filename'; 
7877 +       }
7878 +       if (!empty($MYREQUEST['SH']))
7879 +       {
7880 +               echo <<< EOB
7881 +                       <div class="info"><table cellspacing=0><tbody>
7882 +                       <tr><th>Attribute</th><th>Value</th></tr>
7883 +EOB;
7884 +
7885 +               $m=0;
7886 +               foreach($scope_list as $j => $list) {
7887 +                       foreach($cache[$list] as $i => $entry) {
7888 +                               if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
7889 +                               foreach($entry as $k => $value) {
7890 +                                       if (!$AUTHENTICATED) {
7891 +                                               // hide all path entries if not logged in
7892 +                                               $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
7893 +                                       }
7894 +
7895 +                                       if ($k == "num_hits") {
7896 +                                               $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
7897 +                                       }
7898 +                                       if ($k == 'deletion_time') {
7899 +                                               if(!$entry['deletion_time']) $value = "None";
7900 +                                       }
7901 +                                       echo
7902 +                                               "<tr class=tr-$m>",
7903 +                                               "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
7904 +                                               "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
7905 +                                               "</tr>";
7906 +                                       $m=1-$m;
7907 +                               }
7908 +                               if($fieldkey=='info') {
7909 +                                       echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
7910 +                                       $output = var_export(apc_fetch($entry[$fieldkey]),true);
7911 +                                       echo htmlspecialchars($output);
7912 +                                       echo "</pre></td></tr>\n";
7913 +                               }
7914 +                               break;
7915 +                       }
7916 +               }
7917 +
7918 +               echo <<<EOB
7919 +                       </tbody></table>
7920 +                       </div>
7921 +EOB;
7922 +               break;
7923 +       }
7924 +
7925 +       $cols=6;
7926 +       echo <<<EOB
7927 +               <div class=sorting><form>Scope:
7928 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
7929 +               <select name=SCOPE>
7930 +EOB;
7931 +       echo 
7932 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
7933 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
7934 +               "</select>",
7935 +               ", Sorting:<select name=SORT1>",
7936 +               "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
7937 +               "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
7938 +               "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
7939 +               "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
7940 +               "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
7941 +               "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
7942 +               "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
7943 +       if($fieldname=='info') echo
7944 +               "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
7945 +       echo 
7946 +               '</select>',
7947 +               '<select name=SORT2>',
7948 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
7949 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
7950 +               '</select>',
7951 +               '<select name=COUNT onChange="form.submit()">',
7952 +               '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
7953 +               '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
7954 +               '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
7955 +               '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
7956 +               '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
7957 +               '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
7958 +               '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
7959 +               '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
7960 +               '</select>',
7961 +    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
7962 +               '&nbsp;<input type=submit value="GO!">',
7963 +               '</form></div>',
7964 +
7965 +               '<div class="info"><table cellspacing=0><tbody>',
7966 +               '<tr>',
7967 +               '<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
7968 +               '<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
7969 +               '<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
7970 +               '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
7971 +               '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
7972 +               '<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
7973 +
7974 +       if($fieldname=='info') {
7975 +               $cols+=2;
7976 +                echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
7977 +       }
7978 +       echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
7979 +
7980 +       // builds list with alpha numeric sortable keys
7981 +       //
7982 +       $list = array();
7983 +       foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
7984 +               switch($MYREQUEST['SORT1']) {
7985 +                       case 'A': $k=sprintf('%015d-',$entry['access_time']);   break;
7986 +                       case 'H': $k=sprintf('%015d-',$entry['num_hits']);              break;
7987 +                       case 'Z': $k=sprintf('%015d-',$entry['mem_size']);              break;
7988 +                       case 'M': $k=sprintf('%015d-',$entry['mtime']);                 break;
7989 +                       case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
7990 +                       case 'T': $k=sprintf('%015d-',$entry['ttl']);                   break;
7991 +                       case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
7992 +                       case 'S': $k='';                                                                                break;
7993 +               }
7994 +               if (!$AUTHENTICATED) {
7995 +                       // hide all path entries if not logged in
7996 +                       $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
7997 +               } else {
7998 +                       $list[$k.$entry[$fieldname]]=$entry;
7999 +               }
8000 +       }
8001 +
8002 +       if ($list) {
8003 +               
8004 +               // sort list
8005 +               //
8006 +               switch ($MYREQUEST['SORT2']) {
8007 +                       case "A":       krsort($list);  break;
8008 +                       case "D":       ksort($list);   break;
8009 +               }
8010 +               
8011 +               // output list
8012 +               $i=0;
8013 +               foreach($list as $k => $entry) {
8014 +      if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {  
8015 +        echo
8016 +          '<tr class=tr-',$i%2,'>',
8017 +          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
8018 +          '<td class="td-n center">',$entry['num_hits'],'</td>',
8019 +          '<td class="td-n right">',$entry['mem_size'],'</td>',
8020 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
8021 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
8022 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
8023 +
8024 +        if($fieldname=='info') {
8025 +          if($entry['ttl'])
8026 +            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
8027 +          else
8028 +            echo '<td class="td-n center">None</td>';
8029 +        }
8030 +        if ($entry['deletion_time']) {
8031 +
8032 +          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
8033 +        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
8034 +
8035 +          echo '<td class="td-last center">';
8036 +          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
8037 +          echo '</td>';
8038 +        } else {
8039 +          echo '<td class="td-last center"> &nbsp; </td>';
8040 +        }
8041 +        echo '</tr>';
8042 +        $i++;
8043 +        if ($i == $MYREQUEST['COUNT'])
8044 +          break;
8045 +      }
8046 +               }
8047 +               
8048 +       } else {
8049 +               echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
8050 +       }
8051 +       echo <<< EOB
8052 +               </tbody></table>
8053 +EOB;
8054 +
8055 +       if ($list && $i < count($list)) {
8056 +               echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8057 +       }
8058 +
8059 +       echo <<< EOB
8060 +               </div>
8061 +EOB;
8062 +       break;
8063 +
8064 +
8065 +// -----------------------------------------------
8066 +// Per-Directory System Cache Entries
8067 +// -----------------------------------------------
8068 +case OB_SYS_CACHE_DIR: 
8069 +       if (!$AUTHENTICATED) {
8070 +               break;
8071 +       }
8072 +
8073 +       echo <<<EOB
8074 +               <div class=sorting><form>Scope:
8075 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
8076 +               <select name=SCOPE>
8077 +EOB;
8078 +       echo 
8079 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
8080 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
8081 +               "</select>",
8082 +               ", Sorting:<select name=SORT1>",
8083 +               "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
8084 +               "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
8085 +               "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
8086 +               "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
8087 +               "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
8088 +               "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
8089 +               '</select>',
8090 +               '<select name=SORT2>',
8091 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
8092 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
8093 +               '</select>',
8094 +               '<select name=COUNT onChange="form.submit()">',
8095 +               '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
8096 +               '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
8097 +               '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
8098 +               '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
8099 +               '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
8100 +               '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
8101 +               '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
8102 +               '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
8103 +               '</select>',
8104 +               ", Group By Dir Level:<select name=AGGR>",
8105 +               "<option value='' selected>None</option>";
8106 +               for ($i = 1; $i < 10; $i++)
8107 +                       echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
8108 +               echo '</select>',
8109 +               '&nbsp;<input type=submit value="GO!">',
8110 +               '</form></div>',
8111 +
8112 +               '<div class="info"><table cellspacing=0><tbody>',
8113 +               '<tr>',
8114 +               '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
8115 +               '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
8116 +               '<th>',sortheader('H','Total Hits',     "&OB=".$MYREQUEST['OB']),'</th>',
8117 +               '<th>',sortheader('Z','Total Size',     "&OB=".$MYREQUEST['OB']),'</th>',
8118 +               '<th>',sortheader('C','Avg. Hits',      "&OB=".$MYREQUEST['OB']),'</th>',
8119 +               '<th>',sortheader('A','Avg. Size',      "&OB=".$MYREQUEST['OB']),'</th>',
8120 +               '</tr>';
8121 +
8122 +       // builds list with alpha numeric sortable keys
8123 +       //
8124 +       $tmp = $list = array();
8125 +       foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
8126 +               $n = dirname($entry['filename']);
8127 +               if ($MYREQUEST['AGGR'] > 0) {
8128 +                       $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
8129 +               }
8130 +               if (!isset($tmp[$n])) {
8131 +                       $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
8132 +               }
8133 +               $tmp[$n]['hits'] += $entry['num_hits'];
8134 +               $tmp[$n]['size'] += $entry['mem_size'];
8135 +               ++$tmp[$n]['ents'];
8136 +       }
8137 +
8138 +       foreach ($tmp as $k => $v) {
8139 +               switch($MYREQUEST['SORT1']) {
8140 +                       case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
8141 +                       case 'T': $kn=sprintf('%015d-',$v['ents']);             break;
8142 +                       case 'H': $kn=sprintf('%015d-',$v['hits']);             break;
8143 +                       case 'Z': $kn=sprintf('%015d-',$v['size']);             break;
8144 +                       case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
8145 +                       case 'S': $kn = $k;                                     break;
8146 +               }
8147 +               $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
8148 +       }
8149 +
8150 +       if ($list) {
8151 +               
8152 +               // sort list
8153 +               //
8154 +               switch ($MYREQUEST['SORT2']) {
8155 +                       case "A":       krsort($list);  break;
8156 +                       case "D":       ksort($list);   break;
8157 +               }
8158 +               
8159 +               // output list
8160 +               $i = 0;
8161 +               foreach($list as $entry) {
8162 +                       echo
8163 +                               '<tr class=tr-',$i%2,'>',
8164 +                               "<td class=td-0>",$entry[0],'</a></td>',
8165 +                               '<td class="td-n center">',$entry[1],'</td>',
8166 +                               '<td class="td-n center">',$entry[2],'</td>',
8167 +                               '<td class="td-n center">',$entry[3],'</td>',
8168 +                               '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
8169 +                               '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
8170 +                               '</tr>';
8171 +
8172 +                       if (++$i == $MYREQUEST['COUNT']) break;
8173 +               }
8174 +               
8175 +       } else {
8176 +               echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
8177 +       }
8178 +       echo <<< EOB
8179 +               </tbody></table>
8180 +EOB;
8181 +
8182 +       if ($list && $i < count($list)) {
8183 +               echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8184 +       }
8185 +
8186 +       echo <<< EOB
8187 +               </div>
8188 +EOB;
8189 +       break;
8190 +
8191 +// -----------------------------------------------
8192 +// Version check
8193 +// -----------------------------------------------
8194 +case OB_VERSION_CHECK:
8195 +       echo <<<EOB
8196 +               <div class="info"><h2>APC Version Information</h2>
8197 +               <table cellspacing=0><tbody>
8198 +               <tr>
8199 +               <th></th>
8200 +               </tr>
8201 +EOB;
8202 +
8203 +       $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
8204 +       if (!$rss) {
8205 +               echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
8206 +       } else {
8207 +               $apcversion = phpversion('apc');
8208 +
8209 +               preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
8210 +               echo '<tr class="tr-0 center"><td>';
8211 +               if (version_compare($apcversion, $match[1], '>=')) {
8212 +                       echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
8213 +                       $i = 3;
8214 +               } else {
8215 +                       echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
8216 +                               newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
8217 +                               http://pecl.php.net/package/APC/'.$match[1].'</a>
8218 +                               </div>';
8219 +                       $i = -1;
8220 +               }
8221 +               echo '</td></tr>';
8222 +               echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
8223 +
8224 +               preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
8225 +               next($match[2]); next($match[2]);
8226 +
8227 +               while (list(,$v) = each($match[2])) {
8228 +                       list(,$ver) = explode(' ', $v, 2);
8229 +                       if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
8230 +                               break;
8231 +                       } else if (!$i--) {
8232 +                               break;
8233 +                       }
8234 +                       echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
8235 +                       echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
8236 +                       next($match[2]);
8237 +               }
8238 +               echo '</td></tr>';
8239 +       }
8240 +       echo <<< EOB
8241 +               </tbody></table>
8242 +               </div>
8243 +EOB;
8244 +       break;
8245 +
8246 +}
8247 +
8248 +echo <<< EOB
8249 +       </div>
8250 +EOB;
8251 +
8252 +?>
8253 +
8254 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
8255 +</body>
8256 +</html>
8257 diff -ubrN php-5.2.5-orig/ext/apc/apc_php.h php-5.2.5/ext/apc/apc_php.h
8258 --- php-5.2.5-orig/ext/apc/apc_php.h    1969-12-31 18:00:00.000000000 -0600
8259 +++ php-5.2.5/ext/apc/apc_php.h 2007-12-26 16:51:32.000000000 -0600
8260 @@ -0,0 +1,71 @@
8261 +/*
8262 +  +----------------------------------------------------------------------+
8263 +  | APC                                                                  |
8264 +  +----------------------------------------------------------------------+
8265 +  | Copyright (c) 2006 The PHP Group                                     |
8266 +  +----------------------------------------------------------------------+
8267 +  | This source file is subject to version 3.01 of the PHP license,      |
8268 +  | that is bundled with this package in the file LICENSE, and is        |
8269 +  | available through the world-wide-web at the following url:           |
8270 +  | http://www.php.net/license/3_01.txt                                  |
8271 +  | If you did not receive a copy of the PHP license and are unable to   |
8272 +  | obtain it through the world-wide-web, please send a note to          |
8273 +  | license@php.net so we can mail you a copy immediately.               |
8274 +  +----------------------------------------------------------------------+
8275 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8276 +  |          George Schlossnagle <george@omniti.com>                     |
8277 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
8278 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
8279 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
8280 +  +----------------------------------------------------------------------+
8281 +
8282 +   This software was contributed to PHP by Community Connect Inc. in 2002
8283 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8284 +   Future revisions and derivatives of this source code must acknowledge
8285 +   Community Connect Inc. as the original contributor of this module by
8286 +   leaving this note intact in the source code.
8287 +
8288 +   All other licensing and usage conditions are those of the PHP Group.
8289 +
8290 + */
8291 +
8292 +/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
8293 +
8294 +#ifndef APC_PHP_H
8295 +#define APC_PHP_H
8296 +
8297 +/*
8298 + * The purpose of this header file is to include all PHP and Zend headers that
8299 + * are typically needed elsewhere in APC. This makes it easy to insure that
8300 + * all required headers are available.
8301 + */
8302 +
8303 +#include "php.h"
8304 +#include "zend.h"
8305 +#include "zend_API.h"
8306 +#include "zend_compile.h"
8307 +#include "zend_hash.h"
8308 +#include "zend_extensions.h"
8309 +
8310 +#if ZEND_MODULE_API_NO > 20050922
8311 +#define ZEND_ENGINE_2_2
8312 +#endif
8313 +#if ZEND_MODULE_API_NO > 20050921
8314 +#define ZEND_ENGINE_2_1
8315 +#endif
8316 +#ifdef ZEND_ENGINE_2_1
8317 +#include "zend_vm.h"
8318 +#endif
8319 +
8320 +#include "rfc1867.h"
8321 +
8322 +#endif
8323 +
8324 +/*
8325 + * Local variables:
8326 + * tab-width: 4
8327 + * c-basic-offset: 4
8328 + * End:
8329 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8330 + * vim<600: expandtab sw=4 ts=4 sts=4
8331 + */
8332 diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthreadmutex.c
8333 --- php-5.2.5-orig/ext/apc/apc_pthreadmutex.c   1969-12-31 18:00:00.000000000 -0600
8334 +++ php-5.2.5/ext/apc/apc_pthreadmutex.c        2007-12-26 16:51:32.000000000 -0600
8335 @@ -0,0 +1,111 @@
8336 +/*
8337 +  +----------------------------------------------------------------------+
8338 +  | APC                                                                  |
8339 +  +----------------------------------------------------------------------+
8340 +  | Copyright (c) 2006 The PHP Group                                     |
8341 +  +----------------------------------------------------------------------+
8342 +  | This source file is subject to version 3.01 of the PHP license,      |
8343 +  | that is bundled with this package in the file LICENSE, and is        |
8344 +  | available through the world-wide-web at the following url:           |
8345 +  | http://www.php.net/license/3_01.txt                                  |
8346 +  | If you did not receive a copy of the PHP license and are unable to   |
8347 +  | obtain it through the world-wide-web, please send a note to          |
8348 +  | license@php.net so we can mail you a copy immediately.               |
8349 +  +----------------------------------------------------------------------+
8350 +  | Authors: Brian Shire <shire@php.net>                                 |
8351 +  +----------------------------------------------------------------------+
8352 +
8353 + */
8354 +
8355 +/* $Id: apc_pthreadmutex.c,v 3.3 2007/12/21 01:36:51 shire Exp $ */
8356 +
8357 +#include "apc_pthreadmutex.h"
8358 +
8359 +#ifdef APC_PTHREADMUTEX_LOCKS
8360 +
8361 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock) 
8362 +{ 
8363 +    int result;
8364 +    pthread_mutexattr_t* attr;
8365 +    attr = malloc(sizeof(pthread_mutexattr_t));
8366 +
8367 +    result = pthread_mutexattr_init(attr);
8368 +    if(result == ENOMEM) {
8369 +        apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
8370 +    } else if(result == EINVAL) {
8371 +        apc_eprint("pthread mutex error: attr does not point to writeable memory.");
8372 +    } else if(result == EFAULT) {
8373 +        apc_eprint("pthread mutex error: attr is an invalid pointer.");
8374 +    } 
8375 +
8376 +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
8377 +       result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
8378 +       if (result == EINVAL) {
8379 +               apc_eprint("pthread_mutexattr_settype: unable to set adaptive mutexes");
8380 +       }
8381 +#endif
8382 +
8383 +    /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
8384 +    result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
8385 +    if(result == EINVAL) {
8386 +        apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
8387 +    } else if(result == EFAULT) {
8388 +        apc_eprint("pthread mutex error: attr is an invalid pointer.");
8389 +    } else if(result == ENOTSUP) {
8390 +        apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
8391 +    }
8392 +
8393 +    if(pthread_mutex_init(lock, attr)) { 
8394 +        apc_eprint("unable to initialize pthread lock");
8395 +    }
8396 +    return lock;
8397 +}
8398 +
8399 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
8400 +{
8401 +    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
8402 +}
8403 +
8404 +void apc_pthreadmutex_lock(pthread_mutex_t *lock)
8405 +{
8406 +    int result;
8407 +    result = pthread_mutex_lock(lock);
8408 +    if(result == EINVAL) {
8409 +        apc_eprint("unable to obtain pthread lock (EINVAL)");
8410 +    } else if(result == EDEADLK) {
8411 +        apc_eprint("unable to obtain pthread lock (EDEADLK)");
8412 +    }  
8413 +}
8414 +
8415 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
8416 +{
8417 +    if(pthread_mutex_unlock(lock)) {
8418 +        apc_eprint("unable to unlock pthread lock");
8419 +    }
8420 +}
8421 +
8422 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
8423 +{
8424 +    int rval;
8425 +    rval = pthread_mutex_trylock(lock);
8426 +    if(rval == EBUSY) {     /* Lock is already held */
8427 +        return 0;
8428 +    } else if(rval == 0) {  /* Obtained lock */
8429 +        return 1;
8430 +    } else {                /* Other error */
8431 +        apc_eprint("unable to obtain pthread trylock");
8432 +        return 0;
8433 +    }
8434 +}
8435 +
8436 +
8437 +#endif
8438 +
8439 +/*
8440 + * Local variables:
8441 + * tab-width: 4
8442 + * c-basic-offset: 4
8443 + * End:
8444 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8445 + * vim<600: expandtab sw=4 ts=4 sts=4
8446 + */
8447 diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthreadmutex.h
8448 --- php-5.2.5-orig/ext/apc/apc_pthreadmutex.h   1969-12-31 18:00:00.000000000 -0600
8449 +++ php-5.2.5/ext/apc/apc_pthreadmutex.h        2007-12-26 16:51:32.000000000 -0600
8450 @@ -0,0 +1,48 @@
8451 +/*
8452 +  +----------------------------------------------------------------------+
8453 +  | APC                                                                  |
8454 +  +----------------------------------------------------------------------+
8455 +  | Copyright (c) 2006 The PHP Group                                     |
8456 +  +----------------------------------------------------------------------+
8457 +  | This source file is subject to version 3.01 of the PHP license,      |
8458 +  | that is bundled with this package in the file LICENSE, and is        |
8459 +  | available through the world-wide-web at the following url:           |
8460 +  | http://www.php.net/license/3_01.txt                                  |
8461 +  | If you did not receive a copy of the PHP license and are unable to   |
8462 +  | obtain it through the world-wide-web, please send a note to          |
8463 +  | license@php.net so we can mail you a copy immediately.               |
8464 +  +----------------------------------------------------------------------+
8465 +  | Authors: Brian Shire <shire@php.net>                                 |
8466 +  +----------------------------------------------------------------------+
8467 +
8468 + */
8469 +
8470 +/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
8471 +
8472 +#ifndef APC_PTHREADMUTEX_H
8473 +#define APC_PTHREADMUTEX_H
8474 +
8475 +#include "apc.h"
8476 +
8477 +#ifdef APC_PTHREADMUTEX_LOCKS 
8478 +
8479 +#include <pthread.h>
8480 +
8481 +pthread_mutex_t *apc_pthreadmutex_create();
8482 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
8483 +void apc_pthreadmutex_lock(pthread_mutex_t *lock);
8484 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
8485 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
8486 +
8487 +#endif
8488 +
8489 +#endif
8490 +
8491 +/*
8492 + * Local variables:
8493 + * tab-width: 4
8494 + * c-basic-offset: 4
8495 + * End:
8496 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8497 + * vim<600: expandtab sw=4 ts=4 sts=4
8498 + */
8499 diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
8500 --- php-5.2.5-orig/ext/apc/apc_rfc1867.c        1969-12-31 18:00:00.000000000 -0600
8501 +++ php-5.2.5/ext/apc/apc_rfc1867.c     2007-12-26 16:51:32.000000000 -0600
8502 @@ -0,0 +1,195 @@
8503 +/*
8504 +  +----------------------------------------------------------------------+
8505 +  | APC                                                                  |
8506 +  +----------------------------------------------------------------------+
8507 +  | Copyright (c) 2006 The PHP Group                                     |
8508 +  +----------------------------------------------------------------------+
8509 +  | This source file is subject to version 3.01 of the PHP license,      |
8510 +  | that is bundled with this package in the file LICENSE, and is        |
8511 +  | available through the world-wide-web at the following url:           |
8512 +  | http://www.php.net/license/3_01.txt                                  |
8513 +  | If you did not receive a copy of the PHP license and are unable to   |
8514 +  | obtain it through the world-wide-web, please send a note to          |
8515 +  | license@php.net so we can mail you a copy immediately.               |
8516 +  +----------------------------------------------------------------------+
8517 +  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
8518 +  +----------------------------------------------------------------------+
8519 +
8520 +   This software was contributed to PHP by Community Connect Inc. in 2002
8521 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8522 +   Future revisions and derivatives of this source code must acknowledge
8523 +   Community Connect Inc. as the original contributor of this module by
8524 +   leaving this note intact in the source code.
8525 +
8526 +   All other licensing and usage conditions are those of the PHP Group.
8527 +
8528 + */
8529 +
8530 +/* $Id: apc_rfc1867.c,v 3.12 2007/10/18 20:37:20 rasmus Exp $*/
8531 +
8532 +#include "apc.h"
8533 +#include "apc_globals.h"
8534 +#include "rfc1867.h"
8535 +
8536 +#ifdef PHP_WIN32
8537 +#include "win32/time.h"
8538 +#endif
8539 +
8540 +#ifdef MULTIPART_EVENT_FORMDATA
8541 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8542 +
8543 +static double my_time() {
8544 +    struct timeval a;
8545 +    double t;
8546 +    gettimeofday(&a, NULL);
8547 +    t = a.tv_sec + (a.tv_usec/1000000.00);
8548 +    return t;
8549 +}
8550 +
8551 +void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
8552 +    static char tracking_key[64];
8553 +    static int  key_length = 0;
8554 +    static size_t content_length = 0;
8555 +    static char filename[128];
8556 +    static char name[64];
8557 +    static char *temp_filename=NULL;
8558 +    static int cancel_upload = 0;
8559 +    static double start_time;
8560 +    static size_t bytes_processed = 0;
8561 +    static size_t prev_bytes_processed = 0;
8562 +    static int update_freq = 0;
8563 +    static double rate;
8564 +    zval *track = NULL;
8565 +
8566 +       switch (event) {
8567 +               case MULTIPART_EVENT_START:
8568 +                       {
8569 +                multipart_event_start *data = (multipart_event_start *) event_data;
8570 +                content_length = data->content_length;
8571 +                *tracking_key = '\0';
8572 +                *name = '\0';
8573 +                cancel_upload = 0;
8574 +                temp_filename = NULL;
8575 +                *filename= '\0';
8576 +                key_length = 0;
8577 +                start_time = my_time();
8578 +                bytes_processed = 0;
8579 +                rate = 0;
8580 +                update_freq = APCG(rfc1867_freq);
8581 +                if(update_freq < 0) {  // frequency is a percentage, not bytes
8582 +                    update_freq = content_length * APCG(rfc1867_freq) / 100; 
8583 +                }
8584 +                       }
8585 +                       break;
8586 +
8587 +               case MULTIPART_EVENT_FORMDATA:
8588 +                       {
8589 +                int prefix_len = strlen(APCG(rfc1867_prefix));
8590 +                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
8591 +                               if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) && data->value && data->length && data->length < sizeof(tracking_key) - prefix_len) {
8592 +                    strlcat(tracking_key, APCG(rfc1867_prefix), 63);
8593 +                    strlcat(tracking_key, *data->value, 63);
8594 +                    key_length = data->length + prefix_len;
8595 +                    bytes_processed = data->post_bytes_processed;
8596 +                               }
8597 +                       }
8598 +                       break;
8599 +
8600 +               case MULTIPART_EVENT_FILE_START:
8601 +            if(*tracking_key) {
8602 +                multipart_event_file_start *data = (multipart_event_file_start *) event_data;
8603 +
8604 +                bytes_processed = data->post_bytes_processed;
8605 +                strncpy(filename,*data->filename,127);
8606 +                temp_filename = NULL;
8607 +                strncpy(name,data->name,63);
8608 +                ALLOC_INIT_ZVAL(track);
8609 +                array_init(track);
8610 +                add_assoc_long(track, "total", content_length);
8611 +                add_assoc_long(track, "current", bytes_processed);
8612 +                add_assoc_string(track, "filename", filename, 1);
8613 +                add_assoc_string(track, "name", name, 1);
8614 +                add_assoc_long(track, "done", 0);
8615 +                add_assoc_double(track, "start_time", start_time);
8616 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8617 +                zval_ptr_dtor(&track);
8618 +            }
8619 +            break;
8620 +
8621 +               case MULTIPART_EVENT_FILE_DATA:
8622 +            if(*tracking_key) {
8623 +                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
8624 +                bytes_processed = data->post_bytes_processed;
8625 +                ALLOC_INIT_ZVAL(track);
8626 +                array_init(track);
8627 +                add_assoc_long(track, "total", content_length);
8628 +                add_assoc_long(track, "current", bytes_processed);
8629 +                add_assoc_string(track, "filename", filename, 1);
8630 +                add_assoc_string(track, "name", name, 1);
8631 +                add_assoc_long(track, "done", 0);
8632 +                add_assoc_double(track, "start_time", start_time);
8633 +                if(bytes_processed - prev_bytes_processed > update_freq) {
8634 +                    _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8635 +                    prev_bytes_processed = bytes_processed;
8636 +                }
8637 +                zval_ptr_dtor(&track);
8638 +                       }
8639 +                       break;
8640 +
8641 +               case MULTIPART_EVENT_FILE_END:
8642 +            if(*tracking_key) {
8643 +                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
8644 +                bytes_processed = data->post_bytes_processed;
8645 +                cancel_upload = data->cancel_upload;
8646 +                temp_filename = data->temp_filename;
8647 +                ALLOC_INIT_ZVAL(track);
8648 +                array_init(track);
8649 +                add_assoc_long(track, "total", content_length);
8650 +                add_assoc_long(track, "current", bytes_processed);
8651 +                add_assoc_string(track, "filename", filename, 1);
8652 +                add_assoc_string(track, "name", name, 1);
8653 +                add_assoc_string(track, "temp_filename", temp_filename, 1);
8654 +                add_assoc_long(track, "cancel_upload", cancel_upload);
8655 +                add_assoc_long(track, "done", 0);
8656 +                add_assoc_double(track, "start_time", start_time);
8657 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8658 +                zval_ptr_dtor(&track);
8659 +                       }
8660 +                       break;
8661 +
8662 +               case MULTIPART_EVENT_END:
8663 +            if(*tracking_key) {
8664 +                double now = my_time(); 
8665 +                multipart_event_end *data = (multipart_event_end *) event_data;
8666 +                bytes_processed = data->post_bytes_processed;
8667 +                if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
8668 +                else rate = 8.0*bytes_processed;  /* Too quick */
8669 +                ALLOC_INIT_ZVAL(track);
8670 +                array_init(track);
8671 +                add_assoc_long(track, "total", content_length);
8672 +                add_assoc_long(track, "current", bytes_processed);
8673 +                add_assoc_double(track, "rate", rate);
8674 +                add_assoc_string(track, "filename", filename, 1);
8675 +                add_assoc_string(track, "name", name, 1);
8676 +                if(temp_filename) {
8677 +                    add_assoc_string(track, "temp_filename", temp_filename, 1);
8678 +                }
8679 +                add_assoc_long(track, "cancel_upload", cancel_upload);
8680 +                add_assoc_long(track, "done", 1);
8681 +                add_assoc_double(track, "start_time", start_time);
8682 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8683 +                zval_ptr_dtor(&track);
8684 +                       }
8685 +                       break;
8686 +       }
8687 +}
8688 +
8689 +#endif
8690 +/*
8691 + * Local variables:
8692 + * tab-width: 4
8693 + * c-basic-offset: 4
8694 + * End:
8695 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8696 + * vim<600: expandtab sw=4 ts=4 sts=4
8697 + */
8698 diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.c php-5.2.5/ext/apc/apc_sem.c
8699 --- php-5.2.5-orig/ext/apc/apc_sem.c    1969-12-31 18:00:00.000000000 -0600
8700 +++ php-5.2.5/ext/apc/apc_sem.c 2007-12-26 16:51:32.000000000 -0600
8701 @@ -0,0 +1,177 @@
8702 +/*
8703 +  +----------------------------------------------------------------------+
8704 +  | APC                                                                  |
8705 +  +----------------------------------------------------------------------+
8706 +  | Copyright (c) 2006 The PHP Group                                     |
8707 +  +----------------------------------------------------------------------+
8708 +  | This source file is subject to version 3.01 of the PHP license,      |
8709 +  | that is bundled with this package in the file LICENSE, and is        |
8710 +  | available through the world-wide-web at the following url:           |
8711 +  | http://www.php.net/license/3_01.txt                                  |
8712 +  | If you did not receive a copy of the PHP license and are unable to   |
8713 +  | obtain it through the world-wide-web, please send a note to          |
8714 +  | license@php.net so we can mail you a copy immediately.               |
8715 +  +----------------------------------------------------------------------+
8716 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8717 +  +----------------------------------------------------------------------+
8718 +
8719 +   This software was contributed to PHP by Community Connect Inc. in 2002
8720 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8721 +   Future revisions and derivatives of this source code must acknowledge
8722 +   Community Connect Inc. as the original contributor of this module by
8723 +   leaving this note intact in the source code.
8724 +
8725 +   All other licensing and usage conditions are those of the PHP Group.
8726 +
8727 + */
8728 +
8729 +/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
8730 +
8731 +#include "apc_sem.h"
8732 +#include "apc.h"
8733 +#include "php.h"
8734 +#include <sys/types.h>
8735 +#include <sys/ipc.h>
8736 +#include <sys/sem.h>
8737 +#include <sys/stat.h>
8738 +#include <unistd.h>
8739 +
8740 +#if HAVE_SEMUN
8741 +/* we have semun, no need to define */
8742 +#else
8743 +#undef HAVE_SEMUN
8744 +union semun {
8745 +    int val;                  /* value for SETVAL */
8746 +    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
8747 +    unsigned short *array;    /* array for GETALL, SETALL */
8748 +                              /* Linux specific part: */
8749 +    struct seminfo *__buf;    /* buffer for IPC_INFO */
8750 +};
8751 +#define HAVE_SEMUN 1
8752 +#endif
8753 +
8754 +#ifndef SEM_R
8755 +# define SEM_R 0444
8756 +#endif
8757 +#ifndef SEM_A
8758 +# define SEM_A 0222
8759 +#endif
8760 +
8761 +/* always use SEM_UNDO, otherwise we risk deadlock */
8762 +#define USE_SEM_UNDO
8763 +
8764 +#ifdef USE_SEM_UNDO
8765 +# define UNDO SEM_UNDO
8766 +#else
8767 +# define UNDO 0
8768 +#endif
8769 +
8770 +int apc_sem_create(const char* pathname, int proj, int initval)
8771 +{
8772 +    int semid;
8773 +    int perms;
8774 +    union semun arg;
8775 +    key_t key;
8776 +
8777 +    perms = 0777;
8778 +
8779 +    key = IPC_PRIVATE;
8780 +    if (pathname != NULL) {
8781 +        if ((key = ftok(pathname, proj)) < 0) {
8782 +            apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
8783 +        }
8784 +    }
8785 +    
8786 +    if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
8787 +        /* sempahore created for the first time, initialize now */
8788 +        arg.val = initval;
8789 +        if (semctl(semid, 0, SETVAL, arg) < 0) {
8790 +            apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
8791 +        }
8792 +    }
8793 +    else if (errno == EEXIST) {
8794 +        /* sempahore already exists, don't initialize */
8795 +        if ((semid = semget(key, 1, perms)) < 0) {
8796 +            apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8797 +        }
8798 +        /* insert <sleazy way to avoid race condition> here */
8799 +    }
8800 +    else {
8801 +        apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8802 +    }
8803 +
8804 +    return semid;
8805 +}
8806 +
8807 +void apc_sem_destroy(int semid)
8808 +{
8809 +    /* we expect this call to fail often, so we do not check */
8810 +    union semun arg;
8811 +    semctl(semid, 0, IPC_RMID, arg);
8812 +}
8813 +
8814 +void apc_sem_lock(int semid)
8815 +{
8816 +    struct sembuf op;
8817 +
8818 +    op.sem_num = 0;
8819 +    op.sem_op  = -1;
8820 +    op.sem_flg = UNDO;
8821 +
8822 +    if (semop(semid, &op, 1) < 0) {
8823 +        if (errno != EINTR) {
8824 +            apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
8825 +        }
8826 +    }
8827 +}
8828 +
8829 +void apc_sem_unlock(int semid)
8830 +{
8831 +    struct sembuf op;
8832 +
8833 +    op.sem_num = 0;
8834 +    op.sem_op  = 1;
8835 +    op.sem_flg = UNDO;
8836 +
8837 +    if (semop(semid, &op, 1) < 0) {
8838 +        if (errno != EINTR) {
8839 +            apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
8840 +        }
8841 +    }
8842 +}
8843 +
8844 +void apc_sem_wait_for_zero(int semid)
8845 +{
8846 +    struct sembuf op;
8847 +
8848 +    op.sem_num = 0;
8849 +    op.sem_op  = 0;
8850 +    op.sem_flg = UNDO;
8851 +
8852 +    if (semop(semid, &op, 1) < 0) {
8853 +        if (errno != EINTR) {
8854 +            apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
8855 +        }
8856 +    }
8857 +}
8858 +
8859 +int apc_sem_get_value(int semid)
8860 +{
8861 +    union semun arg;
8862 +    unsigned short val[1];
8863 +
8864 +    arg.array = val;
8865 +    if (semctl(semid, 0, GETALL, arg) < 0) {
8866 +        apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
8867 +    }
8868 +    return val[0];
8869 +}
8870 +
8871 +/*
8872 + * Local variables:
8873 + * tab-width: 4
8874 + * c-basic-offset: 4
8875 + * End:
8876 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8877 + * vim<600: expandtab sw=4 ts=4 sts=4
8878 + */
8879 diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.h php-5.2.5/ext/apc/apc_sem.h
8880 --- php-5.2.5-orig/ext/apc/apc_sem.h    1969-12-31 18:00:00.000000000 -0600
8881 +++ php-5.2.5/ext/apc/apc_sem.h 2007-12-26 16:51:32.000000000 -0600
8882 @@ -0,0 +1,51 @@
8883 +/*
8884 +  +----------------------------------------------------------------------+
8885 +  | APC                                                                  |
8886 +  +----------------------------------------------------------------------+
8887 +  | Copyright (c) 2006 The PHP Group                                     |
8888 +  +----------------------------------------------------------------------+
8889 +  | This source file is subject to version 3.01 of the PHP license,      |
8890 +  | that is bundled with this package in the file LICENSE, and is        |
8891 +  | available through the world-wide-web at the following url:           |
8892 +  | http://www.php.net/license/3_01.txt                                  |
8893 +  | If you did not receive a copy of the PHP license and are unable to   |
8894 +  | obtain it through the world-wide-web, please send a note to          |
8895 +  | license@php.net so we can mail you a copy immediately.               |
8896 +  +----------------------------------------------------------------------+
8897 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8898 +  +----------------------------------------------------------------------+
8899 +
8900 +   This software was contributed to PHP by Community Connect Inc. in 2002
8901 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8902 +   Future revisions and derivatives of this source code must acknowledge
8903 +   Community Connect Inc. as the original contributor of this module by
8904 +   leaving this note intact in the source code.
8905 +
8906 +   All other licensing and usage conditions are those of the PHP Group.
8907 +
8908 + */
8909 +
8910 +/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8911 +
8912 +#ifndef APC_SEM_H
8913 +#define APC_SEM_H
8914 +
8915 +/* Wrapper functions for SysV sempahores */
8916 +
8917 +extern int apc_sem_create(const char* pathname, int proj, int initval);
8918 +extern void apc_sem_destroy(int semid);
8919 +extern void apc_sem_lock(int semid);
8920 +extern void apc_sem_unlock(int semid);
8921 +extern void apc_sem_wait_for_zero(int semid);
8922 +extern int apc_sem_get_value(int semid);
8923 +
8924 +#endif
8925 +
8926 +/*
8927 + * Local variables:
8928 + * tab-width: 4
8929 + * c-basic-offset: 4
8930 + * End:
8931 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8932 + * vim<600: expandtab sw=4 ts=4 sts=4
8933 + */
8934 diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.c php-5.2.5/ext/apc/apc_shm.c
8935 --- php-5.2.5-orig/ext/apc/apc_shm.c    1969-12-31 18:00:00.000000000 -0600
8936 +++ php-5.2.5/ext/apc/apc_shm.c 2007-12-26 16:51:32.000000000 -0600
8937 @@ -0,0 +1,110 @@
8938 +/*
8939 +  +----------------------------------------------------------------------+
8940 +  | APC                                                                  |
8941 +  +----------------------------------------------------------------------+
8942 +  | Copyright (c) 2006 The PHP Group                                     |
8943 +  +----------------------------------------------------------------------+
8944 +  | This source file is subject to version 3.01 of the PHP license,      |
8945 +  | that is bundled with this package in the file LICENSE, and is        |
8946 +  | available through the world-wide-web at the following url:           |
8947 +  | http://www.php.net/license/3_01.txt                                  |
8948 +  | If you did not receive a copy of the PHP license and are unable to   |
8949 +  | obtain it through the world-wide-web, please send a note to          |
8950 +  | license@php.net so we can mail you a copy immediately.               |
8951 +  +----------------------------------------------------------------------+
8952 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8953 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
8954 +  +----------------------------------------------------------------------+
8955 +
8956 +   This software was contributed to PHP by Community Connect Inc. in 2002
8957 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8958 +   Future revisions and derivatives of this source code must acknowledge
8959 +   Community Connect Inc. as the original contributor of this module by
8960 +   leaving this note intact in the source code.
8961 +
8962 +   All other licensing and usage conditions are those of the PHP Group.
8963 +
8964 + */
8965 +
8966 +/* $Id: apc_shm.c,v 3.11 2007/05/09 22:15:33 shire Exp $ */
8967 +
8968 +#include "apc_shm.h"
8969 +#include "apc.h"
8970 +#ifdef PHP_WIN32
8971 +/* shm functions are available in TSRM */
8972 +#include <tsrm/tsrm_win32.h>
8973 +#define key_t long
8974 +#else
8975 +#include <sys/ipc.h>
8976 +#include <sys/shm.h>
8977 +#include <sys/stat.h>
8978 +#endif
8979 +
8980 +#ifndef SHM_R
8981 +# define SHM_R 0444 /* read permission */
8982 +#endif
8983 +#ifndef SHM_A
8984 +# define SHM_A 0222 /* write permission */
8985 +#endif
8986 +
8987 +int apc_shm_create(const char* pathname, int proj, size_t size)
8988 +{
8989 +    int shmid;  /* shared memory id */
8990 +    int oflag;  /* permissions on shm */
8991 +    key_t key;  /* shm key returned by ftok */
8992 +
8993 +    key = IPC_PRIVATE;
8994 +#ifndef PHP_WIN32
8995 +       /* no ftok yet for win32 */
8996 +    if (pathname != NULL) {
8997 +        if ((key = ftok(pathname, proj)) < 0) {
8998 +            apc_eprint("apc_shm_create: ftok failed:");
8999 +        }
9000 +    }
9001 +#endif
9002 +
9003 +    oflag = IPC_CREAT | SHM_R | SHM_A;
9004 +    if ((shmid = shmget(key, size, oflag)) < 0) {
9005 +        apc_eprint("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.", key, size, oflag, strerror(errno));
9006 +    }
9007 +
9008 +    return shmid;
9009 +}
9010 +
9011 +void apc_shm_destroy(int shmid)
9012 +{
9013 +    /* we expect this call to fail often, so we do not check */
9014 +    shmctl(shmid, IPC_RMID, 0);
9015 +}
9016 +
9017 +void* apc_shm_attach(int shmid)
9018 +{
9019 +    void* shmaddr;  /* the shared memory address */
9020 +
9021 +    if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
9022 +        apc_eprint("apc_shm_attach: shmat failed:");
9023 +    }
9024 +
9025 +    /*
9026 +     * We set the shmid for removal immediately after attaching to it. The
9027 +     * segment won't disappear until all processes have detached from it.
9028 +     */
9029 +    apc_shm_destroy(shmid);
9030 +    return shmaddr;
9031 +}
9032 +
9033 +void apc_shm_detach(void* shmaddr)
9034 +{
9035 +    if (shmdt(shmaddr) < 0) {
9036 +        apc_eprint("apc_shm_detach: shmdt failed:");
9037 +    }
9038 +}
9039 +
9040 +/*
9041 + * Local variables:
9042 + * tab-width: 4
9043 + * c-basic-offset: 4
9044 + * End:
9045 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9046 + * vim<600: expandtab sw=4 ts=4 sts=4
9047 + */
9048 diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.h php-5.2.5/ext/apc/apc_shm.h
9049 --- php-5.2.5-orig/ext/apc/apc_shm.h    1969-12-31 18:00:00.000000000 -0600
9050 +++ php-5.2.5/ext/apc/apc_shm.h 2007-12-26 16:51:32.000000000 -0600
9051 @@ -0,0 +1,54 @@
9052 +/*
9053 +  +----------------------------------------------------------------------+
9054 +  | APC                                                                  |
9055 +  +----------------------------------------------------------------------+
9056 +  | Copyright (c) 2006 The PHP Group                                     |
9057 +  +----------------------------------------------------------------------+
9058 +  | This source file is subject to version 3.01 of the PHP license,      |
9059 +  | that is bundled with this package in the file LICENSE, and is        |
9060 +  | available through the world-wide-web at the following url:           |
9061 +  | http://www.php.net/license/3_01.txt                                  |
9062 +  | If you did not receive a copy of the PHP license and are unable to   |
9063 +  | obtain it through the world-wide-web, please send a note to          |
9064 +  | license@php.net so we can mail you a copy immediately.               |
9065 +  +----------------------------------------------------------------------+
9066 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9067 +  +----------------------------------------------------------------------+
9068 +
9069 +   This software was contributed to PHP by Community Connect Inc. in 2002
9070 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9071 +   Future revisions and derivatives of this source code must acknowledge
9072 +   Community Connect Inc. as the original contributor of this module by
9073 +   leaving this note intact in the source code.
9074 +
9075 +   All other licensing and usage conditions are those of the PHP Group.
9076 +
9077 + */
9078 +
9079 +/* $Id: apc_shm.h,v 3.8 2007/05/23 01:23:21 auroraeosrose Exp $ */
9080 +
9081 +#ifndef APC_SHM_H
9082 +#define APC_SHM_H
9083 +
9084 +#include <sys/types.h>
9085 +#ifdef PHP_WIN32
9086 +#include <time.h>
9087 +#endif
9088 +
9089 +/* Wrapper functions for unix shared memory */
9090 +
9091 +extern int apc_shm_create(const char* name, int proj, size_t size);
9092 +extern void apc_shm_destroy(int shmid);
9093 +extern void* apc_shm_attach(int shmid);
9094 +extern void apc_shm_detach(void* shmaddr);
9095 +
9096 +#endif
9097 +
9098 +/*
9099 + * Local variables:
9100 + * tab-width: 4
9101 + * c-basic-offset: 4
9102 + * End:
9103 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9104 + * vim<600: expandtab sw=4 ts=4 sts=4
9105 + */
9106 diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.c php-5.2.5/ext/apc/apc_signal.c
9107 --- php-5.2.5-orig/ext/apc/apc_signal.c 1969-12-31 18:00:00.000000000 -0600
9108 +++ php-5.2.5/ext/apc/apc_signal.c      2007-12-26 16:51:32.000000000 -0600
9109 @@ -0,0 +1,178 @@
9110 +/*
9111 +  +----------------------------------------------------------------------+
9112 +  | APC                                                                  |
9113 +  +----------------------------------------------------------------------+
9114 +  | Copyright (c) 2006 The PHP Group                                     |
9115 +  +----------------------------------------------------------------------+
9116 +  | This source file is subject to version 3.01 of the PHP license,      |
9117 +  | that is bundled with this package in the file LICENSE, and is        |
9118 +  | available through the world-wide-web at the following url:           |
9119 +  | http://www.php.net/license/3_01.txt                                  |
9120 +  | If you did not receive a copy of the PHP license and are unable to   |
9121 +  | obtain it through the world-wide-web, please send a note to          |
9122 +  | license@php.net so we can mail you a copy immediately.               |
9123 +  +----------------------------------------------------------------------+
9124 +  | Authors: Lucas Nealan <lucas@php.net>                                |
9125 +  +----------------------------------------------------------------------+
9126 +
9127 +   This software was contributed to PHP by Facebook Inc. in 2007.
9128 +   
9129 +   Future revisions and derivatives of this source code must acknowledge
9130 +   Facebook Inc. as the original contributor of this module by leaving
9131 +   this note intact in the source code.
9132 +
9133 +   All other licensing and usage conditions are those of the PHP Group.
9134 + */
9135 +
9136 + /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */
9137 +
9138 + /* Allows apc to install signal handlers and maintain signalling
9139 +    to already registered handlers. Registers all signals that
9140 +    coredump by default and unmaps the shared memory segment
9141 +    before the coredump. Note: PHP module init is called before 
9142 +    signals are set by Apache and thus apc_set_signals should
9143 +    be called in request init (RINIT)
9144 +  */
9145 +
9146 +#include <signal.h>
9147 +#include "apc_globals.h"
9148 +#include "apc_sma.h"
9149 +#include "apc_signal.h"
9150 +
9151 +static apc_signal_info_t apc_signal_info = {0};
9152 +
9153 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
9154 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
9155 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
9156 +
9157 +/* {{{ apc_core_unmap 
9158 + *  Coredump signal handler, unmaps shm and calls previously installed handlers 
9159 + */
9160 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) 
9161 +{
9162 +    apc_sma_cleanup();
9163 +    apc_rehandle_signal(signo, siginfo, context);
9164 +
9165 +#if !defined(WIN32) && !defined(NETWARE)
9166 +    kill(getpid(), signo);
9167 +#else
9168 +    raise(signo);
9169 +#endif
9170 +} /* }}} */
9171 +
9172 +/* {{{ apc_rehandle_signal
9173 + *  Call the previously registered handler for a signal
9174 + */
9175 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
9176 +{
9177 +    int i;
9178 +    apc_signal_entry_t p_sig = {0};
9179 +
9180 +    for (i=0;  (i < apc_signal_info.installed && p_sig.signo != signo);  i++) {
9181 +        p_sig = *apc_signal_info.prev[i];
9182 +        if (p_sig.signo == signo) {
9183 +            if (p_sig.siginfo) {
9184 +                (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
9185 +            } else {
9186 +                (*(void (*)(int))p_sig.handler)(signo);
9187 +            }
9188 +        }
9189 +    }
9190 +
9191 +} /* }}} */
9192 +
9193 +/* {{{ apc_register_signal
9194 + *  Set a handler for a previously installed signal and save so we can 
9195 + *  callback when handled 
9196 + */
9197 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
9198 +{
9199 +#if HAVE_SIGACTION
9200 +    struct sigaction sa = {0};
9201 +    apc_signal_entry_t p_sig = {0};
9202 +
9203 +    if (sigaction(signo, NULL, &sa) == 0) {
9204 +        if ((void*)sa.sa_handler == (void*)handler) {
9205 +            return SUCCESS;
9206 +        }
9207 +
9208 +        if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
9209 +            p_sig.signo = signo;
9210 +            p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
9211 +            p_sig.handler = (void *)sa.sa_handler;
9212 +           
9213 +            apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
9214 +            apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
9215 +            *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
9216 +        } else {
9217 +            /* inherit flags and mask if already set */
9218 +            sigemptyset(&sa.sa_mask);
9219 +            sa.sa_flags = 0;
9220 +            sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
9221 +#if defined(SA_ONESHOT)
9222 +            sa.sa_flags = SA_ONESHOT;
9223 +#elif defined(SA_RESETHAND)
9224 +            sa.sa_flags = SA_RESETHAND;
9225 +#endif
9226 +        }
9227 +        sa.sa_handler = (void*)handler;
9228 +
9229 +        if (sigaction(signo, &sa, NULL) < 0) {
9230 +            apc_wprint("Error installing apc signal handler for %d", signo);
9231 +        }
9232 +
9233 +        return SUCCESS;
9234 +    }
9235 +#endif
9236 +    return FAILURE;
9237 +} /* }}} */
9238 +
9239 +/* {{{ apc_set_signals
9240 + *  Install our signal handlers */
9241 +void apc_set_signals(TSRMLS_D) 
9242 +{
9243 +    if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
9244 +        /* ISO C standard signals that coredump */
9245 +        apc_register_signal(SIGSEGV, apc_core_unmap);
9246 +        apc_register_signal(SIGABRT, apc_core_unmap);
9247 +        apc_register_signal(SIGFPE, apc_core_unmap);
9248 +        apc_register_signal(SIGILL, apc_core_unmap);
9249 +        /* extended signals that coredump */
9250 +#ifdef SIGBUS
9251 +        apc_register_signal(SIGBUS, apc_core_unmap);
9252 +#endif
9253 +#ifdef SIGABORT
9254 +        apc_register_signal(SIGABORT, apc_core_unmap);
9255 +#endif
9256 +#ifdef SIGEMT
9257 +        apc_register_signal(SIGEMT, apc_core_unmap);
9258 +#endif
9259 +#ifdef SIGIOT
9260 +        apc_register_signal(SIGIOT, apc_core_unmap);
9261 +#endif
9262 +#ifdef SIGQUIT
9263 +        apc_register_signal(SIGQUIT, apc_core_unmap);
9264 +#endif
9265 +#ifdef SIGSYS
9266 +        apc_register_signal(SIGSYS, apc_core_unmap);
9267 +#endif
9268 +#ifdef SIGTRAP
9269 +        apc_register_signal(SIGTRAP, apc_core_unmap);
9270 +#endif
9271 +#ifdef SIGXCPU
9272 +        apc_register_signal(SIGXCPU, apc_core_unmap);
9273 +#endif
9274 +#ifdef SIGXFSZ
9275 +        apc_register_signal(SIGXFSZ, apc_core_unmap);
9276 +#endif
9277 +    }
9278 +} /* }}} */
9279 +
9280 +/*
9281 + * Local variables:
9282 + * tab-width: 4
9283 + * c-basic-offset: 4
9284 + * End:
9285 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9286 + * vim<600: expandtab sw=4 ts=4 sts=4
9287 + */
9288 diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.h php-5.2.5/ext/apc/apc_signal.h
9289 --- php-5.2.5-orig/ext/apc/apc_signal.h 1969-12-31 18:00:00.000000000 -0600
9290 +++ php-5.2.5/ext/apc/apc_signal.h      2007-12-26 16:51:32.000000000 -0600
9291 @@ -0,0 +1,50 @@
9292 +/*
9293 +  +----------------------------------------------------------------------+
9294 +  | APC                                                                  |
9295 +  +----------------------------------------------------------------------+
9296 +  | Copyright (c) 2006 The PHP Group                                     |
9297 +  +----------------------------------------------------------------------+
9298 +  | This source file is subject to version 3.01 of the PHP license,      |
9299 +  | that is bundled with this package in the file LICENSE, and is        |
9300 +  | available through the world-wide-web at the following url:           |
9301 +  | http://www.php.net/license/3_01.txt                                  |
9302 +  | If you did not receive a copy of the PHP license and are unable to   |
9303 +  | obtain it through the world-wide-web, please send a note to          |
9304 +  | license@php.net so we can mail you a copy immediately.               |
9305 +  +----------------------------------------------------------------------+
9306 +  | Authors: Lucas Nealan <lucas@php.net>                                |
9307 +  +----------------------------------------------------------------------+
9308 +
9309 + */
9310 +
9311 +/* $Id: apc_signal.h,v 1.1 2007/12/26 22:36:06 rasmus Exp $ */
9312 +
9313 +#ifndef APC_SIGNAL_H
9314 +#define APC_SIGNAL_H
9315 +
9316 +#include "apc.h"
9317 +#include "apc_php.h"
9318 +
9319 +typedef struct apc_signal_entry_t {
9320 +    int signo;          /* signal number */
9321 +    int siginfo;        /* siginfo style handler calling */
9322 +    void* handler;      /* signal handler */
9323 +} apc_signal_entry_t;
9324 +
9325 +typedef struct apc_signal_info_t {
9326 +    int installed;                  /* How many signals we've installed handles for */
9327 +    apc_signal_entry_t **prev;      /* Previous signal handlers */
9328 +} apc_signal_info_t;
9329 +
9330 +void apc_set_signals(TSRMLS_D);
9331 +
9332 +#endif
9333 +
9334 +/*
9335 + * Local variables:
9336 + * tab-width: 4
9337 + * c-basic-offset: 4
9338 + * End:
9339 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9340 + * vim<600: expandtab sw=4 ts=4 sts=4
9341 + */
9342 diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.c php-5.2.5/ext/apc/apc_sma.c
9343 --- php-5.2.5-orig/ext/apc/apc_sma.c    1969-12-31 18:00:00.000000000 -0600
9344 +++ php-5.2.5/ext/apc/apc_sma.c 2007-12-26 16:51:32.000000000 -0600
9345 @@ -0,0 +1,628 @@
9346 +/*
9347 +  +----------------------------------------------------------------------+
9348 +  | APC                                                                  |
9349 +  +----------------------------------------------------------------------+
9350 +  | Copyright (c) 2006 The PHP Group                                     |
9351 +  +----------------------------------------------------------------------+
9352 +  | This source file is subject to version 3.01 of the PHP license,      |
9353 +  | that is bundled with this package in the file LICENSE, and is        |
9354 +  | available through the world-wide-web at the following url:           |
9355 +  | http://www.php.net/license/3_01.txt                                  |
9356 +  | If you did not receive a copy of the PHP license and are unable to   |
9357 +  | obtain it through the world-wide-web, please send a note to          |
9358 +  | license@php.net so we can mail you a copy immediately.               |
9359 +  +----------------------------------------------------------------------+
9360 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9361 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
9362 +  +----------------------------------------------------------------------+
9363 +
9364 +   This software was contributed to PHP by Community Connect Inc. in 2002
9365 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9366 +   Future revisions and derivatives of this source code must acknowledge
9367 +   Community Connect Inc. as the original contributor of this module by
9368 +   leaving this note intact in the source code.
9369 +
9370 +   All other licensing and usage conditions are those of the PHP Group.
9371 +
9372 + */
9373 +
9374 +/* $Id: apc_sma.c,v 1.69 2007/12/26 21:35:39 gopalv Exp $ */
9375 +
9376 +#include "apc_sma.h"
9377 +#include "apc.h"
9378 +#include "apc_globals.h"
9379 +#include "apc_lock.h"
9380 +#include "apc_shm.h"
9381 +#include <limits.h>
9382 +#if APC_MMAP
9383 +void *apc_mmap(char *file_mask, size_t size);
9384 +void apc_unmap(void* shmaddr, size_t size);
9385 +#endif
9386 +
9387 +/* {{{ locking macros */
9388 +#define LOCK(c)         { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
9389 +#define RDLOCK(c)       { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
9390 +#define UNLOCK(c)       { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
9391 +/* }}} */
9392 +
9393 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
9394 +
9395 +static int sma_initialized = 0;     /* true if the sma has been initialized */
9396 +static unsigned int sma_numseg;     /* number of shm segments to allow */
9397 +static size_t sma_segsize;          /* size of each shm segment */
9398 +static size_t* sma_segments;        /* array of shm segment ids */
9399 +static void** sma_shmaddrs;         /* array of shm segment addresses */
9400 +static int sma_lastseg = 0;         /* index of MRU segment */
9401 +
9402 +typedef struct header_t header_t;
9403 +struct header_t {
9404 +    apc_lck_t sma_lock;     /* segment lock, MUST BE ALIGNED for futex locks */
9405 +    size_t segsize;         /* size of entire segment */
9406 +    size_t avail;           /* bytes available (not necessarily contiguous) */
9407 +    size_t nfoffset;        /* start next fit search from this offset       */
9408 +#if ALLOC_DISTRIBUTION
9409 +    size_t adist[30];
9410 +#endif
9411 +};
9412 +
9413 +
9414 +/* do not enable for threaded http servers */
9415 +/* #define __APC_SMA_DEBUG__ 1 */
9416 +
9417 +#ifdef __APC_SMA_DEBUG__
9418 +/* global counter for identifying blocks 
9419 + * Technically it is possible to do the same
9420 + * using offsets, but double allocations of the
9421 + * same offset can happen. */
9422 +static volatile size_t block_id = 0;
9423 +#endif
9424 +
9425 +#define APC_SMA_CANARIES 1   
9426 +
9427 +typedef struct block_t block_t;
9428 +struct block_t {
9429 +    size_t size;       /* size of this block */
9430 +    size_t next;       /* offset in segment of next free block */
9431 +#ifdef APC_SMA_CANARIES
9432 +    size_t canary;     /* canary to check for memory overwrites */
9433 +#endif
9434 +#ifdef __APC_SMA_DEBUG__
9435 +    size_t id;         /* identifier for the memory block */ 
9436 +#endif
9437 +};
9438 +
9439 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
9440 + * module. Both assume the presence of a variable shmaddr that points to the
9441 + * beginning of the shared memory segment in question. */
9442 +
9443 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
9444 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
9445 +
9446 +/* Canary macros for setting, checking and resetting memory canaries */
9447 +#ifdef APC_SMA_CANARIES
9448 +    #define SET_CANARY(v) (v)->canary = 0x42424242
9449 +    #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
9450 +    #define RESET_CANARY(v) (v)->canary = -42
9451 +#else
9452 +    #define SET_CANARY(v) 
9453 +    #define CHECK_CANARY(v)
9454 +    #define RESET_CANARY(v)
9455 +#endif
9456 +
9457 +
9458 +#ifdef max
9459 +#undef max
9460 +#endif
9461 +#define max(a, b) ((a) > (b) ? (a) : (b))
9462 +
9463 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
9464 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
9465 +#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
9466 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
9467 +/* }}} */
9468 +
9469 +/* {{{ sma_allocate: tries to allocate size bytes in a segment */
9470 +static int sma_allocate(void* shmaddr, size_t size)
9471 +{
9472 +    header_t* header;       /* header of shared memory segment */
9473 +    block_t* prv;           /* block prior to working block */
9474 +    block_t* cur;           /* working block in list */
9475 +    block_t* prvnextfit;    /* block before next fit */
9476 +    size_t realsize;        /* actual size of block needed, including header */
9477 +    size_t last_offset;     /* save the last search offset */
9478 +    int wrapped=0;
9479 +    const size_t block_size = ALIGNWORD(sizeof(struct block_t));
9480 +
9481 +    realsize = ALIGNWORD(size + block_size);
9482 +
9483 +    /*
9484 +     * First, insure that the segment contains at least realsize free bytes,
9485 +     * even if they are not contiguous.
9486 +     */
9487 +    header = (header_t*) shmaddr;
9488 +    if (header->avail < realsize) {
9489 +        return -1;
9490 +    }
9491 +
9492 +    prvnextfit = 0;     /* initially null (no fit) */
9493 +    last_offset = 0;
9494 +
9495 +    /* If we have a next fit offset, start searching from there */
9496 +    if(header->nfoffset) {
9497 +        prv = BLOCKAT(header->nfoffset);
9498 +        /* if prv is the last block, jump to the beginning */
9499 +        if(prv->next == 0) {
9500 +            prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9501 +            wrapped = 1;
9502 +        }
9503 +    } else {    
9504 +        prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9505 +    }
9506 +   
9507 +    CHECK_CANARY(prv);
9508 +
9509 +    while (prv->next != header->nfoffset) {
9510 +        cur = BLOCKAT(prv->next);
9511 +#ifdef __APC_SMA_DEBUG__
9512 +        CHECK_CANARY(cur);
9513 +#endif
9514 +        /* If it can fit realiszie bytes in cur block, stop searching */
9515 +        if (cur->size >= realsize) {
9516 +            prvnextfit = prv;
9517 +            break;
9518 +        }
9519 +        last_offset = prv->next;
9520 +        prv = cur;
9521 +        if(wrapped && (prv->next >= header->nfoffset)) break;
9522 +
9523 +        /* Check to see if we need to wrap around and search from the top */
9524 +        if(header->nfoffset && prv->next == 0) {
9525 +            prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9526 +#ifdef __APC_SMA_DEBUG__
9527 +            CHECK_CANARY(prv);
9528 +#endif
9529 +            last_offset = 0;
9530 +            wrapped = 1;
9531 +        } 
9532 +    }
9533 +
9534 +    if (prvnextfit == 0) {
9535 +        header->nfoffset = 0;
9536 +        return -1;
9537 +    }
9538 +
9539 +    prv = prvnextfit;
9540 +    cur = BLOCKAT(prv->next);
9541 +
9542 +    CHECK_CANARY(prv);
9543 +    CHECK_CANARY(cur);
9544 +
9545 +    if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
9546 +        /* cur is big enough for realsize, but too small to split - unlink it */
9547 +        prv->next = cur->next;
9548 +    }
9549 +    else {
9550 +        block_t* nxt;      /* the new block (chopped part of cur) */
9551 +        size_t nxtoffset;  /* offset of the block currently after cur */
9552 +        size_t oldsize;    /* size of cur before split */
9553 +
9554 +        /* nextfit is too big; split it into two smaller blocks */
9555 +        nxtoffset = cur->next;
9556 +        oldsize = cur->size;
9557 +        prv->next += realsize;  /* skip over newly allocated block */
9558 +        cur->size = realsize;   /* Set the size of this new block */
9559 +        nxt = BLOCKAT(prv->next);
9560 +        nxt->next = nxtoffset;  /* Re-link the shortened block */
9561 +        nxt->size = oldsize - realsize;  /* and fix the size */
9562 +        SET_CANARY(nxt);
9563 +#ifdef __APC_SMA_DEBUG__
9564 +        nxt->id = -1;
9565 +#endif
9566 +    }
9567 +
9568 +    /* update the block header */
9569 +    header->avail -= cur->size;
9570 +#if ALLOC_DISTRIBUTION
9571 +    header->adist[(int)(log(size)/log(2))]++;
9572 +#endif
9573 +
9574 +    header->nfoffset = last_offset;
9575 +
9576 +    SET_CANARY(cur);
9577 +#ifdef __APC_SMA_DEBUG__
9578 +    cur->id = ++block_id;
9579 +    fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
9580 +#endif
9581 +
9582 +    return OFFSET(cur) + block_size;
9583 +}
9584 +/* }}} */
9585 +
9586 +/* {{{ sma_deallocate: deallocates the block at the given offset */
9587 +static int sma_deallocate(void* shmaddr, int offset)
9588 +{
9589 +    header_t* header;   /* header of shared memory segment */
9590 +    block_t* cur;       /* the new block to insert */
9591 +    block_t* prv;       /* the block before cur */
9592 +    block_t* nxt;       /* the block after cur */
9593 +    size_t size;        /* size of deallocated block */
9594 +
9595 +    offset -= ALIGNWORD(sizeof(struct block_t));
9596 +    assert(offset >= 0);
9597 +
9598 +    /* find position of new block in free list */
9599 +    cur = BLOCKAT(offset);
9600 +    prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9601 +   
9602 +    CHECK_CANARY(cur);
9603 +
9604 +#ifdef __APC_SMA_DEBUG__
9605 +    CHECK_CANARY(prv);
9606 +    fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
9607 +#endif
9608 +    while (prv->next != 0 && prv->next < offset) {
9609 +        prv = BLOCKAT(prv->next);
9610 +#ifdef __APC_SMA_DEBUG__
9611 +        CHECK_CANARY(prv);
9612 +#endif
9613 +    }
9614 +    
9615 +    CHECK_CANARY(prv);
9616 +
9617 +    /* insert new block after prv */
9618 +    cur->next = prv->next;
9619 +    prv->next = offset;
9620 +
9621 +#ifdef __APC_SMA_DEBUG__
9622 +    CHECK_CANARY(cur);
9623 +    cur->id = -1;
9624 +#endif
9625 +    
9626 +    /* update the block header */
9627 +    header = (header_t*) shmaddr;
9628 +    header->avail += cur->size;
9629 +    size = cur->size;
9630 +
9631 +    if (((char *)prv) + prv->size == (char *) cur) {
9632 +        /* cur and prv share an edge, combine them */
9633 +        prv->size += cur->size;
9634 +        prv->next = cur->next;
9635 +        RESET_CANARY(cur);
9636 +        cur = prv;
9637 +    }
9638 +
9639 +    nxt = BLOCKAT(cur->next);
9640 +
9641 +    if (((char *)cur) + cur->size == (char *) nxt) {
9642 +        /* cur and nxt shared an edge, combine them */
9643 +        cur->size += nxt->size;
9644 +        cur->next = nxt->next;
9645 +#ifdef __APC_SMA_DEBUG__
9646 +        CHECK_CANARY(nxt);
9647 +        nxt->id = -1; /* assert this or set it ? */
9648 +#endif
9649 +        RESET_CANARY(nxt);
9650 +    }
9651 +    header->nfoffset = 0;  /* Reset the next fit search marker */
9652 +
9653 +    return size;
9654 +}
9655 +/* }}} */
9656 +
9657 +/* {{{ apc_sma_init */
9658 +
9659 +void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask)
9660 +{
9661 +    int i;
9662 +
9663 +    if (sma_initialized) {
9664 +        return;
9665 +    }
9666 +    sma_initialized = 1;
9667 +
9668 +#if APC_MMAP
9669 +    /*
9670 +     * I don't think multiple anonymous mmaps makes any sense
9671 +     * so force sma_numseg to 1 in this case
9672 +     */
9673 +    if(!mmap_file_mask || 
9674 +       (mmap_file_mask && !strlen(mmap_file_mask)) ||
9675 +       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
9676 +        sma_numseg = 1;
9677 +    } else {
9678 +        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9679 +    }
9680 +#else
9681 +    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9682 +#endif
9683 +
9684 +    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
9685 +
9686 +    sma_segments = (size_t*) apc_emalloc(sma_numseg*sizeof(size_t));
9687 +    sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
9688 +    
9689 +    for (i = 0; i < sma_numseg; i++) {
9690 +        header_t*   header;
9691 +        block_t*    block;
9692 +        void*       shmaddr;
9693 +
9694 +#if APC_MMAP
9695 +        sma_segments[i] = sma_segsize;
9696 +        sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
9697 +        if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
9698 +#else
9699 +        sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
9700 +        sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
9701 +#endif
9702 +        shmaddr = sma_shmaddrs[i];
9703 +    
9704 +        header = (header_t*) shmaddr;
9705 +        apc_lck_create(NULL, 0, 1, header->sma_lock);
9706 +        header->segsize = sma_segsize;
9707 +        header->avail = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
9708 +        header->nfoffset = 0;
9709 +#if ALLOC_DISTRIBUTION
9710 +               {
9711 +           int j;
9712 +           for(j=0; j<30; j++) header->adist[j] = 0; 
9713 +        }
9714 +#endif 
9715 +        block = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9716 +        block->size = 0;
9717 +        block->next = ALIGNWORD(sizeof(header_t)) + ALIGNWORD(sizeof(block_t));
9718 +        SET_CANARY(block);
9719 +#ifdef __APC_SMA_DEBUG__
9720 +        block->id = -1;
9721 +#endif
9722 +        block = BLOCKAT(block->next);
9723 +        block->size = header->avail;
9724 +        block->next = 0;
9725 +        SET_CANARY(block);
9726 +#ifdef __APC_SMA_DEBUG__
9727 +        block->id = -1;
9728 +#endif
9729 +    }
9730 +}
9731 +/* }}} */
9732 +
9733 +/* {{{ apc_sma_cleanup */
9734 +void apc_sma_cleanup()
9735 +{
9736 +    int i;
9737 +
9738 +    assert(sma_initialized);
9739 +
9740 +    for (i = 0; i < sma_numseg; i++) {
9741 +        apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
9742 +#if APC_MMAP
9743 +        apc_unmap(sma_shmaddrs[i], sma_segments[i]);
9744 +#else
9745 +        apc_shm_detach(sma_shmaddrs[i]);
9746 +#endif
9747 +    }
9748 +    sma_initialized = 0;
9749 +    apc_efree(sma_segments);
9750 +    apc_efree(sma_shmaddrs);
9751 +}
9752 +/* }}} */
9753 +
9754 +/* {{{ apc_sma_malloc */
9755 +void* apc_sma_malloc(size_t n)
9756 +{
9757 +    int off;
9758 +    int i;
9759 +
9760 +    TSRMLS_FETCH();
9761 +    assert(sma_initialized);
9762 +    LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9763 +
9764 +    off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
9765 +    if (off != -1) {
9766 +        void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
9767 +        if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9768 +        UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9769 +        return p;
9770 +    }
9771 +    UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9772 +
9773 +    for (i = 0; i < sma_numseg; i++) {
9774 +        if (i == sma_lastseg) {
9775 +            continue;
9776 +        }
9777 +        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9778 +        off = sma_allocate(sma_shmaddrs[i], n);
9779 +        if (off != -1) {
9780 +            void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
9781 +            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9782 +            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9783 +            sma_lastseg = i;
9784 +            return p;
9785 +        }
9786 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9787 +    }
9788 +
9789 +    return NULL;
9790 +}
9791 +/* }}} */
9792 +
9793 +/* {{{ apc_sma_realloc */
9794 +void* apc_sma_realloc(void *p, size_t n)
9795 +{
9796 +    apc_sma_free(p);
9797 +    return apc_sma_malloc(n);
9798 +}
9799 +/* }}} */
9800 +
9801 +/* {{{ apc_sma_strdup */
9802 +char* apc_sma_strdup(const char* s)
9803 +{
9804 +    void* q;
9805 +    int len;
9806 +
9807 +    if(!s) return NULL;
9808 +
9809 +    len = strlen(s)+1;
9810 +    q = apc_sma_malloc(len);
9811 +    if(!q) return NULL;
9812 +    memcpy(q, s, len);
9813 +    return q;
9814 +}
9815 +/* }}} */
9816 +
9817 +/* {{{ apc_sma_free */
9818 +void apc_sma_free(void* p)
9819 +{
9820 +    int i;
9821 +    size_t offset;
9822 +    size_t d_size;
9823 +    TSRMLS_FETCH();
9824 +
9825 +    if (p == NULL) {
9826 +        return;
9827 +    }
9828 +
9829 +    assert(sma_initialized);
9830 +
9831 +    for (i = 0; i < sma_numseg; i++) {
9832 +        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9833 +        offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
9834 +        if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
9835 +            d_size = sma_deallocate(sma_shmaddrs[i], offset);
9836 +            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
9837 +            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9838 +            return;
9839 +        }
9840 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9841 +    }
9842 +
9843 +    apc_eprint("apc_sma_free: could not locate address %p", p);
9844 +}
9845 +/* }}} */
9846 +
9847 +/* {{{ apc_sma_info */
9848 +apc_sma_info_t* apc_sma_info(zend_bool limited)
9849 +{
9850 +    apc_sma_info_t* info;
9851 +    apc_sma_link_t** link;
9852 +    int i;
9853 +       char* shmaddr;
9854 +       block_t* prv;
9855 +       
9856 +    if (!sma_initialized) {
9857 +        return NULL;
9858 +    }
9859 +
9860 +    info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
9861 +    info->num_seg = sma_numseg;
9862 +    info->seg_size = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
9863 +
9864 +    info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
9865 +    for (i = 0; i < sma_numseg; i++) {
9866 +        info->list[i] = NULL;
9867 +    }
9868 +
9869 +    if(limited) return info;
9870 +
9871 +    /* For each segment */
9872 +    for (i = 0; i < sma_numseg; i++) {
9873 +        RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9874 +        shmaddr = sma_shmaddrs[i];
9875 +        prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9876 +
9877 +        link = &info->list[i];
9878 +
9879 +        /* For each block in this segment */
9880 +        while (prv->next != 0) {
9881 +            block_t* cur = BLOCKAT(prv->next);
9882 +#ifdef __APC_SMA_DEBUG__
9883 +            CHECK_CANARY(cur);
9884 +#endif
9885 +
9886 +            *link = apc_emalloc(sizeof(apc_sma_link_t));
9887 +            (*link)->size = cur->size;
9888 +            (*link)->offset = prv->next;
9889 +            (*link)->next = NULL;
9890 +            link = &(*link)->next;
9891 +
9892 +            prv = cur;
9893 +        }
9894 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9895 +    }
9896 +
9897 +    return info;
9898 +}
9899 +/* }}} */
9900 +
9901 +/* {{{ apc_sma_free_info */
9902 +void apc_sma_free_info(apc_sma_info_t* info)
9903 +{
9904 +    int i;
9905 +
9906 +    for (i = 0; i < info->num_seg; i++) {
9907 +        apc_sma_link_t* p = info->list[i];
9908 +        while (p) {
9909 +            apc_sma_link_t* q = p;
9910 +            p = p->next;
9911 +            apc_efree(q);
9912 +        }
9913 +    }
9914 +    apc_efree(info->list);
9915 +    apc_efree(info);
9916 +}
9917 +/* }}} */
9918 +
9919 +/* {{{ apc_sma_get_avail_mem */
9920 +size_t apc_sma_get_avail_mem()
9921 +{
9922 +    size_t avail_mem = 0;
9923 +    int i;
9924 +    
9925 +    for (i = 0; i < sma_numseg; i++) {
9926 +        header_t* header = (header_t*) sma_shmaddrs[i];
9927 +        avail_mem += header->avail;
9928 +    }
9929 +    return avail_mem;
9930 +}
9931 +/* }}} */
9932 +
9933 +#if ALLOC_DISTRIBUTION
9934 +size_t *apc_sma_get_alloc_distribution(void) {
9935 +    header_t* header = (header_t*) sma_shmaddrs[0];
9936 +    return header->adist; 
9937 +}
9938 +#endif
9939 +
9940 +#if 0
9941 +/* {{{ apc_sma_check_integrity */
9942 +void apc_sma_check_integrity()
9943 +{
9944 +    int i;
9945 +
9946 +    /* For each segment */
9947 +    for (i = 0; i < sma_numseg; i++) {
9948 +        char* shmaddr = sma_shmaddrs[i];
9949 +        header_t* header = (header_t*) shmaddr;
9950 +        block_t* prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9951 +        int avail = 0;
9952 +
9953 +        /* For each block in this segment */
9954 +        while (prv->next != 0) {
9955 +            block_t* cur = BLOCKAT(prv->next);
9956 +            avail += cur->size;
9957 +            prv = cur;
9958 +        }
9959 +
9960 +        assert(avail == header->avail);
9961 +    }
9962 +}
9963 +/* }}} */
9964 +#endif
9965 +
9966 +/*
9967 + * Local variables:
9968 + * tab-width: 4
9969 + * c-basic-offset: 4
9970 + * End:
9971 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9972 + * vim<600: expandtab sw=4 ts=4 sts=4
9973 + */
9974 diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.h php-5.2.5/ext/apc/apc_sma.h
9975 --- php-5.2.5-orig/ext/apc/apc_sma.h    1969-12-31 18:00:00.000000000 -0600
9976 +++ php-5.2.5/ext/apc/apc_sma.h 2007-12-26 16:51:32.000000000 -0600
9977 @@ -0,0 +1,82 @@
9978 +/*
9979 +  +----------------------------------------------------------------------+
9980 +  | APC                                                                  |
9981 +  +----------------------------------------------------------------------+
9982 +  | Copyright (c) 2006 The PHP Group                                     |
9983 +  +----------------------------------------------------------------------+
9984 +  | This source file is subject to version 3.01 of the PHP license,      |
9985 +  | that is bundled with this package in the file LICENSE, and is        |
9986 +  | available through the world-wide-web at the following url:           |
9987 +  | http://www.php.net/license/3_01.txt                                  |
9988 +  | If you did not receive a copy of the PHP license and are unable to   |
9989 +  | obtain it through the world-wide-web, please send a note to          |
9990 +  | license@php.net so we can mail you a copy immediately.               |
9991 +  +----------------------------------------------------------------------+
9992 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9993 +  +----------------------------------------------------------------------+
9994 +
9995 +   This software was contributed to PHP by Community Connect Inc. in 2002
9996 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9997 +   Future revisions and derivatives of this source code must acknowledge
9998 +   Community Connect Inc. as the original contributor of this module by
9999 +   leaving this note intact in the source code.
10000 +
10001 +   All other licensing and usage conditions are those of the PHP Group.
10002 +
10003 + */
10004 +
10005 +/* $Id: apc_sma.h,v 1.18 2007/05/11 01:46:31 shire Exp $ */
10006 +
10007 +#ifndef APC_SMA_H
10008 +#define APC_SMA_H
10009 +
10010 +#define ALLOC_DISTRIBUTION 0
10011 +
10012 +#include "apc.h"
10013 +
10014 +/* Simple shared memory allocator */
10015 +
10016 +extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask);
10017 +extern void apc_sma_cleanup();
10018 +extern void* apc_sma_malloc(size_t size);
10019 +extern void* apc_sma_realloc(void* p, size_t size);
10020 +extern char* apc_sma_strdup(const char *s);
10021 +extern void apc_sma_free(void* p);
10022 +#if ALLOC_DISTRIBUTION 
10023 +extern size_t *apc_sma_get_alloc_distribution();
10024 +#endif
10025 +
10026 +/* {{{ struct definition: apc_sma_link_t */
10027 +typedef struct apc_sma_link_t apc_sma_link_t;
10028 +struct apc_sma_link_t {
10029 +    long size;               /* size of this free block */
10030 +    long offset;             /* offset in segment of this block */
10031 +    apc_sma_link_t* next;   /* link to next free block */
10032 +};
10033 +/* }}} */
10034 +
10035 +/* {{{ struct definition: apc_sma_info_t */
10036 +typedef struct apc_sma_info_t apc_sma_info_t;
10037 +struct apc_sma_info_t {
10038 +    int num_seg;            /* number of shared memory segments */
10039 +    long seg_size;           /* size of each shared memory segment */
10040 +    apc_sma_link_t** list;  /* there is one list per segment */
10041 +};
10042 +/* }}} */
10043 +
10044 +extern apc_sma_info_t* apc_sma_info(zend_bool limited);
10045 +extern void apc_sma_free_info(apc_sma_info_t* info);
10046 +
10047 +extern size_t apc_sma_get_avail_mem();
10048 +extern void apc_sma_check_integrity();
10049 +
10050 +#endif
10051 +
10052 +/*
10053 + * Local variables:
10054 + * tab-width: 4
10055 + * c-basic-offset: 4
10056 + * End:
10057 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10058 + * vim<600: expandtab sw=4 ts=4 sts=4
10059 + */
10060 diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
10061 --- php-5.2.5-orig/ext/apc/apc_spin.c   1969-12-31 18:00:00.000000000 -0600
10062 +++ php-5.2.5/ext/apc/apc_spin.c        2007-12-26 16:51:32.000000000 -0600
10063 @@ -0,0 +1,65 @@
10064 +/*
10065 +  +----------------------------------------------------------------------+
10066 +  | APC                                                                  |
10067 +  +----------------------------------------------------------------------+
10068 +  | Copyright (c) 2007 The PHP Group                                     |
10069 +  +----------------------------------------------------------------------+
10070 +  | This source file is subject to version 3.01 of the PHP license,      |
10071 +  | that is bundled with this package in the file LICENSE, and is        |
10072 +  | available through the world-wide-web at the following url:           |
10073 +  | http://www.php.net/license/3_01.txt                                  |
10074 +  | If you did not receive a copy of the PHP license and are unable to   |
10075 +  | obtain it through the world-wide-web, please send a note to          |
10076 +  | license@php.net so we can mail you a copy immediately.               |
10077 +  +----------------------------------------------------------------------+
10078 +  | Authors: Brian Shire <shire@php.net>                                 |
10079 +  +----------------------------------------------------------------------+
10080 +
10081 + */
10082 +
10083 +/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
10084 +
10085 +#include "apc_spin.h"
10086 +
10087 +#ifdef APC_SPIN_LOCKS
10088 +
10089 +slock_t *apc_slock_create(slock_t *lock) 
10090 +{
10091 +   S_INIT_LOCK(lock); 
10092 +}
10093 +
10094 +void apc_slock_destroy(slock_t *lock)
10095 +{
10096 +    S_LOCK_FREE(lock);
10097 +}
10098 +
10099 +void apc_slock_lock(slock_t *lock)
10100 +{
10101 +    S_LOCK(lock);
10102 +}
10103 +
10104 +void apc_slock_unlock(slock_t *lock)
10105 +{
10106 +    S_UNLOCK(lock);
10107 +}
10108 +
10109 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
10110 +{
10111 +    /* Technically we aren't supposed to call this directly, but the original
10112 +     *  code provides no method for absolute non-blocking locks, so we'll call into
10113 +     *  the TAS (test and set) functionality directly 
10114 +     */
10115 +    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
10116 +}
10117 +
10118 +
10119 +#endif
10120 +
10121 +/*
10122 + * Local variables:
10123 + * tab-width: 4
10124 + * c-basic-offset: 4
10125 + * End:
10126 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10127 + * vim<600: expandtab sw=4 ts=4 sts=4
10128 + */
10129 diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
10130 --- php-5.2.5-orig/ext/apc/apc_spin.h   1969-12-31 18:00:00.000000000 -0600
10131 +++ php-5.2.5/ext/apc/apc_spin.h        2007-12-26 16:51:32.000000000 -0600
10132 @@ -0,0 +1,48 @@
10133 +/*
10134 +  +----------------------------------------------------------------------+
10135 +  | APC                                                                  |
10136 +  +----------------------------------------------------------------------+
10137 +  | Copyright (c) 2007 The PHP Group                                     |
10138 +  +----------------------------------------------------------------------+
10139 +  | This source file is subject to version 3.01 of the PHP license,      |
10140 +  | that is bundled with this package in the file LICENSE, and is        |
10141 +  | available through the world-wide-web at the following url:           |
10142 +  | http://www.php.net/license/3_01.txt                                  |
10143 +  | If you did not receive a copy of the PHP license and are unable to   |
10144 +  | obtain it through the world-wide-web, please send a note to          |
10145 +  | license@php.net so we can mail you a copy immediately.               |
10146 +  +----------------------------------------------------------------------+
10147 +  | Authors: Brian Shire <shire@php.net>                                 |
10148 +  +----------------------------------------------------------------------+
10149 +
10150 + */
10151 +
10152 +/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
10153 +
10154 +#ifndef APC_SPIN_H
10155 +#define APC_SPIN_H
10156 +
10157 +#include "apc.h"
10158 +
10159 +#ifdef APC_SPIN_LOCKS 
10160 +
10161 +#include "pgsql_s_lock.h"
10162 +
10163 +pthread_mutex_t *apc_spin_create();
10164 +void apc_spin_destroy(pthread_mutex_t *lock);
10165 +void apc_spin_lock(pthread_mutex_t *lock);
10166 +void apc_spin_unlock(pthread_mutex_t *lock);
10167 +zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
10168 +
10169 +#endif
10170 +
10171 +#endif
10172 +
10173 +/*
10174 + * Local variables:
10175 + * tab-width: 4
10176 + * c-basic-offset: 4
10177 + * End:
10178 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10179 + * vim<600: expandtab sw=4 ts=4 sts=4
10180 + */
10181 diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
10182 --- php-5.2.5-orig/ext/apc/apc_stack.c  1969-12-31 18:00:00.000000000 -0600
10183 +++ php-5.2.5/ext/apc/apc_stack.c       2007-12-26 16:51:32.000000000 -0600
10184 @@ -0,0 +1,105 @@
10185 +/*
10186 +  +----------------------------------------------------------------------+
10187 +  | APC                                                                  |
10188 +  +----------------------------------------------------------------------+
10189 +  | Copyright (c) 2006 The PHP Group                                     |
10190 +  +----------------------------------------------------------------------+
10191 +  | This source file is subject to version 3.01 of the PHP license,      |
10192 +  | that is bundled with this package in the file LICENSE, and is        |
10193 +  | available through the world-wide-web at the following url:           |
10194 +  | http://www.php.net/license/3_01.txt                                  |
10195 +  | If you did not receive a copy of the PHP license and are unable to   |
10196 +  | obtain it through the world-wide-web, please send a note to          |
10197 +  | license@php.net so we can mail you a copy immediately.               |
10198 +  +----------------------------------------------------------------------+
10199 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10200 +  +----------------------------------------------------------------------+
10201 +
10202 +   This software was contributed to PHP by Community Connect Inc. in 2002
10203 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10204 +   Future revisions and derivatives of this source code must acknowledge
10205 +   Community Connect Inc. as the original contributor of this module by
10206 +   leaving this note intact in the source code.
10207 +
10208 +   All other licensing and usage conditions are those of the PHP Group.
10209 +
10210 + */
10211 +
10212 +/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
10213 +
10214 +#include "apc_stack.h"
10215 +#include "apc.h"
10216 +
10217 +struct apc_stack_t {
10218 +    void** data;
10219 +    int capacity;
10220 +    int size;
10221 +};
10222 +
10223 +apc_stack_t* apc_stack_create(int size_hint)
10224 +{
10225 +    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
10226 +
10227 +    stack->capacity = (size_hint > 0) ? size_hint : 10;
10228 +    stack->size = 0;
10229 +    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
10230 +
10231 +    return stack;
10232 +}
10233 +
10234 +void apc_stack_destroy(apc_stack_t* stack)
10235 +{
10236 +    if (stack != NULL) {
10237 +        apc_efree(stack->data);
10238 +        apc_efree(stack);
10239 +    }
10240 +}
10241 +
10242 +void apc_stack_clear(apc_stack_t* stack)
10243 +{
10244 +    assert(stack != NULL);
10245 +    stack->size = 0;
10246 +}
10247 +
10248 +void apc_stack_push(apc_stack_t* stack, void* item)
10249 +{
10250 +    assert(stack != NULL);
10251 +    if (stack->size == stack->capacity) {
10252 +        stack->capacity *= 2;
10253 +        stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
10254 +    }
10255 +    stack->data[stack->size++] = item;
10256 +}
10257 +
10258 +void* apc_stack_pop(apc_stack_t* stack)
10259 +{
10260 +    assert(stack != NULL && stack->size > 0);
10261 +    return stack->data[--stack->size];
10262 +}
10263 +
10264 +void* apc_stack_top(apc_stack_t* stack)
10265 +{
10266 +    assert(stack != NULL && stack->size > 0);
10267 +    return stack->data[stack->size-1];
10268 +}
10269 +
10270 +void* apc_stack_get(apc_stack_t* stack, int n)
10271 +{
10272 +    assert(stack != NULL && stack->size > n);
10273 +    return stack->data[n];
10274 +}
10275 +
10276 +int apc_stack_size(apc_stack_t* stack)
10277 +{
10278 +    assert(stack != NULL);
10279 +    return stack->size;
10280 +}
10281 +
10282 +/*
10283 + * Local variables:
10284 + * tab-width: 4
10285 + * c-basic-offset: 4
10286 + * End:
10287 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10288 + * vim<600: expandtab sw=4 ts=4 sts=4
10289 + */
10290 diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.h php-5.2.5/ext/apc/apc_stack.h
10291 --- php-5.2.5-orig/ext/apc/apc_stack.h  1969-12-31 18:00:00.000000000 -0600
10292 +++ php-5.2.5/ext/apc/apc_stack.h       2007-12-26 16:51:32.000000000 -0600
10293 @@ -0,0 +1,58 @@
10294 +/*
10295 +  +----------------------------------------------------------------------+
10296 +  | APC                                                                  |
10297 +  +----------------------------------------------------------------------+
10298 +  | Copyright (c) 2006 The PHP Group                                     |
10299 +  +----------------------------------------------------------------------+
10300 +  | This source file is subject to version 3.01 of the PHP license,      |
10301 +  | that is bundled with this package in the file LICENSE, and is        |
10302 +  | available through the world-wide-web at the following url:           |
10303 +  | http://www.php.net/license/3_01.txt                                  |
10304 +  | If you did not receive a copy of the PHP license and are unable to   |
10305 +  | obtain it through the world-wide-web, please send a note to          |
10306 +  | license@php.net so we can mail you a copy immediately.               |
10307 +  +----------------------------------------------------------------------+
10308 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10309 +  |          George Schlossnagle <george@omniti.com>                     |
10310 +  +----------------------------------------------------------------------+
10311 +
10312 +   This software was contributed to PHP by Community Connect Inc. in 2002
10313 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10314 +   Future revisions and derivatives of this source code must acknowledge
10315 +   Community Connect Inc. as the original contributor of this module by
10316 +   leaving this note intact in the source code.
10317 +
10318 +   All other licensing and usage conditions are those of the PHP Group.
10319 +
10320 + */
10321 +
10322 +/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
10323 +
10324 +#ifndef APC_STACK_H
10325 +#define APC_STACK_H
10326 +
10327 +/* Basic stack datatype */
10328 +
10329 +#define T apc_stack_t*
10330 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
10331 +
10332 +extern T apc_stack_create(int size_hint);
10333 +extern void apc_stack_destroy(T stack);
10334 +extern void apc_stack_clear(T stack);
10335 +extern void apc_stack_push(T stack, void* item);
10336 +extern void* apc_stack_pop(T stack);
10337 +extern void* apc_stack_top(T stack);
10338 +extern void* apc_stack_get(T stack, int n);
10339 +extern int apc_stack_size(T stack);
10340 +
10341 +#undef T
10342 +#endif
10343 +
10344 +/*
10345 + * Local variables:
10346 + * tab-width: 4
10347 + * c-basic-offset: 4
10348 + * End:
10349 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10350 + * vim<600: expandtab sw=4 ts=4 sts=4
10351 + */
10352 diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.c php-5.2.5/ext/apc/apc_zend.c
10353 --- php-5.2.5-orig/ext/apc/apc_zend.c   1969-12-31 18:00:00.000000000 -0600
10354 +++ php-5.2.5/ext/apc/apc_zend.c        2007-12-26 16:51:32.000000000 -0600
10355 @@ -0,0 +1,277 @@
10356 +/*
10357 +  +----------------------------------------------------------------------+
10358 +  | APC                                                                  |
10359 +  +----------------------------------------------------------------------+
10360 +  | Copyright (c) 2006 The PHP Group                                     |
10361 +  +----------------------------------------------------------------------+
10362 +  | This source file is subject to version 3.01 of the PHP license,      |
10363 +  | that is bundled with this package in the file LICENSE, and is        |
10364 +  | available through the world-wide-web at the following url:           |
10365 +  | http://www.php.net/license/3_01.txt                                  |
10366 +  | If you did not receive a copy of the PHP license and are unable to   |
10367 +  | obtain it through the world-wide-web, please send a note to          |
10368 +  | license@php.net so we can mail you a copy immediately.               |
10369 +  +----------------------------------------------------------------------+
10370 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10371 +  +----------------------------------------------------------------------+
10372 +
10373 +   This software was contributed to PHP by Community Connect Inc. in 2002
10374 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10375 +   Future revisions and derivatives of this source code must acknowledge
10376 +   Community Connect Inc. as the original contributor of this module by
10377 +   leaving this note intact in the source code.
10378 +
10379 +   All other licensing and usage conditions are those of the PHP Group.
10380 +
10381 + */
10382 +
10383 +/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
10384 +
10385 +#include "apc_zend.h"
10386 +#include "apc_globals.h"
10387 +
10388 +void* apc_php_malloc(size_t n)
10389 +{
10390 +    return emalloc(n);
10391 +}
10392 +
10393 +void apc_php_free(void* p)
10394 +{
10395 +    efree(p);
10396 +}
10397 +
10398 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
10399 +# define ZEND_VM_KIND_CALL     1
10400 +#endif
10401 +
10402 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
10403 +# define ZEND_VM_KIND  ZEND_VM_KIND_CALL
10404 +#endif
10405 +
10406 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
10407 +# define APC_OPCODE_OVERRIDE
10408 +#endif
10409 +
10410 +#ifdef APC_OPCODE_OVERRIDE
10411 +
10412 +#ifdef ZEND_ENGINE_2_1
10413 +/* Taken from Zend/zend_vm_execute.h */
10414 +#define _CONST_CODE  0
10415 +#define _TMP_CODE    1
10416 +#define _VAR_CODE    2
10417 +#define _UNUSED_CODE 3
10418 +#define _CV_CODE     4
10419 +static inline int _apc_opcode_handler_decode(zend_op *opline)
10420 +{
10421 +       static const int apc_vm_decode[] = {
10422 +               _UNUSED_CODE, /* 0              */
10423 +               _CONST_CODE,  /* 1 = IS_CONST   */
10424 +               _TMP_CODE,    /* 2 = IS_TMP_VAR */
10425 +               _UNUSED_CODE, /* 3              */
10426 +               _VAR_CODE,    /* 4 = IS_VAR     */
10427 +               _UNUSED_CODE, /* 5              */
10428 +               _UNUSED_CODE, /* 6              */
10429 +               _UNUSED_CODE, /* 7              */
10430 +               _UNUSED_CODE, /* 8 = IS_UNUSED  */
10431 +               _UNUSED_CODE, /* 9              */
10432 +               _UNUSED_CODE, /* 10             */
10433 +               _UNUSED_CODE, /* 11             */
10434 +               _UNUSED_CODE, /* 12             */
10435 +               _UNUSED_CODE, /* 13             */
10436 +               _UNUSED_CODE, /* 14             */
10437 +               _UNUSED_CODE, /* 15             */
10438 +               _CV_CODE      /* 16 = IS_CV     */
10439 +       };
10440 +       return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
10441 +}
10442 +
10443 +# define APC_ZEND_OPLINE                                       zend_op *opline = execute_data->opline;
10444 +# define APC_OPCODE_HANDLER_DECODE(opline)     _apc_opcode_handler_decode(opline)
10445 +# if PHP_MAJOR_VERSION >= 6
10446 +#  define APC_OPCODE_HANDLER_COUNT                     ((25 * 152) + 1)
10447 +# else
10448 +#  define APC_OPCODE_HANDLER_COUNT                     ((25 * 151) + 1)
10449 +# endif
10450 +# 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; }
10451 +
10452 +#else /* ZE2.0 */
10453 +# define APC_ZEND_ONLINE
10454 +# define APC_OPCODE_HANDLER_DECODE(opline)     (opline->opcode)
10455 +# define APC_OPCODE_HANDLER_COUNT                      512
10456 +# define APC_REPLACE_OPCODE(opname)                    zend_opcode_handlers[opname] = apc_op_##opname;
10457 +#endif
10458 +
10459 +static opcode_handler_t *apc_original_opcode_handlers;
10460 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
10461 +
10462 +#define APC_EX_T(offset)                                       (*(temp_variable *)((char*)execute_data->Ts + offset))
10463 +
10464 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
10465 +{
10466 +       *freeval = NULL;
10467 +
10468 +       switch (node->op_type) {
10469 +               case IS_CONST:
10470 +                       return &(node->u.constant);
10471 +               case IS_VAR:
10472 +                       return APC_EX_T(node->u.var).var.ptr;
10473 +               case IS_TMP_VAR:
10474 +                       return (*freeval = &APC_EX_T(node->u.var).tmp_var);
10475 +#ifdef ZEND_ENGINE_2_1
10476 +               case IS_CV:
10477 +               {
10478 +                       zval ***ret = &execute_data->CVs[node->u.var];
10479 +
10480 +                       if (!*ret) {
10481 +                               zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
10482 +
10483 +                               if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
10484 +                                       apc_nprint("Undefined variable: %s", cv->name);
10485 +                                       return &EG(uninitialized_zval);
10486 +                               }
10487 +                       }
10488 +                       return **ret;
10489 +               }
10490 +#endif
10491 +               case IS_UNUSED:
10492 +               default:
10493 +                       return NULL;
10494 +       }
10495 +}
10496 +
10497 +static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
10498 +{
10499 +       APC_ZEND_OPLINE
10500 +       zval *freeop1 = NULL;
10501 +       zval *inc_filename = NULL, tmp_inc_filename;
10502 +       char realpath[MAXPATHLEN];
10503 +       php_stream_wrapper *wrapper;
10504 +       char *path_for_open;
10505 +       int ret = 0;
10506 +       #ifdef ZEND_ENGINE_2
10507 +       apc_opflags_t* flags = NULL;
10508 +       #endif
10509 +
10510 +       if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
10511 +               Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
10512 +               return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10513 +       }
10514 +
10515 +       inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
10516 +       if (Z_TYPE_P(inc_filename) != IS_STRING) {
10517 +               tmp_inc_filename = *inc_filename;
10518 +               zval_copy_ctor(&tmp_inc_filename);
10519 +               convert_to_string(&tmp_inc_filename);
10520 +               inc_filename = &tmp_inc_filename;
10521 +       }
10522 +
10523 +       wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
10524 +       if (wrapper != &php_plain_files_wrapper ||
10525 +               !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
10526 +               !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
10527 +               /* Fallback to original handler */
10528 +               if (inc_filename == &tmp_inc_filename) {
10529 +                       zval_dtor(&tmp_inc_filename);
10530 +               }
10531 +               return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10532 +       }
10533 +
10534 +       if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
10535 +               if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
10536 +                       ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
10537 +                       ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
10538 +               }
10539 +               if (inc_filename == &tmp_inc_filename) {
10540 +                       zval_dtor(&tmp_inc_filename);
10541 +               }
10542 +               if (freeop1) {
10543 +                       zval_dtor(freeop1);
10544 +               }
10545 +               execute_data->opline++;
10546 +               return 0;
10547 +       }
10548 +
10549 +       if (inc_filename == &tmp_inc_filename) {
10550 +               zval_dtor(&tmp_inc_filename);
10551 +       }
10552 +
10553 +       if(APCG(reserved_offset) != -1) {
10554 +               /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
10555 +               flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
10556 +       }
10557 +
10558 +#ifdef ZEND_ENGINE_2
10559 +       if(flags && flags->deep_copy == 1) {
10560 +               /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily 
10561 +                * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
10562 +                */
10563 +               Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
10564 +               ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10565 +               Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
10566 +#else 
10567 +       if(0) {
10568 +               /* do nothing, have nothing, be nothing */
10569 +#endif
10570 +       } else {
10571 +               ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10572 +       }
10573 +
10574 +       return ret;
10575 +}
10576 +
10577 +void apc_zend_init(TSRMLS_D)
10578 +{
10579 +    zend_extension dummy_ext;
10580 +#ifdef ZEND_ENGINE_2
10581 +    APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext); 
10582 +    assert(APCG(reserved_offset) == dummy_ext.resource_number);
10583 +    assert(APCG(reserved_offset) != -1);
10584 +    assert(sizeof(apc_opflags_t) <= sizeof(void*));
10585 +#endif
10586 +       if (!APCG(include_once)) {
10587 +               /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
10588 +               return;
10589 +       }
10590 +
10591 +       memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
10592 +
10593 +       /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
10594 +#ifdef ZEND_ENGINE_2_1
10595 +       apc_original_opcode_handlers = zend_opcode_handlers;
10596 +       zend_opcode_handlers = apc_opcode_handlers;
10597 +#else
10598 +       apc_original_opcode_handlers = apc_opcode_handlers;
10599 +#endif
10600 +
10601 +       APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
10602 +}
10603 +
10604 +void apc_zend_shutdown(TSRMLS_D)
10605 +{
10606 +       if (!APCG(include_once)) {
10607 +               /* Nothing changed, nothing to restore */
10608 +               return;
10609 +       }
10610 +
10611 +#ifdef ZEND_ENGINE_2_1
10612 +       zend_opcode_handlers = apc_original_opcode_handlers;
10613 +#else
10614 +       memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
10615 +#endif
10616 +}
10617 +
10618 +#else /* Opcode Overrides unavailable */
10619 +
10620 +void apc_zend_init(TSRMLS_D) { }
10621 +void apc_zend_shutdown(TSRMLS_D) { }
10622 +
10623 +#endif /* APC_OPCODE_OVERRIDE */
10624 +
10625 +/*
10626 + * Local variables:
10627 + * tab-width: 4
10628 + * c-basic-offset: 4
10629 + * End:
10630 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10631 + * vim<600: expandtab sw=4 ts=4 sts=4
10632 + */
10633 diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
10634 --- php-5.2.5-orig/ext/apc/apc_zend.h   1969-12-31 18:00:00.000000000 -0600
10635 +++ php-5.2.5/ext/apc/apc_zend.h        2007-12-26 16:51:32.000000000 -0600
10636 @@ -0,0 +1,53 @@
10637 +/*
10638 +  +----------------------------------------------------------------------+
10639 +  | APC                                                                  |
10640 +  +----------------------------------------------------------------------+
10641 +  | Copyright (c) 2006 The PHP Group                                     |
10642 +  +----------------------------------------------------------------------+
10643 +  | This source file is subject to version 3.01 of the PHP license,      |
10644 +  | that is bundled with this package in the file LICENSE, and is        |
10645 +  | available through the world-wide-web at the following url:           |
10646 +  | http://www.php.net/license/3_01.txt                                  |
10647 +  | If you did not receive a copy of the PHP license and are unable to   |
10648 +  | obtain it through the world-wide-web, please send a note to          |
10649 +  | license@php.net so we can mail you a copy immediately.               |
10650 +  +----------------------------------------------------------------------+
10651 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10652 +  +----------------------------------------------------------------------+
10653 +
10654 +   This software was contributed to PHP by Community Connect Inc. in 2002
10655 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10656 +   Future revisions and derivatives of this source code must acknowledge
10657 +   Community Connect Inc. as the original contributor of this module by
10658 +   leaving this note intact in the source code.
10659 +
10660 +   All other licensing and usage conditions are those of the PHP Group.
10661 +
10662 + */
10663 +
10664 +/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
10665 +
10666 +#ifndef APC_ZEND_H
10667 +#define APC_ZEND_H
10668 +
10669 +/* Utilities for interfacing with the zend engine */
10670 +
10671 +#include "apc.h"
10672 +#include "apc_php.h"
10673 +
10674 +extern void* apc_php_malloc(size_t n);
10675 +extern void apc_php_free(void* p);
10676 +
10677 +extern void apc_zend_init(TSRMLS_D);
10678 +extern void apc_zend_shutdown(TSRMLS_D);
10679 +
10680 +#endif
10681 +
10682 +/*
10683 + * Local variables:
10684 + * tab-width: 4
10685 + * c-basic-offset: 4
10686 + * End:
10687 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10688 + * vim<600: expandtab sw=4 ts=4 sts=4
10689 + */
10690 diff -ubrN php-5.2.5-orig/ext/apc/arch/atomic.h php-5.2.5/ext/apc/arch/atomic.h
10691 --- php-5.2.5-orig/ext/apc/arch/atomic.h        1969-12-31 18:00:00.000000000 -0600
10692 +++ php-5.2.5/ext/apc/arch/atomic.h     2007-12-26 16:51:32.000000000 -0600
10693 @@ -0,0 +1,38 @@
10694 +/*
10695 +  +----------------------------------------------------------------------+
10696 +  | APC                                                                  |
10697 +  +----------------------------------------------------------------------+
10698 +  | Copyright (c) 2006 The PHP Group                                     |
10699 +  +----------------------------------------------------------------------+
10700 +  | This source file is subject to version 3.01 of the PHP license,      |
10701 +  | that is bundled with this package in the file LICENSE, and is        |
10702 +  | available through the world-wide-web at the following url:           |
10703 +  | http://www.php.net/license/3_01.txt                                  |
10704 +  | If you did not receive a copy of the PHP license and are unable to   |
10705 +  | obtain it through the world-wide-web, please send a note to          |
10706 +  | license@php.net so we can mail you a copy immediately.               |
10707 +  +----------------------------------------------------------------------+
10708 +  | Authors: Brian Shire <shire@php.net>                                 |
10709 +  +----------------------------------------------------------------------+
10710 +
10711 + */
10712 +
10713 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10714 +
10715 +#ifndef APC_ARCH_ATOMIC_H
10716 +
10717 +#define APC_ARCH_ATOMIC_H
10718 +
10719 +#if defined __x86_64__
10720 +#include "x86_64/atomic.h"
10721 +
10722 +#elif defined __i386__
10723 +#include "i386/atomic.h"
10724 +
10725 +#else
10726 +#error "Unknown or Unsupported Architecture.  If you would like futex suupport for your architecture, please file a request at http://pecl.php.net/bugs/report.php?package=APC"
10727 +
10728 +#endif
10729 +
10730 +
10731 +#endif
10732 diff -ubrN php-5.2.5-orig/ext/apc/arch/i386/atomic.h php-5.2.5/ext/apc/arch/i386/atomic.h
10733 --- php-5.2.5-orig/ext/apc/arch/i386/atomic.h   1969-12-31 18:00:00.000000000 -0600
10734 +++ php-5.2.5/ext/apc/arch/i386/atomic.h        2007-12-26 16:51:32.000000000 -0600
10735 @@ -0,0 +1,79 @@
10736 +/*
10737 +  +----------------------------------------------------------------------+
10738 +  | APC                                                                  |
10739 +  +----------------------------------------------------------------------+
10740 +  | Copyright (c) 2006 The PHP Group                                     |
10741 +  +----------------------------------------------------------------------+
10742 +  | This source file is subject to version 3.01 of the PHP license,      |
10743 +  | that is bundled with this package in the file LICENSE, and is        |
10744 +  | available through the world-wide-web at the following url:           |
10745 +  | http://www.php.net/license/3_01.txt                                  |
10746 +  | If you did not receive a copy of the PHP license and are unable to   |
10747 +  | obtain it through the world-wide-web, please send a note to          |
10748 +  | license@php.net so we can mail you a copy immediately.               |
10749 +  +----------------------------------------------------------------------+
10750 +  | Authors: Brian Shire <shire@php.net>                                 |
10751 +  +----------------------------------------------------------------------+
10752 +
10753 + */
10754 +
10755 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10756 +
10757 +
10758 +#include <sys/syscall.h>
10759 +#include <sys/time.h>
10760 +#include <linux/futex.h>
10761 +
10762 +/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
10763 +static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
10764 +
10765 +  long int ret;
10766 +
10767 +  /* i386 system calls are performed with nt 80h operation.
10768 +   *  the argument order is a, b, c, d, S, D  
10769 +   */ 
10770 +  asm volatile ("int $0x80" 
10771 +       : "=a" (ret)
10772 +       : "0" (SYS_futex), 
10773 +         "b" (futex), 
10774 +         "c" (op), 
10775 +         "d" (val),
10776 +         "S" (timeout)
10777 +       : "memory"
10778 +      );
10779 +
10780 +  return ret;
10781 +
10782 +} 
10783 +
10784 +
10785 +static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
10786 +
10787 +    int prev;
10788 +
10789 +    asm volatile ("LOCK cmpxchgl %1, %2"
10790 +                   : "=a" (prev)
10791 +                   : "r" (new), 
10792 +                     "m" (*(ptr)), 
10793 +                     "0"(old)
10794 +                   : "memory", "cc"
10795 +                 );
10796 +
10797 +    return prev;
10798 +}
10799 +
10800 +static inline int apc_xchg(volatile int *ptr, int new) {
10801 +
10802 +  int ret;
10803 +  
10804 +  asm volatile ("LOCK xchgl %[new], %[ptr]"
10805 +                : "=a" (ret)
10806 +                : [new] "0" (new), 
10807 +                  [ptr] "m" (*(ptr))
10808 +                : "memory"
10809 +               );
10810 +
10811 +  return ret;
10812 +  
10813 +}
10814 +
10815 diff -ubrN php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h php-5.2.5/ext/apc/arch/x86_64/atomic.h
10816 --- php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h 1969-12-31 18:00:00.000000000 -0600
10817 +++ php-5.2.5/ext/apc/arch/x86_64/atomic.h      2007-12-26 16:51:32.000000000 -0600
10818 @@ -0,0 +1,80 @@
10819 +/*
10820 +  +----------------------------------------------------------------------+
10821 +  | APC                                                                  |
10822 +  +----------------------------------------------------------------------+
10823 +  | Copyright (c) 2006 The PHP Group                                     |
10824 +  +----------------------------------------------------------------------+
10825 +  | This source file is subject to version 3.01 of the PHP license,      |
10826 +  | that is bundled with this package in the file LICENSE, and is        |
10827 +  | available through the world-wide-web at the following url:           |
10828 +  | http://www.php.net/license/3_01.txt                                  |
10829 +  | If you did not receive a copy of the PHP license and are unable to   |
10830 +  | obtain it through the world-wide-web, please send a note to          |
10831 +  | license@php.net so we can mail you a copy immediately.               |
10832 +  +----------------------------------------------------------------------+
10833 +  | Authors: Brian Shire <shire@php.net>                                 |
10834 +  +----------------------------------------------------------------------+
10835 +
10836 + */
10837 +
10838 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10839 +
10840 +
10841 +#include <sys/syscall.h>
10842 +#include <sys/time.h>
10843 +#include <linux/futex.h>
10844 +
10845 +/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
10846 +static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
10847 +
10848 +  long int ret;
10849 +
10850 +  /* x86_64 system calls are performed with the faster SYSCALL operation.
10851 +   *  the argument order is D, S, d, c, b, a rather than
10852 +   *  a, b, c, d, S, D as on the i386 int 80h call. 
10853 +  */ 
10854 +  asm volatile ("syscall" 
10855 +       : "=a" (ret)
10856 +       : "0" (SYS_futex), 
10857 +         "D" (futex), 
10858 +         "S" (op), 
10859 +         "d" (val),
10860 +         "c" (timeout)
10861 +       : "r11", "rcx", "memory"
10862 +      );
10863 +
10864 +  return ret;
10865 +
10866 +} 
10867 +
10868 +
10869 +static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
10870 +
10871 +    int prev;
10872 +
10873 +    asm volatile ("LOCK cmpxchgl %1, %2"
10874 +                   : "=a" (prev)
10875 +                   : "r" (new), 
10876 +                     "m" (*(ptr)), 
10877 +                     "0"(old)
10878 +                   : "memory", "cc"
10879 +                 );
10880 +
10881 +    return prev;
10882 +}
10883 +
10884 +static inline int apc_xchg(volatile int *ptr, int new) {
10885 +
10886 +    int ret;
10887 +  
10888 +    asm volatile ("LOCK xchgl %[new], %[ptr]"
10889 +                  : "=a" (ret)
10890 +                  : [new] "0" (new), 
10891 +                    [ptr] "m" (*(ptr))
10892 +                  : "memory"
10893 +                 );
10894 +
10895 +    return ret;
10896 +    
10897 +}
10898 +
10899 diff -ubrN php-5.2.5-orig/ext/apc/CHANGELOG php-5.2.5/ext/apc/CHANGELOG
10900 --- php-5.2.5-orig/ext/apc/CHANGELOG    1969-12-31 18:00:00.000000000 -0600
10901 +++ php-5.2.5/ext/apc/CHANGELOG 2007-12-26 16:51:32.000000000 -0600
10902 @@ -0,0 +1,211 @@
10903 +3.0.16: 2007-12-26
10904 +- Fix for longstanding cache-full crash (Christian Seiler)
10905 +  http://news.php.net/php.pecl.dev/4951 for the details
10906 +- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
10907 +- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
10908 +- Minor cleanups (Lucas Nealan)
10909 +- Added configure option to enable apc_cache_info('filehits') (Shire)
10910 +
10911 +3.0.15: 2007-10-18
10912 +- Eliminate a per-request time() syscall (Rasmus)
10913 +- Added rfc1867 prefix, name, and freq ini options (Shire)
10914 +- Allow deletion of individual user cache entries via apc.php (Sara)
10915 +- Fix overzealous cleanup during RSHUTDOWN (Gopal)
10916 +- Fix memory alignment and locking issues (Gopal) 
10917 +- Make apc_compile insert/replace entries (Shire)
10918 +- Make mixed inheritance recompile & cache afresh  (Gopal)
10919 +- Make nostat mode search include_path for canonicalization (Gopal)
10920 +- ZTS & other compile fixes (Gopal, Edin, Shire)
10921 +  
10922 +3.0.14: 2007-03-21
10923 +- Build fix (Shire)
10924 +- Don't hook the upload hook if APC is disabled (Rasmus)
10925 +- Local shadow cache support (Gopal)
10926 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
10927 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
10928 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
10929 +- Allocator fixes to reduce fragmentation (Gopal)
10930 +
10931 +3.0.13: 2007-02-24
10932 +- File upload progress (Rasmus)
10933 +- Pthread mutex and spin locks (Shire)
10934 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
10935 +- apc.stat_ctime flag for ctime checks (Rasmus)
10936 +- Multiple key fetches with apc_fetch (Shire)
10937 +- Canary checks for shm memory deallocation (Gopal)
10938 +- Add hooks for external optimizer (Shire)
10939 +- Obsolete and remove apc optimizer (Gopal)
10940 +- APC info changes - cache insert rate, hit and miss rates (Shire)
10941 +- Fix apc_load_constants (Gopal)
10942 +- Rewrite dump opcode code to use vld (Gopal)
10943 +- Use apc_[ewn]print functions for error reporting (Shire) 
10944 +- Auto global fixes and refactoring (Gopal, Shire)
10945 +- Fix memory leaks in object serialization (Ilia)
10946 +- Memory cleanup code for destructor order (Gopal)
10947 +- Win32 build fixes (Ilia, Wez)
10948 +- ZTS and Php 4 build fixes (Bjori)
10949 +- Add apc_add() function (Rasmus)
10950 +- Add optional limited flag to apc_sma_info() (Rasmus)
10951 +
10952 +3.0.12p2: 2006-09-05
10953 +- Package version up
10954 +
10955 +3.0,12p1: 2006-09-05
10956 +- PHP4 build fixes
10957 +
10958 +3.0.12: 2006-09-05
10959 +- PHP 5.2 compatibility (Gopal)
10960 +- TSRM fixes (Gopal)
10961 +- Add extra flags to op_array->reserved to improve op array 
10962 +  processing code (Gopal)
10963 +- Fix crashes in optimizer and cli mode (Ilia)
10964 +- Optimizer fixes for PHP5 (Ilia, Gopal)
10965 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
10966 +- Php 4 function table and properties fixes (Gopal)
10967 +- Fix memory leaks in apc_cache_info (Gopal)
10968 +
10969 +3.0.11: 2006-08-16
10970 +- Made --enable-apc-mmap the default compile option (for real this time)
10971 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
10972 +  only fetch header information to make it useful when you have tens of
10973 +  thousands of entries.  (Brian Shire)
10974 +- 64-bit fixes (George)
10975 +- Don't mix Full Path and Inode keys (George)
10976 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
10977 +  require_once() and include_once() statements. (Sara)
10978 +- Add a non-blocking write_lock for cache inserts.  This is a better approach
10979 +  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
10980 +- A bit of work on the optimizer.  (Sara)
10981 +- Various memory issues resolved. (Gopal)
10982 +
10983 +3.0.10: 2006-03-11
10984 +- Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
10985 +  includes will not be stat'ed for any changes.  You will have to restart the server if you
10986 +  change anything.  This mode increases performance quite a bit, especially if you have a
10987 +  lot of includes.
10988 +
10989 +- Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
10990 +  than it solves.  I'll need to revisit locking and signal handling at some point soon.
10991 +
10992 +3.0.9: 2006-03-04
10993 +- Eliminate rand() call when slam_defense is not set (Rasmus)
10994 +- Fix for __isset problem (Gopal)
10995 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
10996 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
10997 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
10998 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
10999 +- Add automatic serialization of objects in apc_store() (Marcus)
11000 +- 64-bit .ini flag fix (Rasmus)
11001 +- Static members fix (Gopal)
11002 +- sma_cleanup() mem leak fix (Rasmus)
11003 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
11004 +- Fix autoglobals JIT bug (Gopal)
11005 +- Fix instance bug (Gopal)
11006 +- Add a lock cleanup safety net to request shutdown (Rasmus)
11007 +- Fix apc.slam_defense edge-case bug (Rasmus)
11008 +- User entry memory usage tracking support (Ilia)
11009 +- 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)
11010 +
11011 +3.0.8: 2005-08-24
11012 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
11013 +Cache corruption fix in cache-full cleanup code (Gopal)
11014 +
11015 +3.0.7: 2005-08-16
11016 +- Fix to apc.php to show final segment in frag chart. (Ilia)
11017 +- A couple of win32 fixes. (Frank)
11018 +- Add apc.enable_cli ini directive. (Rasmus)
11019 +- Add test cases. (Marcus)
11020 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
11021 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
11022 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
11023 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
11024 +
11025 +3.0.6: 2005-07-30
11026 +- Added apc.php to package.xml file.
11027 +- Track per-entry memory usage. (Val)
11028 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
11029 +- fcntl locking robustness fixes. (Rasmus)
11030 +- Shared read-locks where possible. (Rasmus)
11031 +- Added file_update_protection configuration parameter. (Rasmus)
11032 +- Windows ZTS fixes (Frank)
11033 +
11034 +3.0.5: 2005-07-27
11035 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
11036 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
11037 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
11038 +- Segfault in cache cleanup code (Ilia, Rasmus)
11039 +
11040 +3.0.4: 2005-07-18
11041 +- Add win32 support (Edin )
11042 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
11043 +- A couple of other minor fixes
11044 +
11045 +3.0.3: 2005-07-05
11046 +- Fix compile problem against PHP 5.0.x
11047 +
11048 +3.0.2: 2005-07-05
11049 +- Better shm error message
11050 +
11051 +3.0.1: 2005-07-05
11052 +- PHP4 build fix
11053 +
11054 +3.0: 2005-06-23
11055 +- PHP 5.1 support (Arun, Gopal, Rasmus)
11056 +- Major Inheritance bug fix (Arun, Gopal)
11057 +
11058 +2.0: 2003-02-10
11059 +- ground-up rewrite sharing none of the original source code (djc)
11060 +
11061 +1.0.10:
11062 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
11063 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
11064 +  this parameter to your php.ini file to activate apc shm or mmap caching
11065 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
11066 +  2001-05-15]
11067 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
11068 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
11069 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
11070 +- fixed regex support [gws 2001-05-16]
11071 +- enhanced reader-writer lock support [rg 2001-05-07]
11072 +
11073 +1.0.9:
11074 +- fixed (?) memory alignment bug on 64 bit archiecures 
11075 +- added many cache visibiliy functions 
11076 +- added opional fcntl locks under shm version 
11077 +- numerous bug fixes 
11078 +
11079 +1.0.8:
11080 +- added ability to detect and decompile compiled files placed as 'source'
11081 +  [gws,dw 2001-01-30]
11082 +- fixed apc_rstat bug [gws 2001-01-29]
11083 +- added hack to support included urls [gws 2001-01-30]
11084 +- fixed apc_cache_index [mb 2001-01-31]
11085 +- added multiple regex support [gs 2001-02-03]
11086 +- added apc_cache_info [mb,gs 2001-02-03]
11087 +
11088 +1.0.7:
11089 +- partially fixed for Solaris [gws 2001-01-29]
11090 +- fixed mtime support for relative includes [gws 2001-01-29]
11091 +- code cleanup [yg,ta,gws 2001-01-29]
11092 +
11093 +1.0.6:
11094 +- support for mtime in mmap [yg,gws 2001-01-27]
11095 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
11096 +
11097 +1.0.5:
11098 +- support for relative include paths [djc,gws 2001-01-19]
11099 +- class member array support fixed [djc 2001-01-18]
11100 +- added apc_cache_index [gws 2001-01-18]
11101 +
11102 +1.0.4:
11103 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
11104 +
11105 +1.0.3:
11106 +- fixed support for class inheritance [djc 2001-01-16]
11107 +
11108 +1.0.2:
11109 +- support for inherited classes [gws 2001-01-15]
11110 +- support for intialization of class variables and objects [gws 2001-01-13]
11111 +
11112 +1.0.1:
11113 +- added optional file modification time check [djc 2001-01-12]
11114 diff -ubrN php-5.2.5-orig/ext/apc/config.m4 php-5.2.5/ext/apc/config.m4
11115 --- php-5.2.5-orig/ext/apc/config.m4    1969-12-31 18:00:00.000000000 -0600
11116 +++ php-5.2.5/ext/apc/config.m4 2007-12-26 16:51:32.000000000 -0600
11117 @@ -0,0 +1,238 @@
11118 +dnl
11119 +dnl $Id: config.m4,v 3.30 2007/12/26 22:31:20 rasmus Exp $
11120 +dnl
11121 +
11122 +AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
11123 +AC_ARG_WITH(apxs,
11124 +[  --with-apxs[=FILE]      Get compiler flags from apxs -q.  Provide the
11125 +                          pathname to the Apache apxs tool; defaults to "apxs".],[
11126 +  if test "$withval" != "no"; then
11127 +    if test "$withval" = "yes"; then
11128 +      APXS=apxs
11129 +      $APXS -q CFLAGS >/dev/null 2>&1
11130 +      if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
11131 +        APXS=/usr/sbin/apxs
11132 +      elif test -x /usr/bin/apxs2;  then
11133 +        APXS=/usr/bin/apxs2
11134 +      elif test -x /usr/sbin/apxs2; then
11135 +        APXS=/usr/sbin/apxs2
11136 +      fi
11137 +    else
11138 +      PHP_EXPAND_PATH($withval, APXS)
11139 +    fi
11140 +
11141 +    $APXS -q CFLAGS >/dev/null 2>&1
11142 +    if test "$?" != "0"; then
11143 +      AC_MSG_RESULT()
11144 +      AC_MSG_RESULT()
11145 +      AC_MSG_RESULT([Sorry, I was not able to successfully run APXS.  Possible reasons:])
11146 +      AC_MSG_RESULT()
11147 +      AC_MSG_RESULT([1.  Perl is not installed;])
11148 +      AC_MSG_RESULT([2.  Apache was not compiled with DSO support (--enable-module=so);])
11149 +      AC_MSG_RESULT([3.  'apxs' is not in your path.  Try to use --with-apxs=/path/to/apxs])
11150 +      AC_MSG_RESULT([The output of $APXS follows])
11151 +      $APXS -q CFLAGS
11152 +      AC_MSG_ERROR([Aborting])
11153 +    fi
11154 +
11155 +    APC_CFLAGS=`$APXS -q CFLAGS`
11156 +    AC_MSG_RESULT(yes)
11157 +  else
11158 +    AC_MSG_RESULT(no)
11159 +  fi
11160 +],[
11161 +  AC_MSG_RESULT(no)
11162 +])
11163 +
11164 +PHP_ARG_ENABLE(apc, whether to enable APC support,
11165 +[  --enable-apc           Enable APC support])
11166 +
11167 +AC_MSG_CHECKING(Checking whether we should enable cache request file info)
11168 +AC_ARG_ENABLE(apc-filehits,
11169 +[  --enable-apc-filehits   Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
11170 +[
11171 +  PHP_APC_FILEHITS=$enableval
11172 +       AC_MSG_RESULT($enableval)
11173 +], 
11174 +[
11175 +  PHP_APC_FILEHITS=no
11176 +       AC_MSG_RESULT(no)
11177 +])
11178 +
11179 +
11180 +
11181 +AC_MSG_CHECKING(Checking whether we should use mmap)
11182 +AC_ARG_ENABLE(apc-mmap,
11183 +[  --disable-apc-mmap
11184 +                          Disable mmap support and use IPC shm instead],
11185 +[
11186 +  PHP_APC_MMAP=$enableval
11187 +  AC_MSG_RESULT($enableval)
11188 +], [
11189 +  PHP_APC_MMAP=yes
11190 +  AC_MSG_RESULT(yes)
11191 +])
11192 +
11193 +AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
11194 +AC_ARG_ENABLE(apc-sem,
11195 +[  --enable-apc-sem
11196 +                          Enable semaphore locks instead of fcntl],
11197 +[
11198 +  PHP_APC_SEM=$enableval
11199 +  AC_MSG_RESULT($enableval)
11200 +], [
11201 +  PHP_APC_SEM=no
11202 +  AC_MSG_RESULT(no)
11203 +])
11204 +
11205 +AC_MSG_CHECKING(Checking whether we should use futex locking)
11206 +AC_ARG_ENABLE(apc-futex,
11207 +[  --enable-apc-futex
11208 +                          Enable linux futex based locks  EXPERIMENTAL ],
11209 +[
11210 +  PHP_APC_FUTEX=$enableval
11211 +  AC_MSG_RESULT($enableval)
11212 +],
11213 +[
11214 +  PHP_APC_FUTEX=no
11215 +  AC_MSG_RESULT(no)
11216 +])
11217 +
11218 +if test "$PHP_APC_FUTEX" != "no"; then
11219 +       AC_CHECK_HEADER(linux/futex.h, , [ AC_MSG_ERROR([futex.h not found.  Please verify you that are running a 2.5 or older linux kernel and that futex support is enabled.]); ] )
11220 +fi
11221 +
11222 +AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
11223 +AC_ARG_ENABLE(apc-pthreadmutex,
11224 +[  --disable-apc-pthreadmutex
11225 +                          Disable pthread mutex locking ],
11226 +[
11227 +  PHP_APC_PTHREADMUTEX=no
11228 +  AC_MSG_RESULT(no)
11229 +],
11230 +[
11231 +  PHP_APC_PTHREADMUTEX=yes
11232 +  AC_MSG_RESULT(yes)
11233 +])
11234 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
11235 +       orig_LIBS="$LIBS"
11236 +       LIBS="$LIBS -lpthread"
11237 +       AC_TRY_RUN(
11238 +                       [
11239 +                               #include <sys/types.h>
11240 +                               #include <pthread.h>
11241 +                                main() {
11242 +                               pthread_mutex_t mutex;
11243 +                               pthread_mutexattr_t attr;       
11244 +
11245 +                               if(pthread_mutexattr_init(&attr)) { 
11246 +                                       puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
11247 +                                       return -1; 
11248 +                               }
11249 +                               if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { 
11250 +                                       puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
11251 +                                       return -1; 
11252 +                               }       
11253 +                               if(pthread_mutex_init(&mutex, &attr)) { 
11254 +                                       puts("Unable to initialize the mutex (pthread_mutex_init).");
11255 +                                       return -1; 
11256 +                               }
11257 +                               if(pthread_mutexattr_destroy(&attr)) { 
11258 +                                       puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
11259 +                                       return -1; 
11260 +                               }
11261 +                               if(pthread_mutex_destroy(&mutex)) { 
11262 +                                       puts("Unable to destroy mutex (pthread_mutex_destroy).");
11263 +                                       return -1; 
11264 +                               }
11265 +
11266 +                               puts("pthread mutex's are supported!");
11267 +                               return 0;
11268 +                                }
11269 +                       ],
11270 +                       [ dnl -Success-
11271 +                               PHP_ADD_LIBRARY(pthread)
11272 +                       ],
11273 +                       [ dnl -Failure-
11274 +                               AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
11275 +                       PHP_APC_PTHREADMUTEX=no
11276 +                       ],
11277 +                       [
11278 +                               PHP_ADD_LIBRARY(pthread)
11279 +                       ]
11280 +       )
11281 +       LIBS="$orig_LIBS"
11282 +fi
11283 +
11284 +AC_MSG_CHECKING(Checking whether we should use spin locks)
11285 +AC_ARG_ENABLE(apc-spinlocks,
11286 +[  --enable-apc-spinlocks
11287 +                          Enable spin locks  EXPERIMENTAL ],
11288 +[
11289 +  PHP_APC_SPINLOCKS=$enableval
11290 +  AC_MSG_RESULT($enableval)
11291 +],
11292 +[
11293 +  PHP_APC_SPINLOCKS=no
11294 +  AC_MSG_RESULT(no)
11295 +])
11296 +
11297 +if test "$PHP_APC" != "no"; then
11298 +  test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
11299 +  test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
11300 +
11301 +       if test "$PHP_APC_SEM" != "no"; then
11302 +               AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
11303 +       elif test "$PHP_APC_FUTEX" != "no"; then
11304 +               AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
11305 +       elif test "$PHP_APC_SPINLOCKS" != "no"; then
11306 +               AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) 
11307 +       elif test "$PHP_APC_PTHREADMUTEX" != "no"; then 
11308 +               AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
11309 +       fi
11310 +
11311 +  AC_CHECK_FUNCS(sigaction)
11312 +  AC_CACHE_CHECK(for union semun, php_cv_semun,
11313 +  [
11314 +    AC_TRY_COMPILE([
11315 +#include <sys/types.h>
11316 +#include <sys/ipc.h>
11317 +#include <sys/sem.h>
11318 +    ], [union semun x;], [
11319 +      php_cv_semun=yes
11320 +    ],[
11321 +      php_cv_semun=no
11322 +    ])
11323 +  ])
11324 +  if test "$php_cv_semun" = "yes"; then
11325 +    AC_DEFINE(HAVE_SEMUN, 1, [ ])
11326 +  else
11327 +    AC_DEFINE(HAVE_SEMUN, 0, [ ])
11328 +  fi
11329 +
11330 +  apc_sources="apc.c php_apc.c \
11331 +               apc_cache.c \
11332 +               apc_compile.c \
11333 +               apc_debug.c \
11334 +               apc_fcntl.c \
11335 +               apc_main.c \
11336 +               apc_mmap.c \
11337 +               apc_sem.c \
11338 +               apc_shm.c \
11339 +               apc_futex.c \
11340 +               apc_pthreadmutex.c \
11341 +               apc_spin.c \
11342 +               pgsql_s_lock.c \
11343 +               apc_sma.c \
11344 +               apc_stack.c \
11345 +               apc_zend.c \
11346 +               apc_rfc1867.c \
11347 +               apc_signal.c "
11348 +
11349 +  PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
11350 +  PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
11351 +  PHP_SUBST(APC_SHARED_LIBADD)
11352 +  PHP_SUBST(APC_CFLAGS)
11353 +  AC_DEFINE(HAVE_APC, 1, [ ])
11354 +fi
11355 +
11356 diff -ubrN php-5.2.5-orig/ext/apc/INSTALL php-5.2.5/ext/apc/INSTALL
11357 --- php-5.2.5-orig/ext/apc/INSTALL      1969-12-31 18:00:00.000000000 -0600
11358 +++ php-5.2.5/ext/apc/INSTALL   2007-12-26 16:51:32.000000000 -0600
11359 @@ -0,0 +1,422 @@
11360 +Installation Instructions for APC
11361 +---------------------------------
11362 +
11363 +This version of APC should work on PHP 4.3.0 - 4.4.x and
11364 +5.1.0 - 5.2.x.  Yes, that means PHP 5.0.x is no longer 
11365 +supported.  Upgrade to PHP 5.1.x or 5.2.x and you will 
11366 +notice all sorts of performance increases.
11367 +
11368 +CVS Instructions
11369 +----------------
11370 +Building from CVS can be done like this:
11371 +
11372 +  cvs -d :pserver:cvsread@cvs.php.net:/repository login
11373 +  Password: phpfi
11374 +  cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
11375 +  cd pecl/apc
11376 +  phpize
11377 +  ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
11378 +  make
11379 +  make install
11380 +
11381 +Suggested Configuration (in your php.ini file)
11382 +----------------------------------------------
11383 +  extension=apc.so
11384 +  apc.enabled=1
11385 +  apc.shm_segments=1
11386 +  apc.shm_size=128
11387 +  apc.ttl=7200
11388 +  apc.user_ttl=7200
11389 +  apc.num_files_hint=1024
11390 +  apc.mmap_file_mask=/tmp/apc.XXXXXX
11391 +  apc.enable_cli=1
11392 +
11393 +These are fully described at the bottom of this file.
11394 +
11395 +PHP 4 Optimization
11396 +------------------
11397 +If you are trying to get every little bit of speed out of PHP4+APC, you need
11398 +to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
11399 +your CPPFLAGS.  (if you don't have httpd.h, install the apache_dev package 
11400 +for your OS) and do:
11401 +  export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
11402 +  setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
11403 +and then re-run your configure script.
11404 +
11405 +This optimization saves a stat syscall on the main script file.  In PHP5 this
11406 +optimization is automatic and doesn't need any special build flags.
11407 +
11408 +The second thing you are going to want to do to save another syscall is to 
11409 +compile using the --with-apxs configure switch.  This should work for both
11410 +Apache1 and Apache2.  Point it directly at your apxs2 script for Apache2.
11411 +eg. --with-apxs=/usr/local/bin/apxs2
11412 +
11413 ++---------------------+
11414 +| QUICK INSTALL (DSO) |
11415 ++---------------------+
11416 +
11417 +These instructions assume your PHP installation is located in /usr/local/php and you
11418 +want Apache optimizations (--with-apxs).
11419 +
11420 +$ gunzip -c apc_x.y.tar.gz | tar xf -
11421 +$ cd apc_x.y
11422 +$ /usr/local/php/bin/phpize
11423 +$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
11424 +$ make
11425 +$ make install
11426 +
11427 +You will probably need to run the final command (make install) as root.
11428 +
11429 +The above sequence of commands will install a .so file in your PHP
11430 +installation extension directory. The output of make install should display
11431 +that path to the screen.
11432 +
11433 +Next you must edit your php.ini file, which is normally located in
11434 +/usr/local/php/lib/php.ini, and add the following line:
11435 +
11436 +    extension="apc.so"
11437 +
11438 +Replace "/path/to/php/extensions" with whatever path was displayed when you
11439 +ran make install above.
11440 +
11441 +Then restart your web server and consult the output of phpinfo(). If there is
11442 +an informational section for APC, the installation was successful.
11443 +
11444 ++------------------------+
11445 +| QUICK INSTALL (Static) |
11446 ++------------------------+
11447 +
11448 +APC will not successfully compile on all systems as a DSO. If you run into
11449 +problems using the DSO quick install, you can try to compile it statically
11450 +into PHP. (The DSO install is recommended, though.)
11451 +
11452 +These instructions assume the current directory is the root of the PHP source
11453 +tree, and that you have already configured PHP by running its bundled
11454 +configure script.
11455 +
11456 +$ cd ext
11457 +$ gunzip -c apc_x.y.tar.gz | tar xf -
11458 +$ cd ..
11459 +$ ./buildconf
11460 +$ ./config.nice
11461 +$ make
11462 +$ make install
11463 +
11464 +Once this is complete, simply restart your web server. You do not need to
11465 +modify your php.ini file to enable APC.
11466 +
11467 ++-----------------+
11468 +| VERBOSE INSTALL |
11469 ++-----------------+
11470 +
11471 +These instructions assume your PHP installation is located in /usr/local/php.
11472 +
11473 +1.  Unpack your distribution file.
11474 +
11475 +    You will have downloaded a file named something like apc_x.y.tar.gz.
11476 +    Unzip this file with a command like
11477 +    
11478 +        gunzip apc_x.y.tar.gz
11479 +    
11480 +    Next you have to untar it with
11481 +    
11482 +        tar xvf apc_x.y.tar
11483 +
11484 +    This will create an apc_x.y directory. cd into this new directory:
11485 +
11486 +        cd apc_x.y
11487 +
11488 +2.  Run phpize.
11489 +
11490 +    phpize is a script that should have been installed with PHP, and is
11491 +    normally located in /usr/local/php/bin assuming you installed PHP in
11492 +    /usr/local/php. (If you do not have the phpize script, you must reinstall
11493 +    PHP and be sure not to disable PEAR.)
11494 +
11495 +    Run the phpize command:
11496 +    
11497 +        /usr/local/php/bin/phpize
11498 +
11499 +    Its output should resemble this:
11500 +
11501 +        autoheader: `config.h.in' is created
11502 +        You should update your `aclocal.m4' by running aclocal.
11503 +        Configuring for:
11504 +          PHP Api Version:   20020918
11505 +          Zend Module Api No:   20020429
11506 +          Zend Extension Api No:   20021010
11507
11508 +    phpize should create a configure script in the current directory. If you
11509 +    get errors instead, you might be missing some required development tools,
11510 +    such as autoconf or libtool. You can try downloading the latest versions
11511 +    of those tools and running phpize again.
11512
11513 +3.  Run the configure script.
11514
11515 +    phpize creates a configure script. The only option you need to specify is
11516 +    the location of your php-config script:
11517 +
11518 +        ./configure --enable-apc
11519 +
11520 +    php-config should be located in the same directory as phpize.
11521 +
11522 +    If you prefer to use mmap instead of the default IPC shared memory support,
11523 +    add --enable-apc-mmap to your configure line. 
11524 +
11525 +       If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
11526 +       --enable-sem to your configure line.  If you don't have a problem
11527 +       with your server segaulting, or any other unnatural accumulation of
11528 +       semaphores on your system, the semaphore based locking is slightly faster.
11529 +
11530 +4.  Compile and install the files. Simply type: make install
11531 +
11532 +    (You may need to be root in order to install)
11533 +
11534 +    If you encounter errors from libtool or gcc during this step, please
11535 +    contact the project maintainer (dcowgill@php.net).
11536 +
11537 +5.  Edit your php.ini
11538 +
11539 +    make install should have printed a line resembling the following:
11540 +
11541 +        Installing shared extensions: /path/to/extension/
11542 +
11543 +    Copy the path /path/to/extension/ and add the following line to your
11544 +    php.ini file (normally located in /usr/local/php/lib/php.ini):
11545 +
11546 +        extension="apc.so"
11547 +
11548 +    If you don't have a php.ini file in that location, you can create it now.
11549 +
11550 +6.  Restart the web server and test the installation.
11551 +
11552 +    Restart your web server now (for apache, it's apachectl restart) and
11553 +    create a small test PHP file in your document root. The file should
11554 +    contain just the following line:
11555 +
11556 +        <?php phpinfo() ?>
11557 +
11558 +    Request that file in a web browser. If there is an entry for APC in the
11559 +    list of installed modules, the installation was successful.
11560 +
11561 +    If APC is not listed, consult your web server error log. If it contains an
11562 +    error message saying that it can't load the APC extension, your system
11563 +    might not be able to load shared libraries created with PHP's build
11564 +    system. One alternative would be to compile APC statically into PHP. See
11565 +    the Quick Install (Static) instructions above.
11566 +
11567 +    You should consult your error log anyway to see if APC generated any
11568 +    errors. On BSD-based platforms, it is typical for APC to be unable to
11569 +    allocate the default-sized shared memory segment. See below for hints on
11570 +    raising your system's shared memory limitations.
11571 +
11572 ++-----------------+
11573 +| CONFIGURING APC |
11574 ++-----------------+
11575 +
11576 +Although the default APC settings are fine for many installations, serious
11577 +users should consider tuning the following parameters:
11578 +
11579 +    OPTION                  DESCRIPTION
11580 +    ------------------      --------------------------------------------------
11581 +    apc.enabled             This can be set to 0 to disable APC. This is
11582 +                            primarily useful when APC is statically compiled
11583 +                            into PHP, since there is no other way to disable
11584 +                            it (when compiled as a DSO, the zend_extension
11585 +                            line can just be commented-out).
11586 +                            (Default: 1)
11587 +                            
11588 +    apc.shm_segments        The number of shared memory segments to allocate
11589 +                            for the compiler cache. If APC is running out of
11590 +                            shared memory but you have already set
11591 +                            apc.shm_size as high as your system allows, you
11592 +                            can try raising this value.  Setting this to a
11593 +                            value other than 1 has no effect in mmap mode
11594 +                            since mmap'ed shm segments don't have size limits.
11595 +                            (Default: 1)
11596 +                            
11597 +    apc.shm_size            The size of each shared memory segment in MB.
11598 +                            By default, some systems (including most BSD
11599 +                            variants) have very low limits on the size of a
11600 +                            shared memory segment.
11601 +                            (Default: 30)
11602 +                            
11603 +    apc.optimization        This option has been deprecated.
11604 +                            (Default: 0)
11605 +    
11606 +    apc.num_files_hint      A "hint" about the number of distinct source files
11607 +                            that will be included or requested on your web
11608 +                            server. Set to zero or omit if you're not sure;
11609 +                            this setting is mainly useful for sites that have
11610 +                            many thousands of source files.
11611 +                            (Default: 1000)
11612 +
11613 +    apc.user_entries_hint   Just like num_files_hint, a "hint" about the number
11614 +                            of distinct user cache variables to store. 
11615 +                            Set to zero or omit if you're not sure;
11616 +                            (Default: 4096)
11617 +
11618 +    apc.ttl                 The number of seconds a cache entry is allowed to
11619 +                            idle in a slot in case this cache entry slot is 
11620 +                            needed by another entry.  Leaving this at zero
11621 +                            means that your cache could potentially fill up
11622 +                            with stale entries while newer entries won't be
11623 +                            cached.  
11624 +                            (Default: 0)
11625 +
11626 +    apc.user_ttl            The number of seconds a user cache entry is allowed 
11627 +                            to idle in a slot in case this cache entry slot is 
11628 +                            needed by another entry.  Leaving this at zero
11629 +                            means that your cache could potentially fill up
11630 +                            with stale entries while newer entries won't be
11631 +                            cached.  
11632 +                            (Default: 0)
11633 +
11634 +
11635 +    apc.gc_ttl              The number of seconds that a cache entry may
11636 +                            remain on the garbage-collection list. This value
11637 +                            provides a failsafe in the event that a server
11638 +                            process dies while executing a cached source file;
11639 +                            if that source file is modified, the memory
11640 +                            allocated for the old version will not be
11641 +                            reclaimed until this TTL reached. Set to zero to
11642 +                            disable this feature.
11643 +                            (Default: 3600)
11644 +
11645 +    apc.cache_by_default    On by default, but can be set to off and used in
11646 +                            conjunction with positive apc.filters so that files
11647 +                            are only cached if matched by a positive filter.
11648 +                            (Default: On)
11649 +
11650 +    apc.filters             A comma-separated list of POSIX extended regular
11651 +                            expressions. If any pattern matches the source
11652 +                            filename, the file will not be cached. Note that
11653 +                            the filename used for matching is the one passed
11654 +                            to include/require, not the absolute path.  If the
11655 +                            first character of the expression is a + then the
11656 +                            expression will be additive in the sense that any
11657 +                            files matched by the expression will be cached, and
11658 +                            if the first character is a - then anything matched
11659 +                            will not be cached.  The - case is the default, so
11660 +                            it can be left off.
11661 +                            (Default: "")
11662 +
11663 +    apc.mmap_file_mask      If compiled with MMAP support by using --enable-mmap
11664 +                            this is the mktemp-style file_mask to pass to the
11665 +                            mmap module for determing whether your mmap'ed memory
11666 +                            region is going to be file-backed or shared memory
11667 +                            backed.  For straight file-backed mmap, set it to
11668 +                            something like /tmp/apc.XXXXXX (exactly 6 X's).
11669 +                            To use POSIX-style shm_open/mmap put a ".shm"
11670 +                            somewhere in your mask.  eg.  "/apc.shm.XXXXXX"
11671 +                            You can also set it to "/dev/zero" to use your 
11672 +                            kernel's /dev/zero interface to anonymous mmap'ed 
11673 +                            memory.  Leaving it undefined will force an 
11674 +                            anonymous mmap.
11675 +                            (Default: "")
11676 +
11677 +    apc.slam_defense        ** DEPRECATED - Use apc.write_lock instead **
11678 +                            On very busy servers whenever you start the server or
11679 +                            modify files you can create a race of many processes
11680 +                            all trying to cache the same file at the same time.
11681 +                            This option sets the percentage of processes that will
11682 +                            skip trying to cache an uncached file.  Or think of it
11683 +                            as the probability of a single process to skip caching.
11684 +                            For example, setting this to 75 would mean that there is
11685 +                            a 75% chance that the process will not cache an uncached
11686 +                            file.  So the higher the setting the greater the defense
11687 +                            against cache slams.  Setting this to 0 disables this
11688 +                            feature.
11689 +                            (Default: 0)
11690 +
11691 +    apc.file_update_protection
11692 +                            When you modify a file on a live web server you really
11693 +                            should do so in an atomic manner.  That is, write to a
11694 +                            temporary file and rename (mv) the file into its permanent
11695 +                            position when it is ready.  Many text editors, cp, tar and
11696 +                            other such programs don't do this.  This means that there
11697 +                            is a chance that a file is accessed (and cached) while it
11698 +                            is still being written to.  This file_update_protection
11699 +                            setting puts a delay on caching brand new files.  The
11700 +                            default is 2 seconds which means that if the modification
11701 +                            timestamp (mtime) on a file shows that it is less than 2
11702 +                            seconds old when it is accessed, it will not be cached.  
11703 +                            The unfortunate person who accessed this half-written file
11704 +                            will still see weirdness, but at least it won't persist.
11705 +                            If you are certain you always atomically update your files
11706 +                            by using something like rsync which does this correctly, you
11707 +                            can turn this protection off by setting it to 0.  If you
11708 +                            have a system that is flooded with io causing some update
11709 +                            procedure to take longer than 2 seconds, you may want to
11710 +                            increase this a bit.
11711 +                            (Default: 2)
11712 +
11713 +    apc.enable_cli          Mostly for testing and debugging.  Setting this enables APC
11714 +                            for the CLI version of PHP.  Normally you wouldn't want to
11715 +                            create, populate and tear down the APC cache on every CLI
11716 +                            request, but for various test scenarios it is handy to be
11717 +                            able to enable APC for the CLI version of APC easily.
11718 +                            (Default: 0)
11719 +
11720 +    apc.max_file_size       Prevents large files from being cached.  
11721 +                            (Default: 1M)
11722 +
11723 +    apc.stat                Whether to stat the main script file and the fullpath
11724 +                            includes.  If you turn this off you will need to restart
11725 +                            your server in order to update scripts.
11726 +                            (Default: 1)
11727 +
11728 +    apc.write_lock          On busy servers when you first start up the server, or when
11729 +                            many files are modified, you can end up with all your processes
11730 +                            trying to compile and cache the same files.  With write_lock 
11731 +                            enabled, only one process at a time will try to compile an
11732 +                            uncached script while the other processes will run uncached
11733 +                            instead of sitting around waiting on a lock.
11734 +                            (Default: 1)
11735 +
11736 +    apc.report_autofilter   Logs any scripts that were automatically excluded from being
11737 +                            cached due to early/late binding issues.
11738 +                            (Default: 0)
11739 +
11740 +    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
11741 +                            if you compiled APC against PHP 5.2.0 or later.  When enabled
11742 +                            any file uploads which includes a field called 
11743 +                            APC_UPLOAD_PROGRESS before the file field in an upload form
11744 +                            will cause APC to automatically create an upload_<key>
11745 +                            user cache entry where <key> is the value of the 
11746 +                            APC_UPLOAD_PROGRESS form entry.
11747 +
11748 +                            Note that the file upload tracking is not threadsafe at this
11749 +                            point, so new uploads that happen while a previous one is 
11750 +                            still going will disable the tracking for the previous.
11751 +                            (Default: 0)
11752 +
11753 +    apc.rfc1867_prefix      Key prefix to use for the user cache entry generated by
11754 +                            rfc1867 upload progress functionality.  
11755 +                            (Default: "upload_")
11756 +
11757 +    apc.rfc1867_name        Specify the hidden form entry name that activates APC upload
11758 +                            progress and specifies the user cache key suffix.
11759 +                            (Default: "APC_UPLOAD_PROGRESS")
11760 +
11761 +    apc.rfc1867_freq        The frequency that updates should be made to the user cache
11762 +                            entry for upload progress.  This can take the form of a 
11763 +                            percentage of the total file size or a size in bytes 
11764 +                            optionally suffixed with 'k', 'm', or 'g' for kilobytes, 
11765 +                            megabytes, or gigabytes respectively (case insensitive).  
11766 +                            A setting of 0 updates as often as possible, which may cause 
11767 +                            slower uploads.
11768 +                            (Default: 0)
11769 +
11770 +    apc.localcache          This enables a lock-free local process shadow-cache which 
11771 +                            reduces lock contention when the cache is being written to.
11772 +                            (Default: 0)
11773 +                            
11774 +    apc.localcache.size     The size of the local process shadow-cache, should be set to 
11775 +                            a sufficently large value, approximately half of num_files_hint.
11776 +                            (Default: 512)
11777 +    
11778 +    apc.include_once_override 
11779 +                            Optimize include_once and require_once calls and avoid the 
11780 +                            expensive system calls used.
11781 +                            (Default: 0)
11782 diff -ubrN php-5.2.5-orig/ext/apc/LICENSE php-5.2.5/ext/apc/LICENSE
11783 --- php-5.2.5-orig/ext/apc/LICENSE      1969-12-31 18:00:00.000000000 -0600
11784 +++ php-5.2.5/ext/apc/LICENSE   2007-12-26 16:51:32.000000000 -0600
11785 @@ -0,0 +1,68 @@
11786 +-------------------------------------------------------------------- 
11787 +                  The PHP License, version 3.01
11788 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
11789 +-------------------------------------------------------------------- 
11790 +
11791 +Redistribution and use in source and binary forms, with or without
11792 +modification, is permitted provided that the following conditions
11793 +are met:
11794 +
11795 +  1. Redistributions of source code must retain the above copyright
11796 +     notice, this list of conditions and the following disclaimer.
11797
11798 +  2. Redistributions in binary form must reproduce the above copyright
11799 +     notice, this list of conditions and the following disclaimer in
11800 +     the documentation and/or other materials provided with the
11801 +     distribution.
11802
11803 +  3. The name "PHP" must not be used to endorse or promote products
11804 +     derived from this software without prior written permission. For
11805 +     written permission, please contact group@php.net.
11806 +  
11807 +  4. Products derived from this software may not be called "PHP", nor
11808 +     may "PHP" appear in their name, without prior written permission
11809 +     from group@php.net.  You may indicate that your software works in
11810 +     conjunction with PHP by saying "Foo for PHP" instead of calling
11811 +     it "PHP Foo" or "phpfoo"
11812
11813 +  5. The PHP Group may publish revised and/or new versions of the
11814 +     license from time to time. Each version will be given a
11815 +     distinguishing version number.
11816 +     Once covered code has been published under a particular version
11817 +     of the license, you may always continue to use it under the terms
11818 +     of that version. You may also choose to use such covered code
11819 +     under the terms of any subsequent version of the license
11820 +     published by the PHP Group. No one other than the PHP Group has
11821 +     the right to modify the terms applicable to covered code created
11822 +     under this License.
11823 +
11824 +  6. Redistributions of any form whatsoever must retain the following
11825 +     acknowledgment:
11826 +     "This product includes PHP software, freely available from
11827 +     <http://www.php.net/software/>".
11828 +
11829 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 
11830 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
11831 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
11832 +PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP
11833 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
11834 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
11835 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
11836 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11837 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
11838 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11839 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11840 +OF THE POSSIBILITY OF SUCH DAMAGE.
11841 +
11842 +-------------------------------------------------------------------- 
11843 +
11844 +This software consists of voluntary contributions made by many
11845 +individuals on behalf of the PHP Group.
11846 +
11847 +The PHP Group can be contacted via Email at group@php.net.
11848 +
11849 +For more information on the PHP Group and the PHP project, 
11850 +please see <http://www.php.net>.
11851 +
11852 +PHP includes the Zend Engine, freely available at
11853 +<http://www.zend.com>.
11854 diff -ubrN php-5.2.5-orig/ext/apc/NOTICE php-5.2.5/ext/apc/NOTICE
11855 --- php-5.2.5-orig/ext/apc/NOTICE       1969-12-31 18:00:00.000000000 -0600
11856 +++ php-5.2.5/ext/apc/NOTICE    2007-12-26 16:51:32.000000000 -0600
11857 @@ -0,0 +1,43 @@
11858 +This is the NOTICE file that holds acknowledgements and stuff.
11859 +
11860 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
11861 +This extension is being released under the PHP License for complete compliance
11862 +with PHP and to encourage wide-spread use.  It is our intention that this
11863 +project be kept open source and that all commercial spin-offs contribute their
11864 +modifications back into the public source-tree.
11865 +
11866 +Creators:
11867 +    Daniel Cowgill
11868 +    George Schlossnagle
11869 +
11870 +PHP5 support and major features by:
11871 +    Arun C. Murthy 
11872 +    Gopal Vijayaraghavan
11873 +    Rasmus Lerdorf
11874 +
11875 +This software was contributed to PHP by Community Connect Inc. in 2002
11876 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11877 +Future revisions and derivatives of this source code must acknowledge
11878 +Community Connect Inc. as the original contributor of this module by
11879 +leaving this note intact in the source code.
11880 +
11881 +All other licensing and usage conditions are those of the PHP Group.
11882 +
11883 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting 
11884 +this project and providing a challenging and stimulating environment in 
11885 +which exciting projects can happen.
11886 +
11887 +Contributors:
11888 +    Mike Bretz          bug fixes, GUI, and lots of work
11889 +    Ricardo Galli       changed read-write locks to prefer readers
11890 +    Yann Grossel        bug fixes
11891 +    Thies Arntzen       bug fixes
11892 +    Sara Golemon        optimizer work
11893 +
11894 +Special Thanks:
11895 +    Florian Baumert     help debugging phplib problems
11896 +    Thomas Duffey       help debugging inheritance issues
11897 +    Vibol Hou           help debugging phplib problems
11898 +    Angel Li            diffs for ANSI comment compliance
11899 +    Christian Rishøj    help debugging phplib problems
11900 +    Sascha Schumann     memory error bug fix
11901 diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
11902 --- php-5.2.5-orig/ext/apc/package.xml  1969-12-31 18:00:00.000000000 -0600
11903 +++ php-5.2.5/ext/apc/package.xml       2007-12-26 16:51:32.000000000 -0600
11904 @@ -0,0 +1,534 @@
11905 +<?xml version="1.0" encoding="UTF-8"?>
11906 +<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
11907 + <name>APC</name>
11908 + <channel>pecl.php.net</channel>
11909 + <summary>Alternative PHP Cache</summary>
11910 + <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
11911 + <lead>
11912 +  <name>Daniel Cowgill</name>
11913 +  <user>dcowgill</user>
11914 +  <email>dan@mail.communityconnect.com</email>
11915 +  <active>no</active>
11916 + </lead>
11917 + <lead>
11918 +  <name>George Schlossnagle</name>
11919 +  <user>gschlossnagle</user>
11920 +  <email>george@omniti.com</email>
11921 +  <active>no</active>
11922 + </lead>
11923 + <lead>
11924 +  <name>Rasmus Lerdorf</name>
11925 +  <user>rasmus</user>
11926 +  <email>rasmus@php.net</email>
11927 +  <active>yes</active>
11928 + </lead>
11929 + <lead>
11930 +  <name>Gopal Vijayaraghavan</name>
11931 +  <user>gopalv</user>
11932 +  <email>gopalv@php.net</email>
11933 +  <active>yes</active>
11934 + </lead>
11935 + <developer>
11936 +  <name>Edin Kadribasic</name>
11937 +  <user>edink</user>
11938 +  <email>edink@emini.dk</email>
11939 +  <active>yes</active>
11940 + </developer>
11941 + <developer>
11942 +  <name>Ilia Alshanetsky</name>
11943 +  <user>iliaa</user>
11944 +  <email>ilia@prohost.org</email>
11945 +  <active>yes</active>
11946 + </developer>
11947 + <developer>
11948 +  <name>Marcus Börger</name>
11949 +  <user>helly</user>
11950 +  <email>helly@php.net</email>
11951 +  <active>yes</active>
11952 + </developer>
11953 + <developer>
11954 +  <name>Sara Golemon</name>
11955 +  <user>pollita</user>
11956 +  <email>pollita@php.net</email>
11957 +  <active>yes</active>
11958 + </developer>
11959 + <developer>
11960 +  <name>Brian Shire</name>
11961 +  <user>shire</user>
11962 +  <email>shire@php.net</email>
11963 +  <active>yes</active>
11964 + </developer>
11965 + <date>2007-12-26</date>
11966 + <time>14:51:32</time>
11967 + <version>
11968 +  <release>3.0.16</release>
11969 +  <api>3.0.0</api>
11970 + </version>
11971 + <stability>
11972 +  <release>stable</release>
11973 +  <api>stable</api>
11974 + </stability>
11975 + <license uri="http://www.php.net/license">PHP License</license>
11976 + <notes>* Fix for longstanding cache-full crash (Christian Seiler)
11977 +  http://news.php.net/php.pecl.dev/4951 for the details
11978 +* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
11979 +* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
11980 +* Minor cleanups (Lucas Nealan)
11981 +* Added configure option to enable apc_cache_info(&apos;filehits&apos;) (Shire)</notes>
11982 + <contents>
11983 +  <dir name="/">
11984 +   <file md5sum="841596cff3b9bd83e79d01ccb591ff55" name="tests/apc_001.phpt" role="test" />
11985 +   <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
11986 +   <file md5sum="411fdc85b170ec696298d38f93132d6b" name="tests/apc_003.phpt" role="test" />
11987 +   <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
11988 +   <file md5sum="2a2e8b29dba8df697dbd81b306ccbe73" name="arch/i386/atomic.h" role="src" />
11989 +   <file md5sum="7f01c5cd3a1742c20d6d285f119596a6" name="arch/x86_64/atomic.h" role="src" />
11990 +   <file md5sum="26748a0d6567c5611408eb69fb25c671" name="arch/atomic.h" role="src" />
11991 +   <file md5sum="0714a0039d9ea63cfc26043a7d86f04c" name="CHANGELOG" role="doc" />
11992 +   <file md5sum="3b6ad608e37fb34b24afb90084b4770b" name="INSTALL" role="doc" />
11993 +   <file md5sum="694f49a7e1f276ba75a3dd2c5acd580d" name="LICENSE" role="doc" />
11994 +   <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
11995 +   <file md5sum="efa40416571fc54aa59912203c0391e6" name="TODO" role="doc" />
11996 +   <file md5sum="b7dd14328e218d3ecc97d85fb83d7ba7" name="TECHNOTES.txt" role="doc" />
11997 +   <file md5sum="c4384f370db6a6112d6c21268bc9a278" name="apc.c" role="src" />
11998 +   <file md5sum="09a525ff9a3850e6de42eee2adf07463" name="apc.dsp" role="src" />
11999 +   <file md5sum="109694ee417962096eb3e962d6bcce8a" name="apc.h" role="src" />
12000 +   <file md5sum="ee19b49ef26dbd491b846a19f9bc9e6a" name="apc_cache.c" role="src" />
12001 +   <file md5sum="e0a4f0c5a49a0beba10f2f831e1b63b6" name="apc_cache.h" role="src" />
12002 +   <file md5sum="7576310688084dd737f7c7bc11c75e22" name="apc_compile.c" role="src" />
12003 +   <file md5sum="a0eea1abcf4ec395ea9a195e98c2cc65" name="apc_compile.h" role="src" />
12004 +   <file md5sum="64bbe1f8cf18261255ef5874039e76e9" name="apc_debug.c" role="src" />
12005 +   <file md5sum="46d182a6122f3c29a1904f62af7cfb51" name="apc_debug.h" role="src" />
12006 +   <file md5sum="3dbdb44d0fc2d45ae15719b4fc5746cd" name="apc_fcntl.c" role="src" />
12007 +   <file md5sum="f4fc86769ce871d42ce0085fa7323d79" name="apc_fcntl.h" role="src" />
12008 +   <file md5sum="9dffe726c9b6cfdd640e07782a0f409b" name="apc_futex.c" role="src" />
12009 +   <file md5sum="ff999238a10bfb6b715e4e8f54ec8326" name="apc_futex.h" role="src" />
12010 +   <file md5sum="33d241202d41095bc1b6fdafc1063cb9" name="apc_globals.h" role="src" />
12011 +   <file md5sum="3e6f98c635b18902aab221f29d8b70ec" name="apc_lock.h" role="src" />
12012 +   <file md5sum="0667187c715fea98569b51a491fb445b" name="apc_main.c" role="src" />
12013 +   <file md5sum="2e8f99d31b4d088eb14859c6e137544a" name="apc_main.h" role="src" />
12014 +   <file md5sum="e9e447ef3994b85d064c9a49f7ed0917" name="apc_mmap.c" role="src" />
12015 +   <file md5sum="a22df1256e20fef8160bbf9529723b50" name="apc_php.h" role="src" />
12016 +   <file md5sum="c285337c2e0b852de9f79ac5015a3fa7" name="apc_pthreadmutex.c" role="src" />
12017 +   <file md5sum="e4e6943b0cfb31facd1148c2dbfc4c93" name="apc_pthreadmutex.h" role="src" />
12018 +   <file md5sum="ea3822772adb45e0046faef855c32aba" name="apc_sem.c" role="src" />
12019 +   <file md5sum="1a7fb689f8d5b01fad537b277c81d59f" name="apc_sem.h" role="src" />
12020 +   <file md5sum="632e60d387e5555f4aa03a8948f52ea7" name="apc_shm.c" role="src" />
12021 +   <file md5sum="6de8e94976f01b2f48ef97020a008774" name="apc_shm.h" role="src" />
12022 +   <file md5sum="25d3e2a3d1c2f9afa8e103492ca7e89e" name="apc_sma.c" role="src" />
12023 +   <file md5sum="fdc0aebc501f2e29389611fa61084da0" name="apc_sma.h" role="src" />
12024 +   <file md5sum="ecd6cc1d56d99dbb7364d40c975fca5e" name="apc_spin.c" role="src" />
12025 +   <file md5sum="c716852258453471a6927f95a617e30f" name="apc_spin.h" role="src" />
12026 +   <file md5sum="17cceda297a61a9185bcafd7d897fad4" name="apc_stack.c" role="src" />
12027 +   <file md5sum="db2f213a3e616313d7864222874197ea" name="apc_stack.h" role="src" />
12028 +   <file md5sum="8cccb8ecfa2d5a893537b2c1a8b6b718" name="apc_zend.c" role="src" />
12029 +   <file md5sum="2ee61624ec5d779d02746ba7254aed14" name="apc_zend.h" role="src" />
12030 +   <file md5sum="113d74a5e70119a63fb86815bf50d03b" name="apc_signal.c" role="src" />
12031 +   <file md5sum="af4c7d0595ce32346f7ee37707d7dada" name="apc_signal.h" role="src" />
12032 +   <file md5sum="5cbb3cbe6477799e7e5fd816eda69937" name="config.m4" role="src" />
12033 +   <file md5sum="b748744f64eb4fbe201cce84cc3d7e33" name="php_apc.c" role="src" />
12034 +   <file md5sum="8c092033ef0cd8a5d207acb4f6ecec11" name="php_apc.h" role="src" />
12035 +   <file md5sum="76fe025ee14897783cee848dc1a77fa6" name="pgsql_s_lock.c" role="src" />
12036 +   <file md5sum="b67725b96ecf0e6851eccce632bab289" name="pgsql_s_lock.h" role="src" />
12037 +   <file md5sum="298e1c6721b21635ef46094c6a175af5" name="apc_fcntl_win32.c" role="src" />
12038 +   <file md5sum="072c127617c90a92331372a3b99494d3" name="apc_rfc1867.c" role="src" />
12039 +   <file md5sum="41fb805e7a151dc6edfe78780b5102d0" name="apc.php" role="php" />
12040 +  </dir>
12041 + </contents>
12042 + <dependencies>
12043 +  <required>
12044 +   <php>
12045 +    <min>4.3.0</min>
12046 +    <exclude>5.0.0</exclude>
12047 +    <exclude>5.0.1</exclude>
12048 +    <exclude>5.0.2</exclude>
12049 +    <exclude>5.0.3</exclude>
12050 +    <exclude>5.0.4</exclude>
12051 +    <exclude>5.0.5</exclude>
12052 +   </php>
12053 +   <pearinstaller>
12054 +    <min>1.4.0</min>
12055 +   </pearinstaller>
12056 +  </required>
12057 + </dependencies>
12058 + <providesextension>apc</providesextension>
12059 + <extsrcrelease>
12060 +  <configureoption default="yes" name="with-apxs" prompt="Use apxs to set compile flags (if using APC with Apache)?" />
12061 + </extsrcrelease>
12062 + <changelog>
12063 +  <release>
12064 +   <stability>
12065 +    <release>stable</release>
12066 +    <api>stable</api>
12067 +   </stability>
12068 +   <version>
12069 +    <release>2.0.0</release>
12070 +    <api>2.0.0</api>
12071 +   </version>
12072 +   <date>2003-07-01</date>
12073 +   <notes>Complete rework.</notes>
12074 +  </release>
12075 +  <release>
12076 +   <stability>
12077 +    <release>stable</release>
12078 +    <api>stable</api>
12079 +   </stability>
12080 +   <version>
12081 +    <release>2.0.1</release>
12082 +    <api>2.0.0</api>
12083 +   </version>
12084 +   <date>2003-07-01</date>
12085 +   <notes>Win32 support added.</notes>
12086 +  </release>
12087 +  <release>
12088 +   <stability>
12089 +    <release>stable</release>
12090 +    <api>stable</api>
12091 +   </stability>
12092 +   <version>
12093 +    <release>2.0.2</release>
12094 +    <api>2.0.0</api>
12095 +   </version>
12096 +   <date>2004-03-12</date>
12097 +   <notes>Fixed non-existant class bug.</notes>
12098 +  </release>
12099 +  <release>
12100 +   <stability>
12101 +    <release>stable</release>
12102 +    <api>stable</api>
12103 +   </stability>
12104 +   <version>
12105 +    <release>3.0.0</release>
12106 +    <api>3.0.0</api>
12107 +   </version>
12108 +   <date>2005-07-05</date>
12109 +   <notes>PHP-5.1 Support and numerous fixes</notes>
12110 +  </release>
12111 +  <release>
12112 +   <stability>
12113 +    <release>stable</release>
12114 +    <api>stable</api>
12115 +   </stability>
12116 +   <version>
12117 +    <release>3.0.1</release>
12118 +    <api>3.0.0</api>
12119 +   </version>
12120 +   <date>2005-07-05</date>
12121 +   <notes>PHP4 build fix</notes>
12122 +  </release>
12123 +  <release>
12124 +   <stability>
12125 +    <release>stable</release>
12126 +    <api>stable</api>
12127 +   </stability>
12128 +   <version>
12129 +    <release>3.0.2</release>
12130 +    <api>3.0.0</api>
12131 +   </version>
12132 +   <date>2005-07-05</date>
12133 +   <notes>Default to mmap and add a better error message for shmget failures</notes>
12134 +  </release>
12135 +  <release>
12136 +   <stability>
12137 +    <release>stable</release>
12138 +    <api>stable</api>
12139 +   </stability>
12140 +   <version>
12141 +    <release>3.0.3</release>
12142 +    <api>3.0.0</api>
12143 +   </version>
12144 +   <date>2005-07-07</date>
12145 +   <notes>Fix compile problem against PHP 5.0.x</notes>
12146 +  </release>
12147 +  <release>
12148 +   <stability>
12149 +    <release>stable</release>
12150 +    <api>stable</api>
12151 +   </stability>
12152 +   <version>
12153 +    <release>3.0.4</release>
12154 +    <api>3.0.0</api>
12155 +   </version>
12156 +   <date>2005-07-18</date>
12157 +   <notes>Add win32 support from Edin.
12158 +Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches
12159 +A couple of other minor fixes.</notes>
12160 +  </release>
12161 +  <release>
12162 +   <stability>
12163 +    <release>stable</release>
12164 +    <api>stable</api>
12165 +   </stability>
12166 +   <version>
12167 +    <release>3.0.5</release>
12168 +    <api>3.0.0</api>
12169 +   </version>
12170 +   <date>2005-07-27</date>
12171 +   <notes>Make it easier for sapis that only populate file_handle-&gt;filename to use APC. (Rasmus)
12172 +Support extensions such as bcompiler that need to hook into compile_file. (Val)
12173 +Ralf Becker&apos;s apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
12174 +Segfault in cache cleanup code (Ilia, Rasmus)</notes>
12175 +  </release>
12176 +  <release>
12177 +   <stability>
12178 +    <release>stable</release>
12179 +    <api>stable</api>
12180 +   </stability>
12181 +   <version>
12182 +    <release>3.0.6</release>
12183 +    <api>3.0.0</api>
12184 +   </version>
12185 +   <date>2005-07-30</date>
12186 +   <notes>Added apc.php to package.xml file.
12187 +Track per-entry memory usage. (Val)
12188 +Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
12189 +fcntl locking robustness fixes. (Rasmus)
12190 +Shared read-locks where possible. (Rasmus)
12191 +Added file_update_protection configuration parameter. (Rasmus)
12192 +Windows ZTS fixes (Frank)</notes>
12193 +  </release>
12194 +  <release>
12195 +   <stability>
12196 +    <release>stable</release>
12197 +    <api>stable</api>
12198 +   </stability>
12199 +   <version>
12200 +    <release>3.0.7</release>
12201 +    <api>3.0.0</api>
12202 +   </version>
12203 +   <date>2005-08-16</date>
12204 +   <notes>Fix to apc.php to show final segment in frag chart. (Ilia)
12205 +A couple of win32 fixes. (Frank)
12206 +Add apc.enable_cli ini directive. (Rasmus)
12207 +Add test cases. (Marcus)
12208 +Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
12209 +Simplify user cache handling by removing the user_cache_stack (Rasmus)
12210 +Fix apc_fetch() memory corruption (Andrei,Rasmus)
12211 +Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)</notes>
12212 +  </release>
12213 +  <release>
12214 +   <stability>
12215 +    <release>stable</release>
12216 +    <api>stable</api>
12217 +   </stability>
12218 +   <version>
12219 +    <release>3.0.8</release>
12220 +    <api>3.0.0</api>
12221 +   </version>
12222 +   <date>2005-08-24</date>
12223 +   <notes>Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
12224 +Cache corruption fix in cache-full cleanup code (Gopal)</notes>
12225 +  </release>
12226 +  <release>
12227 +   <stability>
12228 +    <release>stable</release>
12229 +    <api>stable</api>
12230 +   </stability>
12231 +   <version>
12232 +    <release>3.0.9</release>
12233 +    <api>3.0.0</api>
12234 +   </version>
12235 +   <date>2006-03-04</date>
12236 +   <notes>Eliminate rand() call when slam_defense is not set (Rasmus)
12237 +Fix for __isset problem (Gopal)
12238 +Rewrite allocator from a &quot;best fit&quot; to a &quot;next fit&quot; algorithm (Rasmus)
12239 +Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
12240 +Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
12241 +Add cache busy flag which is set when an expunge is underway (Rasmus)
12242 +Add automatic serialization of objects in apc_store() (Marcus)
12243 +64-bit .ini flag fix (Rasmus)
12244 +Static members fix (Gopal)
12245 +sma_cleanup() mem leak fix (Rasmus)
12246 +Fix for http://pecl.php.net/bugs/5311 (Rasmus)
12247 +Fix autoglobals JIT bug (Gopal)
12248 +Fix instance bug (Gopal)
12249 +Add a lock cleanup safety net to request shutdown (Rasmus)
12250 +Fix apc.slam_defense edge-case bug (Rasmus)
12251 +User entry memory usage tracking support (Ilia)
12252 +Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)</notes>
12253 +  </release>
12254 +  <release>
12255 +   <stability>
12256 +    <release>stable</release>
12257 +    <api>stable</api>
12258 +   </stability>
12259 +   <version>
12260 +    <release>3.0.10</release>
12261 +    <api>3.0.0</api>
12262 +   </version>
12263 +   <date>2006-03-11</date>
12264 +   <notes>* Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
12265 +  includes will not be stat&apos;ed for any changes.  You will have to restart the server if you
12266 +  change anything.  This mode increases performance quite a bit, especially if you have a
12267 +  lot of includes.
12268 +
12269 +* Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
12270 +  than it solves.  I&apos;ll need to revisit locking and signal handling at some point soon.</notes>
12271 +  </release>
12272 +  <release>
12273 +   <stability>
12274 +    <release>stable</release>
12275 +    <api>stable</api>
12276 +   </stability>
12277 +   <version>
12278 +    <release>3.0.11</release>
12279 +    <api>3.0.0</api>
12280 +   </version>
12281 +   <date>2006-08-16</date>
12282 +   <notes>* Made --enable-apc-mmap the default compile option (for real this time)
12283 +
12284 +* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
12285 +  only fetch header information to make it useful when you have tens of
12286 +  thousands of entries.  (Brian Shire)
12287 +
12288 +* 64-bit fixes (George)
12289 +
12290 +* Don&apos;t mix Full Path and Inode keys (George)
12291 +
12292 +* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
12293 +  require_once() and include_once() statements. (Sara)
12294 +
12295 +* Add a non-blocking write_lock for cache inserts.  This is a better approach
12296 +  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
12297 +
12298 +* A bit of work on the optimizer.  (Sara)
12299 +
12300 +* Various memory issues resolved. (Gopal)</notes>
12301 +  </release>
12302 +  <release>
12303 +   <stability>
12304 +    <release>stable</release>
12305 +    <api>stable</api>
12306 +   </stability>
12307 +   <version>
12308 +    <release>3.0.12</release>
12309 +    <api>3.0.0</api>
12310 +   </version>
12311 +   <date>2006-09-04</date>
12312 +   <notes>* Fix stray debug message
12313 +
12314 +* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
12315 +
12316 +* Performance boost - Replace multiple loops over the opcode
12317 +  array with a single loop for copying, jump fixups and auto
12318 +  global pre-fetches. (Gopal)
12319 +
12320 +* Perform fetch_global checks only in php5 and only if 
12321 +  auto_globals_jit is enabled. (Gopal)
12322 +
12323 +* Fix bug #8579 - scrub php4 classes&apos; function_table and default
12324 +  properties before inserting into cache. (Gopal)
12325 +
12326 +* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a 
12327 +  op1-&gt;type.  The opcodes applicable are ZEND_FETCH_R and 
12328 +  ZEND_FETCH_W. (Gopal)
12329 +
12330 +* PHP 5.2 Compatibility (Gopal)
12331 +
12332 +* Make the include_once override optional - default off (Sara)
12333 +
12334 +* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
12335 +
12336 +* Ensure that the apc_globals-&gt;cache_stack is cleared before the 
12337 +  shm cache is destroyed. Fixes segfault for corner-case i.e request
12338 +  shutdown (apc_deactivate) is not called before module shutdown 
12339 +  calls (php_apc_shutdown_globals)  (Gopal)
12340 +
12341 +* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
12342 +
12343 +* Fix memory leak of apc_cache_info_t-&gt;deleted_list (Gopal)</notes>
12344 +  </release>
12345 +  <release>
12346 +   <stability>
12347 +    <release>stable</release>
12348 +    <api>stable</api>
12349 +   </stability>
12350 +   <version>
12351 +    <release>3.0.12p1</release>
12352 +    <api>3.0.0</api>
12353 +   </version>
12354 +   <date>2006-09-05</date>
12355 +   <notes>* The only change here is a trivial PHP 4 build fix.</notes>
12356 +  </release>
12357 +  <release>
12358 +   <stability>
12359 +    <release>stable</release>
12360 +    <api>stable</api>
12361 +   </stability>
12362 +   <version>
12363 +    <release>3.0.12p2</release>
12364 +    <api>3.0.0</api>
12365 +   </version>
12366 +   <date>2006-09-05</date>
12367 +   <notes>* Let&apos;s get the version number right.  3.0.12p2 now.</notes>
12368 +  </release>
12369 +  <release>
12370 +   <stability>
12371 +    <release>stable</release>
12372 +    <api>stable</api>
12373 +   </stability>
12374 +   <version>
12375 +    <release>3.0.13</release>
12376 +    <api>3.0.0</api>
12377 +   </version>
12378 +   <date>2007-02-24</date>
12379 +   <notes>* PHP 5.2 file upload progress tracking support (Rasmus)
12380 +* Pthread mutex and spin locks (Shire)
12381 +* Recursive zval support for apc_fetch/_store (Shire, Gopal)
12382 +* apc.stat_ctime flag for ctime checks (Rasmus)
12383 +* Multiple key fetches with apc_fetch (Shire)
12384 +* Canary checks for shm memory deallocation (Gopal)
12385 +* Add hooks for external optimizer (Shire)
12386 +* Obsolete and remove apc optimizer (Gopal)
12387 +* APC info changes - cache insert rate, hit and miss rates (Shire)
12388 +* Fix apc_load_constants (Gopal)
12389 +* Rewrite dump opcode code to use vld (Gopal)
12390 +* Use apc_[ewn]print functions for error reporting (Shire) 
12391 +* Auto global fixes and refactoring (Gopal, Shire)
12392 +* Fix memory leaks in object serialization (Ilia)
12393 +* Memory cleanup code for destructor order (Gopal)
12394 +* Win32 build fixes (Ilia, Wez)
12395 +* ZTS and Php 4 build fixes (Bjori)
12396 +* Add apc_add() function (Rasmus)
12397 +* Add optional limited flag to apc_sma_info() (Rasmus)</notes>
12398 +  </release>
12399 +  <release>
12400 +   <stability>
12401 +    <release>stable</release>
12402 +    <api>stable</api>
12403 +   </stability>
12404 +   <version>
12405 +    <release>3.0.14</release>
12406 +    <api>3.0.0</api>
12407 +   </version>
12408 +   <date>2007-04-02</date>
12409 +   <notes>* Build fix (Shire)
12410 +* Don&apos;t hook the upload hook if APC is disabled (Rasmus)
12411 +* Local shadow cache support (Gopal)
12412 +* Avoid uneccessary loops over op_arrays for &quot;known&quot; auto-globals (Gopal)
12413 +* Fix apc_add() to overwrite timed out user entries (Rasmus)
12414 +* Fix double inclusion of files with conditional classes in php4 (Gopal)
12415 +* Allocator fixes to reduce fragmentation (Gopal)</notes>
12416 +  </release>
12417 +  <release>
12418 +   <stability>
12419 +    <release>stable</release>
12420 +    <api>stable</api>
12421 +   </stability>
12422 +   <version>
12423 +    <release>3.0.15</release>
12424 +    <api>3.0.0</api>
12425 +   </version>
12426 +   <date>2007-10-18</date>
12427 +   <notes>* Eliminate a per-request time() syscall (Rasmus)
12428 +* Added rfc1867 prefix, name, and freq ini options (Shire)
12429 +* Allow deletion of individual user cache entries via apc.php (Sara)
12430 +* Fix overzealous cleanup during RSHUTDOWN (Gopal)
12431 +* Fix memory alignment and locking issues (Gopal)
12432 +* Make apc_compile insert/replace entries (Shire)
12433 +* Make mixed inheritance recompile &amp; cache afresh  (Gopal)
12434 +* Make nostat mode search include_path for canonicalization (Gopal)
12435 +* ZTS &amp; other compile fixes (Gopal, Edin, Shire)</notes>
12436 +  </release>
12437 + </changelog>
12438 +</package>
12439 diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.c php-5.2.5/ext/apc/pgsql_s_lock.c
12440 --- php-5.2.5-orig/ext/apc/pgsql_s_lock.c       1969-12-31 18:00:00.000000000 -0600
12441 +++ php-5.2.5/ext/apc/pgsql_s_lock.c    2007-12-26 16:51:32.000000000 -0600
12442 @@ -0,0 +1,481 @@
12443 +/*
12444 +  +----------------------------------------------------------------------+
12445 +  | APC                                                                  |
12446 +  +----------------------------------------------------------------------+
12447 +  | Copyright (c) 2007 The PHP Group                                     |
12448 +  +----------------------------------------------------------------------+
12449 +  | This source file is subject to version 3.01 of the PHP license,      |
12450 +  | that is bundled with this package in the file LICENSE, and is        |
12451 +  | available through the world-wide-web at the following url:           |
12452 +  | http://www.php.net/license/3_01.txt                                  |
12453 +  | If you did not receive a copy of the PHP license and are unable to   |
12454 +  | obtain it through the world-wide-web, please send a note to          |
12455 +  | license@php.net so we can mail you a copy immediately.               |
12456 +  +----------------------------------------------------------------------+
12457 +  | The following code was ported from the PostgreSQL project, please    |
12458 +  |  see appropriate copyright notices that follow.                      |
12459 +  | Initial conversion by Brian Shire <shire@php.net>                    |
12460 +  +----------------------------------------------------------------------+
12461 +
12462 + */
12463 +
12464 +/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
12465 +
12466 +/*-------------------------------------------------------------------------
12467 + *
12468 + * s_lock.c
12469 + *        Hardware-dependent implementation of spinlocks.
12470 + *
12471 + *
12472 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
12473 + * Portions Copyright (c) 1994, Regents of the University of California
12474 + *
12475 + *
12476 + * IDENTIFICATION
12477 + *       $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
12478 + *
12479 + *-------------------------------------------------------------------------
12480 + */
12481 +/* #include "postgres.h"  -- Removed for APC */
12482 +
12483 +/* -- Added for APC -- */
12484 +#include "apc.h"
12485 +#ifdef APC_SPIN_LOCKS
12486 +
12487 +#ifdef S_LOCK_TEST
12488 +#include <stdio.h>
12489 +#endif
12490 +#ifndef WIN32
12491 +#include <sys/select.h>
12492 +#endif
12493 +/* ---- */
12494 +
12495 +#include <time.h>
12496 +#include <unistd.h>
12497 +
12498 +/* #include "storage/s_lock.h" -- Removed for APC */
12499 +#include "pgsql_s_lock.h"
12500 +
12501 +static int     spins_per_delay = DEFAULT_SPINS_PER_DELAY;
12502 +
12503 +
12504 +/* -- APC specific additions ------------------------------*/
12505 +/* The following dependencies have been copied from 
12506 + * other pgsql source files.  The original locations 
12507 + * have been noted.
12508 + */
12509 +
12510 +/* -- from include/c.h -- */
12511 +#ifndef TRUE
12512 +#define TRUE  1
12513 +#endif
12514 +
12515 +#ifndef FALSE
12516 +#define FALSE 0
12517 +#endif
12518 +
12519 +/* -- from include/pg_config_manual.h -- */
12520 +#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
12521 +
12522 +/*
12523 + * Max
12524 + *    Return the maximum of two numbers.
12525 + */
12526 +#define Max(x, y)   ((x) > (y) ? (x) : (y))
12527 +
12528 +/* -- from include/c.h -- */
12529 +/*
12530 + * Min
12531 + *    Return the minimum of two numbers.
12532 + */
12533 +#define Min(x, y)   ((x) < (y) ? (x) : (y))
12534 +
12535 +
12536 +/* -- from backend/port/win32/signal.c -- */
12537 +/*
12538 + * pg_usleep --- delay the specified number of microseconds.
12539 + *
12540 + * NOTE: although the delay is specified in microseconds, the effective
12541 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen.  Expect
12542 + * the requested delay to be rounded up to the next resolution boundary.
12543 + *
12544 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
12545 + */
12546 +void
12547 +pg_usleep(long microsec)
12548 +{
12549 +       if (microsec > 0)
12550 +       {
12551 +#ifndef WIN32
12552 +               struct timeval delay;
12553 +
12554 +               delay.tv_sec = microsec / 1000000L;
12555 +               delay.tv_usec = microsec % 1000000L;
12556 +               (void) select(0, NULL, NULL, NULL, &delay);
12557 +#else
12558 +               SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
12559 +#endif
12560 +       }
12561 +}
12562 +
12563 +/* -- End APC specific additions ------------------------------*/
12564 +
12565 +
12566 +/*
12567 + * s_lock_stuck() - complain about a stuck spinlock
12568 + */
12569 +static void
12570 +s_lock_stuck(volatile slock_t *lock, const char *file, int line)
12571 +{
12572 +#if defined(S_LOCK_TEST)
12573 +       fprintf(stderr,
12574 +                       "\nStuck spinlock (%p) detected at %s:%d.\n",
12575 +                       lock, file, line);
12576 +       exit(1);
12577 +#else
12578 +  /* -- Removed for APC
12579 +       elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
12580 +                lock, file, line);
12581 +  */
12582 +  apc_eprint("Stuck spinlock (%p) detected", lock);
12583 +#endif
12584 +}
12585 +
12586 +
12587 +/*
12588 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
12589 + */
12590 +void
12591 +s_lock(volatile slock_t *lock, const char *file, int line)
12592 +{
12593 +       /*
12594 +        * We loop tightly for awhile, then delay using pg_usleep() and try again.
12595 +        * Preferably, "awhile" should be a small multiple of the maximum time we
12596 +        * expect a spinlock to be held.  100 iterations seems about right as an
12597 +        * initial guess.  However, on a uniprocessor the loop is a waste of
12598 +        * cycles, while in a multi-CPU scenario it's usually better to spin a bit
12599 +        * longer than to call the kernel, so we try to adapt the spin loop count
12600 +        * depending on whether we seem to be in a uniprocessor or multiprocessor.
12601 +        *
12602 +        * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
12603 +        * be wrong; there are platforms where that can result in a "stuck
12604 +        * spinlock" failure.  This has been seen particularly on Alphas; it seems
12605 +        * that the first TAS after returning from kernel space will always fail
12606 +        * on that hardware.
12607 +        *
12608 +        * Once we do decide to block, we use randomly increasing pg_usleep()
12609 +        * delays. The first delay is 1 msec, then the delay randomly increases to
12610 +        * about one second, after which we reset to 1 msec and start again.  The
12611 +        * idea here is that in the presence of heavy contention we need to
12612 +        * increase the delay, else the spinlock holder may never get to run and
12613 +        * release the lock.  (Consider situation where spinlock holder has been
12614 +        * nice'd down in priority by the scheduler --- it will not get scheduled
12615 +        * until all would-be acquirers are sleeping, so if we always use a 1-msec
12616 +        * sleep, there is a real possibility of starvation.)  But we can't just
12617 +        * clamp the delay to an upper bound, else it would take a long time to
12618 +        * make a reasonable number of tries.
12619 +        *
12620 +        * We time out and declare error after NUM_DELAYS delays (thus, exactly
12621 +        * that many tries).  With the given settings, this will usually take 2 or
12622 +        * so minutes.  It seems better to fix the total number of tries (and thus
12623 +        * the probability of unintended failure) than to fix the total time
12624 +        * spent.
12625 +        *
12626 +        * The pg_usleep() delays are measured in milliseconds because 1 msec is a
12627 +        * common resolution limit at the OS level for newer platforms. On older
12628 +        * platforms the resolution limit is usually 10 msec, in which case the
12629 +        * total delay before timeout will be a bit more.
12630 +        */
12631 +#define MIN_SPINS_PER_DELAY 10
12632 +#define MAX_SPINS_PER_DELAY 1000
12633 +#define NUM_DELAYS                     1000
12634 +#define MIN_DELAY_MSEC         1
12635 +#define MAX_DELAY_MSEC         1000
12636 +
12637 +       int                     spins = 0;
12638 +       int                     delays = 0;
12639 +       int                     cur_delay = 0;
12640 +  
12641 +       while (TAS(lock))
12642 +       {
12643 +               /* CPU-specific delay each time through the loop */
12644 +               SPIN_DELAY();
12645 +
12646 +               /* Block the process every spins_per_delay tries */
12647 +               if (++spins >= spins_per_delay)
12648 +               {
12649 +                       if (++delays > NUM_DELAYS)
12650 +                               s_lock_stuck(lock, file, line);
12651 +
12652 +                       if (cur_delay == 0) /* first time to delay? */
12653 +                               cur_delay = MIN_DELAY_MSEC;
12654 +
12655 +                       pg_usleep(cur_delay * 1000L);
12656 +
12657 +#if defined(S_LOCK_TEST)
12658 +                       fprintf(stdout, "*");
12659 +                       fflush(stdout);
12660 +#endif
12661 +
12662 +                       /* increase delay by a random fraction between 1X and 2X */
12663 +                       cur_delay += (int) (cur_delay *
12664 +                                         ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
12665 +                       /* wrap back to minimum delay when max is exceeded */
12666 +                       if (cur_delay > MAX_DELAY_MSEC)
12667 +                               cur_delay = MIN_DELAY_MSEC;
12668 +
12669 +                       spins = 0;
12670 +               }
12671 +       }
12672 +
12673 +       /*
12674 +        * If we were able to acquire the lock without delaying, it's a good
12675 +        * indication we are in a multiprocessor.  If we had to delay, it's a sign
12676 +        * (but not a sure thing) that we are in a uniprocessor. Hence, we
12677 +        * decrement spins_per_delay slowly when we had to delay, and increase it
12678 +        * rapidly when we didn't.  It's expected that spins_per_delay will
12679 +        * converge to the minimum value on a uniprocessor and to the maximum
12680 +        * value on a multiprocessor.
12681 +        *
12682 +        * Note: spins_per_delay is local within our current process. We want to
12683 +        * average these observations across multiple backends, since it's
12684 +        * relatively rare for this function to even get entered, and so a single
12685 +        * backend might not live long enough to converge on a good value.      That
12686 +        * is handled by the two routines below.
12687 +        */
12688 +       if (cur_delay == 0)
12689 +       {
12690 +               /* we never had to delay */
12691 +               if (spins_per_delay < MAX_SPINS_PER_DELAY)
12692 +                       spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
12693 +       }
12694 +       else
12695 +       {
12696 +               if (spins_per_delay > MIN_SPINS_PER_DELAY)
12697 +                       spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
12698 +       }
12699 +}
12700 +
12701 +
12702 +#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
12703 +/*
12704 + * Set local copy of spins_per_delay during backend startup.
12705 + *
12706 + * NB: this has to be pretty fast as it is called while holding a spinlock
12707 + */
12708 +void
12709 +set_spins_per_delay(int shared_spins_per_delay)
12710 +{
12711 +       spins_per_delay = shared_spins_per_delay;
12712 +}
12713 +
12714 +/*
12715 + * Update shared estimate of spins_per_delay during backend exit.
12716 + *
12717 + * NB: this has to be pretty fast as it is called while holding a spinlock
12718 + */
12719 +int
12720 +update_spins_per_delay(int shared_spins_per_delay)
12721 +{
12722 +       /*
12723 +        * We use an exponential moving average with a relatively slow adaption
12724 +        * rate, so that noise in any one backend's result won't affect the shared
12725 +        * value too much.      As long as both inputs are within the allowed range,
12726 +        * the result must be too, so we need not worry about clamping the result.
12727 +        *
12728 +        * We deliberately truncate rather than rounding; this is so that single
12729 +        * adjustments inside a backend can affect the shared estimate (see the
12730 +        * asymmetric adjustment rules above).
12731 +        */
12732 +       return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
12733 +}
12734 +#endif
12735 +
12736 +/*
12737 + * Various TAS implementations that cannot live in s_lock.h as no inline
12738 + * definition exists (yet).
12739 + * In the future, get rid of tas.[cso] and fold it into this file.
12740 + *
12741 + * If you change something here, you will likely need to modify s_lock.h too,
12742 + * because the definitions for these are split between this file and s_lock.h.
12743 + */
12744 +
12745 +
12746 +#ifdef HAVE_SPINLOCKS                  /* skip spinlocks if requested */
12747 +
12748 +
12749 +#if defined(__GNUC__)
12750 +
12751 +/*
12752 + * All the gcc flavors that are not inlined
12753 + */
12754 +
12755 +
12756 +/*
12757 + * Note: all the if-tests here probably ought to be testing gcc version
12758 + * rather than platform, but I don't have adequate info to know what to
12759 + * write.  Ideally we'd flush all this in favor of the inline version.
12760 + */
12761 +#if defined(__m68k__) && !defined(__linux__)
12762 +/* really means: extern int tas(slock_t* **lock); */
12763 +static void
12764 +tas_dummy()
12765 +{
12766 +       __asm__         __volatile__(
12767 +#if defined(__NetBSD__) && defined(__ELF__)
12768 +/* no underscore for label and % for registers */
12769 +                                                                                "\
12770 +.global                tas                             \n\
12771 +tas:                                                   \n\
12772 +                       movel   %sp@(0x4),%a0   \n\
12773 +                       tas     %a0@            \n\
12774 +                       beq     _success        \n\
12775 +                       moveq   #-128,%d0       \n\
12776 +                       rts                             \n\
12777 +_success:                                              \n\
12778 +                       moveq   #0,%d0          \n\
12779 +                       rts                             \n"
12780 +#else
12781 +                                                                                "\
12782 +.global                _tas                            \n\
12783 +_tas:                                                  \n\
12784 +                       movel   sp@(0x4),a0     \n\
12785 +                       tas     a0@                     \n\
12786 +                       beq     _success        \n\
12787 +                       moveq   #-128,d0        \n\
12788 +                       rts                                     \n\
12789 +_success:                                              \n\
12790 +                       moveq   #0,d0           \n\
12791 +                       rts                                     \n"
12792 +#endif   /* __NetBSD__ && __ELF__ */
12793 +       );
12794 +}
12795 +#endif   /* __m68k__ && !__linux__ */
12796 +#else                                                  /* not __GNUC__ */
12797 +
12798 +/*
12799 + * All non gcc
12800 + */
12801 +
12802 +
12803 +#if defined(sun3)
12804 +static void
12805 +tas_dummy()                                            /* really means: extern int tas(slock_t
12806 +                                                                * *lock); */
12807 +{
12808 +       asm("LLA0:");
12809 +       asm("   .data");
12810 +       asm("   .text");
12811 +       asm("|#PROC# 04");
12812 +       asm("   .globl  _tas");
12813 +       asm("_tas:");
12814 +       asm("|#PROLOGUE# 1");
12815 +       asm("   movel   sp@(0x4),a0");
12816 +       asm("   tas a0@");
12817 +       asm("   beq LLA1");
12818 +       asm("   moveq   #-128,d0");
12819 +       asm("   rts");
12820 +       asm("LLA1:");
12821 +       asm("   moveq   #0,d0");
12822 +       asm("   rts");
12823 +       asm("   .data");
12824 +}
12825 +#endif   /* sun3 */
12826 +#endif   /* not __GNUC__ */
12827 +#endif   /* HAVE_SPINLOCKS */
12828 +
12829 +
12830 +
12831 +/*****************************************************************************/
12832 +#if defined(S_LOCK_TEST)
12833 +
12834 +/*
12835 + * test program for verifying a port's spinlock support.
12836 + */
12837 +
12838 +struct test_lock_struct
12839 +{
12840 +       char            pad1;
12841 +       slock_t         lock;
12842 +       char            pad2;
12843 +};
12844 +
12845 +volatile struct test_lock_struct test_lock;
12846 +
12847 +int
12848 +main()
12849 +{
12850 +       srandom((unsigned int) time(NULL));
12851 +
12852 +       test_lock.pad1 = test_lock.pad2 = 0x44;
12853 +
12854 +       S_INIT_LOCK(&test_lock.lock);
12855 +
12856 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12857 +       {
12858 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12859 +               return 1;
12860 +       }
12861 +
12862 +       if (!S_LOCK_FREE(&test_lock.lock))
12863 +       {
12864 +               printf("S_LOCK_TEST: failed, lock not initialized\n");
12865 +               return 1;
12866 +       }
12867 +
12868 +       S_LOCK(&test_lock.lock);
12869 +
12870 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12871 +       {
12872 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12873 +               return 1;
12874 +       }
12875 +
12876 +       if (S_LOCK_FREE(&test_lock.lock))
12877 +       {
12878 +               printf("S_LOCK_TEST: failed, lock not locked\n");
12879 +               return 1;
12880 +       }
12881 +
12882 +       S_UNLOCK(&test_lock.lock);
12883 +
12884 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12885 +       {
12886 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12887 +               return 1;
12888 +       }
12889 +
12890 +       if (!S_LOCK_FREE(&test_lock.lock))
12891 +       {
12892 +               printf("S_LOCK_TEST: failed, lock not unlocked\n");
12893 +               return 1;
12894 +       }
12895 +
12896 +       S_LOCK(&test_lock.lock);
12897 +
12898 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12899 +       {
12900 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12901 +               return 1;
12902 +       }
12903 +
12904 +       if (S_LOCK_FREE(&test_lock.lock))
12905 +       {
12906 +               printf("S_LOCK_TEST: failed, lock not re-locked\n");
12907 +               return 1;
12908 +       }
12909 +
12910 +       printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
12911 +       printf("             exit with a 'stuck spinlock' message\n");
12912 +       printf("             if S_LOCK() and TAS() are working.\n");
12913 +       fflush(stdout);
12914 +
12915 +       s_lock(&test_lock.lock, __FILE__, __LINE__);
12916 +
12917 +       printf("S_LOCK_TEST: failed, lock not locked\n");
12918 +       return 1;
12919 +}
12920 +
12921 +#endif   /* S_LOCK_TEST */
12922 +
12923 +#endif /* APC_SPIN_LOCKS */
12924 diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.h php-5.2.5/ext/apc/pgsql_s_lock.h
12925 --- php-5.2.5-orig/ext/apc/pgsql_s_lock.h       1969-12-31 18:00:00.000000000 -0600
12926 +++ php-5.2.5/ext/apc/pgsql_s_lock.h    2007-12-26 16:51:32.000000000 -0600
12927 @@ -0,0 +1,928 @@
12928 +/*
12929 +  +----------------------------------------------------------------------+
12930 +  | APC                                                                  |
12931 +  +----------------------------------------------------------------------+
12932 +  | Copyright (c) 2007 The PHP Group                                     |
12933 +  +----------------------------------------------------------------------+
12934 +  | This source file is subject to version 3.01 of the PHP license,      |
12935 +  | that is bundled with this package in the file LICENSE, and is        |
12936 +  | available through the world-wide-web at the following url:           |
12937 +  | http://www.php.net/license/3_01.txt                                  |
12938 +  | If you did not receive a copy of the PHP license and are unable to   |
12939 +  | obtain it through the world-wide-web, please send a note to          |
12940 +  | license@php.net so we can mail you a copy immediately.               |
12941 +  +----------------------------------------------------------------------+
12942 +  | The following code was ported from the PostgreSQL project, please    |
12943 +  |  see appropriate copyright notices that follow.                      |
12944 +  | Initial conversion by Brian Shire <shire@php.net>                    |
12945 +  +----------------------------------------------------------------------+
12946 +
12947 + */
12948 +
12949 +/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
12950 +
12951 +/*-------------------------------------------------------------------------
12952 + *
12953 + * s_lock.h
12954 + *        Hardware-dependent implementation of spinlocks.
12955 + *
12956 + *     NOTE: none of the macros in this file are intended to be called directly.
12957 + *     Call them through the hardware-independent macros in spin.h.
12958 + *
12959 + *     The following hardware-dependent macros must be provided for each
12960 + *     supported platform:
12961 + *
12962 + *     void S_INIT_LOCK(slock_t *lock)
12963 + *             Initialize a spinlock (to the unlocked state).
12964 + *
12965 + *     void S_LOCK(slock_t *lock)
12966 + *             Acquire a spinlock, waiting if necessary.
12967 + *             Time out and abort() if unable to acquire the lock in a
12968 + *             "reasonable" amount of time --- typically ~ 1 minute.
12969 + *
12970 + *     void S_UNLOCK(slock_t *lock)
12971 + *             Unlock a previously acquired lock.
12972 + *
12973 + *     bool S_LOCK_FREE(slock_t *lock)
12974 + *             Tests if the lock is free. Returns TRUE if free, FALSE if locked.
12975 + *             This does *not* change the state of the lock.
12976 + *
12977 + *     void SPIN_DELAY(void)
12978 + *             Delay operation to occur inside spinlock wait loop.
12979 + *
12980 + *     Note to implementors: there are default implementations for all these
12981 + *     macros at the bottom of the file.  Check if your platform can use
12982 + *     these or needs to override them.
12983 + *
12984 + *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
12985 + *     TAS():
12986 + *
12987 + *     int TAS(slock_t *lock)
12988 + *             Atomic test-and-set instruction.  Attempt to acquire the lock,
12989 + *             but do *not* wait.      Returns 0 if successful, nonzero if unable
12990 + *             to acquire the lock.
12991 + *
12992 + *     TAS() is NOT part of the API, and should never be called directly.
12993 + *
12994 + *     CAUTION: on some platforms TAS() may sometimes report failure to acquire
12995 + *     a lock even when the lock is not locked.  For example, on Alpha TAS()
12996 + *     will "fail" if interrupted.  Therefore TAS() should always be invoked
12997 + *     in a retry loop, even if you are certain the lock is free.
12998 + *
12999 + *     ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
13000 + *     points, ie, loads and stores of other values must not be moved across
13001 + *     a lock or unlock.  In most cases it suffices to make the operation be
13002 + *     done through a "volatile" pointer.
13003 + *
13004 + *     On most supported platforms, TAS() uses a tas() function written
13005 + *     in assembly language to execute a hardware atomic-test-and-set
13006 + *     instruction.  Equivalent OS-supplied mutex routines could be used too.
13007 + *
13008 + *     If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
13009 + *     defined), then we fall back on an emulation that uses SysV semaphores
13010 + *     (see spin.c).  This emulation will be MUCH MUCH slower than a proper TAS()
13011 + *     implementation, because of the cost of a kernel call per lock or unlock.
13012 + *     An old report is that Postgres spends around 40% of its time in semop(2)
13013 + *     when using the SysV semaphore code.
13014 + *
13015 + *
13016 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
13017 + * Portions Copyright (c) 1994, Regents of the University of California
13018 + *
13019 + *       $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
13020 + *
13021 + *-------------------------------------------------------------------------
13022 + */
13023 +#ifndef S_LOCK_H
13024 +#define S_LOCK_H
13025 +
13026 +/** APC namespace protection ************************************************/
13027 +/* hack to protect against any possible runtime namespace collisions...*/
13028 +#define pg_usleep               apc_spin_pg_usleep
13029 +#define s_lock                  apc_spin_s_lock
13030 +#define spins_per_delay         apc_spin_spins_per_delay
13031 +/****************************************************************************/
13032 +
13033 +
13034 +/* #include "storage/pg_sema.h"   -- Removed for APC */
13035 +
13036 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
13037 +
13038 +#ifdef HAVE_SPINLOCKS  /* skip spinlocks if requested */
13039 +
13040 +
13041 +#if defined(__GNUC__) || defined(__ICC)
13042 +/*************************************************************************
13043 + * All the gcc inlines
13044 + * Gcc consistently defines the CPU as __cpu__.
13045 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
13046 + */
13047 +
13048 +/*----------
13049 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
13050 +
13051 +       __asm__ __volatile__(
13052 +               "       instruction     \n"
13053 +               "       instruction     \n"
13054 +               "       instruction     \n"
13055 +:              "=r"(_res), "+m"(*lock)         // return register, in/out lock value
13056 +:              "r"(lock)                                       // lock pointer, in input register
13057 +:              "memory", "cc");                        // show clobbered registers here
13058 +
13059 + * The output-operands list (after first colon) should always include
13060 + * "+m"(*lock), whether or not the asm code actually refers to this
13061 + * operand directly.  This ensures that gcc believes the value in the
13062 + * lock variable is used and set by the asm code.  Also, the clobbers
13063 + * list (after third colon) should always include "memory"; this prevents
13064 + * gcc from thinking it can cache the values of shared-memory fields
13065 + * across the asm code.  Add "cc" if your asm code changes the condition
13066 + * code register, and also list any temp registers the code uses.
13067 + *----------
13068 + */
13069 +
13070 +
13071 +#ifdef __i386__                /* 32-bit i386 */
13072 +#define HAS_TEST_AND_SET
13073 +
13074 +typedef unsigned char slock_t;
13075 +
13076 +#define TAS(lock) tas(lock)
13077 +
13078 +static __inline__ int
13079 +tas(volatile slock_t *lock)
13080 +{
13081 +       register slock_t _res = 1;
13082 +
13083 +       /*
13084 +        * Use a non-locking test before asserting the bus lock.  Note that the
13085 +        * extra test appears to be a small loss on some x86 platforms and a small
13086 +        * win on others; it's by no means clear that we should keep it.
13087 +        */
13088 +       __asm__ __volatile__(
13089 +               "       cmpb    $0,%1   \n"
13090 +               "       jne             1f              \n"
13091 +               "       lock                    \n"
13092 +               "       xchgb   %0,%1   \n"
13093 +               "1: \n"
13094 +:              "+q"(_res), "+m"(*lock)
13095 +:
13096 +:              "memory", "cc");
13097 +       return (int) _res;
13098 +}
13099 +
13100 +#define SPIN_DELAY() spin_delay()
13101 +
13102 +static __inline__ void
13103 +spin_delay(void)
13104 +{
13105 +       /*
13106 +        * This sequence is equivalent to the PAUSE instruction ("rep" is
13107 +        * ignored by old IA32 processors if the following instruction is
13108 +        * not a string operation); the IA-32 Architecture Software
13109 +        * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
13110 +        * PAUSE in the inner loop of a spin lock is necessary for good
13111 +        * performance:
13112 +        *
13113 +        *     The PAUSE instruction improves the performance of IA-32
13114 +        *     processors supporting Hyper-Threading Technology when
13115 +        *     executing spin-wait loops and other routines where one
13116 +        *     thread is accessing a shared lock or semaphore in a tight
13117 +        *     polling loop. When executing a spin-wait loop, the
13118 +        *     processor can suffer a severe performance penalty when
13119 +        *     exiting the loop because it detects a possible memory order
13120 +        *     violation and flushes the core processor's pipeline. The
13121 +        *     PAUSE instruction provides a hint to the processor that the
13122 +        *     code sequence is a spin-wait loop. The processor uses this
13123 +        *     hint to avoid the memory order violation and prevent the
13124 +        *     pipeline flush. In addition, the PAUSE instruction
13125 +        *     de-pipelines the spin-wait loop to prevent it from
13126 +        *     consuming execution resources excessively.
13127 +        */
13128 +       __asm__ __volatile__(
13129 +               " rep; nop                      \n");
13130 +}
13131 +
13132 +#endif  /* __i386__ */
13133 +
13134 +
13135 +#ifdef __x86_64__              /* AMD Opteron, Intel EM64T */
13136 +#define HAS_TEST_AND_SET
13137 +
13138 +typedef unsigned char slock_t;
13139 +
13140 +#define TAS(lock) tas(lock)
13141 +
13142 +static __inline__ int
13143 +tas(volatile slock_t *lock)
13144 +{
13145 +       register slock_t _res = 1;
13146 +
13147 +       /*
13148 +        * On Opteron, using a non-locking test before the locking instruction
13149 +        * is a huge loss.  On EM64T, it appears to be a wash or small loss,
13150 +        * so we needn't bother to try to distinguish the sub-architectures.
13151 +        */
13152 +       __asm__ __volatile__(
13153 +               "       lock                    \n"
13154 +               "       xchgb   %0,%1   \n"
13155 +:              "+q"(_res), "+m"(*lock)
13156 +:
13157 +:              "memory", "cc");
13158 +       return (int) _res;
13159 +}
13160 +
13161 +#define SPIN_DELAY() spin_delay()
13162 +
13163 +static __inline__ void
13164 +spin_delay(void)
13165 +{
13166 +       /*
13167 +        * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
13168 +        * Opteron, but it may be of some use on EM64T, so we keep it.
13169 +        */
13170 +       __asm__ __volatile__(
13171 +               " rep; nop                      \n");
13172 +}
13173 +
13174 +#endif  /* __x86_64__ */
13175 +
13176 +
13177 +#if defined(__ia64__) || defined(__ia64)       /* Intel Itanium */
13178 +#define HAS_TEST_AND_SET
13179 +
13180 +typedef unsigned int slock_t;
13181 +
13182 +#define TAS(lock) tas(lock)
13183 +
13184 +#ifndef __INTEL_COMPILER
13185 +
13186 +static __inline__ int
13187 +tas(volatile slock_t *lock)
13188 +{
13189 +       long int        ret;
13190 +
13191 +       __asm__ __volatile__(
13192 +               "       xchg4   %0=%1,%2        \n"
13193 +:              "=r"(ret), "+m"(*lock)
13194 +:              "r"(1)
13195 +:              "memory");
13196 +       return (int) ret;
13197 +}
13198 +
13199 +#else /* __INTEL_COMPILER */
13200 +
13201 +static __inline__ int
13202 +tas(volatile slock_t *lock)
13203 +{
13204 +       int             ret;
13205 +
13206 +       ret = _InterlockedExchange(lock,1);     /* this is a xchg asm macro */
13207 +
13208 +       return ret;
13209 +}
13210 +
13211 +#endif /* __INTEL_COMPILER */
13212 +#endif  /* __ia64__ || __ia64 */
13213 +
13214 +
13215 +#if defined(__arm__) || defined(__arm)
13216 +#define HAS_TEST_AND_SET
13217 +
13218 +typedef unsigned char slock_t;
13219 +
13220 +#define TAS(lock) tas(lock)
13221 +
13222 +static __inline__ int
13223 +tas(volatile slock_t *lock)
13224 +{
13225 +       register slock_t _res = 1;
13226 +
13227 +       __asm__ __volatile__(
13228 +               "       swpb    %0, %0, [%2]    \n"
13229 +:              "+r"(_res), "+m"(*lock)
13230 +:              "r"(lock)
13231 +:              "memory");
13232 +       return (int) _res;
13233 +}
13234 +
13235 +#endif  /* __arm__ */
13236 +
13237 +
13238 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
13239 +#if defined(__s390__) || defined(__s390x__)
13240 +#define HAS_TEST_AND_SET
13241 +
13242 +typedef unsigned int slock_t;
13243 +
13244 +#define TAS(lock)         tas(lock)
13245 +
13246 +static __inline__ int
13247 +tas(volatile slock_t *lock)
13248 +{
13249 +       int                     _res = 0;
13250 +
13251 +       __asm__ __volatile__(
13252 +               "       cs      %0,%3,0(%2)             \n"
13253 +:              "+d"(_res), "+m"(*lock)
13254 +:              "a"(lock), "d"(1)
13255 +:              "memory", "cc");
13256 +       return _res;
13257 +}
13258 +
13259 +#endif  /* __s390__ || __s390x__ */
13260 +
13261 +
13262 +#if defined(__sparc__)         /* Sparc */
13263 +#define HAS_TEST_AND_SET
13264 +
13265 +typedef unsigned char slock_t;
13266 +
13267 +#define TAS(lock) tas(lock)
13268 +
13269 +static __inline__ int
13270 +tas(volatile slock_t *lock)
13271 +{
13272 +       register slock_t _res;
13273 +
13274 +       /*
13275 +        *      See comment in /pg/backend/port/tas/solaris_sparc.s for why this
13276 +        *      uses "ldstub", and that file uses "cas".  gcc currently generates
13277 +        *      sparcv7-targeted binaries, so "cas" use isn't possible.
13278 +        */
13279 +       __asm__ __volatile__(
13280 +               "       ldstub  [%2], %0        \n"
13281 +:              "=r"(_res), "+m"(*lock)
13282 +:              "r"(lock)
13283 +:              "memory");
13284 +       return (int) _res;
13285 +}
13286 +
13287 +#endif  /* __sparc__ */
13288 +
13289 +
13290 +/* PowerPC */
13291 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
13292 +#define HAS_TEST_AND_SET
13293 +
13294 +#if defined(__ppc64__) || defined(__powerpc64__)
13295 +typedef unsigned long slock_t;
13296 +#else
13297 +typedef unsigned int slock_t;
13298 +#endif
13299 +
13300 +#define TAS(lock) tas(lock)
13301 +/*
13302 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
13303 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
13304 + */
13305 +static __inline__ int
13306 +tas(volatile slock_t *lock)
13307 +{
13308 +       slock_t _t;
13309 +       int _res;
13310 +
13311 +       __asm__ __volatile__(
13312 +"      lwarx   %0,0,%3         \n"
13313 +"      cmpwi   %0,0            \n"
13314 +"      bne     1f                      \n"
13315 +"      addi    %0,%0,1         \n"
13316 +"      stwcx.  %0,0,%3         \n"
13317 +"      beq     2f              \n"
13318 +"1:    li      %1,1            \n"
13319 +"      b               3f                      \n"
13320 +"2:                                            \n"
13321 +"      isync                           \n"
13322 +"      li      %1,0            \n"
13323 +"3:                                            \n"
13324 +
13325 +:      "=&r"(_t), "=r"(_res), "+m"(*lock)
13326 +:      "r"(lock)
13327 +:      "memory", "cc");
13328 +       return _res;
13329 +}
13330 +
13331 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
13332 +#define S_UNLOCK(lock) \
13333 +do \
13334 +{ \
13335 +       __asm__ __volatile__ (" sync \n"); \
13336 +       *((volatile slock_t *) (lock)) = 0; \
13337 +} while (0)
13338 +
13339 +#endif /* powerpc */
13340 +
13341 +
13342 +/* Linux Motorola 68k */
13343 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
13344 +#define HAS_TEST_AND_SET
13345 +
13346 +typedef unsigned char slock_t;
13347 +
13348 +#define TAS(lock) tas(lock)
13349 +
13350 +static __inline__ int
13351 +tas(volatile slock_t *lock)
13352 +{
13353 +       register int rv;
13354 +
13355 +       __asm__ __volatile__(
13356 +               "       clrl    %0              \n"
13357 +               "       tas             %1              \n"
13358 +               "       sne             %0              \n"
13359 +:              "=d"(rv), "+m"(*lock)
13360 +:
13361 +:              "memory", "cc");
13362 +       return rv;
13363 +}
13364 +
13365 +#endif  /* (__mc68000__ || __m68k__) && __linux__ */
13366 +
13367 +
13368 +/*
13369 + * VAXen -- even multiprocessor ones
13370 + * (thanks to Tom Ivar Helbekkmo)
13371 + */
13372 +#if defined(__vax__)
13373 +#define HAS_TEST_AND_SET
13374 +
13375 +typedef unsigned char slock_t;
13376 +
13377 +#define TAS(lock) tas(lock)
13378 +
13379 +static __inline__ int
13380 +tas(volatile slock_t *lock)
13381 +{
13382 +       register int    _res;
13383 +
13384 +       __asm__ __volatile__(
13385 +               "       movl    $1, %0                  \n"
13386 +               "       bbssi   $0, (%2), 1f    \n"
13387 +               "       clrl    %0                              \n"
13388 +               "1: \n"
13389 +:              "=&r"(_res), "+m"(*lock)
13390 +:              "r"(lock)
13391 +:              "memory");
13392 +       return _res;
13393 +}
13394 +
13395 +#endif  /* __vax__ */
13396 +
13397 +
13398 +#if defined(__ns32k__)         /* National Semiconductor 32K */
13399 +#define HAS_TEST_AND_SET
13400 +
13401 +typedef unsigned char slock_t;
13402 +
13403 +#define TAS(lock) tas(lock)
13404 +
13405 +static __inline__ int
13406 +tas(volatile slock_t *lock)
13407 +{
13408 +       register int    _res;
13409 +
13410 +       __asm__ __volatile__(
13411 +               "       sbitb   0, %1   \n"
13412 +               "       sfsd    %0              \n"
13413 +:              "=r"(_res), "+m"(*lock)
13414 +:
13415 +:              "memory");
13416 +       return _res;
13417 +}
13418 +
13419 +#endif  /* __ns32k__ */
13420 +
13421 +
13422 +#if defined(__alpha) || defined(__alpha__)     /* Alpha */
13423 +/*
13424 + * Correct multi-processor locking methods are explained in section 5.5.3
13425 + * of the Alpha AXP Architecture Handbook, which at this writing can be
13426 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
13427 + * For gcc we implement the handbook's code directly with inline assembler.
13428 + */
13429 +#define HAS_TEST_AND_SET
13430 +
13431 +typedef unsigned long slock_t;
13432 +
13433 +#define TAS(lock)  tas(lock)
13434 +
13435 +static __inline__ int
13436 +tas(volatile slock_t *lock)
13437 +{
13438 +       register slock_t _res;
13439 +
13440 +       __asm__ __volatile__(
13441 +               "       ldq             $0, %1  \n"
13442 +               "       bne             $0, 2f  \n"
13443 +               "       ldq_l   %0, %1  \n"
13444 +               "       bne             %0, 2f  \n"
13445 +               "       mov             1,  $0  \n"
13446 +               "       stq_c   $0, %1  \n"
13447 +               "       beq             $0, 2f  \n"
13448 +               "       mb                              \n"
13449 +               "       br              3f              \n"
13450 +               "2:     mov             1, %0   \n"
13451 +               "3:                                     \n"
13452 +:              "=&r"(_res), "+m"(*lock)
13453 +:
13454 +:              "memory", "0");
13455 +       return (int) _res;
13456 +}
13457 +
13458 +#define S_UNLOCK(lock) \
13459 +do \
13460 +{\
13461 +       __asm__ __volatile__ (" mb \n"); \
13462 +       *((volatile slock_t *) (lock)) = 0; \
13463 +} while (0)
13464 +
13465 +#endif /* __alpha || __alpha__ */
13466 +
13467 +
13468 +#if defined(__mips__) && !defined(__sgi)       /* non-SGI MIPS */
13469 +/* Note: on SGI we use the OS' mutex ABI, see below */
13470 +/* Note: R10000 processors require a separate SYNC */
13471 +#define HAS_TEST_AND_SET
13472 +
13473 +typedef unsigned int slock_t;
13474 +
13475 +#define TAS(lock) tas(lock)
13476 +
13477 +static __inline__ int
13478 +tas(volatile slock_t *lock)
13479 +{
13480 +       register volatile slock_t *_l = lock;
13481 +       register int _res;
13482 +       register int _tmp;
13483 +
13484 +       __asm__ __volatile__(
13485 +               "       .set push           \n"
13486 +               "       .set mips2          \n"
13487 +               "       .set noreorder      \n"
13488 +               "       .set nomacro        \n"
13489 +               "       ll      %0, %2      \n"
13490 +               "       or      %1, %0, 1   \n"
13491 +               "       sc      %1, %2      \n"
13492 +               "       xori    %1, 1       \n"
13493 +               "       or      %0, %0, %1  \n"
13494 +               "       sync                \n"
13495 +               "       .set pop              "
13496 +:              "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
13497 +:
13498 +:              "memory");
13499 +       return _res;
13500 +}
13501 +
13502 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
13503 +#define S_UNLOCK(lock) \
13504 +do \
13505 +{ \
13506 +       __asm__ __volatile__( \
13507 +               "       .set push           \n" \
13508 +               "       .set mips2          \n" \
13509 +               "       .set noreorder      \n" \
13510 +               "       .set nomacro        \n" \
13511 +               "       sync                \n" \
13512 +               "       .set pop              "); \
13513 +       *((volatile slock_t *) (lock)) = 0; \
13514 +} while (0)
13515 +
13516 +#endif /* __mips__ && !__sgi */
13517 +
13518 +
13519 +/* These live in s_lock.c, but only for gcc */
13520 +
13521 +
13522 +#if defined(__m68k__) && !defined(__linux__)   /* non-Linux Motorola 68k */
13523 +#define HAS_TEST_AND_SET
13524 +
13525 +typedef unsigned char slock_t;
13526 +#endif
13527 +
13528 +
13529 +#endif /* __GNUC__ */
13530 +
13531 +
13532 +
13533 +/*
13534 + * ---------------------------------------------------------------------
13535 + * Platforms that use non-gcc inline assembly:
13536 + * ---------------------------------------------------------------------
13537 + */
13538 +
13539 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
13540 +
13541 +
13542 +#if defined(USE_UNIVEL_CC)             /* Unixware compiler */
13543 +#define HAS_TEST_AND_SET
13544 +
13545 +typedef unsigned char slock_t;
13546 +
13547 +#define TAS(lock)      tas(lock)
13548 +
13549 +asm int
13550 +tas(volatile slock_t *s_lock)
13551 +{
13552 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
13553 +%mem s_lock
13554 +       pushl %ebx
13555 +       movl s_lock, %ebx
13556 +       movl $255, %eax
13557 +       lock
13558 +       xchgb %al, (%ebx)
13559 +       popl %ebx
13560 +}
13561 +
13562 +#endif  /* defined(USE_UNIVEL_CC) */
13563 +
13564 +
13565 +#if defined(__alpha) || defined(__alpha__)     /* Tru64 Unix Alpha compiler */
13566 +/*
13567 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
13568 + * have some builtin functions that accomplish much the same results.
13569 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
13570 + * regardless of the compiler in use.  LOCK_LONG and UNLOCK_LONG only
13571 + * operate on an int (ie, longword), but that's OK as long as we define
13572 + * S_INIT_LOCK to zero out the whole quadword.
13573 + */
13574 +#define HAS_TEST_AND_SET
13575 +
13576 +typedef unsigned long slock_t;
13577 +
13578 +#include <alpha/builtins.h>
13579 +#define S_INIT_LOCK(lock)  (*(lock) = 0)
13580 +#define TAS(lock)                 (__LOCK_LONG_RETRY((lock), 1) == 0)
13581 +#define S_UNLOCK(lock)    __UNLOCK_LONG(lock)
13582 +
13583 +#endif  /* __alpha || __alpha__ */
13584 +
13585 +
13586 +#if defined(__hppa) || defined(__hppa__)       /* HP PA-RISC, GCC and HP compilers */
13587 +/*
13588 + * HP's PA-RISC
13589 + *
13590 + * See src/backend/port/hpux/tas.c.template for details about LDCWX.  Because
13591 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
13592 + * struct.  The active word in the struct is whichever has the aligned address;
13593 + * the other three words just sit at -1.
13594 + *
13595 + * When using gcc, we can inline the required assembly code.
13596 + */
13597 +#define HAS_TEST_AND_SET
13598 +
13599 +typedef struct
13600 +{
13601 +       int                     sema[4];
13602 +} slock_t;
13603 +
13604 +#define TAS_ACTIVE_WORD(lock)  ((volatile int *) (((long) (lock) + 15) & ~15))
13605 +
13606 +#if defined(__GNUC__)
13607 +
13608 +static __inline__ int
13609 +tas(volatile slock_t *lock)
13610 +{
13611 +       volatile int *lockword = TAS_ACTIVE_WORD(lock);
13612 +       register int lockval;
13613 +
13614 +       __asm__ __volatile__(
13615 +               "       ldcwx   0(0,%2),%0      \n"
13616 +:              "=r"(lockval), "+m"(*lockword)
13617 +:              "r"(lockword)
13618 +:              "memory");
13619 +       return (lockval == 0);
13620 +}
13621 +
13622 +#endif /* __GNUC__ */
13623 +
13624 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
13625 +
13626 +#define S_INIT_LOCK(lock) \
13627 +       do { \
13628 +               volatile slock_t *lock_ = (lock); \
13629 +               lock_->sema[0] = -1; \
13630 +               lock_->sema[1] = -1; \
13631 +               lock_->sema[2] = -1; \
13632 +               lock_->sema[3] = -1; \
13633 +       } while (0)
13634 +
13635 +#define S_LOCK_FREE(lock)      (*TAS_ACTIVE_WORD(lock) != 0)
13636 +
13637 +#endif  /* __hppa || __hppa__ */
13638 +
13639 +
13640 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
13641 +
13642 +#define HAS_TEST_AND_SET
13643 +
13644 +typedef unsigned int slock_t;
13645 +
13646 +#include <ia64/sys/inline.h>
13647 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
13648 +
13649 +#endif /* HPUX on IA64, non gcc */
13650 +
13651 +
13652 +#if defined(__sgi)     /* SGI compiler */
13653 +/*
13654 + * SGI IRIX 5
13655 + * slock_t is defined as a unsigned long. We use the standard SGI
13656 + * mutex API.
13657 + *
13658 + * The following comment is left for historical reasons, but is probably
13659 + * not a good idea since the mutex ABI is supported.
13660 + *
13661 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
13662 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
13663 + * for the R3000 chips out there.
13664 + */
13665 +#define HAS_TEST_AND_SET
13666 +
13667 +typedef unsigned long slock_t;
13668 +
13669 +#include "mutex.h"
13670 +#define TAS(lock)      (test_and_set(lock,1))
13671 +#define S_UNLOCK(lock) (test_then_and(lock,0))
13672 +#define S_INIT_LOCK(lock)      (test_then_and(lock,0))
13673 +#define S_LOCK_FREE(lock)      (test_then_add(lock,0) == 0)
13674 +#endif  /* __sgi */
13675 +
13676 +
13677 +#if defined(sinix)             /* Sinix */
13678 +/*
13679 + * SINIX / Reliant UNIX
13680 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
13681 + * member. (Basically same as SGI)
13682 + */
13683 +#define HAS_TEST_AND_SET
13684 +
13685 +#include "abi_mutex.h"
13686 +typedef abilock_t slock_t;
13687 +
13688 +#define TAS(lock)      (!acquire_lock(lock))
13689 +#define S_UNLOCK(lock) release_lock(lock)
13690 +#define S_INIT_LOCK(lock)      init_lock(lock)
13691 +#define S_LOCK_FREE(lock)      (stat_lock(lock) == UNLOCKED)
13692 +#endif  /* sinix */
13693 +
13694 +
13695 +#if defined(_AIX)      /* AIX */
13696 +/*
13697 + * AIX (POWER)
13698 + */
13699 +#define HAS_TEST_AND_SET
13700 +
13701 +typedef unsigned int slock_t;
13702 +
13703 +#define TAS(lock)                      _check_lock(lock, 0, 1)
13704 +#define S_UNLOCK(lock)         _clear_lock(lock, 0)
13705 +#endif  /* _AIX */
13706 +
13707 +
13708 +#if defined (nextstep)         /* Nextstep */
13709 +#define HAS_TEST_AND_SET
13710 +
13711 +typedef struct mutex slock_t;
13712 +
13713 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
13714 +
13715 +#define S_LOCK(lock)   mutex_lock(lock)
13716 +#define S_UNLOCK(lock) mutex_unlock(lock)
13717 +#define S_INIT_LOCK(lock)      mutex_init(lock)
13718 +/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
13719 +#define S_LOCK_FREE(alock)     ((alock)->lock == 0)
13720 +#endif  /* nextstep */
13721 +
13722 +
13723 +/* These are in s_lock.c */
13724 +
13725 +
13726 +#if defined(sun3)              /* Sun3 */
13727 +#define HAS_TEST_AND_SET
13728 +
13729 +typedef unsigned char slock_t;
13730 +#endif
13731 +
13732 +
13733 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
13734 +#define HAS_TEST_AND_SET
13735 +
13736 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
13737 +typedef unsigned int slock_t;
13738 +#else
13739 +typedef unsigned char slock_t;
13740 +#endif
13741 +
13742 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
13743 +                                                                         slock_t cmp);
13744 +
13745 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
13746 +#endif
13747 +
13748 +
13749 +#ifdef WIN32_ONLY_COMPILER
13750 +typedef LONG slock_t;
13751 +
13752 +#define HAS_TEST_AND_SET
13753 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
13754 +
13755 +#define SPIN_DELAY() spin_delay()
13756 +
13757 +static __forceinline void
13758 +spin_delay(void)
13759 +{
13760 +       /* See comment for gcc code. Same code, MASM syntax */
13761 +       __asm rep nop;
13762 +}
13763 +
13764 +#endif
13765 +
13766 +  
13767 +#endif /* !defined(HAS_TEST_AND_SET) */
13768 +
13769 +
13770 +/* Blow up if we didn't have any way to do spinlocks */
13771 +#ifndef HAS_TEST_AND_SET
13772 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
13773 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
13774 +/* #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. */ 
13775 +#endif
13776 +
13777 +
13778 +#else  /* !HAVE_SPINLOCKS */
13779 +
13780 +
13781 +/*
13782 + * Fake spinlock implementation using semaphores --- slow and prone
13783 + * to fall foul of kernel limits on number of semaphores, so don't use this
13784 + * unless you must!  The subroutines appear in spin.c.
13785 + */
13786 +
13787 +/* -- Removed for APC
13788 +typedef PGSemaphoreData slock_t;
13789 +
13790 +extern bool s_lock_free_sema(volatile slock_t *lock);
13791 +extern void s_unlock_sema(volatile slock_t *lock);
13792 +extern void s_init_lock_sema(volatile slock_t *lock);
13793 +extern int     tas_sema(volatile slock_t *lock);
13794 +
13795 +#define S_LOCK_FREE(lock)      s_lock_free_sema(lock)
13796 +#define S_UNLOCK(lock)  s_unlock_sema(lock)
13797 +#define S_INIT_LOCK(lock)      s_init_lock_sema(lock)
13798 +#define TAS(lock)      tas_sema(lock)
13799 +*/
13800 +
13801 +#endif /* HAVE_SPINLOCKS */
13802 +
13803 +
13804 +/*
13805 + * Default Definitions - override these above as needed.
13806 + */
13807 +
13808 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
13809 +
13810 +#if !defined(S_LOCK)
13811 +#define S_LOCK(lock) \
13812 +       do { \
13813 +               if (TAS(lock)) \
13814 +                       s_lock((lock), __FILE__, __LINE__); \
13815 +       } while (0)
13816 +#endif  /* S_LOCK */
13817 +
13818 +#if !defined(S_LOCK_FREE)
13819 +#define S_LOCK_FREE(lock)      (*(lock) == 0)
13820 +#endif  /* S_LOCK_FREE */
13821 +
13822 +#if !defined(S_UNLOCK)
13823 +#define S_UNLOCK(lock)         (*((volatile slock_t *) (lock)) = 0)
13824 +#endif  /* S_UNLOCK */
13825 +
13826 +#if !defined(S_INIT_LOCK)
13827 +#define S_INIT_LOCK(lock)      S_UNLOCK(lock)
13828 +#endif  /* S_INIT_LOCK */
13829 +
13830 +#if !defined(SPIN_DELAY)
13831 +#define SPIN_DELAY()   ((void) 0)
13832 +#endif  /* SPIN_DELAY */
13833 +
13834 +#if !defined(TAS)
13835 +extern int     tas(volatile slock_t *lock);            /* in port/.../tas.s, or
13836 +                                                                                                * s_lock.c */
13837 +
13838 +#define TAS(lock)              tas(lock)
13839 +#endif  /* TAS */
13840 +
13841 +
13842 +/*
13843 + * Platform-independent out-of-line support routines
13844 + */
13845 +extern void s_lock(volatile slock_t *lock, const char *file, int line);
13846 +
13847 +/* Support for dynamic adjustment of spins_per_delay */
13848 +#define DEFAULT_SPINS_PER_DELAY  100
13849 +
13850 +#if 0  /* -- Removed from APC use -- */
13851 +extern void set_spins_per_delay(int shared_spins_per_delay);
13852 +extern int     update_spins_per_delay(int shared_spins_per_delay);
13853 +#endif
13854 +
13855 +#endif  /* S_LOCK_H */
13856 diff -ubrN php-5.2.5-orig/ext/apc/php_apc.c php-5.2.5/ext/apc/php_apc.c
13857 --- php-5.2.5-orig/ext/apc/php_apc.c    1969-12-31 18:00:00.000000000 -0600
13858 +++ php-5.2.5/ext/apc/php_apc.c 2007-12-26 16:51:32.000000000 -0600
13859 @@ -0,0 +1,991 @@
13860 +/*
13861 +  +----------------------------------------------------------------------+
13862 +  | APC                                                                  |
13863 +  +----------------------------------------------------------------------+
13864 +  | Copyright (c) 2006 The PHP Group                                     |
13865 +  +----------------------------------------------------------------------+
13866 +  | This source file is subject to version 3.01 of the PHP license,      |
13867 +  | that is bundled with this package in the file LICENSE, and is        |
13868 +  | available through the world-wide-web at the following url:           |
13869 +  | http://www.php.net/license/3_01.txt                                  |
13870 +  | If you did not receive a copy of the PHP license and are unable to   |
13871 +  | obtain it through the world-wide-web, please send a note to          |
13872 +  | license@php.net so we can mail you a copy immediately.               |
13873 +  +----------------------------------------------------------------------+
13874 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
13875 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
13876 +  +----------------------------------------------------------------------+
13877 +
13878 +   This software was contributed to PHP by Community Connect Inc. in 2002
13879 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13880 +   Future revisions and derivatives of this source code must acknowledge
13881 +   Community Connect Inc. as the original contributor of this module by
13882 +   leaving this note intact in the source code.
13883 +
13884 +   All other licensing and usage conditions are those of the PHP Group.
13885 +
13886 + */
13887 +
13888 +/* $Id: php_apc.c,v 3.154 2007/12/26 22:31:20 rasmus Exp $ */
13889 +
13890 +#include "apc_zend.h"
13891 +#include "apc_cache.h"
13892 +#include "apc_main.h"
13893 +#include "apc_sma.h"
13894 +#include "apc_lock.h"
13895 +#include "php_globals.h"
13896 +#include "php_ini.h"
13897 +#include "ext/standard/info.h"
13898 +#include "SAPI.h"
13899 +#include "rfc1867.h"
13900 +#include "php_apc.h"
13901 +#if PHP_API_VERSION <= 20020918
13902 +#if HAVE_APACHE
13903 +#ifdef APC_PHP4_STAT
13904 +#undef XtOffsetOf
13905 +#include "httpd.h"
13906 +#endif
13907 +#endif
13908 +#endif
13909 +
13910 +#if HAVE_SIGACTION
13911 +#include "apc_signal.h"
13912 +#endif
13913 +
13914 +/* {{{ PHP_FUNCTION declarations */
13915 +PHP_FUNCTION(apc_cache_info);
13916 +PHP_FUNCTION(apc_clear_cache);
13917 +PHP_FUNCTION(apc_sma_info);
13918 +PHP_FUNCTION(apc_store);
13919 +PHP_FUNCTION(apc_fetch);
13920 +PHP_FUNCTION(apc_delete);
13921 +PHP_FUNCTION(apc_compile_file);
13922 +PHP_FUNCTION(apc_define_constants);
13923 +PHP_FUNCTION(apc_load_constants);
13924 +PHP_FUNCTION(apc_add);
13925 +/* }}} */
13926 +
13927 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
13928 +ZEND_DECLARE_MODULE_GLOBALS(apc)
13929 +
13930 +/* True globals */
13931 +apc_cache_t* apc_cache = NULL;       
13932 +apc_cache_t* apc_user_cache = NULL;
13933 +void* apc_compiled_filters = NULL;
13934 +
13935 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
13936 +{
13937 +    apc_globals->filters = NULL;
13938 +    apc_globals->initialized = 0;
13939 +    apc_globals->cache_stack = apc_stack_create(0);
13940 +    apc_globals->cache_by_default = 1;
13941 +    apc_globals->slam_defense = 0;
13942 +    apc_globals->mem_size_ptr = NULL;
13943 +    apc_globals->fpstat = 1;
13944 +    apc_globals->stat_ctime = 0;
13945 +    apc_globals->write_lock = 1;
13946 +    apc_globals->report_autofilter = 0;
13947 +    apc_globals->apc_optimize_function = NULL;
13948 +#ifdef MULTIPART_EVENT_FORMDATA
13949 +    apc_globals->rfc1867 = 0;
13950 +#endif
13951 +    apc_globals->copied_zvals = NULL;
13952 +#ifdef ZEND_ENGINE_2
13953 +    apc_globals->reserved_offset = -1;
13954 +#endif
13955 +    apc_globals->localcache = 0;
13956 +    apc_globals->localcache_size = 0;
13957 +    apc_globals->lcache = NULL;
13958 +    apc_globals->force_file_update = 0;
13959 +    apc_globals->coredump_unmap = 0;
13960 +}
13961 +
13962 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
13963 +{
13964 +    /* deallocate the ignore patterns */
13965 +    if (apc_globals->filters != NULL) {
13966 +        int i;
13967 +        for (i=0; apc_globals->filters[i] != NULL; i++) {
13968 +            apc_efree(apc_globals->filters[i]);
13969 +        }
13970 +        apc_efree(apc_globals->filters);
13971 +    }
13972 +
13973 +    /* the stack should be empty */
13974 +    assert(apc_stack_size(apc_globals->cache_stack) == 0); 
13975 +
13976 +    /* apc cleanup */
13977 +    apc_stack_destroy(apc_globals->cache_stack);
13978 +
13979 +    /* the rest of the globals are cleaned up in apc_module_shutdown() */
13980 +}
13981 +
13982 +/* }}} */
13983 +
13984 +/* {{{ PHP_INI */
13985 +
13986 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
13987 +{
13988 +    APCG(filters) = apc_tokenize(new_value, ',');
13989 +    return SUCCESS;
13990 +}
13991 +/* }}} */
13992 +
13993 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
13994 +{
13995 +#if APC_MMAP
13996 +    if(atoi(new_value)!=1) {
13997 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
13998 +    }
13999 +    APCG(shm_segments) = 1; 
14000 +#else
14001 +    APCG(shm_segments) = atoi(new_value);
14002 +#endif
14003 +    return SUCCESS;
14004 +}
14005 +/* }}} */
14006 +
14007 +#ifdef MULTIPART_EVENT_FORMDATA
14008 +static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
14009 +{
14010 +    int tmp;
14011 +    tmp = zend_atoi(new_value, new_value_length);
14012 +    if(tmp < 0) {
14013 +        apc_eprint("rfc1867_freq must be greater than or equal to zero.");
14014 +        return FAILURE;
14015 +    }
14016 +    if(new_value[new_value_length-1] == '%') {
14017 +        if(tmp > 100) {
14018 +            apc_eprint("rfc1867_freq cannot be over 100%%");
14019 +            return FAILURE;
14020 +        }
14021 +        APCG(rfc1867_freq) = tmp / 100.0;
14022 +    } else {
14023 +        APCG(rfc1867_freq) = tmp;
14024 +    }
14025 +    return SUCCESS;
14026 +}
14027 +/* }}} */
14028 +#endif
14029 +
14030 +#ifdef ZEND_ENGINE_2
14031 +#define OnUpdateInt OnUpdateLong
14032 +#endif
14033 +
14034 +PHP_INI_BEGIN()
14035 +STD_PHP_INI_BOOLEAN("apc.enabled",      "1",    PHP_INI_SYSTEM, OnUpdateBool,              enabled,         zend_apc_globals, apc_globals)
14036 +STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    PHP_INI_SYSTEM, OnUpdateShmSegments,       shm_segments,    zend_apc_globals, apc_globals)
14037 +STD_PHP_INI_ENTRY("apc.shm_size",       "30",   PHP_INI_SYSTEM, OnUpdateInt,            shm_size,        zend_apc_globals, apc_globals)
14038 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool,     include_once,    zend_apc_globals, apc_globals)
14039 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt,            num_files_hint,  zend_apc_globals, apc_globals)
14040 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt,          user_entries_hint, zend_apc_globals, apc_globals)
14041 +STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", PHP_INI_SYSTEM, OnUpdateInt,            gc_ttl,           zend_apc_globals, apc_globals)
14042 +STD_PHP_INI_ENTRY("apc.ttl",            "0",    PHP_INI_SYSTEM, OnUpdateInt,            ttl,              zend_apc_globals, apc_globals)
14043 +STD_PHP_INI_ENTRY("apc.user_ttl",       "0",    PHP_INI_SYSTEM, OnUpdateInt,            user_ttl,         zend_apc_globals, apc_globals)
14044 +#if APC_MMAP
14045 +STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
14046 +#endif
14047 +PHP_INI_ENTRY("apc.filters",        NULL,     PHP_INI_SYSTEM, OnUpdate_filters)
14048 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1",  PHP_INI_ALL, OnUpdateBool,         cache_by_default, zend_apc_globals, apc_globals)
14049 +STD_PHP_INI_ENTRY("apc.slam_defense", "0",      PHP_INI_SYSTEM, OnUpdateInt,            slam_defense,     zend_apc_globals, apc_globals)
14050 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection,  zend_apc_globals, apc_globals)
14051 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0",      PHP_INI_SYSTEM, OnUpdateBool,           enable_cli,       zend_apc_globals, apc_globals)
14052 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M",    PHP_INI_SYSTEM, OnUpdateInt,            max_file_size,    zend_apc_globals, apc_globals)
14053 +STD_PHP_INI_BOOLEAN("apc.stat", "1",            PHP_INI_SYSTEM, OnUpdateBool,           fpstat,           zend_apc_globals, apc_globals)
14054 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0",      PHP_INI_SYSTEM, OnUpdateBool,           stat_ctime,       zend_apc_globals, apc_globals)
14055 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1",      PHP_INI_SYSTEM, OnUpdateBool,           write_lock,       zend_apc_globals, apc_globals)
14056 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool,         report_autofilter,zend_apc_globals, apc_globals)
14057 +#ifdef MULTIPART_EVENT_FORMDATA
14058 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
14059 +STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
14060 +STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
14061 +STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
14062 +#endif
14063 +STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
14064 +STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size,  zend_apc_globals, apc_globals)
14065 +STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
14066 +PHP_INI_END()
14067 +
14068 +/* }}} */
14069 +
14070 +/* {{{ PHP_MINFO_FUNCTION(apc) */
14071 +static PHP_MINFO_FUNCTION(apc)
14072 +{
14073 +    php_info_print_table_start();
14074 +    php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
14075 +    php_info_print_table_row(2, "Version", APC_VERSION);
14076 +#if APC_MMAP
14077 +    php_info_print_table_row(2, "MMAP Support", "Enabled");
14078 +    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
14079 +#else
14080 +    php_info_print_table_row(2, "MMAP Support", "Disabled");
14081 +#endif
14082 +#if APC_SEM_LOCKS
14083 +    php_info_print_table_row(2, "Locking type", "IPC Semaphore");
14084 +#elif APC_FUTEX_LOCKS
14085 +    php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
14086 +#elif APC_PTHREADMUTEX_LOCKS
14087 +    php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
14088 +#elif APC_SPIN_LOCKS
14089 +    php_info_print_table_row(2, "Locking type", "spin Locks");
14090 +#else
14091 +    php_info_print_table_row(2, "Locking type", "File Locks");
14092 +#endif
14093 +    php_info_print_table_row(2, "Revision", "$Revision: 3.154 $");
14094 +    php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
14095 +    php_info_print_table_end();
14096 +    DISPLAY_INI_ENTRIES();
14097 +}
14098 +/* }}} */
14099 +
14100 +#ifdef MULTIPART_EVENT_FORMDATA
14101 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
14102 +#endif
14103 +
14104 +/* {{{ PHP_MINIT_FUNCTION(apc) */
14105 +static PHP_MINIT_FUNCTION(apc)
14106 +{
14107 +    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
14108 +
14109 +    REGISTER_INI_ENTRIES();
14110 +
14111 +    /* Disable APC in cli mode unless overridden by apc.enable_cli */
14112 +    if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
14113 +        APCG(enabled) = 0;
14114 +    }
14115 +
14116 +    if (APCG(enabled)) {
14117 +        if(APCG(initialized)) {
14118 +            apc_process_init(module_number TSRMLS_CC);
14119 +        } else {
14120 +            apc_module_init(module_number TSRMLS_CC);
14121 +            apc_zend_init(TSRMLS_C);
14122 +            apc_process_init(module_number TSRMLS_CC);
14123 +#ifdef MULTIPART_EVENT_FORMDATA
14124 +            /* File upload progress tracking */
14125 +            if(APCG(rfc1867)) {
14126 +                php_rfc1867_callback = apc_rfc1867_progress;
14127 +            }
14128 +#endif
14129 +        }
14130 +    }
14131 +
14132 +    return SUCCESS;
14133 +}
14134 +/* }}} */
14135 +
14136 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
14137 +static PHP_MSHUTDOWN_FUNCTION(apc)
14138 +{
14139 +    if(APCG(enabled)) {
14140 +        apc_process_shutdown(TSRMLS_C);
14141 +        apc_zend_shutdown(TSRMLS_C);
14142 +        apc_module_shutdown(TSRMLS_C);
14143 +#ifndef ZTS
14144 +        php_apc_shutdown_globals(&apc_globals);
14145 +#endif
14146 +    }
14147 +#ifdef ZTS
14148 +    ts_free_id(apc_globals_id);
14149 +#endif
14150 +    UNREGISTER_INI_ENTRIES();
14151 +    return SUCCESS;
14152 +}
14153 +/* }}} */
14154 +
14155 +/* {{{ PHP_RINIT_FUNCTION(apc) */
14156 +static PHP_RINIT_FUNCTION(apc)
14157 +{
14158 +    if(APCG(enabled)) {
14159 +        apc_request_init(TSRMLS_C);
14160 +
14161 +#if HAVE_SIGACTION
14162 +        apc_set_signals();
14163 +#endif
14164 +    }
14165 +    return SUCCESS;
14166 +}
14167 +/* }}} */
14168 +
14169 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
14170 +static PHP_RSHUTDOWN_FUNCTION(apc)
14171 +{
14172 +    if(APCG(enabled)) {
14173 +        apc_request_shutdown(TSRMLS_C);
14174 +    }
14175 +    return SUCCESS;
14176 +}
14177 +/* }}} */
14178 +
14179 +/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
14180 +PHP_FUNCTION(apc_cache_info)
14181 +{
14182 +    apc_cache_info_t* info;
14183 +    apc_cache_link_t* p;
14184 +    zval* list;
14185 +    char *cache_type;
14186 +    int ct_len;
14187 +    zend_bool limited=0;
14188 +
14189 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
14190 +        return;
14191 +    }
14192 +
14193 +    if(ZEND_NUM_ARGS()) {
14194 +        if(!strcasecmp(cache_type,"user")) {
14195 +            info = apc_cache_info(apc_user_cache, limited);
14196 +        } else if(!strcasecmp(cache_type,"filehits")) {
14197 +#ifdef APC_FILEHITS
14198 +            RETVAL_ZVAL(APCG(filehits), 1, 0);
14199 +            return;
14200 +#else
14201 +            RETURN_FALSE;
14202 +#endif
14203 +        } else {
14204 +            info = apc_cache_info(apc_cache, limited);
14205 +        }
14206 +    } else info = apc_cache_info(apc_cache, limited);
14207 +
14208 +    if(!info) {
14209 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available.  Perhaps APC is not enabled? Check apc.enabled in your ini file");
14210 +        RETURN_FALSE;
14211 +    }
14212 +
14213 +    array_init(return_value);
14214 +    add_assoc_long(return_value, "num_slots", info->num_slots);
14215 +    add_assoc_long(return_value, "ttl", info->ttl);
14216 +    add_assoc_long(return_value, "num_hits", info->num_hits);
14217 +    add_assoc_long(return_value, "num_misses", info->num_misses);
14218 +    add_assoc_long(return_value, "start_time", info->start_time);
14219 +    add_assoc_long(return_value, "expunges", info->expunges);
14220 +    add_assoc_long(return_value, "mem_size", info->mem_size);
14221 +    add_assoc_long(return_value, "num_entries", info->num_entries);
14222 +    add_assoc_long(return_value, "num_inserts", info->num_inserts);
14223 +#ifdef MULTIPART_EVENT_FORMDATA
14224 +    add_assoc_long(return_value, "file_upload_progress", 1);
14225 +#else
14226 +    add_assoc_long(return_value, "file_upload_progress", 0);
14227 +#endif
14228 +#if APC_MMAP
14229 +    add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
14230 +#else
14231 +    add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
14232 +#endif
14233 +#if APC_SEM_LOCKS
14234 +    add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
14235 +#elif APC_FUTEX_LOCKS
14236 +    add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
14237 +#elif APC_PTHREADMUTEX_LOCKS
14238 +    add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
14239 +#elif APC_SPIN_LOCKS
14240 +    add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
14241 +#else
14242 +    add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
14243 +#endif
14244 +    if(limited) {
14245 +        apc_cache_free_info(info);
14246 +        return;
14247 +    }
14248 +    
14249 +    ALLOC_INIT_ZVAL(list);
14250 +    array_init(list);
14251 +
14252 +    for (p = info->list; p != NULL; p = p->next) {
14253 +        zval* link;
14254 +
14255 +        ALLOC_INIT_ZVAL(link);
14256 +        array_init(link);
14257 +
14258 +        if(p->type == APC_CACHE_ENTRY_FILE) {
14259 +            add_assoc_string(link, "filename", p->data.file.filename, 1);
14260 +            add_assoc_long(link, "device", p->data.file.device);
14261 +            add_assoc_long(link, "inode", p->data.file.inode);
14262 +            add_assoc_string(link, "type", "file", 1);
14263 +        } else if(p->type == APC_CACHE_ENTRY_USER) {
14264 +            add_assoc_string(link, "info", p->data.user.info, 1);
14265 +            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
14266 +            add_assoc_string(link, "type", "user", 1);
14267 +        }
14268 +        add_assoc_long(link, "num_hits", p->num_hits);
14269 +        add_assoc_long(link, "mtime", p->mtime);
14270 +        add_assoc_long(link, "creation_time", p->creation_time);
14271 +        add_assoc_long(link, "deletion_time", p->deletion_time);
14272 +        add_assoc_long(link, "access_time", p->access_time);
14273 +        add_assoc_long(link, "ref_count", p->ref_count);
14274 +        add_assoc_long(link, "mem_size", p->mem_size);
14275 +        add_next_index_zval(list, link);
14276 +    }
14277 +    add_assoc_zval(return_value, "cache_list", list);
14278 +
14279 +    ALLOC_INIT_ZVAL(list);
14280 +    array_init(list);
14281 +
14282 +    for (p = info->deleted_list; p != NULL; p = p->next) {
14283 +        zval* link;
14284 +
14285 +        ALLOC_INIT_ZVAL(link);
14286 +        array_init(link);
14287 +
14288 +        if(p->type == APC_CACHE_ENTRY_FILE) {
14289 +            add_assoc_string(link, "filename", p->data.file.filename, 1);
14290 +            add_assoc_long(link, "device", p->data.file.device);
14291 +            add_assoc_long(link, "inode", p->data.file.inode);
14292 +            add_assoc_string(link, "type", "file", 1);
14293 +        } else if(p->type == APC_CACHE_ENTRY_USER) {
14294 +            add_assoc_string(link, "info", p->data.user.info, 1);
14295 +            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
14296 +            add_assoc_string(link, "type", "user", 1);
14297 +        }
14298 +        add_assoc_long(link, "num_hits", p->num_hits);
14299 +        add_assoc_long(link, "mtime", p->mtime);
14300 +        add_assoc_long(link, "creation_time", p->creation_time);
14301 +        add_assoc_long(link, "deletion_time", p->deletion_time);
14302 +        add_assoc_long(link, "access_time", p->access_time);
14303 +        add_assoc_long(link, "ref_count", p->ref_count);
14304 +        add_assoc_long(link, "mem_size", p->mem_size);
14305 +        add_next_index_zval(list, link);
14306 +    }
14307 +    add_assoc_zval(return_value, "deleted_list", list);
14308 +
14309 +    apc_cache_free_info(info);
14310 +}
14311 +/* }}} */
14312 +
14313 +/* {{{ proto void apc_clear_cache() */
14314 +PHP_FUNCTION(apc_clear_cache)
14315 +{
14316 +    char *cache_type;
14317 +    int ct_len;
14318 +
14319 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
14320 +        return;
14321 +    }
14322 +
14323 +    if(ZEND_NUM_ARGS()) {
14324 +        if(!strcasecmp(cache_type,"user")) {
14325 +            apc_cache_clear(apc_user_cache);
14326 +            RETURN_TRUE;
14327 +        }
14328 +    }
14329 +    apc_cache_clear(apc_cache);
14330 +}
14331 +/* }}} */
14332 +
14333 +/* {{{ proto array apc_sma_info([bool limited]) */
14334 +PHP_FUNCTION(apc_sma_info)
14335 +{
14336 +    apc_sma_info_t* info;
14337 +    zval* block_lists;
14338 +    int i;
14339 +    zend_bool limited = 0;
14340 +
14341 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
14342 +        return;
14343 +    }
14344 +
14345 +    info = apc_sma_info(limited);
14346 +
14347 +    if(!info) {
14348 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
14349 +        RETURN_FALSE;
14350 +    }
14351 +
14352 +    array_init(return_value);
14353 +    add_assoc_long(return_value, "num_seg", info->num_seg);
14354 +    add_assoc_long(return_value, "seg_size", info->seg_size);
14355 +    add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
14356 +
14357 +    if(limited) {
14358 +        apc_sma_free_info(info);
14359 +        return;
14360 +    }
14361 +
14362 +#if ALLOC_DISTRIBUTION
14363 +    {
14364 +        size_t *adist = apc_sma_get_alloc_distribution();
14365 +        zval* list;
14366 +        ALLOC_INIT_ZVAL(list);
14367 +        array_init(list);
14368 +        for(i=0; i<30; i++) {
14369 +            add_next_index_long(list, adist[i]);
14370 +        }
14371 +        add_assoc_zval(return_value, "adist", list);
14372 +    }
14373 +#endif
14374 +    ALLOC_INIT_ZVAL(block_lists);
14375 +    array_init(block_lists);
14376 +
14377 +    for (i = 0; i < info->num_seg; i++) {
14378 +        apc_sma_link_t* p;
14379 +        zval* list;
14380 +
14381 +        ALLOC_INIT_ZVAL(list);
14382 +        array_init(list);
14383 +
14384 +        for (p = info->list[i]; p != NULL; p = p->next) {
14385 +            zval* link;
14386 +
14387 +            ALLOC_INIT_ZVAL(link);
14388 +            array_init(link);
14389 +
14390 +            add_assoc_long(link, "size", p->size);
14391 +            add_assoc_long(link, "offset", p->offset);
14392 +            add_next_index_zval(list, link);
14393 +        }
14394 +        add_next_index_zval(block_lists, list);
14395 +    }
14396 +    add_assoc_zval(return_value, "block_lists", block_lists);
14397 +    apc_sma_free_info(info);
14398 +}
14399 +/* }}} */
14400 +
14401 +/* {{{ _apc_store */
14402 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
14403 +    apc_cache_entry_t *entry;
14404 +    apc_cache_key_t key;
14405 +    time_t t;
14406 +    size_t mem_size = 0;
14407 +
14408 +#if PHP_API_VERSION < 20041225
14409 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14410 +    t = ((request_rec *)SG(server_context))->request_time;
14411 +#else
14412 +    t = time(0);
14413 +#endif
14414 +#else
14415 +    t = sapi_get_request_time(TSRMLS_C);
14416 +#endif
14417 +
14418 +    if(!APCG(enabled)) return 0;
14419 +
14420 +    HANDLE_BLOCK_INTERRUPTIONS();
14421 +
14422 +    APCG(mem_size_ptr) = &mem_size;
14423 +    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
14424 +        APCG(mem_size_ptr) = NULL;
14425 +        apc_cache_expunge(apc_cache,t);
14426 +        apc_cache_expunge(apc_user_cache,t);
14427 +        HANDLE_UNBLOCK_INTERRUPTIONS();
14428 +        return 0;
14429 +    }
14430 +
14431 +    if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
14432 +        APCG(mem_size_ptr) = NULL;
14433 +        apc_cache_free_entry(entry);
14434 +        apc_cache_expunge(apc_cache,t);
14435 +        apc_cache_expunge(apc_user_cache,t);
14436 +        HANDLE_UNBLOCK_INTERRUPTIONS();
14437 +        return 0;
14438 +    }
14439 +
14440 +    if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
14441 +        APCG(mem_size_ptr) = NULL;
14442 +        apc_cache_free_entry(entry);
14443 +        apc_cache_expunge(apc_cache,t);
14444 +        apc_cache_expunge(apc_user_cache,t);
14445 +        HANDLE_UNBLOCK_INTERRUPTIONS();
14446 +        return 0;
14447 +    }
14448 +
14449 +    APCG(mem_size_ptr) = NULL;
14450 +
14451 +    HANDLE_UNBLOCK_INTERRUPTIONS();
14452 +
14453 +    return 1;
14454 +}
14455 +/* }}} */
14456 +
14457 +/* {{{ proto int apc_store(string key, zval var [, ttl ])
14458 + */
14459 +PHP_FUNCTION(apc_store) {
14460 +    zval *val;
14461 +    char *strkey;
14462 +    int strkey_len;
14463 +    long ttl = 0L;
14464 +
14465 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
14466 +        return;
14467 +    }
14468 +
14469 +    if(!strkey_len) RETURN_FALSE;
14470 +
14471 +    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
14472 +    RETURN_FALSE;
14473 +}
14474 +/* }}} */
14475 +
14476 +/* {{{ proto int apc_add(string key, zval var [, ttl ])
14477 + */
14478 +PHP_FUNCTION(apc_add) {
14479 +    zval *val;
14480 +    char *strkey;
14481 +    int strkey_len;
14482 +    long ttl = 0L;
14483 +
14484 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
14485 +        return;
14486 +    }
14487 +
14488 +    if(!strkey_len) RETURN_FALSE;
14489 +
14490 +    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
14491 +    RETURN_FALSE;
14492 +}
14493 +/* }}} */
14494 +
14495 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
14496 +    return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
14497 +}
14498 +
14499 +/* {{{ RETURN_ZVAL for php4 */
14500 +#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
14501 +#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } 
14502 +#define RETVAL_ZVAL(zv, copy, dtor)     ZVAL_ZVAL(return_value, zv, copy, dtor)
14503 +#define ZVAL_ZVAL(z, zv, copy, dtor) {  \
14504 +        int is_ref, refcount;           \
14505 +        is_ref = (z)->is_ref;           \
14506 +        refcount = (z)->refcount;       \
14507 +        *(z) = *(zv);                   \
14508 +        if (copy) {                     \
14509 +            zval_copy_ctor(z);          \
14510 +        }                               \
14511 +        if (dtor) {                     \
14512 +            if (!copy) {                \
14513 +                ZVAL_NULL(zv);          \
14514 +            }                           \
14515 +            zval_ptr_dtor(&zv);         \
14516 +        }                               \
14517 +        (z)->is_ref = is_ref;           \
14518 +        (z)->refcount = refcount;       \
14519 +    }
14520 +#endif
14521 +/* }}} */
14522 +
14523 +/* {{{ proto mixed apc_fetch(mixed key)
14524 + */
14525 +PHP_FUNCTION(apc_fetch) {
14526 +    zval *key;
14527 +    HashTable *hash;
14528 +    HashPosition hpos;
14529 +    zval **hentry;
14530 +    zval *result;
14531 +    zval *result_entry;
14532 +    char *strkey;
14533 +    int strkey_len;
14534 +    apc_cache_entry_t* entry;
14535 +    time_t t;
14536 +
14537 +    if(!APCG(enabled)) RETURN_FALSE;
14538 +
14539 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
14540 +        return;
14541 +    }
14542 +
14543 +#if PHP_API_VERSION < 20041225
14544 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14545 +    t = ((request_rec *)SG(server_context))->request_time;
14546 +#else 
14547 +    t = time(0);
14548 +#endif
14549 +#else
14550 +    t = sapi_get_request_time(TSRMLS_C);
14551 +#endif
14552 +
14553 +    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
14554 +        convert_to_string(key);
14555 +    }
14556 +    
14557 +    if(Z_TYPE_P(key) == IS_STRING) {
14558 +        strkey = Z_STRVAL_P(key);
14559 +        strkey_len = Z_STRLEN_P(key);
14560 +        if(!strkey_len) RETURN_FALSE;
14561 +        entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
14562 +        if(entry) {
14563 +            /* deep-copy returned shm zval to emalloc'ed return_value */
14564 +            apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
14565 +            apc_cache_release(apc_user_cache, entry);
14566 +        } else {
14567 +            RETURN_FALSE;
14568 +        }
14569 +    } else if(Z_TYPE_P(key) == IS_ARRAY) {
14570 +        hash = Z_ARRVAL_P(key);
14571 +        MAKE_STD_ZVAL(result);
14572 +        array_init(result); 
14573 +        zend_hash_internal_pointer_reset_ex(hash, &hpos);
14574 +        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
14575 +            if(Z_TYPE_PP(hentry) != IS_STRING) {
14576 +                apc_wprint("apc_fetch() expects a string or array of strings.");
14577 +                RETURN_FALSE;
14578 +            }
14579 +            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
14580 +            if(entry) {
14581 +                /* deep-copy returned shm zval to emalloc'ed return_value */
14582 +                MAKE_STD_ZVAL(result_entry);
14583 +                apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
14584 +                apc_cache_release(apc_user_cache, entry);
14585 +                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
14586 +            } /* don't set values we didn't find */
14587 +            zend_hash_move_forward_ex(hash, &hpos);
14588 +        }
14589 +        RETURN_ZVAL(result, 0, 1);
14590 +    } else {
14591 +        apc_wprint("apc_fetch() expects a string or array of strings.");
14592 +        RETURN_FALSE;
14593 +    }
14594 +
14595 +    return;
14596 +}
14597 +/* }}} */
14598 +
14599 +/* {{{ proto mixed apc_delete(string key)
14600 + */
14601 +PHP_FUNCTION(apc_delete) {
14602 +    char *strkey;
14603 +    int strkey_len;
14604 +
14605 +    if(!APCG(enabled)) RETURN_FALSE;
14606 +
14607 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
14608 +        return;
14609 +    }
14610 +
14611 +    if(!strkey_len) RETURN_FALSE;
14612 +
14613 +    if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
14614 +        RETURN_TRUE;
14615 +    } else {
14616 +        RETURN_FALSE;
14617 +    }
14618 +}
14619 +/* }}} */
14620 +
14621 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
14622 +    char *const_key;
14623 +    unsigned int const_key_len;
14624 +    zval **entry;
14625 +    HashPosition pos;
14626 +
14627 +    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
14628 +    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
14629 +        zend_constant c;
14630 +        int key_type;
14631 +        ulong num_key;
14632 +
14633 +        key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
14634 +        if(key_type != HASH_KEY_IS_STRING) {
14635 +            zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14636 +            continue;
14637 +        }
14638 +        switch(Z_TYPE_PP(entry)) {
14639 +            case IS_LONG:
14640 +            case IS_DOUBLE:
14641 +            case IS_STRING:
14642 +            case IS_BOOL:
14643 +            case IS_RESOURCE:
14644 +            case IS_NULL:
14645 +                break;
14646 +            default:
14647 +                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14648 +                continue;
14649 +        }
14650 +        c.value = **entry;
14651 +        zval_copy_ctor(&c.value);
14652 +        c.flags = case_sensitive;
14653 +        c.name = zend_strndup(const_key, const_key_len);
14654 +        c.name_len = const_key_len;
14655 +#ifdef ZEND_ENGINE_2
14656 +        c.module_number = PHP_USER_CONSTANT;
14657 +#endif
14658 +        zend_register_constant(&c TSRMLS_CC);
14659 +
14660 +        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14661 +    }
14662 +}
14663 +
14664 +/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
14665 + */
14666 +PHP_FUNCTION(apc_define_constants) {
14667 +    char *strkey;
14668 +    int strkey_len;
14669 +    zval *constants = NULL;
14670 +    zend_bool case_sensitive = 1;
14671 +    int argc = ZEND_NUM_ARGS();
14672 +
14673 +    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
14674 +        return;
14675 +    }
14676 +
14677 +    if(!strkey_len) RETURN_FALSE;
14678 +
14679 +    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
14680 +    if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
14681 +    RETURN_FALSE;
14682 +} /* }}} */
14683 +
14684 +/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
14685 + */
14686 +PHP_FUNCTION(apc_load_constants) {
14687 +    char *strkey;
14688 +    int strkey_len;
14689 +    apc_cache_entry_t* entry;
14690 +    time_t t;
14691 +    zend_bool case_sensitive = 1;
14692 +
14693 +    if(!APCG(enabled)) RETURN_FALSE;
14694 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
14695 +        return;
14696 +    }
14697 +
14698 +    if(!strkey_len) RETURN_FALSE;
14699 +
14700 +#if PHP_API_VERSION < 20041225
14701 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14702 +    t = ((request_rec *)SG(server_context))->request_time;
14703 +#else 
14704 +    t = time(0);
14705 +#endif
14706 +#else 
14707 +    t = sapi_get_request_time(TSRMLS_C);
14708 +#endif
14709 +
14710 +    entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
14711 +
14712 +    if(entry) {
14713 +        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
14714 +        apc_cache_release(apc_user_cache, entry);
14715 +        RETURN_TRUE;
14716 +    } else {
14717 +        RETURN_FALSE;
14718 +    }
14719 +}
14720 +/* }}} */
14721 +
14722 +/* {{{ proto boolean apc_compile_file(string filename)
14723 + */
14724 +PHP_FUNCTION(apc_compile_file) {
14725 +    char *filename;
14726 +    int filename_len;
14727 +    zend_file_handle file_handle;
14728 +    zend_op_array *op_array;
14729 +    long slam_defense = 0;
14730 +    char** filters = NULL;
14731 +    zend_bool cache_by_default = 1;
14732 +    HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
14733 +    HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
14734 +
14735 +    if(!APCG(enabled)) RETURN_FALSE;
14736 +
14737 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
14738 +        return;
14739 +    }
14740 +
14741 +    if(!filename) RETURN_FALSE;
14742 +
14743 +    /* reset slam defense, filters, and cache_by_default */
14744 +    slam_defense = APCG(slam_defense);
14745 +    APCG(slam_defense) = 0;
14746 +   
14747 +    filters = APCG(filters);
14748 +    APCG(filters) = NULL;
14749 +
14750 +    cache_by_default = APCG(cache_by_default);
14751 +    APCG(cache_by_default) = 1;
14752 +
14753 +    /* Replace function/class tables to avoid namespace conflicts */
14754 +    zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
14755 +    cg_orig_function_table = CG(function_table);
14756 +    CG(function_table) = &cg_function_table;
14757 +    zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
14758 +    cg_orig_class_table = CG(class_table);
14759 +    CG(class_table) = &cg_class_table;
14760 +    eg_orig_function_table = EG(function_table);
14761 +    EG(function_table) = CG(function_table);
14762 +    eg_orig_class_table = EG(class_table);
14763 +    EG(class_table) = CG(class_table);
14764 +    APCG(force_file_update) = 1;
14765 +    
14766 +    /* Compile the file, loading it into the cache */
14767 +    file_handle.type = ZEND_HANDLE_FILENAME;
14768 +    file_handle.filename = filename;
14769 +    file_handle.free_filename = 0;
14770 +    file_handle.opened_path = NULL;
14771 +    zend_try {
14772 +        op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
14773 +    } zend_catch {
14774 +        apc_wprint("Error compiling %s in apc_compile_file.", filename);
14775 +        op_array = NULL;
14776 +    } zend_end_try();
14777 +
14778 +    /* Return class/function tables to previous states, destroy temp tables */
14779 +    APCG(force_file_update) = 0;
14780 +    CG(function_table) = cg_orig_function_table;
14781 +    zend_hash_destroy(&cg_function_table);
14782 +    CG(class_table) = cg_orig_class_table;
14783 +    zend_hash_destroy(&cg_class_table);
14784 +    EG(function_table) = eg_orig_function_table;
14785 +    EG(class_table) = eg_orig_class_table;
14786 +    
14787 +    /* Restore global settings */
14788 +    APCG(slam_defense) = slam_defense;
14789 +    APCG(filters) = filters;
14790 +    APCG(cache_by_default) = cache_by_default;
14791 +
14792 +    if(op_array == NULL) { RETURN_FALSE; }
14793 +
14794 +    /* Free up everything */
14795 +    zend_destroy_file_handle(&file_handle TSRMLS_CC);
14796 +#ifdef ZEND_ENGINE_2
14797 +    destroy_op_array(op_array TSRMLS_CC);
14798 +#else
14799 +    destroy_op_array(op_array);
14800 +#endif
14801 +    efree(op_array);
14802 +
14803 +    RETURN_TRUE;
14804 +}
14805 +/* }}} */
14806 +
14807 +/* {{{ apc_functions[] */
14808 +function_entry apc_functions[] = {
14809 +       PHP_FE(apc_cache_info,          NULL)
14810 +       PHP_FE(apc_clear_cache,         NULL)
14811 +       PHP_FE(apc_sma_info,            NULL)
14812 +       PHP_FE(apc_store,               NULL)
14813 +       PHP_FE(apc_fetch,               NULL)
14814 +       PHP_FE(apc_delete,              NULL)
14815 +       PHP_FE(apc_define_constants,    NULL)
14816 +       PHP_FE(apc_load_constants,      NULL)
14817 +       PHP_FE(apc_compile_file,        NULL)
14818 +       PHP_FE(apc_add,                 NULL)
14819 +       {NULL,          NULL,                           NULL}
14820 +};
14821 +/* }}} */
14822 +
14823 +/* {{{ module definition structure */
14824 +
14825 +zend_module_entry apc_module_entry = {
14826 +       STANDARD_MODULE_HEADER,
14827 +       "apc",
14828 +       apc_functions,
14829 +       PHP_MINIT(apc),
14830 +       PHP_MSHUTDOWN(apc),
14831 +       PHP_RINIT(apc),
14832 +       PHP_RSHUTDOWN(apc),
14833 +       PHP_MINFO(apc),
14834 +       APC_VERSION,
14835 +       STANDARD_MODULE_PROPERTIES
14836 +};
14837 +
14838 +#ifdef COMPILE_DL_APC
14839 +ZEND_GET_MODULE(apc)
14840 +#endif
14841 +/* }}} */
14842 +
14843 +/*
14844 + * Local variables:
14845 + * tab-width: 4
14846 + * c-basic-offset: 4
14847 + * End:
14848 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
14849 + * vim<600: expandtab sw=4 ts=4 sts=4
14850 + */
14851 diff -ubrN php-5.2.5-orig/ext/apc/php_apc.h php-5.2.5/ext/apc/php_apc.h
14852 --- php-5.2.5-orig/ext/apc/php_apc.h    1969-12-31 18:00:00.000000000 -0600
14853 +++ php-5.2.5/ext/apc/php_apc.h 2007-12-26 16:51:32.000000000 -0600
14854 @@ -0,0 +1,52 @@
14855 +/*
14856 +  +----------------------------------------------------------------------+
14857 +  | APC                                                                  |
14858 +  +----------------------------------------------------------------------+
14859 +  | Copyright (c) 2006 The PHP Group                                     |
14860 +  +----------------------------------------------------------------------+
14861 +  | This source file is subject to version 3.01 of the PHP license,      |
14862 +  | that is bundled with this package in the file LICENSE, and is        |
14863 +  | available through the world-wide-web at the following url:           |
14864 +  | http://www.php.net/license/3_01.txt                                  |
14865 +  | If you did not receive a copy of the PHP license and are unable to   |
14866 +  | obtain it through the world-wide-web, please send a note to          |
14867 +  | license@php.net so we can mail you a copy immediately.               |
14868 +  +----------------------------------------------------------------------+
14869 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
14870 +  |          George Schlossnagle <george@omniti.com>                     |
14871 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
14872 +  +----------------------------------------------------------------------+
14873 +
14874 +   This software was contributed to PHP by Community Connect Inc. in 2002
14875 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
14876 +   Future revisions and derivatives of this source code must acknowledge
14877 +   Community Connect Inc. as the original contributor of this module by
14878 +   leaving this note intact in the source code.
14879 +
14880 +   All other licensing and usage conditions are those of the PHP Group.
14881 +
14882 + */
14883 +
14884 +/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
14885 +
14886 +#ifndef PHP_APC_H
14887 +#define PHP_APC_H
14888 +
14889 +#include "apc_php.h"
14890 +#include "apc_globals.h"
14891 +
14892 +extern zend_module_entry apc_module_entry;
14893 +#define apc_module_ptr &apc_module_entry
14894 +
14895 +#define phpext_apc_ptr apc_module_ptr
14896 +
14897 +#endif /* PHP_APC_H */
14898 +
14899 +/*
14900 + * Local variables:
14901 + * tab-width: 4
14902 + * c-basic-offset: 4
14903 + * End:
14904 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
14905 + * vim<600: expandtab sw=4 ts=4 sts=4
14906 + */
14907 diff -ubrN php-5.2.5-orig/ext/apc/TECHNOTES.txt php-5.2.5/ext/apc/TECHNOTES.txt
14908 --- php-5.2.5-orig/ext/apc/TECHNOTES.txt        1969-12-31 18:00:00.000000000 -0600
14909 +++ php-5.2.5/ext/apc/TECHNOTES.txt     2007-12-26 16:51:32.000000000 -0600
14910 @@ -0,0 +1,361 @@
14911 +APC Quick-Start Braindump
14912 +
14913 +This is a rapidly written braindump of how APC currently works in the
14914 +form of a quick-start guide to start hacking on APC.
14915 +
14916 +1. Install and use APC a bit so you know what it does from the end-user's
14917 +   perspective.  
14918 +   user-space functions are all explained here: 
14919 +
14920 +2. Grab the current APC code from CVS:
14921 +    
14922 +    cvs -d:pserver:cvsread@cvs.php.net:/repository login
14923 +    Password: phpfi
14924 +    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
14925 +
14926 +   apc/php_apc.c has most of the code for the user-visible stuff.  It is
14927 +   also a regular PHP extension in the sense that there are MINIT, MINFO, 
14928 +   MSHUTDOWN, RSHUTDOWN, etc. functions.  
14929 +
14930 +3. Build it.
14931 +
14932 +   cd pecl/apc
14933 +   phpize
14934 +   ./configure --enable-apc --enable-mmap
14935 +   make
14936 +   cp modules/apc.so /usr/local/lib/php
14937 +   apachectl restart
14938 +
14939 +4. Debugging Hints
14940 +
14941 +     apachectl stop
14942 +     gdb /usr/bin/httpd
14943 +     break ??
14944 +     run -X
14945 +
14946 +   Grab the .gdbinit from the PHP source tree and have a look at the macros.
14947 +
14948 +5. Look through apc/apc_sma.c
14949 +   It is a pretty standard memory allocator.
14950 +
14951 +   apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
14952 +   caller just like malloc, realloc, strdup and free
14953 +
14954 +   On server startup the MINIT hook in php_apc.c calls apc_module_init() in
14955 +   apc_main.c which in turn calls apc_sma_init().  apc_sma_init calls into
14956 +   apc_mmap.c to mmap the specified sized segment (I tend to just use a single
14957 +   segment).  apc_mmap.c should be self-explanatory.  It mmaps a temp file and
14958 +   then unlinks that file right after the mmap to provide automatic shared memory
14959 +   cleanup in case the process dies.
14960 +
14961 +   Once the region has been initialized we stick a header_t at the beginning
14962 +   of the region.  It contains the total size in header->segsize and the number 
14963 +   of bytes available in header->avail.  
14964 +
14965 +   After the header comes a bit of a hack.  A zero-sized block is inserted just
14966 +   to make things easier later on.  And then a huge block that is basically
14967 +   the size of the entire segment minus the two (for the 0-sized block, and this one)
14968 +   block headers.
14969 +
14970 +   The code for this is:
14971 +
14972 +     header = (header_t*) shmaddr;
14973 +     header->segsize = sma_segsize;
14974 +     header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
14975 +     memset(&header->lock,0,sizeof(header->lock));
14976 +     sma_lock = &header->lock;
14977 +     block = BLOCKAT(sizeof(header_t));
14978 +     block->size = 0;
14979 +     block->next = sizeof(header_t) + sizeof(block_t);
14980 +     block = BLOCKAT(block->next);
14981 +     block->size = header->avail;
14982 +     block->next = 0;
14983 +
14984 +   So the shared memory looks like this:
14985 +
14986 +     +--------+-------+---------------------------------+
14987 +     | header | block |             block               |
14988 +     +--------+-------+---------------------------------+
14989 +
14990 +   sma_shmaddrs[0] gives you the address of header
14991 +
14992 +   The blocks are just a simple offset-based linked list (so no pointers):
14993 +
14994 +     typedef struct block_t block_t;
14995 +     struct block_t {
14996 +         size_t size;       /* size of this block */
14997 +         size_t next;       /* offset in segment of next free block */
14998 +         size_t canary;     /* canary to check for memory overwrites */
14999 +#ifdef __APC_SMA_DEBUG__
15000 +         int id;         /* identifier for the memory block */
15001 +#endif
15002 +     };
15003 +
15004 +   The BLOCKAT macro turns an offset into an actual address for you:
15005 +
15006 +     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
15007 +
15008 +   where shmaddr = sma_shaddrs[0]
15009 +
15010 +   And the OFFSET macro goes the other way:
15011 +
15012 +     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
15013 +
15014 +   Allocating a block with a call to apc_sma_allocate() walks through the
15015 +   linked list of blocks until it finds one that is >= to the requested size.
15016 +   The first call to apc_sma_allocate() will hit the second block.  We then
15017 +   chop up that block so it looks like this:
15018 +
15019 +     +--------+-------+-------+-------------------------+
15020 +     | header | block | block |         block           |
15021 +     +--------+-------+-------+-------------------------+
15022 +
15023 +   Then we unlink that block from the linked list so it won't show up
15024 +   as an available block on the next allocate.  So we actually have:
15025 +
15026 +     +--------+-------+       +-------------------------+
15027 +     | header | block |------>|         block           |
15028 +     +--------+-------+       +-------------------------+
15029 +
15030 +   And header->avail along with block->size of the remaining large
15031 +   block are updated accordingly.  The arrow there representing the
15032 +   link which now points to a block with an offset further along in
15033 +   the segment.
15034 +
15035 +   When the block is freed using apc_sma_deallocate() the steps are
15036 +   basically just reversed.  The block is put back and then the deallocate
15037 +   code looks at the block before and after to see if the block immediately
15038 +   before and after are free and if so the blocks are combined.  So you never
15039 +   have 2 free blocks next to each other, apart from at the front with that
15040 +   0-sized dummy block.  This mostly prevents fragmentation.  I have been
15041 +   toying with the idea of always allocating block at 2^n boundaries to make
15042 +   it more likely that they will be re-used to cut down on fragmentation further.
15043 +   That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
15044 +  
15045 +   Of course, anytime we fiddle with our shared memory segment we lock using
15046 +   the locking macros, LOCK() and UNLOCK().
15047 +
15048 +   That should mostly take care of the low-level shared memory handling.
15049 +
15050 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
15051 +   cache logic.
15052 +
15053 +   The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
15054 +   and apc_cache.c for actual cache manipulation.  
15055 +  
15056 +   After the shared memory segment is created and the caches are initialized,
15057 +   apc_module_init() installs the my_compile_file() function overriding Zend's
15058 +   version.  I'll talk about my_compile_file() and the rest of apc_compile.c
15059 +   in the next section.  For now I will stick with apc_main.c and apc_cache.c
15060 +   and talk about the actual caches.  A cache consists of a block of shared
15061 +   memory returned by apc_sma_allocate() via apc_sma_malloc().  You will 
15062 +   notice references to apc_emalloc().  apc_emalloc() is just a thin wrapper
15063 +   around PHP's own emalloc() function which allocates per-process memory from
15064 +   PHP's pool-based memory allocator.  Don't confuse apc_emalloc() and 
15065 +   apc_sma_malloc() as the first is per-process and the second is shared memory.
15066 +
15067 +   The cache is stored in/described by this struct allocated locally using
15068 +   emalloc():
15069 +
15070 +     struct apc_cache_t {
15071 +         void* shmaddr;              /* process (local) address of shared cache */
15072 +         header_t* header;           /* cache header (stored in SHM) */
15073 +         slot_t** slots;             /* array of cache slots (stored in SHM) */
15074 +         int num_slots;              /* number of slots in cache */
15075 +         int gc_ttl;                 /* maximum time on GC list for a slot */
15076 +         int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
15077 +     };
15078 +
15079 +   Whenever you see functions that take a 'cache' argument, this is what they
15080 +   take.  And apc_cache_create() returns a pointer to this populated struct.
15081 +
15082 +   At the beginning of the cache we have a header.  Remember, we are down a level now
15083 +   from the sma stuff.  The sma stuff is the low-level shared-memory allocator which
15084 +   has its own header which is completely separate and invisible to apc_cache.c.  
15085 +   As far as apc_cache.c is concerned the block of memory it is working with could 
15086 +   have come from a call to malloc().
15087 +
15088 +   The header looks like this:
15089 +
15090 +     typedef struct header_t header_t;
15091 +     struct header_t {
15092 +         int num_hits;               /* total successful hits in cache */
15093 +         int num_misses;             /* total unsuccessful hits in cache */
15094 +         slot_t* deleted_list;       /* linked list of to-be-deleted slots */
15095 +     };
15096 +
15097 +   Since this is at the start of the shared memory segment, these values are accessible
15098 +   across all the yapache processes and hence access to them has to be locked.
15099 +
15100 +   After the header we have an array of slots.  The number of slots is user-defined
15101 +   through the apc.num_slots ini hint.  Each slot is described by:
15102 +
15103 +     typedef struct slot_t slot_t;
15104 +     struct slot_t {
15105 +         apc_cache_key_t key;        /* slot key */
15106 +         apc_cache_entry_t* value;   /* slot value */
15107 +         slot_t* next;               /* next slot in linked list */
15108 +         int num_hits;               /* number of hits to this bucket */
15109 +        time_t creation_time;       /* time slot was initialized */
15110 +        time_t deletion_time;       /* time slot was removed from cache */
15111 +        time_t access_time;         /* time slot was last accessed */
15112 +     };
15113 +
15114 +   The slot_t *next there is a linked list to other slots that happened to hash to the
15115 +   same array position.
15116 +
15117 +   apc_cache_insert() shows what happens on a new cache insert.
15118 +
15119 +     slot = &cache->slots[hash(key) % cache->num_slots];
15120 +
15121 +   cache->slots is our array of slots in the segment.  hash() is simply:
15122 +
15123 +     static unsigned int hash(apc_cache_key_t key)
15124 +     {
15125 +         return key.data.file.device + key.data.file.inode;
15126 +     }
15127 +
15128 +   That is, we use the file's device and inode to uniquely identify it.  Initially
15129 +   we had used the file's full path, but getting that requires a realpath() call which
15130 +   is amazingly expensive since it has to stat each component of the path to resolve
15131 +   symlinks and get rid of relative path components.  By using the device+inode we
15132 +   can uniquely identify a file with a single stat.
15133 +
15134 +   So, on an insert we find the array position in the slots array by hasing the device+inode.
15135 +   If there are currently no other slots there, we just create the slot and stick it into
15136 +   the array:
15137 +
15138 +     *slot = make_slot(key, value, *slot, t)
15139 +
15140 +   If there are other slots already at this position we walk the link list to get to
15141 +   the end.  Here is the loop:
15142 +
15143 +     while (*slot) {
15144 +         if (key_equals((*slot)->key.data.file, key.data.file)) {
15145 +            /* If existing slot for the same device+inode is different, remove it and insert the new version */
15146 +            if ((*slot)->key.mtime != key.mtime) {
15147 +                remove_slot(cache, slot);
15148 +                break;
15149 +            }
15150 +            UNLOCK(cache);
15151 +            return 0;
15152 +        } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
15153 +             remove_slot(cache, slot);
15154 +             continue;
15155 +         }
15156 +         slot = &(*slot)->next;
15157 +     }
15158 +
15159 +   That first key_equals() check sees if we have an exact match meaning the file
15160 +   is already in the cache.  Since we try to find the file in the cache before doing
15161 +   an insert, this will generally only happen if another process managed to beat us
15162 +   to inserting it.  If we have a newer version of the file at this point we remove
15163 +   it an insert the new version.  If our version is not newer we just return without
15164 +   doing anything.
15165 +
15166 +   While walking the linked list we also check to see if the cache has a TTL defined.
15167 +   If while walking the linked list we see a slot that has expired, we remove it
15168 +   since we are right there looking at it.  This is the only place we remove stale
15169 +   entries unless the shared memory segment fills up and we force a full expunge via
15170 +   apc_cache_expunge().  apc_cache_expunge() walks the entire slots array and walks
15171 +   down every linked list removing stale slots to free up room.  This is obviously
15172 +   slow and thus only happens when we have run out of room.
15173 +
15174 +   apc_cache_find() simply hashes and returns the entry if it is there.  If it is there
15175 +   but older than the mtime in the entry we are looking for, we delete the one that is
15176 +   there and return indicating we didn't find it.
15177 +
15178 +   Next we need to understand what an actual cache entry looks like.  Have a look at
15179 +   apc_cache.h for the structs.  I sort of glossed over the key part earlier saying
15180 +   that we just used the device+inode to find a hash slot.  It is actually a bit more
15181 +   complex than that because we have two kinds of caches.  We have the standard file
15182 +   cache containing opcode arrays, but we also have a user-controlled cache that the
15183 +   user can insert whatever they want into via apc_store().  For the user cache we
15184 +   obviously don't have a device+inode.  The actual identifier is provided by the user
15185 +   as a char *.  So the key is actually a union that looks like this:
15186 +
15187 +     typedef union _apc_cache_key_data_t {
15188 +         struct {
15189 +             int device;             /* the filesystem device */
15190 +             int inode;              /* the filesystem inode */
15191 +         } file;
15192 +         struct {
15193 +             char *identifier;
15194 +         } user;
15195 +     } apc_cache_key_data_t;
15196 +
15197 +     struct apc_cache_key_t {
15198 +         apc_cache_key_data_t data;
15199 +         int mtime;                  /* the mtime of this cached entry */
15200 +     };   
15201 +
15202 +   And we have two sets of functions to do inserts and finds.  apc_cache_user_find() 
15203 +   and apc_cache_user_insert() operate on the user cache.
15204 +
15205 +   Ok, on to the actual cache entry.  Again, because we have two kinds of caches, we
15206 +   also have the corresponding two kinds of cache entries described by this union:
15207 +
15208 +     typedef union _apc_cache_entry_value_t {
15209 +         struct {
15210 +             char *filename;             /* absolute path to source file */
15211 +             zend_op_array* op_array;    /* op_array allocated in shared memory */
15212 +             apc_function_t* functions;  /* array of apc_function_t's */
15213 +             apc_class_t* classes;       /* array of apc_class_t's */
15214 +         } file;
15215 +         struct {
15216 +             char *info;
15217 +             zval *val;
15218 +             unsigned int ttl;
15219 +         } user;
15220 +     } apc_cache_entry_value_t;
15221 +
15222 +   And then the actual cache entry:
15223 +
15224 +     struct apc_cache_entry_t {
15225 +         apc_cache_entry_value_t data;
15226 +         unsigned char type;
15227 +         int ref_count;
15228 +     };
15229 +
15230 +   The user entry is pretty simple and not all that important for now.  I will
15231 +   concentrate on the file entries since that is what holds the actual compiled
15232 +   opcode arrays along with the functions and classes required by the executor.
15233 +
15234 +   apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
15235 +   The main thing to understand here is that we need more than just the opcode
15236 +   array, we also need the functions and classes created by the compiler when it
15237 +   created the opcode array.  As far as the executor is concerned, it doesn't know
15238 +   that it isn't operating in normal mode being called right after the parse/compile
15239 +   phase, so we need to recreate everything so it looks exactly like it would at
15240 +   that point. 
15241 +
15242 +7. my_compile_file() and apc_compile.c
15243 +
15244 +   my_compile_file() in apc_main.c controls where we get the opcodes from.  If
15245 +   the user-specified filters exclude the file from being cached, then we just
15246 +   call the original compile function and return.  Otherwise we fetch the request
15247 +   time from Apache to avoid an extra syscall, create the key so we can look up
15248 +   the file in the cache.  If we find it we stick it on a local stack which we
15249 +   use at cleanup time to make sure we return everything back to normal after a 
15250 +   request and call cached_compile() which installs the functions and classes
15251 +   associated with the op_array in this entry and then copy the op_array down
15252 +   into our memory space for execution.
15253 +
15254 +   If we didn't find the file in the cache, we need to compile it and insert it.
15255 +   To compile it we simply call the original compile function:
15256 +
15257 +      op_array = old_compile_file(h, type TSRMLS_CC);
15258 +
15259 +   To do the insert we need to copy the functions, classes and the opcode array
15260 +   the compile phase created into shared memory.  This all happens in apc_compile.c
15261 +   in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
15262 +   functions.  Then we make the file entry and do the insert.  Both of these
15263 +   operations were described in the previous section.  
15264 +
15265 +8. The Optimizer
15266 +   
15267 +   The optimizer has been deprecated.
15268 +
15269 +If you made it to the end of this, you should have a pretty good idea of where things are in
15270 +the code.  I skimmed over a lot of things, so plan on spending some time reading through the code.
15271 +
15272 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_001.phpt php-5.2.5/ext/apc/tests/apc_001.phpt
15273 --- php-5.2.5-orig/ext/apc/tests/apc_001.phpt   1969-12-31 18:00:00.000000000 -0600
15274 +++ php-5.2.5/ext/apc/tests/apc_001.phpt        2007-12-26 16:51:32.000000000 -0600
15275 @@ -0,0 +1,27 @@
15276 +--TEST--
15277 +APC: apc_store/fetch with strings
15278 +--SKIPIF--
15279 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15280 +--INI--
15281 +apc.enabled=1
15282 +apc.enable_cli=1
15283 +apc.file_update_protection=0
15284 +--FILE--
15285 +<?php
15286 +
15287 +$foo = 'hello world';
15288 +var_dump($foo);
15289 +apc_store('foo',$foo);
15290 +$bar = apc_fetch('foo');
15291 +var_dump($bar);
15292 +$bar = 'nice';
15293 +var_dump($bar);
15294 +
15295 +?>
15296 +===DONE===
15297 +<?php exit(0); ?>
15298 +--EXPECTF--
15299 +string(11) "hello world"
15300 +string(11) "hello world"
15301 +string(4) "nice"
15302 +===DONE===
15303 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_002.phpt php-5.2.5/ext/apc/tests/apc_002.phpt
15304 --- php-5.2.5-orig/ext/apc/tests/apc_002.phpt   1969-12-31 18:00:00.000000000 -0600
15305 +++ php-5.2.5/ext/apc/tests/apc_002.phpt        2007-12-26 16:51:32.000000000 -0600
15306 @@ -0,0 +1,34 @@
15307 +--TEST--
15308 +APC: apc_store/fetch with objects
15309 +--SKIPIF--
15310 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15311 +--INI--
15312 +apc.enabled=1
15313 +apc.enable_cli=1
15314 +apc.file_update_protection=0
15315 +--FILE--
15316 +<?php
15317 +
15318 +class foo { }
15319 +$foo = new foo;
15320 +var_dump($foo);
15321 +apc_store('foo',$foo);
15322 +unset($foo);
15323 +$bar = apc_fetch('foo');
15324 +var_dump($bar);
15325 +$bar->a = true;
15326 +var_dump($bar);
15327 +
15328 +?>
15329 +===DONE===
15330 +<?php exit(0); ?>
15331 +--EXPECTF--
15332 +object(foo)#%d (0) {
15333 +}
15334 +object(foo)#%d (0) {
15335 +}
15336 +object(foo)#%d (1) {
15337 +  ["a"]=>
15338 +  bool(true)
15339 +}
15340 +===DONE===
15341 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_003.phpt php-5.2.5/ext/apc/tests/apc_003.phpt
15342 --- php-5.2.5-orig/ext/apc/tests/apc_003.phpt   1969-12-31 18:00:00.000000000 -0600
15343 +++ php-5.2.5/ext/apc/tests/apc_003.phpt        2007-12-26 16:51:32.000000000 -0600
15344 @@ -0,0 +1,112 @@
15345 +--TEST--
15346 +APC: apc_store/fetch with objects
15347 +--SKIPIF--
15348 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15349 +--INI--
15350 +apc.enabled=1
15351 +apc.enable_cli=1
15352 +apc.file_update_protection=0
15353 +--FILE--
15354 +<?php
15355 +
15356 +class foo { }
15357 +$foo = new foo;
15358 +var_dump($foo);
15359 +apc_store('foo',$foo);
15360 +unset($foo);
15361 +$bar = apc_fetch('foo');
15362 +var_dump($bar);
15363 +$bar->a = true;
15364 +var_dump($bar);
15365 +
15366 +class bar extends foo
15367 +{
15368 +       public    $pub = 'bar';
15369 +       protected $pro = 'bar';
15370 +       private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
15371 +       
15372 +       function __construct()
15373 +       {
15374 +               $this->bar = true;
15375 +       }
15376 +       
15377 +       function change()
15378 +       {
15379 +               $this->pri = 'mod';
15380 +       }
15381 +}
15382 +
15383 +class baz extends bar
15384 +{
15385 +       private $pri = 'baz';
15386 +
15387 +       function __construct()
15388 +       {
15389 +               parent::__construct();
15390 +               $this->baz = true;
15391 +       }
15392 +}
15393 +
15394 +$baz = new baz;
15395 +var_dump($baz);
15396 +$baz->change();
15397 +var_dump($baz);
15398 +apc_store('baz', $baz);
15399 +unset($baz);
15400 +var_dump(apc_fetch('baz'));
15401 +
15402 +?>
15403 +===DONE===
15404 +<?php exit(0); ?>
15405 +--EXPECTF--
15406 +object(foo)#%d (0) {
15407 +}
15408 +object(foo)#%d (0) {
15409 +}
15410 +object(foo)#%d (1) {
15411 +  ["a"]=>
15412 +  bool(true)
15413 +}
15414 +object(baz)#%d (6) {
15415 +  ["pri:private"]=>
15416 +  string(3) "baz"
15417 +  ["pub"]=>
15418 +  string(3) "bar"
15419 +  ["pro:protected"]=>
15420 +  string(3) "bar"
15421 +  ["pri:private"]=>
15422 +  string(3) "bar"
15423 +  ["bar"]=>
15424 +  bool(true)
15425 +  ["baz"]=>
15426 +  bool(true)
15427 +}
15428 +object(baz)#%d (6) {
15429 +  ["pri:private"]=>
15430 +  string(3) "baz"
15431 +  ["pub"]=>
15432 +  string(3) "bar"
15433 +  ["pro:protected"]=>
15434 +  string(3) "bar"
15435 +  ["pri:private"]=>
15436 +  string(3) "mod"
15437 +  ["bar"]=>
15438 +  bool(true)
15439 +  ["baz"]=>
15440 +  bool(true)
15441 +}
15442 +object(baz)#%d (6) {
15443 +  ["pri:private"]=>
15444 +  string(3) "baz"
15445 +  ["pub"]=>
15446 +  string(3) "bar"
15447 +  ["pro:protected"]=>
15448 +  string(3) "bar"
15449 +  ["pri:private"]=>
15450 +  string(3) "mod"
15451 +  ["bar"]=>
15452 +  bool(true)
15453 +  ["baz"]=>
15454 +  bool(true)
15455 +}
15456 +===DONE===
15457 diff -ubrN php-5.2.5-orig/ext/apc/tests/skipif.inc php-5.2.5/ext/apc/tests/skipif.inc
15458 --- php-5.2.5-orig/ext/apc/tests/skipif.inc     1969-12-31 18:00:00.000000000 -0600
15459 +++ php-5.2.5/ext/apc/tests/skipif.inc  2007-12-26 16:51:32.000000000 -0600
15460 @@ -0,0 +1,6 @@
15461 +<?php
15462 +
15463 +if (!extension_loaded("apc")) die("skip");
15464 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
15465 +
15466 +?>
15467 diff -ubrN php-5.2.5-orig/ext/apc/TODO php-5.2.5/ext/apc/TODO
15468 --- php-5.2.5-orig/ext/apc/TODO 1969-12-31 18:00:00.000000000 -0600
15469 +++ php-5.2.5/ext/apc/TODO      2007-12-26 16:51:32.000000000 -0600
15470 @@ -0,0 +1,30 @@
15471 +Known Bugs
15472
15473 +1.   Gallery2 doesn't work with PHP5+APC.  There is something wrong
15474 +     with the way methods are restored in some edge case I haven't
15475 +     been able to figure out yet.
15476 +     To reproduce install gallery2 and click down to an individual photo.
15477 +
15478 +2.   apc_store() probably needs some checks to skip trying to store
15479 +     internal classes.  Something along the lines of:
15480 +
15481 +     if(Z_TYPE_P(val) == IS_OBJECT) {
15482 +        zend_class_entry *ce = Z_OBJCE_P(val);
15483 +        if(ce->type == ZEND_INTERNAL_CLASS) {
15484 +            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
15485 +            RETURN_FALSE;
15486 +        }
15487 +     }
15488 +
15489 +     in the apc_store() function in php_apc.c but I am wondering if it needs to do more
15490 +     than that.
15491 +
15492 +Enhancements
15493 +
15494 +1.   Some faster platform-specific locking mechanisms wouldd be nice.  futex support
15495 +     for the 2.6 Linux kernels, and/or x86-specific spinlock support.
15496 +
15497 +2.   The optimizer needs a lot of work.  
15498 +
15499 +3.   Assert() elimination in the optimizer when some debug flag somewhere isn't set.
15500 +