add option to compile APC for php5
[packages.git] / lang / php5 / patches / 005-APC.patch
1 diff -ruN php-5.1.6.old/ext/apc/apc.c php-5.1.6/ext/APC/apc.c
2 --- php-5.1.6.old/ext/apc/apc.c 1969-12-31 18:00:00.000000000 -0600
3 +++ php-5.1.6/ext/apc/apc.c     2007-04-02 18:05:30.000000000 -0500
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.17 2007/03/17 14:01:41 gopalv 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_DBG
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 -ruN php-5.1.6.old/ext/apc/apc_cache.c php-5.1.6/ext/APC/apc_cache.c
560 --- php-5.1.6.old/ext/apc/apc_cache.c   1969-12-31 18:00:00.000000000 -0600
561 +++ php-5.1.6/ext/apc/apc_cache.c       2007-04-02 18:05:30.000000000 -0500
562 @@ -0,0 +1,1328 @@
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.140 2007/04/02 22:57:10 rasmus 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 +    apc_cache_entry_t *value;   /* shallow copy of slot->value */
663 +    local_slot_t *next;         /* only for dead list */
664 +};
665 +/* }}} */
666 +/* {{{ struct definition apc_local_cache_t */
667 +struct apc_local_cache_t {
668 +    apc_cache_t* shmcache;      /* the real cache in shm */
669 +    local_slot_t* slots;        /* process (local) cache of objects */
670 +    local_slot_t* dead_list;    /* list of objects pending removal */
671 +    int num_slots;              /* number of slots in cache */
672 +    int ttl;                    /* time to live */
673 +    int num_hits;               /* number of hits */
674 +    int generation;             /* every generation lives between expunges */
675 +};
676 +/* }}} */
677 +
678 +/* {{{ key_equals */
679 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
680 +/* }}} */
681 +
682 +/* {{{ hash */
683 +static unsigned int hash(apc_cache_key_t key)
684 +{
685 +    return key.data.file.device + key.data.file.inode;
686 +}
687 +/* }}} */
688 +
689 +/* {{{ string_nhash_8 */
690 +static unsigned int string_nhash_8(const char *s, size_t len)
691 +{
692 +    register const unsigned int *iv = (const unsigned int *)s;
693 +    register unsigned int h = 0;
694 +    register const unsigned int *e  = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
695 +
696 +    for(;iv<e;iv++) {
697 +        h += *iv;
698 +        h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
699 +    }
700 +    s = (const char *)iv;
701 +    for(len %= sizeof(unsigned int);len;len--) {
702 +        h += *(s++);
703 +    }
704 +    h ^= (h >> 13);
705 +    h ^= (h >> 7);
706 +    return h;
707 +}
708 +/* }}} */
709 +
710 +/* {{{ make_slot */
711 +slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
712 +{
713 +    slot_t* p = apc_sma_malloc(sizeof(slot_t));
714 +    if (!p) return NULL;
715 +
716 +    if(value->type == APC_CACHE_ENTRY_USER) {
717 +        char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
718 +        if (!identifier) {
719 +            apc_sma_free(p);
720 +            return NULL;
721 +        }
722 +        key.data.user.identifier = identifier;
723 +    } else if(key.type == APC_CACHE_KEY_FPFILE) {
724 +        char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
725 +        if (!fullpath) {
726 +            apc_sma_free(p);
727 +            return NULL;
728 +        }
729 +        key.data.fpfile.fullpath = fullpath;
730 +    }
731 +    p->key = key;
732 +    p->value = value;
733 +    p->next = next;
734 +    p->num_hits = 0;
735 +    p->creation_time = t;
736 +    p->access_time = t;
737 +    p->deletion_time = 0;
738 +    return p;
739 +}
740 +/* }}} */
741 +
742 +/* {{{ free_slot */
743 +static void free_slot(slot_t* slot)
744 +{
745 +    if(slot->value->type == APC_CACHE_ENTRY_USER) {
746 +        apc_sma_free((char *)slot->key.data.user.identifier);
747 +    } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
748 +        apc_sma_free((char *)slot->key.data.fpfile.fullpath);
749 +    }
750 +    apc_cache_free_entry(slot->value);
751 +    apc_sma_free(slot);
752 +}
753 +/* }}} */
754 +
755 +/* {{{ remove_slot */
756 +static void remove_slot(apc_cache_t* cache, slot_t** slot)
757 +{
758 +    slot_t* dead = *slot;
759 +    *slot = (*slot)->next;
760 +
761 +    cache->header->mem_size -= dead->value->mem_size;
762 +    cache->header->num_entries--;
763 +    if (dead->value->ref_count <= 0) {
764 +        free_slot(dead);
765 +    }
766 +    else {
767 +        dead->next = cache->header->deleted_list;
768 +        dead->deletion_time = time(0);
769 +        cache->header->deleted_list = dead;
770 +    }
771 +}
772 +/* }}} */
773 +
774 +/* {{{ process_pending_removals */
775 +static void process_pending_removals(apc_cache_t* cache)
776 +{
777 +    slot_t** slot;
778 +    time_t now;
779 +
780 +    /* This function scans the list of removed cache entries and deletes any
781 +     * entry whose reference count is zero (indicating that it is no longer
782 +     * being executed) or that has been on the pending list for more than
783 +     * cache->gc_ttl seconds (we issue a warning in the latter case).
784 +     */
785 +
786 +    if (!cache->header->deleted_list)
787 +        return;
788 +
789 +    slot = &cache->header->deleted_list;
790 +    now = time(0);
791 +
792 +    while (*slot != NULL) {
793 +        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
794 +
795 +        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
796 +            slot_t* dead = *slot;
797 +
798 +            if (dead->value->ref_count > 0) {
799 +                switch(dead->value->type) {
800 +                    case APC_CACHE_ENTRY_FILE:
801 +                        apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
802 +                            "was on gc-list for %d seconds", dead->value->data.file.filename,
803 +                            dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
804 +                        break;
805 +                    case APC_CACHE_ENTRY_USER:
806 +                        apc_log(APC_WARNING, "GC cache entry '%s' "
807 +                            "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
808 +                        break;
809 +                }
810 +            }
811 +            *slot = dead->next;
812 +            free_slot(dead);
813 +        }
814 +        else {
815 +            slot = &(*slot)->next;
816 +        }
817 +    }
818 +}
819 +/* }}} */
820 +
821 +/* {{{ prevent_garbage_collection */
822 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
823 +{
824 +    /* set reference counts on zend objects to an arbitrarily high value to
825 +     * prevent garbage collection after execution */
826 +
827 +    enum { BIG_VALUE = 1000 };
828 +
829 +    if(entry->data.file.op_array) {
830 +        entry->data.file.op_array->refcount[0] = BIG_VALUE;
831 +    }
832 +    if (entry->data.file.functions) {
833 +        int i;
834 +        apc_function_t* fns = entry->data.file.functions;
835 +        for (i=0; fns[i].function != NULL; i++) {
836 +#ifdef ZEND_ENGINE_2            
837 +            *(fns[i].function->op_array.refcount) = BIG_VALUE;
838 +#else            
839 +            fns[i].function->op_array.refcount[0] = BIG_VALUE;
840 +#endif            
841 +        }
842 +    }
843 +    if (entry->data.file.classes) {
844 +        int i;
845 +        apc_class_t* classes = entry->data.file.classes;
846 +        for (i=0; classes[i].class_entry != NULL; i++) {
847 +#ifdef ZEND_ENGINE_2            
848 +            classes[i].class_entry->refcount = BIG_VALUE;
849 +#else            
850 +            classes[i].class_entry->refcount[0] = BIG_VALUE;
851 +#endif
852 +        }
853 +    }
854 +}
855 +/* }}} */
856 +
857 +/* {{{ apc_cache_create */
858 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
859 +{
860 +    apc_cache_t* cache;
861 +    int cache_size;
862 +    int num_slots;
863 +    int i;
864 +
865 +    num_slots = size_hint > 0 ? size_hint*2 : 2000;
866 +
867 +    cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
868 +    cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
869 +
870 +    cache->shmaddr = apc_sma_malloc(cache_size);
871 +    memset(cache->shmaddr, 0, cache_size);
872 +
873 +    cache->header = (header_t*) cache->shmaddr;
874 +    cache->header->num_hits = 0;
875 +    cache->header->num_misses = 0;
876 +    cache->header->deleted_list = NULL;
877 +    cache->header->start_time = time(NULL);
878 +    cache->header->expunges = 0;
879 +    cache->header->busy = 0;
880 +
881 +    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
882 +    cache->num_slots = num_slots;
883 +    cache->gc_ttl = gc_ttl;
884 +    cache->ttl = ttl;
885 +    CREATE_LOCK(cache->header->lock);
886 +#if NONBLOCKING_LOCK_AVAILABLE
887 +    CREATE_LOCK(cache->header->wrlock);
888 +#endif
889 +    for (i = 0; i < num_slots; i++) {
890 +        cache->slots[i] = NULL;
891 +    }
892 +
893 +    return cache;
894 +}
895 +/* }}} */
896 +
897 +/* {{{ apc_cache_destroy */
898 +void apc_cache_destroy(apc_cache_t* cache)
899 +{
900 +    DESTROY_LOCK(cache);
901 +    apc_efree(cache);
902 +}
903 +/* }}} */
904 +
905 +/* {{{ apc_cache_clear */
906 +void apc_cache_clear(apc_cache_t* cache)
907 +{
908 +    int i;
909 +
910 +    if(!cache) return;
911 +
912 +    LOCK(cache);
913 +    cache->header->busy = 1;
914 +    cache->header->num_hits = 0;
915 +    cache->header->num_misses = 0;
916 +    cache->header->start_time = time(NULL);
917 +    cache->header->expunges = 0;
918 +
919 +    for (i = 0; i < cache->num_slots; i++) {
920 +        slot_t* p = cache->slots[i];
921 +        while (p) {
922 +            remove_slot(cache, &p);
923 +        }
924 +        cache->slots[i] = NULL;
925 +    }
926 +    
927 +    cache->header->busy = 0;
928 +    UNLOCK(cache);
929 +}
930 +/* }}} */
931 +
932 +/* {{{ apc_cache_expunge */
933 +void apc_cache_expunge(apc_cache_t* cache, time_t t)
934 +{
935 +    int i;
936 +
937 +    if(!cache) return;
938 +
939 +    if(!cache->ttl) {
940 +        /* 
941 +         * If cache->ttl is not set, we wipe out the entire cache when
942 +         * we run out of space. 
943 +         */
944 +        LOCK(cache);
945 +        cache->header->busy = 1;
946 +        cache->header->expunges++;
947 +        for (i = 0; i < cache->num_slots; i++) {
948 +            slot_t* p = cache->slots[i];
949 +            while (p) {
950 +                remove_slot(cache, &p);
951 +            }
952 +            cache->slots[i] = NULL;
953 +        }
954 +        cache->header->busy = 0;
955 +        UNLOCK(cache);
956 +    } else {
957 +        slot_t **p;
958 +
959 +        /*
960 +         * If the ttl for the cache is set we walk through and delete stale 
961 +         * entries.  For the user cache that is slightly confusing since
962 +         * we have the individual entry ttl's we can look at, but that would be
963 +         * too much work.  So if you want the user cache expunged, set a high
964 +         * default apc.user_ttl and still provide a specific ttl for each entry
965 +         * on insert
966 +         */
967 +
968 +        LOCK(cache);
969 +        cache->header->busy = 1;
970 +        cache->header->expunges++;
971 +        for (i = 0; i < cache->num_slots; i++) {
972 +            p = &cache->slots[i];
973 +            while(*p) {
974 +                /* 
975 +                 * For the user cache we look at the individual entry ttl values
976 +                 * and if not set fall back to the default ttl for the user cache
977 +                 */
978 +                if((*p)->value->type == APC_CACHE_ENTRY_USER) {
979 +                    if((*p)->value->data.user.ttl) {
980 +                        if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
981 +                            remove_slot(cache, p);
982 +                            continue;
983 +                        }
984 +                    } else if(cache->ttl) {
985 +                        if((*p)->creation_time + cache->ttl < t) {
986 +                            remove_slot(cache, p);
987 +                            continue;
988 +                        }
989 +                    }
990 +                } else if((*p)->access_time < (t - cache->ttl)) {
991 +                    remove_slot(cache, p);
992 +                    continue;
993 +                }
994 +                p = &(*p)->next;
995 +            }
996 +        }
997 +        cache->header->busy = 0;
998 +        UNLOCK(cache);
999 +    }
1000 +}
1001 +/* }}} */
1002 +
1003 +/* {{{ apc_cache_insert */
1004 +int apc_cache_insert(apc_cache_t* cache,
1005 +                     apc_cache_key_t key,
1006 +                     apc_cache_entry_t* value,
1007 +                     time_t t)
1008 +{
1009 +    slot_t** slot;
1010 +
1011 +    if (!value) {
1012 +        return 0;
1013 +    }
1014 +
1015 +#ifdef __DEBUG_APC__
1016 +    fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
1017 +#endif
1018 +
1019 +    LOCK(cache);
1020 +    process_pending_removals(cache);
1021 +
1022 +    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1023 +    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1024 +
1025 +    while(*slot) {
1026 +      if(key.type == (*slot)->key.type) {
1027 +        if(key.type == APC_CACHE_KEY_FILE) {
1028 +            if(key_equals((*slot)->key.data.file, key.data.file)) {
1029 +                /* If existing slot for the same device+inode is different, remove it and insert the new version */
1030 +                if ((*slot)->key.mtime != key.mtime) {
1031 +                    remove_slot(cache, slot);
1032 +                    break;
1033 +                }
1034 +                UNLOCK(cache);
1035 +                return 0;
1036 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1037 +                remove_slot(cache, slot);
1038 +                continue;
1039 +            }
1040 +        } else {   /* APC_CACHE_KEY_FPFILE */
1041 +                if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1042 +                /* Hrm.. it's already here, remove it and insert new one */
1043 +                remove_slot(cache, slot);
1044 +                break;
1045 +            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1046 +                remove_slot(cache, slot);
1047 +                continue;
1048 +            }
1049 +        }
1050 +      }
1051 +      slot = &(*slot)->next;
1052 +    }
1053 +
1054 +    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1055 +        UNLOCK(cache);
1056 +        return -1;
1057 +    }
1058 +   
1059 +    cache->header->mem_size += value->mem_size;
1060 +    cache->header->num_entries++;
1061 +    cache->header->num_inserts++;
1062 +    
1063 +    UNLOCK(cache);
1064 +    return 1;
1065 +}
1066 +/* }}} */
1067 +
1068 +/* {{{ apc_cache_user_insert */
1069 +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)
1070 +{
1071 +    slot_t** slot;
1072 +    size_t* mem_size_ptr = NULL;
1073 +
1074 +    if (!value) {
1075 +        return 0;
1076 +    }
1077 +
1078 +    LOCK(cache);
1079 +    process_pending_removals(cache);
1080 +
1081 +    slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
1082 +
1083 +    if (APCG(mem_size_ptr) != NULL) {
1084 +        mem_size_ptr = APCG(mem_size_ptr);
1085 +        APCG(mem_size_ptr) = NULL;
1086 +    }
1087 +
1088 +    while (*slot) {
1089 +        if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
1090 +            /* 
1091 +             * At this point we have found the user cache entry.  If we are doing 
1092 +             * an exclusive insert (apc_add) we are going to bail right away if
1093 +             * the user entry already exists and it has no ttl, or
1094 +             * there is a ttl and the entry has not timed out yet.
1095 +             */
1096 +            if(exclusive && (  !(*slot)->value->data.user.ttl ||
1097 +                              ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) 
1098 +                            ) ) {
1099 +                UNLOCK(cache);
1100 +                return 0;
1101 +            }
1102 +            remove_slot(cache, slot);
1103 +            break;
1104 +        } else 
1105 +        /* 
1106 +         * This is a bit nasty.  The idea here is to do runtime cleanup of the linked list of
1107 +         * slot entries so we don't always have to skip past a bunch of stale entries.  We check
1108 +         * for staleness here and get rid of them by first checking to see if the cache has a global
1109 +         * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
1110 +         * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
1111 +         */
1112 +        if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || 
1113 +           ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
1114 +            remove_slot(cache, slot);
1115 +            continue;
1116 +        }
1117 +        slot = &(*slot)->next;
1118 +    }
1119 +
1120 +    if (mem_size_ptr != NULL) {
1121 +        APCG(mem_size_ptr) = mem_size_ptr;
1122 +    }
1123 +
1124 +    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1125 +        UNLOCK(cache);
1126 +        return 0;
1127 +    }
1128 +    if (APCG(mem_size_ptr) != NULL) {
1129 +        value->mem_size = *APCG(mem_size_ptr);
1130 +        cache->header->mem_size += *APCG(mem_size_ptr);
1131 +    }
1132 +    cache->header->num_entries++;
1133 +    cache->header->num_inserts++;
1134 +
1135 +    UNLOCK(cache);
1136 +    return 1;
1137 +}
1138 +/* }}} */
1139 +
1140 +/* {{{ apc_cache_find_slot */
1141 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1142 +{
1143 +    slot_t** slot;
1144 +    volatile slot_t* retval = NULL;
1145 +
1146 +    LOCK(cache);
1147 +    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1148 +    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1149 +
1150 +    while (*slot) {
1151 +      if(key.type == (*slot)->key.type) {
1152 +        if(key.type == APC_CACHE_KEY_FILE) {
1153 +            if(key_equals((*slot)->key.data.file, key.data.file)) {
1154 +                if((*slot)->key.mtime != key.mtime) {
1155 +                    remove_slot(cache, slot);
1156 +                    cache->header->num_misses++;
1157 +                    UNLOCK(cache);
1158 +                    return NULL;
1159 +                }
1160 +                (*slot)->num_hits++;
1161 +                (*slot)->value->ref_count++;
1162 +                (*slot)->access_time = t;
1163 +                prevent_garbage_collection((*slot)->value);
1164 +                cache->header->num_hits++;
1165 +                retval = *slot;
1166 +                UNLOCK(cache);
1167 +                return (slot_t*)retval;
1168 +            }
1169 +        } else {  /* APC_CACHE_KEY_FPFILE */
1170 +            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1171 +                /* TTL Check ? */
1172 +                (*slot)->num_hits++;
1173 +                (*slot)->value->ref_count++;
1174 +                (*slot)->access_time = t;
1175 +                prevent_garbage_collection((*slot)->value);
1176 +                cache->header->num_hits++;
1177 +                retval = *slot;
1178 +                UNLOCK(cache);
1179 +                return (slot_t*)retval;
1180 +            }
1181 +        }
1182 +      }
1183 +      slot = &(*slot)->next;
1184 +    }
1185 +    cache->header->num_misses++;
1186 +    UNLOCK(cache);
1187 +    return NULL;
1188 +}
1189 +/* }}} */
1190 +
1191 +/* {{{ apc_cache_find */
1192 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1193 +{
1194 +    slot_t * slot = apc_cache_find_slot(cache, key, t);
1195 +    return (slot) ? slot->value : NULL;
1196 +}
1197 +/* }}} */
1198 +
1199 +/* {{{ apc_cache_user_find */
1200 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
1201 +{
1202 +    slot_t** slot;
1203 +    volatile apc_cache_entry_t* value = NULL;
1204 +
1205 +    LOCK(cache);
1206 +
1207 +    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1208 +
1209 +    while (*slot) {
1210 +        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1211 +            /* Check to make sure this entry isn't expired by a hard TTL */
1212 +            if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
1213 +                remove_slot(cache, slot);
1214 +                UNLOCK(cache);
1215 +                return NULL;
1216 +            }
1217 +            /* Otherwise we are fine, increase counters and return the cache entry */
1218 +            (*slot)->num_hits++;
1219 +            (*slot)->value->ref_count++;
1220 +            (*slot)->access_time = t;
1221 +
1222 +            cache->header->num_hits++;
1223 +            value = (*slot)->value;
1224 +            UNLOCK(cache);
1225 +            return (apc_cache_entry_t*)value;
1226 +        }
1227 +        slot = &(*slot)->next;
1228 +    }
1229
1230 +    UNLOCK(cache);
1231 +    return NULL;
1232 +}
1233 +/* }}} */
1234 +
1235 +/* {{{ apc_cache_user_delete */
1236 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
1237 +{
1238 +    slot_t** slot;
1239 +
1240 +    LOCK(cache);
1241 +
1242 +    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1243 +
1244 +    while (*slot) {
1245 +        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1246 +            remove_slot(cache, slot);
1247 +            UNLOCK(cache);
1248 +            return 1;
1249 +        }
1250 +        slot = &(*slot)->next;
1251 +    }
1252 +
1253 +    UNLOCK(cache);
1254 +    return 0;
1255 +}
1256 +/* }}} */
1257 +
1258 +/* {{{ apc_cache_release */
1259 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
1260 +{
1261 +    /* local cache refcount-- is done in apc_local_cache_cleanup */
1262 +    if(entry->local) return;
1263 +
1264 +    LOCK(cache);
1265 +    entry->ref_count--;
1266 +    UNLOCK(cache);
1267 +}
1268 +/* }}} */
1269 +
1270 +/* {{{ apc_cache_make_file_key */
1271 +int apc_cache_make_file_key(apc_cache_key_t* key,
1272 +                       const char* filename,
1273 +                       const char* include_path,
1274 +                       time_t t
1275 +                                          TSRMLS_DC)
1276 +{
1277 +    static char canon_path[MAXPATHLEN];
1278 +    struct stat *tmp_buf=NULL;
1279 +    struct apc_fileinfo_t fileinfo = { {0}, };
1280 +    int len;
1281 +       
1282 +    assert(key != NULL);
1283 +
1284 +    if (!filename || !SG(request_info).path_translated) {
1285 +#ifdef __DEBUG_APC__
1286 +        fprintf(stderr,"No filename and no path_translated - bailing\n");
1287 +#endif
1288 +        return 0;
1289 +       }
1290 +
1291 +    len = strlen(filename);
1292 +    if(APCG(fpstat)==0) {
1293 +        if(IS_ABSOLUTE_PATH(filename,len)) {
1294 +            key->data.fpfile.fullpath = filename;
1295 +            key->data.fpfile.fullpath_len = len;
1296 +            key->mtime = t;
1297 +            key->type = APC_CACHE_KEY_FPFILE;
1298 +        } else {
1299 +            if(!realpath(filename, canon_path)) {
1300 +                fprintf(stderr, "realpath failed to canonicalize %s - bailing\n", filename);
1301 +                return 0;
1302 +            }
1303 +            key->data.fpfile.fullpath = canon_path;
1304 +            key->data.fpfile.fullpath_len = strlen(canon_path);
1305 +            key->mtime = t;
1306 +            key->type = APC_CACHE_KEY_FPFILE;
1307 +        }
1308 +        return 1;
1309 +    } 
1310 +
1311 +    if(!strcmp(SG(request_info).path_translated, filename)) {
1312 +        tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
1313 +    }
1314 +    if(tmp_buf) { 
1315 +               fileinfo.st_buf = *tmp_buf;
1316 +    } else {
1317 +        if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1318 +#ifdef __DEBUG_APC__
1319 +            fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
1320 +#endif
1321 +            return 0;
1322 +        }
1323 +    }
1324 +
1325 +    if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
1326 +#ifdef __DEBUG_APC__
1327 +        fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
1328 +#endif
1329 +        return 0;
1330 +    }
1331 +
1332 +    /*
1333 +     * This is a bit of a hack.
1334 +     *
1335 +     * Here I am checking to see if the file is at least 2 seconds old.  
1336 +     * The idea is that if the file is currently being written to then its
1337 +     * mtime is going to match or at most be 1 second off of the current
1338 +     * request time and we want to avoid caching files that have not been
1339 +     * completely written.  Of course, people should be using atomic 
1340 +     * mechanisms to push files onto live web servers, but adding this
1341 +     * tiny safety is easier than educating the world.  This is now
1342 +     * configurable, but the default is still 2 seconds.
1343 +     */
1344 +    if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) { 
1345 +#ifdef __DEBUG_APC__
1346 +        fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
1347 +#endif
1348 +        return 0;
1349 +    }
1350 +
1351 +    key->data.file.device = fileinfo.st_buf.st_dev;
1352 +    key->data.file.inode  = fileinfo.st_buf.st_ino;
1353 +    /* 
1354 +     * If working with content management systems that like to munge the mtime, 
1355 +     * it might be appropriate to key off of the ctime to be immune to systems
1356 +     * that try to backdate a template.  If the mtime is set to something older
1357 +     * than the previous mtime of a template we will obviously never see this
1358 +     * "older" template.  At some point the Smarty templating system did this.
1359 +     * I generally disagree with using the ctime here because you lose the 
1360 +     * ability to warm up new content by saving it to a temporary file, hitting
1361 +     * it once to cache it and then renaming it into its permanent location so
1362 +     * set the apc.stat_ctime=true to enable this check.
1363 +     */
1364 +    if(APCG(stat_ctime)) {
1365 +        key->mtime  = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime; 
1366 +    } else {
1367 +        key->mtime = fileinfo.st_buf.st_mtime;
1368 +    }
1369 +    key->type = APC_CACHE_KEY_FILE;
1370 +    return 1;
1371 +}
1372 +/* }}} */
1373 +
1374 +/* {{{ apc_cache_make_user_key */
1375 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
1376 +{
1377 +    assert(key != NULL);
1378 +
1379 +    if (!identifier)
1380 +        return 0;
1381 +
1382 +    key->data.user.identifier = identifier;
1383 +    key->data.user.identifier_len = identifier_len;
1384 +    key->mtime = t;
1385 +    key->type = APC_CACHE_KEY_USER;
1386 +    return 1;
1387 +}
1388 +/* }}} */
1389 +
1390 +/* {{{ apc_cache_make_file_entry */
1391 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
1392 +                                        zend_op_array* op_array,
1393 +                                        apc_function_t* functions,
1394 +                                        apc_class_t* classes)
1395 +{
1396 +    apc_cache_entry_t* entry;
1397 +
1398 +    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1399 +    if (!entry) return NULL;
1400 +
1401 +    entry->data.file.filename  = apc_xstrdup(filename, apc_sma_malloc);
1402 +    if(!entry->data.file.filename) {
1403 +#ifdef __DEBUG_APC__
1404 +        fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
1405 +#endif
1406 +        apc_sma_free(entry);
1407 +        return NULL;
1408 +    }
1409 +#ifdef __DEBUG_APC__
1410 +    fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
1411 +#endif
1412 +    entry->data.file.op_array  = op_array;
1413 +    entry->data.file.functions = functions;
1414 +    entry->data.file.classes   = classes;
1415 +    entry->type = APC_CACHE_ENTRY_FILE;
1416 +    entry->ref_count = 0;
1417 +    entry->mem_size = 0;
1418 +    entry->autofiltered = 0;
1419 +    entry->local = 0;
1420 +    return entry;
1421 +}
1422 +/* }}} */
1423 +
1424 +/* {{{ apc_cache_store_zval */
1425 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1426 +{
1427 +    smart_str buf = {0};
1428 +    php_serialize_data_t var_hash;
1429 +    TSRMLS_FETCH();
1430 +
1431 +    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1432 +        if(!dst) {
1433 +            CHECK(dst = (zval*) allocate(sizeof(zval)));
1434 +        }
1435 +               
1436 +        PHP_VAR_SERIALIZE_INIT(var_hash);
1437 +        php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
1438 +        PHP_VAR_SERIALIZE_DESTROY(var_hash);
1439 +               
1440 +        dst->type = IS_NULL; /* in case we fail */
1441 +        if(buf.c) {
1442 +            dst->type = src->type & ~IS_CONSTANT_INDEX;
1443 +            dst->value.str.len = buf.len;
1444 +            CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
1445 +            dst->type = src->type;
1446 +            smart_str_free(&buf);
1447 +        }
1448 +        return dst; 
1449 +    } else {
1450 +        
1451 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1452 +        HashTable *old = APCG(copied_zvals);
1453 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1454 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1455 +        
1456 +        dst = apc_copy_zval(dst, src, allocate, deallocate);
1457 +
1458 +        if(APCG(copied_zvals)) {
1459 +            zend_hash_destroy(APCG(copied_zvals));
1460 +            efree(APCG(copied_zvals));
1461 +        }
1462 +
1463 +        APCG(copied_zvals) = old;
1464 +
1465 +        return dst;
1466 +    }
1467 +}
1468 +/* }}} */
1469 +
1470 +/* {{{ apc_cache_fetch_zval */
1471 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1472 +{
1473 +    TSRMLS_FETCH();
1474 +    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1475 +        php_unserialize_data_t var_hash;
1476 +        const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
1477 +
1478 +        PHP_VAR_UNSERIALIZE_INIT(var_hash);
1479 +        if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
1480 +            PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1481 +            zval_dtor(dst);
1482 +            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));
1483 +            dst->type = IS_NULL;
1484 +        }
1485 +        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);         
1486 +        return dst; 
1487 +    } else {
1488 +    
1489 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1490 +        HashTable *old = APCG(copied_zvals);
1491 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1492 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1493 +        
1494 +        dst = apc_copy_zval(dst, src, allocate, deallocate);
1495 +
1496 +        if(APCG(copied_zvals)) {
1497 +            zend_hash_destroy(APCG(copied_zvals));
1498 +            efree(APCG(copied_zvals));
1499 +        }
1500 +
1501 +        APCG(copied_zvals) = old;
1502 +
1503 +        return dst;
1504 +    }
1505 +}
1506 +/* }}} */
1507 +
1508 +/* {{{ apc_cache_free_zval */
1509 +void apc_cache_free_zval(zval* src, apc_free_t deallocate)
1510 +{
1511 +    TSRMLS_FETCH();
1512 +    if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1513 +        if (src->value.str.val) {
1514 +               deallocate(src->value.str.val);
1515 +        }
1516 +        deallocate(src);
1517 +    } else {
1518 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
1519 +        HashTable *old = APCG(copied_zvals);
1520 +        APCG(copied_zvals) = emalloc(sizeof(HashTable));
1521 +        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1522 +        
1523 +        apc_free_zval(src, deallocate);
1524 +
1525 +        if(APCG(copied_zvals)) {
1526 +            zend_hash_destroy(APCG(copied_zvals));
1527 +            efree(APCG(copied_zvals));
1528 +        }
1529 +
1530 +        APCG(copied_zvals) = old;
1531 +    }
1532 +}
1533 +/* }}} */
1534 +
1535 +/* {{{ apc_cache_make_user_entry */
1536 +apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
1537 +{
1538 +    apc_cache_entry_t* entry;
1539 +
1540 +    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1541 +    if (!entry) return NULL;
1542 +
1543 +    entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
1544 +    entry->data.user.info_len = info_len;
1545 +    if(!entry->data.user.info) {
1546 +        apc_sma_free(entry);
1547 +        return NULL;
1548 +    }
1549 +    entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
1550 +    if(!entry->data.user.val) {
1551 +        apc_sma_free(entry->data.user.info);
1552 +        apc_sma_free(entry);
1553 +        return NULL;
1554 +    }
1555 +    INIT_PZVAL(entry->data.user.val);
1556 +    entry->data.user.ttl = ttl;
1557 +    entry->type = APC_CACHE_ENTRY_USER;
1558 +    entry->ref_count = 0;
1559 +    entry->mem_size = 0;
1560 +    entry->autofiltered = 0;
1561 +    entry->local = 0;
1562 +    return entry;
1563 +}
1564 +/* }}} */
1565 +
1566 +/* {{{ apc_cache_free_entry */
1567 +void apc_cache_free_entry(apc_cache_entry_t* entry)
1568 +{
1569 +    if (entry != NULL) {
1570 +        assert(entry->ref_count == 0);
1571 +        switch(entry->type) {
1572 +            case APC_CACHE_ENTRY_FILE:
1573 +                apc_sma_free(entry->data.file.filename);
1574 +                apc_free_op_array(entry->data.file.op_array, apc_sma_free);
1575 +                apc_free_functions(entry->data.file.functions, apc_sma_free);
1576 +                apc_free_classes(entry->data.file.classes, apc_sma_free);
1577 +                break;
1578 +            case APC_CACHE_ENTRY_USER:
1579 +                apc_sma_free(entry->data.user.info);
1580 +                apc_cache_free_zval(entry->data.user.val, apc_sma_free);
1581 +                break;
1582 +        }
1583 +        apc_sma_free(entry);
1584 +    }
1585 +}
1586 +/* }}} */
1587 +
1588 +/* {{{ apc_cache_info */
1589 +apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
1590 +{
1591 +    apc_cache_info_t* info;
1592 +    slot_t* p;
1593 +    int i;
1594 +
1595 +    if(!cache) return NULL;
1596 +
1597 +    LOCK(cache);
1598 +
1599 +    info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
1600 +    if(!info) {
1601 +        UNLOCK(cache);
1602 +        return NULL;
1603 +    }
1604 +    info->num_slots = cache->num_slots;
1605 +    info->ttl = cache->ttl;
1606 +    info->num_hits = cache->header->num_hits;
1607 +    info->num_misses = cache->header->num_misses;
1608 +    info->list = NULL;
1609 +    info->deleted_list = NULL;
1610 +    info->start_time = cache->header->start_time;
1611 +    info->expunges = cache->header->expunges;
1612 +    info->mem_size = cache->header->mem_size;
1613 +    info->num_entries = cache->header->num_entries;
1614 +    info->num_inserts = cache->header->num_inserts;
1615 +
1616 +    if(!limited) {
1617 +        /* For each hashtable slot */
1618 +        for (i = 0; i < info->num_slots; i++) {
1619 +            p = cache->slots[i];
1620 +            for (; p != NULL; p = p->next) {
1621 +                apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1622 +
1623 +                if(p->value->type == APC_CACHE_ENTRY_FILE) {
1624 +                    link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1625 +                    link->data.file.device = p->key.data.file.device;
1626 +                    link->data.file.inode = p->key.data.file.inode;
1627 +                    link->type = APC_CACHE_ENTRY_FILE;
1628 +                } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1629 +                    link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1630 +                    link->data.user.ttl = p->value->data.user.ttl;
1631 +                    link->type = APC_CACHE_ENTRY_USER;
1632 +                }
1633 +                link->num_hits = p->num_hits;
1634 +                link->mtime = p->key.mtime;
1635 +                link->creation_time = p->creation_time;
1636 +                link->deletion_time = p->deletion_time;
1637 +                link->access_time = p->access_time;
1638 +                link->ref_count = p->value->ref_count;
1639 +                link->mem_size = p->value->mem_size;
1640 +                link->next = info->list;
1641 +                info->list = link;
1642 +            }
1643 +        }
1644 +
1645 +        /* For each slot pending deletion */
1646 +        for (p = cache->header->deleted_list; p != NULL; p = p->next) {
1647 +            apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1648 +
1649 +            if(p->value->type == APC_CACHE_ENTRY_FILE) {
1650 +                link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1651 +                if(p->key.type == APC_CACHE_KEY_FILE) {
1652 +                    link->data.file.device = p->key.data.file.device;
1653 +                    link->data.file.inode = p->key.data.file.inode;
1654 +                } else { /* This is a no-stat fullpath file entry */
1655 +                    link->data.file.device = 0;
1656 +                    link->data.file.inode = 0;
1657 +                }
1658 +                link->type = APC_CACHE_ENTRY_FILE;
1659 +            } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1660 +                link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1661 +                link->data.user.ttl = p->value->data.user.ttl;
1662 +                link->type = APC_CACHE_ENTRY_USER;
1663 +            }
1664 +            link->num_hits = p->num_hits;
1665 +            link->mtime = p->key.mtime;
1666 +            link->creation_time = p->creation_time;
1667 +            link->deletion_time = p->deletion_time;
1668 +            link->access_time = p->access_time;
1669 +            link->ref_count = p->value->ref_count;
1670 +            link->mem_size = p->value->mem_size;
1671 +            link->next = info->deleted_list;
1672 +            info->deleted_list = link;
1673 +        }
1674 +    }
1675 +
1676 +    UNLOCK(cache);
1677 +    return info;
1678 +}
1679 +/* }}} */
1680 +
1681 +/* {{{ apc_cache_free_info */
1682 +void apc_cache_free_info(apc_cache_info_t* info)
1683 +{
1684 +    apc_cache_link_t* p = info->list;
1685 +    apc_cache_link_t* q = NULL;
1686 +    while (p != NULL) {
1687 +        q = p;
1688 +        p = p->next;
1689 +        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1690 +        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1691 +        apc_efree(q);
1692 +    }
1693 +    p = info->deleted_list;
1694 +    while (p != NULL) {
1695 +        q = p;
1696 +        p = p->next;
1697 +        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1698 +        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1699 +        apc_efree(q);
1700 +    }
1701 +    apc_efree(info);
1702 +}
1703 +/* }}} */
1704 +
1705 +/* {{{ apc_cache_unlock */
1706 +void apc_cache_unlock(apc_cache_t* cache)
1707 +{
1708 +    UNLOCK(cache);
1709 +}
1710 +/* }}} */
1711 +
1712 +/* {{{ apc_cache_busy */
1713 +zend_bool apc_cache_busy(apc_cache_t* cache)
1714 +{
1715 +    return cache->header->busy;
1716 +}
1717 +/* }}} */
1718 +
1719 +#if NONBLOCKING_LOCK_AVAILABLE
1720 +/* {{{ apc_cache_write_lock */
1721 +zend_bool apc_cache_write_lock(apc_cache_t* cache)
1722 +{
1723 +    return apc_lck_nb_lock(cache->header->wrlock);
1724 +}
1725 +/* }}} */
1726 +
1727 +/* {{{ apc_cache_write_unlock */
1728 +void apc_cache_write_unlock(apc_cache_t* cache)
1729 +{
1730 +    apc_lck_unlock(cache->header->wrlock);
1731 +}
1732 +/* }}} */
1733 +#endif
1734 +
1735 +/* {{{ make_local_slot */
1736 +static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot) 
1737 +{
1738 +    apc_cache_entry_t* value;
1739 +
1740 +    value = apc_emalloc(sizeof(apc_cache_entry_t));
1741 +    memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
1742 +    value->local = 1;
1743 +
1744 +    lslot->original = slot;
1745 +    lslot->value = value;
1746 +    lslot->num_hits++;
1747 +
1748 +    return lslot; /* for what joy ? ... consistency */
1749 +}
1750 +/* }}} */
1751 +
1752 +/* {{{ free_local_slot */
1753 +static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot) 
1754 +{
1755 +    local_slot_t * dead = NULL;
1756 +    if(!lslot->original) return;
1757 +
1758 +    /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
1759 +    dead = apc_emalloc(sizeof(local_slot_t));
1760 +    memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
1761 +
1762 +    lslot->original = NULL;
1763 +    lslot->value = NULL;
1764 +
1765 +    dead->next = cache->dead_list;
1766 +    cache->dead_list = dead;
1767 +}
1768 +/* }}} */
1769 +
1770 +/* {{{ apc_local_cache_create */
1771 +apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
1772 +{
1773 +    apc_local_cache_t* cache = NULL;
1774 +
1775 +    cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
1776 +
1777 +    cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
1778 +    memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
1779 +
1780 +    cache->shmcache = shmcache;
1781 +    cache->num_slots = num_slots;
1782 +    cache->ttl = ttl;
1783 +    cache->num_hits = 0;
1784 +    cache->generation = shmcache->header->expunges;
1785 +    cache->dead_list = NULL;
1786 +
1787 +    return cache;
1788 +}
1789 +/* }}} */
1790 +
1791 +/* {{{ apc_local_cache_cleanup */
1792 +void apc_local_cache_cleanup(apc_local_cache_t* cache) {
1793 +    local_slot_t * lslot;
1794 +    time_t t = time(0);
1795 +    
1796 +    int i;
1797 +    for(i = 0; i < cache->num_slots; i++) {
1798 +        slot_t * slot = cache->slots[i].original;
1799 +        if((slot && slot->access_time < (t - cache->ttl)) ||
1800 +                cache->generation != cache->shmcache->header->expunges) {
1801 +            free_local_slot(cache, &cache->slots[i]);
1802 +        }
1803 +    }
1804 +
1805 +    LOCK(cache->shmcache);
1806 +    for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
1807 +        lslot->original->num_hits += lslot->num_hits;
1808 +        lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
1809 +        apc_efree(lslot->value);
1810 +    }
1811 +    UNLOCK(cache->shmcache);
1812 +
1813 +    cache->dead_list = NULL;
1814 +}
1815 +/* }}} */
1816 +
1817 +/* {{{ apc_local_cache_destroy */
1818 +void apc_local_cache_destroy(apc_local_cache_t* cache)
1819 +{
1820 +    int i;
1821 +    for(i = 0; i < cache->num_slots; i++) {
1822 +        free_local_slot(cache, &cache->slots[i]);
1823 +    }
1824 +
1825 +    apc_local_cache_cleanup(cache);
1826 +
1827 +    LOCK(cache->shmcache);
1828 +    cache->shmcache->header->num_hits += cache->num_hits;
1829 +    UNLOCK(cache->shmcache);
1830 +
1831 +    apc_efree(cache->slots);
1832 +    apc_efree(cache);
1833 +}
1834 +/* }}} */
1835 +
1836 +/* {{{ apc_local_cache_find */
1837 +apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
1838 +{
1839 +    slot_t* slot;
1840 +    local_slot_t* lslot; 
1841 +
1842 +    if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
1843 +    else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1844 +
1845 +    slot = lslot->original;
1846 +
1847 +    if(slot && key.type == slot->key.type) {
1848 +        if(slot->access_time < (t - cache->ttl)) {
1849 +            goto not_found;
1850 +        }
1851 +        if(key.type == APC_CACHE_KEY_FILE && 
1852 +           key_equals(slot->key.data.file, key.data.file)) {
1853 +            if(slot->key.mtime != key.mtime) {
1854 +                free_local_slot(cache, lslot);
1855 +                goto not_found;
1856 +            }
1857 +            return lslot->value;
1858 +        } else if(key.type == APC_CACHE_KEY_FPFILE) {
1859 +            if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1860 +                return lslot->value;
1861 +            }
1862 +        }
1863 +    }
1864 +not_found:
1865 +    if(apc_cache_busy(cache->shmcache)) {
1866 +        return NULL;
1867 +    }
1868 +
1869 +    slot = apc_cache_find_slot(cache->shmcache, key, t);
1870 +
1871 +    if(!slot) return NULL;
1872 +   
1873 +    /* i.e maintain a sort of top list */
1874 +    if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits)  < slot->num_hits) {
1875 +        free_local_slot(cache, lslot);
1876 +        make_local_slot(cache, lslot, slot); 
1877 +        return lslot->value;
1878 +    }
1879 +    return slot->value;
1880 +}
1881 +/* }}} */
1882 +
1883 +/*
1884 + * Local variables:
1885 + * tab-width: 4
1886 + * c-basic-offset: 4
1887 + * End:
1888 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1889 + * vim<600: expandtab sw=4 ts=4 sts=4
1890 + */
1891 diff -ruN php-5.1.6.old/ext/apc/apc_cache.h php-5.1.6/ext/APC/apc_cache.h
1892 --- php-5.1.6.old/ext/apc/apc_cache.h   1969-12-31 18:00:00.000000000 -0600
1893 +++ php-5.1.6/ext/apc/apc_cache.h       2007-04-02 18:05:30.000000000 -0500
1894 @@ -0,0 +1,313 @@
1895 +/*
1896 +  +----------------------------------------------------------------------+
1897 +  | APC                                                                  |
1898 +  +----------------------------------------------------------------------+
1899 +  | Copyright (c) 2006 The PHP Group                                     |
1900 +  +----------------------------------------------------------------------+
1901 +  | This source file is subject to version 3.01 of the PHP license,      |
1902 +  | that is bundled with this package in the file LICENSE, and is        |
1903 +  | available through the world-wide-web at the following url:           |
1904 +  | http://www.php.net/license/3_01.txt.                                 |
1905 +  | If you did not receive a copy of the PHP license and are unable to   |
1906 +  | obtain it through the world-wide-web, please send a note to          |
1907 +  | license@php.net so we can mail you a copy immediately.               |
1908 +  +----------------------------------------------------------------------+
1909 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
1910 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
1911 +  +----------------------------------------------------------------------+
1912 +
1913 +   This software was contributed to PHP by Community Connect Inc. in 2002
1914 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1915 +   Future revisions and derivatives of this source code must acknowledge
1916 +   Community Connect Inc. as the original contributor of this module by
1917 +   leaving this note intact in the source code.
1918 +
1919 +   All other licensing and usage conditions are those of the PHP Group.
1920 +
1921 + */
1922 +
1923 +/* $Id: apc_cache.h,v 3.45 2007/03/22 16:03:59 gopalv Exp $ */
1924 +
1925 +#ifndef APC_CACHE_H
1926 +#define APC_CACHE_H
1927 +
1928 +/*
1929 + * This module defines the shared memory file cache. Basically all of the
1930 + * logic for storing and retrieving cache entries lives here.
1931 + */
1932 +
1933 +#include "apc.h"
1934 +#include "apc_compile.h"
1935 +
1936 +#define APC_CACHE_ENTRY_FILE   1
1937 +#define APC_CACHE_ENTRY_USER   2
1938 +
1939 +#define APC_CACHE_KEY_FILE     1
1940 +#define APC_CACHE_KEY_USER     2
1941 +#define APC_CACHE_KEY_FPFILE   3
1942 +
1943 +/* {{{ struct definition: apc_cache_key_t */
1944 +#define T apc_cache_t*
1945 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
1946 +
1947 +typedef union _apc_cache_key_data_t {
1948 +    struct {
1949 +        dev_t device;             /* the filesystem device */
1950 +        ino_t inode;              /* the filesystem inode */
1951 +    } file;
1952 +    struct {
1953 +        const char *identifier;
1954 +        int identifier_len;
1955 +    } user;
1956 +    struct {
1957 +        const char *fullpath;
1958 +        int fullpath_len;
1959 +    } fpfile;
1960 +} apc_cache_key_data_t;
1961 +
1962 +typedef struct apc_cache_key_t apc_cache_key_t;
1963 +struct apc_cache_key_t {
1964 +    apc_cache_key_data_t data;
1965 +    time_t mtime;                 /* the mtime of this cached entry */
1966 +    unsigned char type;
1967 +};
1968 +/* }}} */
1969 +
1970 +/* {{{ struct definition: apc_cache_entry_t */
1971 +typedef union _apc_cache_entry_value_t {
1972 +    struct {
1973 +        char *filename;             /* absolute path to source file */
1974 +        zend_op_array* op_array;    /* op_array allocated in shared memory */
1975 +        apc_function_t* functions;  /* array of apc_function_t's */
1976 +        apc_class_t* classes;       /* array of apc_class_t's */
1977 +    } file;
1978 +    struct {
1979 +        char *info; 
1980 +        int info_len; 
1981 +        zval *val;
1982 +        unsigned int ttl;
1983 +    } user;
1984 +} apc_cache_entry_value_t;
1985 +
1986 +typedef struct apc_cache_entry_t apc_cache_entry_t;
1987 +struct apc_cache_entry_t {
1988 +    apc_cache_entry_value_t data;
1989 +    unsigned char type;
1990 +    unsigned char autofiltered;
1991 +    unsigned char local;
1992 +    int ref_count;
1993 +    size_t mem_size;
1994 +};
1995 +/* }}} */
1996 +
1997 +/*
1998 + * apc_cache_create creates the shared memory compiler cache. This function
1999 + * should be called just once (ideally in the web server parent process, e.g.
2000 + * in apache), otherwise you will end up with multiple caches (which won't
2001 + * necessarily break anything). Returns a pointer to the cache object.
2002 + *
2003 + * size_hint is a "hint" at the total number of source files that will be
2004 + * cached. It determines the physical size of the hash table. Passing 0 for
2005 + * this argument will use a reasonable default value.
2006 + *
2007 + * gc_ttl is the maximum time a cache entry may speed on the garbage
2008 + * collection list. This is basically a work around for the inherent
2009 + * unreliability of our reference counting mechanism (see apc_cache_release).
2010 + *
2011 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
2012 + * is needed.  This helps in cleaning up the cache and ensuring that entries 
2013 + * hit frequently stay cached and ones not hit very often eventually disappear.
2014 + */
2015 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
2016 +
2017 +/*
2018 + * apc_cache_destroy releases any OS resources associated with a cache object.
2019 + * Under apache, this function can be safely called by the child processes
2020 + * when they exit.
2021 + */
2022 +extern void apc_cache_destroy(T cache);
2023 +
2024 +/*
2025 + * apc_cache_clear empties a cache. This can safely be called at any time,
2026 + * even while other server processes are executing cached source files.
2027 + */
2028 +extern void apc_cache_clear(T cache);
2029 +
2030 +/*
2031 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
2032 + * Internally, the filename is translated to a canonical representation, so
2033 + * that relative and absolute filenames will map to a single key. Returns
2034 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
2035 + * returned, the caller must free the cache entry by calling
2036 + * apc_cache_free_entry (see below).
2037 + *
2038 + * key is the value created by apc_cache_make_file_key for file keys.
2039 + *
2040 + * value is a cache entry returned by apc_cache_make_entry (see below).
2041 + */
2042 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
2043 +                            apc_cache_entry_t* value, time_t t);
2044 +
2045 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
2046 +                            apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
2047 +
2048 +/*
2049 + * apc_cache_find searches for a cache entry by filename, and returns a
2050 + * pointer to the entry if found, NULL otherwise.
2051 + *
2052 + * key is a value created by apc_cache_make_file_key for file keys.
2053 + */
2054 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
2055 +
2056 +/*
2057 + * apc_cache_user_find searches for a cache entry by its hashed identifier, 
2058 + * and returns a pointer to the entry if found, NULL otherwise.
2059 + *
2060 + */
2061 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
2062 +
2063 +/*
2064 + * apc_cache_user_delete finds an entry in the user cache and deletes it.
2065 + */
2066 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
2067 +
2068 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
2069 + * zval from it.
2070 + *
2071 + */
2072 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
2073 +
2074 +/*
2075 + * apc_cache_release decrements the reference count associated with a cache
2076 + * entry. Calling apc_cache_find automatically increments the reference count,
2077 + * and this function must be called post-execution to return the count to its
2078 + * original value. Failing to do so will prevent the entry from being
2079 + * garbage-collected.
2080 + *
2081 + * entry is the cache entry whose ref count you want to decrement.
2082 + */
2083 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
2084 +
2085 +/*
2086 + * apc_cache_make_file_key creates a key object given a relative or absolute
2087 + * filename and an optional list of auxillary paths to search. include_path is
2088 + * searched if the filename cannot be found relative to the current working
2089 + * directory.
2090 + *
2091 + * key points to caller-allocated storage (must not be null).
2092 + *
2093 + * filename is the path to the source file.
2094 + *
2095 + * include_path is a colon-separated list of directories to search.
2096 + *
2097 + * and finally we pass in the current request time so we can avoid
2098 + * caching files with a current mtime which tends to indicate that
2099 + * they are still being written to.
2100 + */
2101 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
2102 +                                   const char* filename,
2103 +                                   const char* include_path,
2104 +                                   time_t t
2105 +                                                              TSRMLS_DC);
2106 +
2107 +/*
2108 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
2109 + * and the compilation results returned by the PHP compiler.
2110 + */
2111 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2112 +                                                    zend_op_array* op_array,
2113 +                                                    apc_function_t* functions,
2114 +                                                    apc_class_t* classes);
2115 +/*
2116 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
2117 + * and the zval to be stored.
2118 + */
2119 +extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
2120 +
2121 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
2122 +
2123 +/*
2124 + * Frees all memory associated with an object returned by apc_cache_make_entry
2125 + * (see above).
2126 + */
2127 +extern void apc_cache_free_entry(apc_cache_entry_t* entry);
2128 +
2129 +/* {{{ struct definition: apc_cache_link_data_t */
2130 +typedef union _apc_cache_link_data_t {
2131 +    struct {
2132 +        char *filename;
2133 +        dev_t device;
2134 +        ino_t inode;
2135 +    } file;
2136 +    struct {
2137 +        char *info;
2138 +        unsigned int ttl;
2139 +    } user;
2140 +} apc_cache_link_data_t;
2141 +/* }}} */
2142 +
2143 +/* {{{ struct definition: apc_cache_link_t */
2144 +typedef struct apc_cache_link_t apc_cache_link_t;
2145 +struct apc_cache_link_t {
2146 +    apc_cache_link_data_t data;
2147 +    unsigned char type;
2148 +    int num_hits;
2149 +    time_t mtime;
2150 +    time_t creation_time;
2151 +    time_t deletion_time;
2152 +    time_t access_time;
2153 +    int ref_count;
2154 +    size_t mem_size;
2155 +    apc_cache_link_t* next;
2156 +};
2157 +/* }}} */
2158 +
2159 +/* {{{ struct definition: apc_cache_info_t */
2160 +typedef struct apc_cache_info_t apc_cache_info_t;
2161 +struct apc_cache_info_t {
2162 +    int num_slots;
2163 +    int num_hits;
2164 +    int num_misses;
2165 +    int ttl;
2166 +    apc_cache_link_t* list;
2167 +    apc_cache_link_t* deleted_list;
2168 +    time_t start_time;
2169 +    int expunges;
2170 +    int num_entries;
2171 +    int num_inserts;
2172 +    size_t mem_size;
2173 +};
2174 +/* }}} */
2175 +
2176 +extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
2177 +extern void apc_cache_free_info(apc_cache_info_t* info);
2178 +extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
2179 +extern void apc_cache_unlock(apc_cache_t* cache);
2180 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
2181 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
2182 +extern void apc_cache_write_unlock(apc_cache_t* cache);
2183 +
2184 +/* 
2185 + * Process local cache, which keeps a refcount hungry version of the slots
2186 + * for quick access without a lock - as long as the entry exists in local
2187 + * cache, the refcount of the shm version will be +1 more than required.
2188 + * It holds no data, only a shallow copy of apc_cache_entry.
2189 + */
2190 +typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */ 
2191 +
2192 +extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
2193 +extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
2194 +extern void apc_local_cache_destroy(apc_local_cache_t* cache);
2195 +extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
2196 +
2197 +#undef T
2198 +#endif
2199 +
2200 +/*
2201 + * Local variables:
2202 + * tab-width: 4
2203 + * c-basic-offset: 4
2204 + * End:
2205 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
2206 + * vim<600: expandtab sw=4 ts=4 sts=4
2207 + */
2208 diff -ruN php-5.1.6.old/ext/apc/apc_compile.c php-5.1.6/ext/APC/apc_compile.c
2209 --- php-5.1.6.old/ext/apc/apc_compile.c 1969-12-31 18:00:00.000000000 -0600
2210 +++ php-5.1.6/ext/apc/apc_compile.c     2007-04-02 18:05:30.000000000 -0500
2211 @@ -0,0 +1,2530 @@
2212 +/*
2213 +  +----------------------------------------------------------------------+
2214 +  | APC                                                                  |
2215 +  +----------------------------------------------------------------------+
2216 +  | Copyright (c) 2006 The PHP Group                                     |
2217 +  +----------------------------------------------------------------------+
2218 +  | This source file is subject to version 3.01 of the PHP license,      |
2219 +  | that is bundled with this package in the file LICENSE, and is        |
2220 +  | available through the world-wide-web at the following url:           |
2221 +  | http://www.php.net/license/3_01.txt.                                 |
2222 +  | If you did not receive a copy of the PHP license and are unable to   |
2223 +  | obtain it through the world-wide-web, please send a note to          |
2224 +  | license@php.net so we can mail you a copy immediately.               |
2225 +  +----------------------------------------------------------------------+
2226 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
2227 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
2228 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
2229 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
2230 +  +----------------------------------------------------------------------+
2231 +
2232 +   This software was contributed to PHP by Community Connect Inc. in 2002
2233 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
2234 +   Future revisions and derivatives of this source code must acknowledge
2235 +   Community Connect Inc. as the original contributor of this module by
2236 +   leaving this note intact in the source code.
2237 +
2238 +   All other licensing and usage conditions are those of the PHP Group.
2239 +
2240 + */
2241 +
2242 +/* $Id: apc_compile.c,v 3.85 2007/03/28 07:35:55 gopalv Exp $ */
2243 +
2244 +#include "apc_compile.h"
2245 +#include "apc_globals.h"
2246 +#include "apc_zend.h"
2247 +
2248 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
2249 +typedef void  (*ht_free_fun_t)(void*, apc_free_t);
2250 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
2251 +
2252 +#ifdef ZEND_ENGINE_2
2253 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
2254 +#endif
2255 +
2256 +#define CHECK(p) { if ((p) == NULL) return NULL; }
2257 +
2258 +/* {{{ internal function declarations */
2259 +
2260 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
2261 +
2262 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
2263 +
2264 +/*
2265 + * The "copy" functions perform deep-copies on a particular data structure
2266 + * (passed as the second argument). They also optionally allocate space for
2267 + * the destination data structure if the first argument is null.
2268 + */
2269 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
2270 +static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
2271 +static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
2272 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
2273 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
2274 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
2275 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
2276 +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, ...);
2277 +#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
2278 +    my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
2279 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
2280 +#ifdef ZEND_ENGINE_2
2281 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
2282 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
2283 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
2284 +#endif
2285 +/*
2286 + * The "destroy" functions free the memory associated with a particular data
2287 + * structure but do not free the pointer to the data structure.
2288 + *
2289 + * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
2290 + * the zval* has other references elsewhere 
2291 + */
2292 +static int  my_destroy_zval(zval*, apc_free_t); 
2293 +static void my_destroy_zval_ptr(zval**, apc_free_t);
2294 +static void my_destroy_zend_op(zend_op*, apc_free_t);
2295 +static void my_destroy_znode(znode*, apc_free_t);
2296 +static void my_destroy_function(zend_function*, apc_free_t);
2297 +static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
2298 +static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
2299 +static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2300 +static void my_destroy_op_array(zend_op_array*, apc_free_t);
2301 +#ifdef ZEND_ENGINE_2
2302 +static void my_destroy_property_info(zend_property_info*, apc_free_t);
2303 +static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
2304 +static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
2305 +#endif
2306 +
2307 +/*
2308 + * The "free" functions work exactly like their "destroy" counterparts (see
2309 + * above) but also free the pointer to the data structure.
2310 + */
2311 +static void my_free_zval_ptr(zval**, apc_free_t);
2312 +static void my_free_function(zend_function*, apc_free_t);
2313 +static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2314 +#ifdef ZEND_ENGINE_2
2315 +static void my_free_property_info(zend_property_info* src, apc_free_t);
2316 +static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
2317 +static void my_free_arg_info(zend_arg_info*, apc_free_t);
2318 +#endif
2319 +
2320 +/*
2321 + * The "fixup" functions need for ZEND_ENGINE_2
2322 + */
2323 +#ifdef ZEND_ENGINE_2
2324 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2325 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
2326 +/* my_fixup_function_for_execution is the same as my_fixup_function
2327 + * but named differently for clarity
2328 + */
2329 +#define my_fixup_function_for_execution my_fixup_function
2330 +
2331 +#ifdef ZEND_ENGINE_2_2
2332 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2333 +#define my_fixup_property_info_for_execution my_fixup_property_info
2334 +#endif
2335 +
2336 +#endif
2337 +
2338 +/*
2339 + * These functions return "1" if the member/function is
2340 + * defined/overridden in the 'current' class and not inherited.
2341 + */
2342 +static int my_check_copy_function(Bucket* src, va_list args);
2343 +static int my_check_copy_default_property(Bucket* p, va_list args);
2344 +#ifdef ZEND_ENGINE_2
2345 +static int my_check_copy_property_info(Bucket* src, va_list args);
2346 +static int my_check_copy_static_member(Bucket* src, va_list args);
2347 +#endif
2348 +
2349 +/* }}} */
2350 +
2351 +/* {{{ check_op_array_integrity */
2352 +#if 0
2353 +static void check_op_array_integrity(zend_op_array* src)
2354 +{
2355 +    int i, j;
2356 +
2357 +    /* These sorts of checks really aren't particularly effective, but they
2358 +     * can provide a welcome sanity check when debugging. Just don't enable
2359 +     * for production use!  */
2360 +
2361 +    assert(src->refcount != NULL);
2362 +    assert(src->opcodes != NULL);
2363 +    assert(src->last > 0);
2364 +
2365 +    for (i = 0; i < src->last; i++) {
2366 +        zend_op* op = &src->opcodes[i];
2367 +        znode* nodes[] = { &op->result, &op->op1, &op->op2 };
2368 +        for (j = 0; j < 3; j++) {
2369 +            assert(nodes[j]->op_type == IS_CONST ||
2370 +                   nodes[j]->op_type == IS_VAR ||
2371 +                   nodes[j]->op_type == IS_TMP_VAR ||
2372 +                   nodes[j]->op_type == IS_UNUSED);
2373 +
2374 +            if (nodes[j]->op_type == IS_CONST) {
2375 +                int type = nodes[j]->u.constant.type;
2376 +                assert(type == IS_RESOURCE ||
2377 +                       type == IS_BOOL ||
2378 +                       type == IS_LONG ||
2379 +                       type == IS_DOUBLE ||
2380 +                       type == IS_NULL ||
2381 +                       type == IS_CONSTANT ||
2382 +                       type == IS_STRING ||
2383 +                       type == FLAG_IS_BC ||
2384 +                       type == IS_ARRAY ||
2385 +                       type == IS_CONSTANT_ARRAY ||
2386 +                       type == IS_OBJECT);
2387 +            }
2388 +        }
2389 +    }
2390 +}
2391 +#endif
2392 +/* }}} */
2393 +
2394 +/* {{{ is_derived_class */
2395 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
2396 +{
2397 +    int i;
2398 +
2399 +    /*
2400 +     * Scan the op_array for execution-time class declarations of derived
2401 +     * classes. If we find one whose key matches our current class key, we
2402 +     * know the current class is a derived class.
2403 +     *
2404 +     * This check is exceedingly inefficient (fortunately it only has to occur
2405 +     * once, when the source file is first compiled and cached), but the
2406 +     * compiler should save this information for us -- definitely a candidate
2407 +     * for a Zend Engine patch.
2408 +     *
2409 +     * XXX checking for derived classes provides a minimal (albeit measurable)
2410 +     * speed up. It may not be worth the added complexity -- considere
2411 +     * removing this optimization.
2412 +     */
2413 +
2414 +    for (i = 0; i < op_array->last; i++) {
2415 +        zend_op* op = &op_array->opcodes[i];
2416 +
2417 +#ifdef ZEND_ENGINE_2        
2418 +        if (op->opcode == ZEND_DECLARE_CLASS &&
2419 +            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2420 +#else            
2421 +        if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
2422 +            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2423 +#endif            
2424 +        {
2425 +            if (op->op1.u.constant.value.str.len == key_size &&
2426 +                !memcmp(op->op1.u.constant.value.str.val, key, key_size))
2427 +            {
2428 +                return 1;
2429 +            }
2430 +        }
2431 +    }
2432 +
2433 +    return 0;
2434 +}
2435 +/* }}} */
2436 +
2437 +/* {{{ my_bitwise_copy_function */
2438 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
2439 +{
2440 +    assert(src != NULL);
2441 +
2442 +    if (!dst) {
2443 +        CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
2444 +    }
2445 +
2446 +    /* We only need to do a bitwise copy */
2447 +    memcpy(dst, src, sizeof(src[0]));
2448 +
2449 +    return dst;
2450 +}
2451 +/* }}} */
2452 +
2453 +/* {{{ my_copy_zval_ptr */
2454 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
2455 +{
2456 +    int local_dst_alloc = 0;
2457 +    zval* dst_new;
2458 +    
2459 +    assert(src != NULL);
2460 +
2461 +    if (!dst) {
2462 +        CHECK(dst = (zval**) allocate(sizeof(zval*)));
2463 +        local_dst_alloc = 1;
2464 +    }
2465 +
2466 +    if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
2467 +        if(local_dst_alloc) deallocate(dst);
2468 +        return NULL;
2469 +    }
2470 +    dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
2471 +    if(dst_new != *dst) {
2472 +        deallocate(*dst);
2473 +        *dst = dst_new;
2474 +    }
2475 +
2476 +    (*dst)->refcount = (*src)->refcount;
2477 +    (*dst)->is_ref = (*src)->is_ref;
2478 +    
2479 +    return dst;
2480 +}
2481 +/* }}} */
2482 +
2483 +/* {{{ my_copy_zval */
2484 +static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
2485 +{
2486 +    zval **tmp;
2487 +    TSRMLS_FETCH();
2488 +    
2489 +    assert(dst != NULL);
2490 +    assert(src != NULL);
2491 +
2492 +    memcpy(dst, src, sizeof(src[0]));
2493 +
2494 +    switch (src->type & ~IS_CONSTANT_INDEX) {
2495 +    case IS_RESOURCE:
2496 +    case IS_BOOL:
2497 +    case IS_LONG:
2498 +    case IS_DOUBLE:
2499 +    case IS_NULL:
2500 +        break;
2501 +
2502 +    case IS_CONSTANT:
2503 +    case IS_STRING:
2504 +#ifndef ZEND_ENGINE_2        
2505 +    case FLAG_IS_BC:
2506 +#endif        
2507 +        if (src->value.str.val) {
2508 +            CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
2509 +                                                   src->value.str.len+1,
2510 +                                                   allocate));
2511 +        }
2512 +        break;
2513 +    
2514 +    case IS_ARRAY:
2515 +
2516 +        if(APCG(copied_zvals)) {
2517 +            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
2518 +                (*tmp)->refcount++;
2519 +                return *tmp;
2520 +            }
2521 +        
2522 +            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
2523 +        }
2524 +        /* fall through */
2525
2526 +    case IS_CONSTANT_ARRAY:
2527 +
2528 +        CHECK(dst->value.ht =
2529 +            my_copy_hashtable(NULL,
2530 +                              src->value.ht,
2531 +                              (ht_copy_fun_t) my_copy_zval_ptr,
2532 +                              (ht_free_fun_t) my_free_zval_ptr,
2533 +                              1,
2534 +                              allocate, deallocate));
2535 +        break;
2536 +
2537 +    case IS_OBJECT:
2538 +#ifndef ZEND_ENGINE_2        
2539 +        CHECK(dst->value.obj.ce =
2540 +            my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
2541 +
2542 +        if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
2543 +                              src->value.obj.properties,
2544 +                              (ht_copy_fun_t) my_copy_zval_ptr,
2545 +                              (ht_free_fun_t) my_free_zval_ptr,
2546 +                              1,
2547 +                              allocate, deallocate))) {
2548 +            my_destroy_class_entry(dst->value.obj.ce, deallocate);
2549 +            return NULL;
2550 +        }
2551 +        break;
2552 +#else
2553 +       dst->type = IS_NULL;
2554 +#endif        
2555 +        break;
2556 +
2557 +    default:
2558 +        assert(0);
2559 +    }
2560 +
2561 +    return dst;
2562 +}
2563 +/* }}} */
2564 +
2565 +/* {{{ my_copy_znode */
2566 +static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
2567 +{
2568 +    assert(dst != NULL);
2569 +    assert(src != NULL);
2570 +
2571 +    memcpy(dst, src, sizeof(src[0]));
2572 +
2573 +#ifdef IS_CV
2574 +    assert(dst ->op_type == IS_CONST ||
2575 +           dst ->op_type == IS_VAR ||
2576 +           dst ->op_type == IS_CV ||
2577 +           dst ->op_type == IS_TMP_VAR ||
2578 +           dst ->op_type == IS_UNUSED);
2579 +#else
2580 +    assert(dst ->op_type == IS_CONST ||
2581 +           dst ->op_type == IS_VAR ||
2582 +           dst ->op_type == IS_TMP_VAR ||
2583 +           dst ->op_type == IS_UNUSED);
2584 +#endif
2585 +
2586 +    if (src->op_type == IS_CONST) {
2587 +        if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
2588 +            return NULL;
2589 +        }
2590 +    }
2591 +
2592 +    return dst;
2593 +}
2594 +/* }}} */
2595 +
2596 +/* {{{ my_copy_zend_op */
2597 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
2598 +{
2599 +    assert(dst != NULL);
2600 +    assert(src != NULL);
2601 +
2602 +    memcpy(dst, src, sizeof(src[0]));
2603 +
2604 +    if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL 
2605 +            || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
2606 +            || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
2607 +    {
2608 +        return NULL;
2609 +    }
2610 +
2611 +    return dst;
2612 +}
2613 +/* }}} */
2614 +
2615 +/* {{{ my_copy_function */
2616 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
2617 +{
2618 +    int local_dst_alloc = 0;
2619 +       TSRMLS_FETCH();
2620 +
2621 +    assert(src != NULL);
2622 +
2623 +    if(!dst) local_dst_alloc = 1;
2624 +    CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
2625 +
2626 +    switch (src->type) {
2627 +    case ZEND_INTERNAL_FUNCTION:
2628 +    case ZEND_OVERLOADED_FUNCTION:
2629 +        /* shallow copy because op_array is internal */
2630 +        dst->op_array = src->op_array;
2631 +        break;
2632 +        
2633 +    case ZEND_USER_FUNCTION:
2634 +    case ZEND_EVAL_CODE:
2635 +        if(!apc_copy_op_array(&dst->op_array,
2636 +                                &src->op_array,
2637 +                                allocate, deallocate TSRMLS_CC)) {
2638 +            if(local_dst_alloc) deallocate(dst);
2639 +            return NULL;
2640 +        }
2641 +        break;
2642 +
2643 +    default:
2644 +        assert(0);
2645 +    }
2646 +#ifdef ZEND_ENGINE_2
2647 +    /* 
2648 +     * op_array bitwise copying overwrites what ever you modified
2649 +     * before apc_copy_op_array - which is why this code is outside 
2650 +     * my_bitwise_copy_function. 
2651 +     */
2652 +
2653 +    /* zend_do_inheritance will re-look this up, because the pointers
2654 +     * in prototype are from a function table of another class. It just
2655 +     * helps if that one is from EG(class_table).
2656 +     */
2657 +    dst->common.prototype = NULL; 
2658 +
2659 +    /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
2660 +     * have to carry around a prototype. Thankfully zend_do_inheritance
2661 +     * sets this properly as well
2662 +     */
2663 +    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
2664 +#endif
2665 +
2666 +
2667 +    return dst;
2668 +}
2669 +/* }}} */
2670 +
2671 +/* {{{ my_copy_function_entry */
2672 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2673 +{
2674 +    int local_dst_alloc = 0;
2675 +    assert(src != NULL);
2676 +
2677 +    if (!dst) {
2678 +        CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
2679 +        local_dst_alloc = 1;
2680 +    }
2681 +
2682 +    /* Start with a bitwise copy */
2683 +    memcpy(dst, src, sizeof(src[0]));
2684 +
2685 +    dst->fname = NULL;
2686 +#ifdef ZEND_ENGINE_2
2687 +    dst->arg_info = NULL;
2688 +#else
2689 +    dst->func_arg_types = NULL;
2690 +#endif
2691 +
2692 +    if (src->fname) {
2693 +        if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
2694 +            goto cleanup;
2695 +        }
2696 +    }
2697 +
2698 +#ifdef ZEND_ENGINE_2    
2699 +    if (src->arg_info) {
2700 +        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
2701 +                                                src->arg_info,
2702 +                                                src->num_args,
2703 +                                                allocate,
2704 +                                                deallocate))) {
2705 +            goto cleanup;
2706 +        }
2707 +    }
2708 +#else    
2709 +    if (src->func_arg_types) {
2710 +        if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
2711 +                                                src->func_arg_types[0]+1,
2712 +                                                allocate))) {
2713 +            goto cleanup;
2714 +        }
2715 +    }
2716 +#endif
2717 +
2718 +    return dst;
2719 +
2720 +cleanup:
2721 +    if(dst->fname) deallocate(dst->fname);
2722 +    if(local_dst_alloc) deallocate(dst);
2723 +    return NULL;
2724 +}
2725 +/* }}} */
2726 +
2727 +#ifdef ZEND_ENGINE_2
2728 +/* {{{ my_copy_property_info */
2729 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2730 +{
2731 +    int local_dst_alloc = 0;
2732 +    
2733 +    assert(src != NULL);
2734 +
2735 +    if (!dst) {
2736 +        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2737 +        local_dst_alloc = 1;
2738 +    }
2739 +
2740 +    /* Start with a bitwise copy */
2741 +    memcpy(dst, src, sizeof(*src));
2742 +
2743 +    dst->name = NULL;
2744 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2745 +    dst->doc_comment = NULL;
2746 +#endif
2747 +
2748 +    if (src->name) {
2749 +        /* private members are stored inside property_info as a mangled
2750 +         * string of the form:
2751 +         *      \0<classname>\0<membername>\0
2752 +         */
2753 +        if(!(dst->name = 
2754 +                    apc_xmemcpy(src->name, src->name_length+1, allocate))) {
2755 +            goto cleanup;
2756 +        }
2757 +    }
2758 +
2759 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2760 +    if (src->doc_comment) {
2761 +        if( !(dst->doc_comment =
2762 +                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
2763 +            goto cleanup;
2764 +        }
2765 +    }
2766 +#endif
2767 +
2768 +    return dst;
2769 +
2770 +cleanup:
2771 +    if(dst->name) deallocate(dst->name);
2772 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2773 +    if(dst->doc_comment) deallocate(dst->doc_comment);
2774 +#endif
2775 +    if(local_dst_alloc) deallocate(dst);
2776 +    return NULL;
2777 +}
2778 +/* }}} */
2779 +
2780 +/* {{{ my_copy_property_info_for_execution */
2781 +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)
2782 +{
2783 +    int local_dst_alloc = 0;
2784 +    
2785 +    assert(src != NULL);
2786 +
2787 +    if (!dst) {
2788 +        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2789 +        local_dst_alloc = 1;
2790 +    }
2791 +
2792 +    /* We need only a shallow copy */
2793 +    memcpy(dst, src, sizeof(*src));
2794 +
2795 +    return dst;
2796 +}
2797 +/* }}} */
2798 +
2799 +/* {{{ my_copy_arg_info_array */
2800 +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)
2801 +{
2802 +    int local_dst_alloc = 0;
2803 +    int i = 0;
2804 +
2805 +    
2806 +    if (!dst) {
2807 +        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
2808 +        local_dst_alloc = 1;
2809 +    }
2810 +
2811 +    /* Start with a bitwise copy */
2812 +    memcpy(dst, src, sizeof(*src)*num_args);
2813 +
2814 +    for(i=0; i < num_args; i++) {
2815 +        if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {            
2816 +            if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
2817 +            if(local_dst_alloc) deallocate(dst);
2818 +            return NULL;
2819 +        }
2820 +    }
2821 +
2822 +    return dst;    
2823 +}
2824 +/* }}} */
2825 +
2826 +/* {{{ my_copy_arg_info */
2827 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2828 +{
2829 +    int local_dst_alloc = 0;
2830 +    
2831 +    assert(src != NULL);
2832 +
2833 +    if (!dst) {
2834 +        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
2835 +        local_dst_alloc = 1;
2836 +    }
2837 +
2838 +    /* Start with a bitwise copy */
2839 +    memcpy(dst, src, sizeof(*src));
2840 +
2841 +    dst->name = NULL;
2842 +    dst->class_name = NULL;
2843 +
2844 +    if (src->name) {
2845 +        if(!(dst->name = 
2846 +                    apc_xmemcpy(src->name, src->name_len+1, allocate))) {
2847 +            goto cleanup;
2848 +        }
2849 +    }
2850 +
2851 +    if (src->class_name) {
2852 +        if(!(dst->class_name = 
2853 +                    apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
2854 +            goto cleanup;
2855 +        }
2856 +    }
2857 +
2858 +    return dst;
2859 +
2860 +cleanup:
2861 +    if(dst->name) deallocate(dst->name);
2862 +    if(dst->class_name) deallocate(dst->name);
2863 +    if(local_dst_alloc) deallocate(dst);
2864 +    return NULL;
2865 +}
2866 +/* }}} */
2867 +#endif
2868 +
2869 +/* {{{ my_copy_class_entry */
2870 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2871 +{
2872 +    int local_dst_alloc = 0;
2873 +    int i = 0;
2874 +
2875 +    assert(src != NULL);
2876 +
2877 +    if (!dst) {
2878 +        CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
2879 +        local_dst_alloc = 1;
2880 +    }
2881 +
2882 +    /* Start with a bitwise copy */
2883 +    memcpy(dst, src, sizeof(*src));
2884 +
2885 +    dst->name = NULL;
2886 +    dst->builtin_functions = NULL;
2887 +    memset(&dst->function_table, 0, sizeof(dst->function_table));
2888 +    memset(&dst->default_properties, 0, sizeof(dst->default_properties));
2889 +#ifndef ZEND_ENGINE_2
2890 +    dst->refcount = NULL;
2891 +#else
2892 +    dst->static_members = NULL;
2893 +    dst->doc_comment = NULL;
2894 +    dst->filename = NULL;
2895 +    memset(&dst->properties_info, 0, sizeof(dst->properties_info));
2896 +    memset(&dst->constants_table, 0, sizeof(dst->constants_table));
2897 +    memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
2898 +#endif
2899 +
2900 +    if (src->name) {
2901 +        if(!(dst->name = apc_xstrdup(src->name, allocate))) {
2902 +            goto cleanup;
2903 +        }
2904 +    }
2905 +
2906 +#ifndef ZEND_ENGINE_2    
2907 +    if(!(dst->refcount = apc_xmemcpy(src->refcount,
2908 +                                      sizeof(src->refcount[0]),
2909 +                                      allocate))) {
2910 +        goto cleanup;
2911 +    }
2912 +#endif        
2913 +
2914 +    if(!(my_copy_hashtable_ex(&dst->function_table,
2915 +                            &src->function_table,
2916 +                            (ht_copy_fun_t) my_copy_function,
2917 +                            (ht_free_fun_t) my_free_function,
2918 +                            0,
2919 +                            allocate, deallocate,
2920 +                            (ht_check_copy_fun_t) my_check_copy_function,
2921 +                            src))) {
2922 +        goto cleanup;
2923 +    }
2924 +
2925 +#ifdef ZEND_ENGINE_2
2926 +
2927 +    /* the interfaces are populated at runtime using ADD_INTERFACE */
2928 +    dst->interfaces = NULL; 
2929 +
2930 +    /* the current count includes inherited interfaces as well,
2931 +       the real dynamic ones are the first <n> which are zero'd
2932 +       out in zend_do_end_class_declaration */
2933 +    for(i = 0 ; i < src->num_interfaces ; i++) {
2934 +        if(src->interfaces[i])
2935 +        {
2936 +            dst->num_interfaces = i;
2937 +            break;
2938 +        }
2939 +    }
2940 +
2941 +    /* these will either be set inside my_fixup_hashtable or 
2942 +     * they will be copied out from parent inside zend_do_inheritance 
2943 +     */
2944 +    dst->constructor =  NULL;
2945 +    dst->destructor = NULL;
2946 +    dst->clone = NULL;
2947 +    dst->__get = NULL;
2948 +    dst->__set = NULL;
2949 +    dst->__unset = NULL;
2950 +    dst->__isset = NULL;
2951 +    dst->__call = NULL;
2952 +#ifdef ZEND_ENGINE_2_2
2953 +    dst->__tostring = NULL;
2954 +#endif
2955 +
2956 +    /* unset function proxies */
2957 +    dst->serialize_func = NULL;
2958 +    dst->unserialize_func = NULL;
2959 +    
2960 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
2961 +#endif
2962 +
2963 +    if(!(my_copy_hashtable_ex(&dst->default_properties,
2964 +                            &src->default_properties,
2965 +                            (ht_copy_fun_t) my_copy_zval_ptr,
2966 +                            (ht_free_fun_t) my_free_zval_ptr,
2967 +                            1,
2968 +                            allocate,deallocate,
2969 +                            (ht_check_copy_fun_t) my_check_copy_default_property,
2970 +                            src))) {
2971 +        goto cleanup;
2972 +    }
2973 +
2974 +#ifdef ZEND_ENGINE_2
2975 +    
2976 +    if(!(my_copy_hashtable_ex(&dst->properties_info,
2977 +                            &src->properties_info,
2978 +                            (ht_copy_fun_t) my_copy_property_info,
2979 +                            (ht_free_fun_t) my_free_property_info,
2980 +                            0,
2981 +                            allocate, deallocate,
2982 +                            (ht_check_copy_fun_t) my_check_copy_property_info,
2983 +                            src))) {
2984 +        goto cleanup;
2985 +    }
2986 +
2987 +#ifdef ZEND_ENGINE_2_2
2988 +    /* php5.2 introduced a scope attribute for property info */
2989 +    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
2990 +#endif
2991 +    
2992 +    if(!my_copy_hashtable_ex(&dst->default_static_members,
2993 +                            &src->default_static_members,
2994 +                            (ht_copy_fun_t) my_copy_zval_ptr,
2995 +                            (ht_free_fun_t) my_free_zval_ptr,
2996 +                            1,
2997 +                            allocate, deallocate,
2998 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
2999 +                            src,
3000 +                            &src->default_static_members)) {
3001 +        goto cleanup;
3002 +    }
3003 +    if(src->static_members != &src->default_static_members)
3004 +    {
3005 +        if(!(dst->static_members = my_copy_hashtable_ex(NULL,
3006 +                            src->static_members,
3007 +                            (ht_copy_fun_t) my_copy_zval_ptr,
3008 +                            (ht_free_fun_t) my_free_zval_ptr,
3009 +                            1,
3010 +                            allocate, deallocate,
3011 +                            (ht_check_copy_fun_t) my_check_copy_static_member,
3012 +                            src,
3013 +                            src->static_members))) {
3014 +            goto cleanup;
3015 +        }
3016 +    }
3017 +    else
3018 +    {
3019 +        dst->static_members = &dst->default_static_members;
3020 +    }
3021 +
3022 +    if(!(my_copy_hashtable(&dst->constants_table,
3023 +                            &src->constants_table,
3024 +                            (ht_copy_fun_t) my_copy_zval_ptr,
3025 +                            (ht_free_fun_t) my_free_zval_ptr,
3026 +                            1,
3027 +                            allocate, deallocate))) {
3028 +        goto cleanup;
3029 +    }
3030 +
3031 +    if (src->doc_comment) {
3032 +        if(!(dst->doc_comment =
3033 +                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3034 +            goto cleanup;
3035 +        }
3036 +    }
3037 +#endif
3038 +    
3039 +    if (src->builtin_functions) {
3040 +        int i, n;
3041 +
3042 +        for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
3043 +
3044 +        if(!(dst->builtin_functions =
3045 +            (zend_function_entry*)
3046 +                allocate((n + 1) * sizeof(zend_function_entry)))) {
3047 +            goto cleanup;
3048 +        }
3049 +
3050 +
3051 +        for (i = 0; i < n; i++) {
3052 +            if(!my_copy_function_entry(&dst->builtin_functions[i],
3053 +                                   &src->builtin_functions[i],
3054 +                                   allocate, deallocate)) {
3055 +                int ii;
3056 +
3057 +                for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
3058 +                goto cleanup;
3059 +            }
3060 +        }
3061 +        dst->builtin_functions[n].fname = NULL;
3062 +    }
3063 +
3064 +#ifdef ZEND_ENGINE_2
3065 +    if (src->filename) {
3066 +        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3067 +            goto cleanup;
3068 +        }
3069 +    }
3070 +#endif
3071 +   
3072 +    return dst;
3073 +
3074 +
3075 +cleanup:
3076 +    if(dst->name) deallocate(dst->name);
3077 +#ifdef ZEND_ENGINE_2
3078 +    if(dst->doc_comment) deallocate(dst->doc_comment);
3079 +    if(dst->filename) deallocate(dst->filename);
3080 +#else
3081 +    if(dst->refcount) deallocate(dst->refcount);
3082 +#endif
3083 +    
3084 +    if(dst->builtin_functions) deallocate(dst->builtin_functions);
3085 +    if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
3086 +    if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3087 +
3088 +#ifdef ZEND_ENGINE_2
3089 +    if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
3090 +    if(dst->default_static_members.arBuckets)
3091 +    {
3092 +        my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3093 +    }
3094 +    if(dst->static_members && dst->static_members != &(dst->default_static_members))
3095 +    {
3096 +        my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3097 +        deallocate(dst->static_members);
3098 +    }
3099 +    if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3100 +#endif
3101 +    if(local_dst_alloc) deallocate(dst);
3102 +
3103 +    return NULL;
3104 +}
3105 +/* }}} */
3106 +
3107 +/* {{{ my_copy_hashtable */
3108 +static HashTable* my_copy_hashtable_ex(HashTable* dst,
3109 +                                    HashTable* src,
3110 +                                    ht_copy_fun_t copy_fn,
3111 +                                    ht_free_fun_t free_fn,
3112 +                                    int holds_ptrs,
3113 +                                    apc_malloc_t allocate, 
3114 +                                    apc_free_t deallocate,
3115 +                                    ht_check_copy_fun_t check_fn,
3116 +                                    ...)
3117 +{
3118 +    Bucket* curr = NULL;
3119 +    Bucket* prev = NULL;
3120 +    Bucket* newp = NULL;
3121 +    int first = 1;
3122 +    int local_dst_alloc = 0;
3123 +    int index = 0;
3124 +
3125 +    assert(src != NULL);
3126 +
3127 +    if (!dst) {
3128 +        CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
3129 +        local_dst_alloc = 1;
3130 +    }
3131 +
3132 +    memcpy(dst, src, sizeof(src[0]));
3133 +
3134 +    /* allocate buckets for the new hashtable */
3135 +    if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
3136 +        if(local_dst_alloc) deallocate(dst);
3137 +        return NULL;
3138 +    }
3139 +
3140 +    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
3141 +    dst->pInternalPointer = NULL;
3142 +    dst->pListHead = NULL;
3143 +    
3144 +    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
3145 +        int n = curr->h % dst->nTableSize;
3146 +
3147 +        if(check_fn) {
3148 +            va_list args;
3149 +            va_start(args, check_fn);
3150 +
3151 +            /* Call the check_fn to see if the current bucket 
3152 +             * needs to be copied out
3153 +             */
3154 +            if(!check_fn(curr, args)) {
3155 +                dst->nNumOfElements--;
3156 +                continue;
3157 +            }
3158 +
3159 +            va_end(args);
3160 +        }
3161 +
3162 +        /* create a copy of the bucket 'curr' */
3163 +        if(!(newp =
3164 +            (Bucket*) apc_xmemcpy(curr,
3165 +                                  sizeof(Bucket) + curr->nKeyLength - 1,
3166 +                                  allocate))) {
3167 +            goto cleanup;
3168 +        }
3169 +
3170 +        /* insert 'newp' into the linked list at its hashed index */
3171 +        if (dst->arBuckets[n]) {
3172 +            newp->pNext = dst->arBuckets[n];
3173 +            newp->pLast = NULL;
3174 +            newp->pNext->pLast = newp;
3175 +        }
3176 +        else {
3177 +            newp->pNext = newp->pLast = NULL;
3178 +        }
3179 +
3180 +        dst->arBuckets[n] = newp;
3181 +
3182 +        /* copy the bucket data using our 'copy_fn' callback function */
3183 +        if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
3184 +            goto cleanup;
3185 +        }
3186 +
3187 +        if (holds_ptrs) {
3188 +            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
3189 +        }
3190 +        else {
3191 +            newp->pDataPtr = NULL;
3192 +        }
3193 +
3194 +        /* insert 'newp' into the table-thread linked list */
3195 +        newp->pListLast = prev;
3196 +        newp->pListNext = NULL;
3197 +
3198 +        if (prev) {
3199 +            prev->pListNext = newp;
3200 +        }
3201 +
3202 +        if (first) {
3203 +            dst->pListHead = newp;
3204 +            first = 0;
3205 +        }
3206 +
3207 +        prev = newp;
3208 +    }
3209 +
3210 +    dst->pListTail = newp;
3211 +
3212 +    return dst;
3213 +    
3214 +    cleanup:
3215 +    for(index = 0; index < dst->nTableSize; index++)
3216 +    {
3217 +        curr = dst->arBuckets[index];
3218 +        while(curr != NULL)
3219 +        {
3220 +            Bucket * tmp = curr;
3221 +            if(curr->pData && free_fn)
3222 +            {
3223 +                free_fn(curr->pData, deallocate);
3224 +            }
3225 +            curr = curr->pNext;
3226 +            deallocate(tmp);
3227 +        }
3228 +    }   
3229 +    deallocate(dst->arBuckets);
3230 +    if(local_dst_alloc) deallocate(dst);
3231 +    else dst->arBuckets = NULL;
3232 +
3233 +    return NULL;
3234 +}
3235 +/* }}} */
3236 +
3237 +/* {{{ my_copy_static_variables */
3238 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
3239 +{ 
3240 +    if (src->static_variables == NULL) {
3241 +        return NULL;
3242 +    }
3243 +
3244 +    return my_copy_hashtable(NULL,
3245 +                             src->static_variables,
3246 +                             (ht_copy_fun_t) my_copy_zval_ptr,
3247 +                             (ht_free_fun_t) my_free_zval_ptr,
3248 +                             1,
3249 +                             allocate, deallocate);
3250 +}
3251 +/* }}} */
3252 +
3253 +/* {{{ apc_copy_zval */
3254 +zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
3255 +{
3256 +    int local_dst_alloc = 0;
3257 +    assert(src != NULL);
3258 +
3259 +    if (!dst) {
3260 +        CHECK(dst = (zval*) allocate(sizeof(zval)));
3261 +        local_dst_alloc = 1;
3262 +    }
3263 +
3264 +    dst = my_copy_zval(dst, src, allocate, deallocate);
3265 +    if(!dst) {
3266 +        if(local_dst_alloc) deallocate(dst);
3267 +        return NULL;
3268 +    }
3269 +    return dst; 
3270 +}
3271 +/* }}} */
3272 +
3273 +#ifdef ZEND_ENGINE_2
3274 +/* {{{ apc_fixup_op_array_jumps */
3275 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
3276 +{
3277 +    int i;
3278 +
3279 +    for (i=0; i < dst->last; ++i) {
3280 +        zend_op *zo = &(dst->opcodes[i]);
3281 +        /*convert opline number to jump address*/
3282 +        switch (zo->opcode) {
3283 +            case ZEND_JMP:
3284 +                /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
3285 +                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
3286 +                break;
3287 +            case ZEND_JMPZ:
3288 +            case ZEND_JMPNZ:
3289 +            case ZEND_JMPZ_EX:
3290 +            case ZEND_JMPNZ_EX:
3291 +                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
3292 +                break;
3293 +            default:
3294 +                break;
3295 +        }
3296 +    }
3297 +}
3298 +/* }}} */
3299 +#endif
3300 +
3301 +/* {{{ apc_copy_op_array */
3302 +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)
3303 +{
3304 +    int i;
3305 +    int local_dst_alloc = 0;
3306 +    apc_fileinfo_t fileinfo;
3307 +    char canon_path[MAXPATHLEN];
3308 +    char *fullpath = NULL;
3309 +#ifdef ZEND_ENGINE_2
3310 +    apc_opflags_t * flags = NULL;
3311 +#endif
3312 +
3313 +    assert(src != NULL);
3314 +
3315 +    if (!dst) {
3316 +        CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
3317 +        local_dst_alloc = 1;
3318 +    }
3319 +
3320 +    if(APCG(apc_optimize_function)) {
3321 +        APCG(apc_optimize_function)(src TSRMLS_CC);
3322 +    }
3323 +    
3324 +    /* start with a bitwise copy of the array */
3325 +    memcpy(dst, src, sizeof(src[0]));
3326 +
3327 +    dst->function_name = NULL;
3328 +    dst->filename = NULL;
3329 +    dst->refcount = NULL;
3330 +    dst->opcodes = NULL;
3331 +    dst->brk_cont_array = NULL;
3332 +    dst->static_variables = NULL;
3333 +#ifdef ZEND_ENGINE_2
3334 +    dst->try_catch_array = NULL;
3335 +    dst->arg_info = NULL;
3336 +    dst->doc_comment = NULL;
3337 +#else
3338 +    dst->arg_types = NULL;
3339 +#endif
3340 +#ifdef ZEND_ENGINE_2_1
3341 +    dst->vars = NULL;
3342 +#endif
3343 +
3344 +    /* copy the arg types array (if set) */
3345 +#ifdef ZEND_ENGINE_2
3346 +    if (src->arg_info) {
3347 +        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
3348 +                                                src->arg_info,
3349 +                                                src->num_args,
3350 +                                                allocate,
3351 +                                                deallocate))) {
3352 +            goto cleanup;
3353 +        }
3354 +    }
3355 +#else    
3356 +    if (src->arg_types) {
3357 +        if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
3358 +                        sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
3359 +                        allocate))) {
3360 +            goto cleanup;
3361 +        }
3362 +    }
3363 +#endif
3364 +
3365 +    if (src->function_name) {
3366 +        if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
3367 +            goto cleanup;
3368 +        }
3369 +    }
3370 +    if (src->filename) {
3371 +        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3372 +            goto cleanup;
3373 +        }
3374 +    }
3375 +
3376 +    if(!(dst->refcount = apc_xmemcpy(src->refcount,
3377 +                                      sizeof(src->refcount[0]),
3378 +                                      allocate))) {
3379 +        goto cleanup;
3380 +    }
3381 +
3382 +    /* deep-copy the opcodes */
3383 +    if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
3384 +        goto cleanup;
3385 +    }
3386 +
3387 +#ifdef ZEND_ENGINE_2
3388 +    if(APCG(reserved_offset) != -1) {
3389 +        /* Insanity alert: the void* pointer is cast into an apc_opflags_t 
3390 +         * struct. apc_zend_init() checks to ensure that it fits in a void* */
3391 +        flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
3392 +        memset(flags, 0, sizeof(apc_opflags_t));
3393 +        /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
3394 +    }
3395 +#endif
3396 +    
3397 +    for (i = 0; i < src->last; i++) {
3398 +#ifdef ZEND_ENGINE_2
3399 +        zend_op *zo = &(src->opcodes[i]);
3400 +        /* a lot of files are merely constant arrays with no jumps */
3401 +        switch (zo->opcode) {
3402 +            case ZEND_JMP:
3403 +            case ZEND_JMPZ:
3404 +            case ZEND_JMPNZ:
3405 +            case ZEND_JMPZ_EX:
3406 +            case ZEND_JMPNZ_EX:
3407 +                if(flags != NULL) {
3408 +                    flags->has_jumps = 1;
3409 +                }
3410 +                break;
3411 +#ifdef ZEND_ENGINE_2
3412 +            /* auto_globals_jit was not in php-4.3.* */
3413 +            case ZEND_FETCH_R:
3414 +            case ZEND_FETCH_W:
3415 +            case ZEND_FETCH_IS:
3416 +            case ZEND_FETCH_FUNC_ARG:
3417 +                if(PG(auto_globals_jit) && flags != NULL)
3418 +                {
3419 +                     /* The fetch is only required if auto_globals_jit=1  */
3420 +                    if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
3421 +                            zo->op1.op_type == IS_CONST && 
3422 +                            zo->op1.u.constant.type == IS_STRING) {
3423 +                        znode * varname = &zo->op1;
3424 +                        if (varname->u.constant.value.str.val[0] == '_') {
3425 +#define SET_IF_AUTOGLOBAL(member) \
3426 +    if(!strcmp(varname->u.constant.value.str.val, #member)) \
3427 +        flags->member = 1 /* no ';' here */
3428 +                            SET_IF_AUTOGLOBAL(_GET);
3429 +                            else SET_IF_AUTOGLOBAL(_POST);
3430 +                            else SET_IF_AUTOGLOBAL(_COOKIE);
3431 +                            else SET_IF_AUTOGLOBAL(_SERVER);
3432 +                            else SET_IF_AUTOGLOBAL(_ENV);
3433 +                            else SET_IF_AUTOGLOBAL(_FILES);
3434 +                            else SET_IF_AUTOGLOBAL(_REQUEST);
3435 +                            else if(zend_is_auto_global(
3436 +                                            varname->u.constant.value.str.val,
3437 +                                            varname->u.constant.value.str.len
3438 +                                            TSRMLS_CC))
3439 +                            {
3440 +                                flags->unknown_global = 1;
3441 +                            }
3442 +                        }
3443 +                    }
3444 +                }
3445 +                break;
3446 +#endif
3447 +            case ZEND_RECV_INIT:
3448 +                if(zo->op2.op_type == IS_CONST &&
3449 +                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
3450 +                    if(flags != NULL) {
3451 +                        flags->deep_copy = 1;
3452 +                    }
3453 +                }
3454 +                break;
3455 +            default:
3456 +                if((zo->op1.op_type == IS_CONST &&
3457 +                    zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
3458 +                    (zo->op2.op_type == IS_CONST &&
3459 +                        zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
3460 +                    if(flags != NULL) {
3461 +                        flags->deep_copy = 1;
3462 +                    }
3463 +                }
3464 +                break;
3465 +        }
3466 +#endif
3467 +        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
3468 +            int ii;
3469 +            for(ii = i-1; ii>=0; ii--) {
3470 +                my_destroy_zend_op(dst->opcodes+ii, deallocate);
3471 +            }
3472 +            goto  cleanup;
3473 +        }
3474 +#ifdef ZEND_ENGINE_2
3475 +/* This code breaks apc's rule#1 - cache what you compile */
3476 +        if(APCG(fpstat)==0) {
3477 +            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
3478 +                (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
3479 +                /* constant includes */
3480 +                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),len)) { 
3481 +                    if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
3482 +                        if((IS_ABSOLUTE_PATH(fileinfo.fullpath, strlen(fileinfo.fullpath)) && (fullpath = fileinfo.fullpath))
3483 +                                || (fullpath = realpath(fileinfo.fullpath, canon_path))) {
3484 +                            /* is either an absolute path or it goes through a realpath() */
3485 +                            zend_op *dzo = &(dst->opcodes[i]);
3486 +                            deallocate(dzo->op1.u.constant.value.str.val);
3487 +                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
3488 +                            dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
3489 +                        }
3490 +                    }
3491 +                }
3492 +            }
3493 +        }
3494 +#endif 
3495 +    }
3496 +
3497 +#ifdef ZEND_ENGINE_2
3498 +    if(flags == NULL || flags->has_jumps) {
3499 +        apc_fixup_op_array_jumps(dst,src);
3500 +    }
3501 +#endif
3502 +
3503 +    /* copy the break-continue array */
3504 +    if (src->brk_cont_array) {
3505 +        if(!(dst->brk_cont_array =
3506 +            apc_xmemcpy(src->brk_cont_array,
3507 +                        sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
3508 +                        allocate))) {
3509 +            goto cleanup_opcodes;
3510 +        }
3511 +    }
3512 +
3513 +    /* copy the table of static variables */
3514 +    if (src->static_variables) {
3515 +        if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
3516 +            goto cleanup_opcodes;
3517 +        }
3518 +    }
3519 +    
3520 +#ifdef ZEND_ENGINE_2
3521 +    if (src->try_catch_array) {
3522 +        if(!(dst->try_catch_array = 
3523 +                apc_xmemcpy(src->try_catch_array,
3524 +                        sizeof(src->try_catch_array[0]) * src->last_try_catch,
3525 +                        allocate))) {
3526 +            goto cleanup_opcodes;
3527 +        }
3528 +    }
3529 +#endif
3530 +
3531 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
3532 +    if (src->vars) {
3533 +        if(!(dst->vars = apc_xmemcpy(src->vars,
3534 +                            sizeof(src->vars[0]) * src->last_var,
3535 +                            allocate))) {
3536 +            goto cleanup_opcodes;
3537 +        }
3538 +        
3539 +        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
3540 +        
3541 +        for(i = 0; i <  src->last_var; i++) {
3542 +            if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
3543 +                                src->vars[i].name_len + 1,
3544 +                                allocate))) {
3545 +                dst->last_var = i;
3546 +                goto cleanup_opcodes;
3547 +            }
3548 +        }
3549 +    }
3550 +#endif
3551 +
3552 +#ifdef ZEND_ENGINE_2
3553 +    if (src->doc_comment) {
3554 +        if (!(dst->doc_comment 
3555 +                = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3556 +            goto cleanup_opcodes;
3557 +        }
3558 +    }
3559 +#endif
3560 +
3561 +    return dst;
3562 +
3563 +cleanup_opcodes:
3564 +    if(dst->opcodes) {
3565 +        for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
3566 +    }
3567 +cleanup:
3568 +    if(dst->function_name) deallocate(dst->function_name);
3569 +    if(dst->refcount) deallocate(dst->refcount);
3570 +    if(dst->filename) deallocate(dst->filename);
3571 +#ifdef ZEND_ENGINE_2
3572 +    if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
3573 +    if(dst->try_catch_array) deallocate(dst->try_catch_array);
3574 +    if(dst->doc_comment) deallocate(dst->doc_comment);
3575 +#else
3576 +    if(dst->arg_types) deallocate(dst->arg_types);
3577 +#endif
3578 +    if(dst->opcodes) deallocate(dst->opcodes);
3579 +    if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
3580 +    if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
3581 +#ifdef ZEND_ENGINE_2_1
3582 +    if (dst->vars) {
3583 +       for(i=0; i < dst->last_var; i++) {
3584 +            if(dst->vars[i].name) deallocate(dst->vars[i].name);    
3585 +        }
3586 +        deallocate(dst->vars);
3587 +    }
3588 +#endif
3589 +    if(local_dst_alloc) deallocate(dst);
3590 +    return NULL;
3591 +}
3592 +/* }}} */
3593 +
3594 +/* {{{ apc_copy_new_functions */
3595 +apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3596 +{
3597 +    apc_function_t* array;
3598 +    int new_count;              /* number of new functions in table */
3599 +    int i;
3600 +
3601 +    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
3602 +    assert(new_count >= 0);
3603 +
3604 +    CHECK(array =
3605 +        (apc_function_t*)
3606 +            allocate(sizeof(apc_function_t) * (new_count+1)));
3607 +
3608 +    if (new_count == 0) {
3609 +        array[0].function = NULL;
3610 +        return array;
3611 +    }
3612 +    
3613 +    /* Skip the first `old_count` functions in the table */
3614 +    zend_hash_internal_pointer_reset(CG(function_table));
3615 +    for (i = 0; i < old_count; i++) {
3616 +        zend_hash_move_forward(CG(function_table));
3617 +    }
3618 +
3619 +    /* Add the next `new_count` functions to our array */
3620 +    for (i = 0; i < new_count; i++) {
3621 +        char* key;
3622 +        uint key_size;
3623 +        zend_function* fun;
3624 +
3625 +        zend_hash_get_current_key_ex(CG(function_table),
3626 +                                     &key,
3627 +                                     &key_size,
3628 +                                     NULL,
3629 +                                     0,
3630 +                                     NULL);
3631 +
3632 +        zend_hash_get_current_data(CG(function_table), (void**) &fun);
3633 +
3634 +        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3635 +            int ii;
3636 +            for(ii=i-1; ii>=0; ii--) {
3637 +                deallocate(array[ii].name);
3638 +                my_free_function(array[ii].function, deallocate);
3639 +            }
3640 +            deallocate(array);
3641 +            return NULL;
3642 +        }
3643 +        array[i].name_len = (int) key_size-1;
3644 +        if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
3645 +            int ii;
3646 +            deallocate(array[i].name);
3647 +            for(ii=i-1; ii>=0; ii--) {
3648 +                deallocate(array[ii].name);
3649 +                my_free_function(array[ii].function, deallocate);
3650 +            }
3651 +            deallocate(array);
3652 +            return NULL;
3653 +        }
3654 +        zend_hash_move_forward(CG(function_table));
3655 +    }
3656 +
3657 +    array[i].function = NULL;
3658 +    return array;
3659 +}
3660 +/* }}} */
3661 +
3662 +/* {{{ apc_copy_new_classes */
3663 +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)
3664 +{
3665 +    apc_class_t* array;
3666 +    int new_count;              /* number of new classes in table */
3667 +    int i;
3668 +    
3669 +    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
3670 +    assert(new_count >= 0);
3671 +
3672 +    CHECK(array =
3673 +        (apc_class_t*)
3674 +            allocate(sizeof(apc_class_t)*(new_count+1)));
3675 +    
3676 +    if (new_count == 0) {
3677 +        array[0].class_entry = NULL;
3678 +        return array;
3679 +    }
3680 +
3681 +    /* Skip the first `old_count` classes in the table */
3682 +    zend_hash_internal_pointer_reset(CG(class_table));
3683 +    for (i = 0; i < old_count; i++) {
3684 +        zend_hash_move_forward(CG(class_table));
3685 +    }
3686 +
3687 +    /* Add the next `new_count` classes to our array */
3688 +    for (i = 0; i < new_count; i++) {
3689 +        char* key;
3690 +        uint key_size;
3691 +        zend_class_entry* elem = NULL;
3692 +
3693 +        array[i].class_entry = NULL;
3694 +
3695 +        zend_hash_get_current_key_ex(CG(class_table),
3696 +                                     &key,
3697 +                                     &key_size,
3698 +                                     NULL,
3699 +                                     0,
3700 +                                     NULL);
3701 +
3702 +       zend_hash_get_current_data(CG(class_table), (void**) &elem);
3703 +  
3704 +        
3705 +#ifdef ZEND_ENGINE_2
3706 +               elem = *((zend_class_entry**)elem);
3707 +#endif
3708 +        
3709 +        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3710 +            int ii;
3711 +
3712 +            for(ii=i-1; ii>=0; ii--) {
3713 +                deallocate(array[ii].name);
3714 +                my_destroy_class_entry(array[ii].class_entry, deallocate);
3715 +                deallocate(array[ii].class_entry);
3716 +            }
3717 +            deallocate(array);
3718 +            return NULL;
3719 +        }
3720 +        array[i].name_len = (int) key_size-1;
3721 +        if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
3722 +            int ii;
3723 +            
3724 +            deallocate(array[i].name);
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 +
3734 +        /*
3735 +         * If the class has a pointer to its parent class, save the parent
3736 +         * name so that we can enable compile-time inheritance when we reload
3737 +         * the child class; otherwise, set the parent name to null and scan
3738 +         * the op_array to determine if this class inherits from some base
3739 +         * class at execution-time.
3740 +         */
3741 +
3742 +        if (elem->parent) {
3743 +            if(!(array[i].parent_name =
3744 +                apc_xstrdup(elem->parent->name, allocate))) {
3745 +                int ii;
3746 +                 
3747 +                for(ii=i; ii>=0; ii--) {
3748 +                    deallocate(array[ii].name);
3749 +                    my_destroy_class_entry(array[ii].class_entry, deallocate);
3750 +                    deallocate(array[ii].class_entry);
3751 +                    if(ii==i) continue;
3752 +                    if(array[ii].parent_name) deallocate(array[ii].parent_name);
3753 +                }
3754 +                deallocate(array);
3755 +                return NULL;
3756 +            }
3757 +            array[i].is_derived = 1;
3758 +        }
3759 +        else {
3760 +            array[i].parent_name = NULL;
3761 +            array[i].is_derived = is_derived_class(op_array, key, key_size);
3762 +        }
3763 +
3764 +        zend_hash_move_forward(CG(class_table));
3765 +    }
3766 +
3767 +    array[i].class_entry = NULL;
3768 +    return array;
3769 +}
3770 +/* }}} */
3771 +
3772 +/* {{{ my_destroy_zval_ptr */
3773 +static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
3774 +{
3775 +    assert(src != NULL);
3776 +    if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
3777 +        deallocate(src[0]);
3778 +    }
3779 +}
3780 +/* }}} */
3781 +
3782 +/* {{{ my_destroy_zval */
3783 +static int my_destroy_zval(zval* src, apc_free_t deallocate)
3784 +{
3785 +    zval **tmp;
3786 +    TSRMLS_FETCH();
3787 +
3788 +    switch (src->type & ~IS_CONSTANT_INDEX) {
3789 +    case IS_RESOURCE:
3790 +    case IS_BOOL:
3791 +    case IS_LONG:
3792 +    case IS_DOUBLE:
3793 +    case IS_NULL:
3794 +        break;
3795 +
3796 +    case IS_CONSTANT:
3797 +    case IS_STRING:
3798 +#ifndef ZEND_ENGINE_2        
3799 +    case FLAG_IS_BC:
3800 +#endif        
3801 +        deallocate(src->value.str.val);
3802 +        break;
3803 +    
3804 +    case IS_ARRAY:
3805 +    
3806 +        /* Maintain a list of zvals we've copied to properly handle recursive structures */
3807 +        if(APCG(copied_zvals)) {
3808 +            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3809 +                (*tmp)->refcount--;
3810 +                return FAILURE;
3811 +            } 
3812 +            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
3813 +        }
3814 +        /* fall through */
3815 +
3816 +    case IS_CONSTANT_ARRAY:
3817 +        my_free_hashtable(src->value.ht,
3818 +                          (ht_free_fun_t) my_free_zval_ptr,
3819 +                          deallocate);
3820 +        break;
3821 +
3822 +    case IS_OBJECT:
3823 +#ifndef ZEND_ENGINE_2        
3824 +        my_destroy_class_entry(src->value.obj.ce, deallocate);
3825 +        deallocate(src->value.obj.ce);
3826 +        my_free_hashtable(src->value.obj.properties,
3827 +                          (ht_free_fun_t) my_free_zval_ptr,
3828 +                          deallocate);
3829 +#endif        
3830 +        break;
3831 +
3832 +    default:
3833 +        assert(0);
3834 +    }
3835 +
3836 +    return SUCCESS;
3837 +}
3838 +/* }}} */
3839 +
3840 +/* {{{ my_destroy_znode */
3841 +static void my_destroy_znode(znode* src, apc_free_t deallocate)
3842 +{
3843 +    if (src->op_type == IS_CONST) {
3844 +        my_destroy_zval(&src->u.constant, deallocate);
3845 +    }
3846 +}
3847 +/* }}} */
3848 +
3849 +/* {{{ my_destroy_zend_op */
3850 +static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
3851 +{
3852 +    my_destroy_znode(&src->result, deallocate);
3853 +    my_destroy_znode(&src->op1, deallocate);
3854 +    my_destroy_znode(&src->op2, deallocate);
3855 +}
3856 +/* }}} */
3857 +
3858 +/* {{{ my_destroy_function */
3859 +static void my_destroy_function(zend_function* src, apc_free_t deallocate)
3860 +{
3861 +    assert(src != NULL);
3862 +
3863 +    switch (src->type) {
3864 +    case ZEND_INTERNAL_FUNCTION:
3865 +    case ZEND_OVERLOADED_FUNCTION:
3866 +        break;
3867 +        
3868 +    case ZEND_USER_FUNCTION:
3869 +    case ZEND_EVAL_CODE:
3870 +        my_destroy_op_array(&src->op_array, deallocate);
3871 +        break;
3872 +
3873 +    default:
3874 +        assert(0);
3875 +    }
3876 +}
3877 +/* }}} */
3878 +
3879 +/* {{{ my_destroy_function_entry */
3880 +static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
3881 +{
3882 +    assert(src != NULL);
3883 +
3884 +    deallocate(src->fname);
3885 +#ifdef ZEND_ENGINE_2    
3886 +    if (src->arg_info) {
3887 +            my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
3888 +    }
3889 +#else
3890 +    if (src->func_arg_types) {
3891 +        deallocate(src->func_arg_types);
3892 +    }
3893 +#endif    
3894 +}
3895 +/* }}} */
3896 +
3897 +#ifdef ZEND_ENGINE_2    
3898 +/* {{{ my_destroy_property_info*/
3899 +static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
3900 +{
3901 +    assert(src != NULL);
3902 +
3903 +    deallocate(src->name);
3904 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
3905 +    if(src->doc_comment) deallocate(src->doc_comment);
3906 +#endif
3907 +}
3908 +/* }}} */
3909 +
3910 +/* {{{ my_destroy_arg_info_array */
3911 +static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
3912 +{
3913 +    int i = 0;
3914 +    
3915 +    assert(src != NULL);
3916 +
3917 +    for(i=0; i < num_args; i++) {
3918 +        my_destroy_arg_info(&src[i], deallocate);
3919 +    }
3920 +}
3921 +/* }}} */
3922 +
3923 +/* {{{ my_destroy_arg_info */
3924 +static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
3925 +{
3926 +    assert(src != NULL);
3927 +
3928 +    deallocate(src->name);
3929 +    deallocate(src->class_name);
3930 +}
3931 +/* }}} */
3932 +#endif    
3933 +
3934 +/* {{{ my_destroy_class_entry */
3935 +static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
3936 +{
3937 +    uint i;
3938 +
3939 +    assert(src != NULL);
3940 +
3941 +    deallocate(src->name);
3942 +#ifndef ZEND_ENGINE_2    
3943 +    deallocate(src->refcount);
3944 +#else
3945 +    if(src->doc_comment) deallocate(src->doc_comment);
3946 +    if(src->filename) deallocate(src->filename);
3947 +#endif
3948 +
3949 +    my_destroy_hashtable(&src->function_table,
3950 +                         (ht_free_fun_t) my_free_function,
3951 +                         deallocate);
3952 +
3953 +    my_destroy_hashtable(&src->default_properties,
3954 +                         (ht_free_fun_t) my_free_zval_ptr,
3955 +                         deallocate);
3956 +
3957 +#ifdef ZEND_ENGINE_2
3958 +    my_destroy_hashtable(&src->properties_info, 
3959 +                            (ht_free_fun_t) my_free_property_info,
3960 +                            deallocate);
3961 +    if(src->static_members) 
3962 +    {
3963 +        my_destroy_hashtable(src->static_members,
3964 +                         (ht_free_fun_t) my_free_zval_ptr,
3965 +                         deallocate);
3966 +        if(src->static_members != &(src->default_static_members))
3967 +        {
3968 +            deallocate(src->static_members);
3969 +        }
3970 +    }
3971 +
3972 +    my_destroy_hashtable(&src->constants_table, 
3973 +                            (ht_free_fun_t) my_free_zval_ptr,
3974 +                            deallocate);
3975 +#endif
3976 +
3977 +    if (src->builtin_functions) {
3978 +        for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
3979 +            my_destroy_function_entry(&src->builtin_functions[i], deallocate);
3980 +        }
3981 +        deallocate(src->builtin_functions);
3982 +    }
3983 +}
3984 +/* }}} */
3985 +
3986 +/* {{{ my_destroy_hashtable */
3987 +static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
3988 +{
3989 +    int i;
3990 +
3991 +    assert(src != NULL);
3992 +
3993 +    for (i = 0; i < src->nTableSize; i++) {
3994 +        Bucket* p = src->arBuckets[i];
3995 +        while (p != NULL) {
3996 +            Bucket* q = p;
3997 +            p = p->pNext;
3998 +            free_fn(q->pData, deallocate);
3999 +            deallocate(q);
4000 +        }
4001 +    }
4002 +
4003 +    deallocate(src->arBuckets);
4004 +}
4005 +/* }}} */
4006 +
4007 +/* {{{ my_destroy_op_array */
4008 +static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
4009 +{
4010 +    int i;
4011 +
4012 +    assert(src != NULL);
4013 +
4014 +#ifdef ZEND_ENGINE_2
4015 +    if (src->arg_info) {
4016 +        my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
4017 +    }
4018 +#else    
4019 +    if (src->arg_types) {
4020 +        deallocate(src->arg_types);
4021 +    }
4022 +#endif
4023 +
4024 +    deallocate(src->function_name);
4025 +    deallocate(src->filename);
4026 +    deallocate(src->refcount);
4027 +
4028 +    for (i = 0; i < src->last; i++) {
4029 +        my_destroy_zend_op(src->opcodes + i, deallocate);
4030 +    }
4031 +    deallocate(src->opcodes);
4032 +
4033 +    if (src->brk_cont_array) {
4034 +        deallocate(src->brk_cont_array);
4035 +    }
4036 +
4037 +    if (src->static_variables) {
4038 +        my_free_hashtable(src->static_variables,
4039 +                          (ht_free_fun_t) my_free_zval_ptr,
4040 +                          deallocate);
4041 +    }
4042 +    
4043 +#ifdef ZEND_ENGINE_2_1
4044 +    if (src->vars) {
4045 +       for(i=0; i < src->last_var; i++) {
4046 +            if(src->vars[i].name) deallocate(src->vars[i].name);    
4047 +        }
4048 +        deallocate(src->vars);
4049 +    }
4050 +#endif
4051 +#ifdef ZEND_ENGINE_2
4052 +    if(src->try_catch_array) {
4053 +        deallocate(src->try_catch_array);
4054 +    }
4055 +    if (src->doc_comment) {
4056 +        deallocate(src->doc_comment);
4057 +    }
4058 +#endif
4059 +}
4060 +/* }}} */
4061 +
4062 +/* {{{ my_free_zval_ptr */
4063 +static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
4064 +{
4065 +    my_destroy_zval_ptr(src, deallocate);
4066 +    deallocate(src);
4067 +}
4068 +/* }}} */
4069 +
4070 +#ifdef ZEND_ENGINE_2
4071 +/* {{{ my_free_property_info */
4072 +static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
4073 +{
4074 +    my_destroy_property_info(src, deallocate);
4075 +    deallocate(src);
4076 +}
4077 +/* }}} */
4078 +
4079 +/* {{{ my_free_arg_info_array */
4080 +static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
4081 +{
4082 +    my_destroy_arg_info_array(src, num_args, deallocate);
4083 +    deallocate(src);
4084 +}
4085 +/* }}} */
4086 +
4087 +/* {{{ my_free_arg_info */
4088 +static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
4089 +{
4090 +    my_destroy_arg_info(src, deallocate);
4091 +    deallocate(src);
4092 +}
4093 +/* }}} */
4094 +#endif
4095 +
4096 +/* {{{ my_free_function */
4097 +static void my_free_function(zend_function* src, apc_free_t deallocate)
4098 +{
4099 +    my_destroy_function(src, deallocate);
4100 +    deallocate(src);
4101 +}
4102 +/* }}} */
4103 +
4104 +/* {{{ my_free_hashtable */
4105 +static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4106 +{
4107 +    my_destroy_hashtable(src, free_fn, deallocate);
4108 +    deallocate(src);
4109 +}
4110 +/* }}} */
4111 +
4112 +/* {{{ apc_free_op_array */
4113 +void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
4114 +{
4115 +    if (src != NULL) {
4116 +        my_destroy_op_array(src, deallocate);
4117 +        deallocate(src);
4118 +    }
4119 +}
4120 +/* }}} */
4121 +
4122 +/* {{{ apc_free_functions */
4123 +void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
4124 +{
4125 +    int i;
4126 +
4127 +    if (src != NULL) {
4128 +        for (i = 0; src[i].function != NULL; i++) {
4129 +            deallocate(src[i].name);
4130 +            my_destroy_function(src[i].function, deallocate);
4131 +            deallocate(src[i].function);
4132 +        }   
4133 +        deallocate(src);
4134 +    }   
4135 +}
4136 +/* }}} */
4137 +
4138 +/* {{{ apc_free_classes */
4139 +void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
4140 +{
4141 +    int i;
4142 +
4143 +    if (src != NULL) {
4144 +        for (i = 0; src[i].class_entry != NULL; i++) {
4145 +            deallocate(src[i].name);
4146 +            deallocate(src[i].parent_name);
4147 +            my_destroy_class_entry(src[i].class_entry, deallocate);
4148 +            deallocate(src[i].class_entry);
4149 +        }   
4150 +        deallocate(src);
4151 +    }   
4152 +}
4153 +/* }}} */
4154 +
4155 +/* {{{ apc_free_zval */
4156 +void apc_free_zval(zval* src, apc_free_t deallocate)
4157 +{
4158 +    if (src != NULL) {
4159 +        if(my_destroy_zval(src, deallocate) == SUCCESS) {
4160 +            deallocate(src);
4161 +        }
4162 +    }
4163 +}
4164 +/* }}} */
4165 +
4166 +
4167 +/* Used only by my_prepare_op_array_for_execution */
4168 +#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                                \
4169 +                         /* The fetch is only required if auto_globals_jit=1  */                \
4170 +                        if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&                            \
4171 +                            zo->op1.op_type == IS_CONST &&                                      \
4172 +                            zo->op1.u.constant.type == IS_STRING &&                             \
4173 +                            zo->op1.u.constant.value.str.val[0] == '_') {                       \
4174 +                                                                                                \
4175 +                            znode* varname = &zo->op1;                                          \
4176 +                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
4177 +                                                          varname->u.constant.value.str.len     \
4178 +                                                          TSRMLS_CC);                           \
4179 +                        }                                                                       \
4180 +
4181 +/* {{{ my_prepare_op_array_for_execution */
4182 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC) 
4183 +{
4184 +    /* combine my_fetch_global_vars and my_copy_data_exceptions.
4185 +     *   - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4186 +     *   - If the opcode stream contain mutable data, ensure a copy.
4187 +     *   - Fixup array jumps in the same loop.
4188 +     */
4189 +    int i=src->last;
4190 +    zend_op *zo;
4191 +    zend_op *dzo;
4192 +#ifdef ZEND_ENGINE_2
4193 +    apc_opflags_t * flags = APCG(reserved_offset) != -1 ? 
4194 +                                (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
4195 +    int needcopy = flags ? flags->deep_copy : 1;
4196 +    /* auto_globals_jit was not in php4 */
4197 +    int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
4198 +
4199 +#define FETCH_AUTOGLOBAL(member) do { \
4200 +    if(flags && flags->member == 1) { \
4201 +        zend_is_auto_global(#member,\
4202 +                            (sizeof(#member) - 1)\
4203 +                            TSRMLS_CC);\
4204 +    } \
4205 +}while(0); 
4206 +            
4207 +    FETCH_AUTOGLOBAL(_GET);
4208 +    FETCH_AUTOGLOBAL(_POST);
4209 +    FETCH_AUTOGLOBAL(_COOKIE);
4210 +    FETCH_AUTOGLOBAL(_SERVER);
4211 +    FETCH_AUTOGLOBAL(_ENV);
4212 +    FETCH_AUTOGLOBAL(_FILES);
4213 +    FETCH_AUTOGLOBAL(_REQUEST);
4214 +
4215 +#else
4216 +    int needcopy = 0;
4217 +    int do_prepare_fetch_global = 0;
4218 +    int j = 0;
4219 +
4220 +    for(j = 0; j < src->last; j++) {
4221 +        zo = &src->opcodes[j];
4222 +        
4223 +        if( ((zo->op1.op_type == IS_CONST &&
4224 +              zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
4225 +            ((zo->op2.op_type == IS_CONST &&
4226 +              zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4227 +            needcopy = 1;
4228 +        }
4229 +    }
4230 +#endif
4231 +    
4232 +    if(needcopy) {
4233 +
4234 +        dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes, 
4235 +                                    sizeof(zend_op) * src->last,
4236 +                                    apc_php_malloc);
4237 +        zo = src->opcodes;
4238 +        dzo = dst->opcodes;
4239 +        while(i > 0) {
4240 +
4241 +            if( ((zo->op1.op_type == IS_CONST &&
4242 +                  zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
4243 +                ((zo->op2.op_type == IS_CONST &&
4244 +                  zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4245 +
4246 +                if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
4247 +                    assert(0); /* emalloc failed or a bad constant array */
4248 +                }
4249 +            }
4250 +            
4251 +#ifdef ZEND_ENGINE_2
4252 +            switch(zo->opcode) {
4253 +                case ZEND_JMP:
4254 +                    dzo->op1.u.jmp_addr = dst->opcodes + 
4255 +                                            (zo->op1.u.jmp_addr - src->opcodes);
4256 +                    break;
4257 +                case ZEND_JMPZ:
4258 +                case ZEND_JMPNZ:
4259 +                case ZEND_JMPZ_EX:
4260 +                case ZEND_JMPNZ_EX:
4261 +                    dzo->op2.u.jmp_addr = dst->opcodes + 
4262 +                                            (zo->op2.u.jmp_addr - src->opcodes);
4263 +                    break;
4264 +                case ZEND_FETCH_R:
4265 +                case ZEND_FETCH_W:
4266 +                case ZEND_FETCH_IS:
4267 +                case ZEND_FETCH_FUNC_ARG:
4268 +                    if(do_prepare_fetch_global)
4269 +                    {
4270 +                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4271 +                    }
4272 +                    break;
4273 +                default:
4274 +                    break;
4275 +            }
4276 +#endif
4277 +            i--;
4278 +            zo++;
4279 +            dzo++;
4280 +        }
4281 +#ifdef ZEND_ENGINE_2
4282 +    } else {  /* !needcopy */
4283 +        /* The fetch is only required if auto_globals_jit=1  */
4284 +        if(do_prepare_fetch_global)
4285 +        {
4286 +            zo = src->opcodes;
4287 +            while(i > 0) {
4288 +
4289 +                if(zo->opcode == ZEND_FETCH_R || 
4290 +                   zo->opcode == ZEND_FETCH_W ||
4291 +                   zo->opcode == ZEND_FETCH_IS ||
4292 +                   zo->opcode == ZEND_FETCH_FUNC_ARG 
4293 +                  ) {
4294 +                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4295 +                }
4296 +
4297 +                i--;
4298 +                zo++;
4299 +            }
4300 +        }
4301 +#endif
4302 +    }
4303 +    return 1;
4304 +}
4305 +/* }}} */
4306 +
4307 +/* {{{ apc_copy_op_array_for_execution */
4308 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4309 +{
4310 +    if(dst == NULL) {
4311 +        dst = (zend_op_array*) emalloc(sizeof(src[0]));
4312 +    }
4313 +    memcpy(dst, src, sizeof(src[0]));
4314 +    dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
4315 +
4316 +    dst->refcount = apc_xmemcpy(src->refcount,
4317 +                                      sizeof(src->refcount[0]),
4318 +                                      apc_php_malloc);
4319 +    
4320 +    my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
4321 +
4322 +    return dst;
4323 +}
4324 +/* }}} */
4325 +
4326 +/* {{{ apc_copy_function_for_execution */
4327 +zend_function* apc_copy_function_for_execution(zend_function* src)
4328 +{
4329 +    zend_function* dst;
4330 +    TSRMLS_FETCH();
4331 +
4332 +    dst = (zend_function*) emalloc(sizeof(src[0]));
4333 +    memcpy(dst, src, sizeof(src[0]));
4334 +    apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
4335 +    return dst;
4336 +}
4337 +/* }}} */
4338 +
4339 +/* {{{ apc_copy_function_for_execution_ex */
4340 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
4341 +{
4342 +    if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
4343 +    return apc_copy_function_for_execution(src);
4344 +}
4345 +/* }}} */
4346 +
4347 +/* {{{ apc_copy_class_entry_for_execution */
4348 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
4349 +{
4350 +    zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
4351 +    memcpy(dst, src, sizeof(src[0]));
4352 +
4353 +#ifdef ZEND_ENGINE_2
4354 +    if(src->num_interfaces)
4355 +    {
4356 +        /* These are slots to be populated later by ADD_INTERFACE insns */
4357 +        dst->interfaces = apc_php_malloc(
4358 +                            sizeof(zend_class_entry*) * src->num_interfaces);
4359 +        memset(dst->interfaces, 0, 
4360 +                            sizeof(zend_class_entry*) * src->num_interfaces);
4361 +    }
4362 +    else
4363 +    {
4364 +        /* assert(dst->interfaces == NULL); */
4365 +    }
4366 +#endif
4367 +
4368 +#ifndef ZEND_ENGINE_2    
4369 +    dst->refcount = apc_xmemcpy(src->refcount,
4370 +                                      sizeof(src->refcount[0]),
4371 +                                      apc_php_malloc);
4372 +#endif        
4373 +
4374 +    /* Deep-copy the class properties, because they will be modified */
4375 +
4376 +    my_copy_hashtable(&dst->default_properties,
4377 +                      &src->default_properties,
4378 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4379 +                      (ht_free_fun_t) my_free_zval_ptr,
4380 +                      1,
4381 +                      apc_php_malloc, apc_php_free);
4382 +
4383 +    /* For derived classes, we must also copy the function hashtable (although
4384 +     * we can merely bitwise copy the functions it contains) */
4385 +
4386 +    my_copy_hashtable(&dst->function_table,
4387 +                      &src->function_table,
4388 +                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
4389 +                      NULL,
4390 +                      0,
4391 +                      apc_php_malloc, apc_php_free);
4392 +#ifdef ZEND_ENGINE_2
4393 +    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
4394 +
4395 +    /* zend_do_inheritance merges properties_info.
4396 +     * Need only shallow copying as it doesn't hold the pointers.
4397 +     */
4398 +    my_copy_hashtable(&dst->properties_info,
4399 +                      &src->properties_info,
4400 +                      (ht_copy_fun_t) my_copy_property_info_for_execution,
4401 +                      NULL,
4402 +                      0,
4403 +                      apc_php_malloc, apc_php_free);
4404 +
4405 +#ifdef ZEND_ENGINE_2_2
4406 +    /* php5.2 introduced a scope attribute for property info */
4407 +    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4408 +#endif
4409 +
4410 +    /* if inheritance results in a hash_del, it might result in
4411 +     * a pefree() of the pointers here. Deep copying required. 
4412 +     */
4413 +
4414 +    my_copy_hashtable(&dst->constants_table,
4415 +                      &src->constants_table,
4416 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4417 +                      NULL,
4418 +                      1,
4419 +                      apc_php_malloc, apc_php_free);
4420 +
4421 +    my_copy_hashtable(&dst->default_static_members,
4422 +                      &src->default_static_members,
4423 +                      (ht_copy_fun_t) my_copy_zval_ptr,
4424 +                      (ht_free_fun_t) my_free_zval_ptr,
4425 +                      1,
4426 +                      apc_php_malloc, apc_php_free);
4427 +
4428 +    if(src->static_members != &(src->default_static_members))
4429 +    {
4430 +        dst->static_members = my_copy_hashtable(NULL,
4431 +                          src->static_members,
4432 +                          (ht_copy_fun_t) my_copy_zval_ptr,
4433 +                          (ht_free_fun_t) my_free_zval_ptr,
4434 +                          1,
4435 +                          apc_php_malloc, apc_php_free);
4436 +    }
4437 +    else 
4438 +    {
4439 +        dst->static_members = &(dst->default_static_members);
4440 +    }
4441 +
4442 +#endif
4443 +
4444 +    return dst;
4445 +}
4446 +/* }}} */
4447 +
4448 +/* {{{ apc_free_class_entry_after_execution */
4449 +void apc_free_class_entry_after_execution(zend_class_entry* src)
4450 +{
4451 +#ifdef ZEND_ENGINE_2
4452 +    if(src->num_interfaces > 0 && src->interfaces) {
4453 +        apc_php_free(src->interfaces);
4454 +        src->interfaces = NULL;
4455 +        src->num_interfaces = 0;
4456 +    }
4457 +    /* my_destroy_hashtable() does not play nice with refcounts */
4458 +
4459 +    zend_hash_clean(&src->default_static_members);
4460 +    if(src->static_members != &(src->default_static_members))
4461 +    {
4462 +        zend_hash_destroy(src->static_members);
4463 +        apc_php_free(src->static_members);
4464 +        src->static_members = NULL;
4465 +    }
4466 +    else
4467 +    {
4468 +        src->static_members = NULL;
4469 +    }
4470 +    zend_hash_clean(&src->default_properties);
4471 +    zend_hash_clean(&src->constants_table);
4472 +#endif
4473 +
4474 +    /* TODO: more cleanup */
4475 +}
4476 +/* }}} */
4477 +
4478 +#ifdef ZEND_ENGINE_2
4479 +
4480 +/* {{{ my_fixup_function */
4481 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4482 +{
4483 +    zend_function* zf = p->pData;
4484 +
4485 +    #define SET_IF_SAME_NAME(member) \
4486 +    do { \
4487 +        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
4488 +            dst->member = zf; \
4489 +        } \
4490 +    } \
4491 +    while(0)
4492 +
4493 +    if(zf->common.scope == src)
4494 +    {
4495 +    
4496 +        /* Fixing up the default functions for objects here since
4497 +         * we need to compare with the newly allocated functions
4498 +         *
4499 +         * caveat: a sub-class method can have the same name as the
4500 +         * parent's constructor and create problems.
4501 +         */
4502 +        
4503 +        if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
4504 +        else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
4505 +        else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
4506 +        else
4507 +        {
4508 +            SET_IF_SAME_NAME(__get);
4509 +            SET_IF_SAME_NAME(__set);
4510 +            SET_IF_SAME_NAME(__unset);
4511 +            SET_IF_SAME_NAME(__isset);
4512 +            SET_IF_SAME_NAME(__call);
4513 +#ifdef ZEND_ENGINE_2_2
4514 +            SET_IF_SAME_NAME(__tostring);
4515 +#endif
4516 +        }
4517 +        zf->common.scope = dst;
4518 +    }
4519 +    else
4520 +    {
4521 +        /* no other function should reach here */
4522 +        assert(0);
4523 +    }
4524 +
4525 +    #undef SET_IF_SAME_NAME
4526 +}
4527 +/* }}} */
4528 +
4529 +#ifdef ZEND_ENGINE_2_2
4530 +/* {{{ my_fixup_property_info */
4531 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4532 +{
4533 +    zend_property_info* property_info = (zend_property_info*)p->pData;
4534 +
4535 +    if(property_info->ce == src)
4536 +    {
4537 +        property_info->ce = dst;
4538 +    }
4539 +    else
4540 +    {
4541 +        assert(0); /* should never happen */
4542 +    }
4543 +}
4544 +/* }}} */
4545 +#endif
4546 +
4547 +/* {{{ my_fixup_hashtable */
4548 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
4549 +{
4550 +    Bucket *p;
4551 +    
4552 +       uint i;
4553 +    
4554 +       for (i = 0; i < ht->nTableSize; i++) {
4555 +               if(!ht->arBuckets) break;
4556 +        p = ht->arBuckets[i];
4557 +               while (p != NULL) {
4558 +            fixup(p, src, dst);
4559 +                       p = p->pNext;
4560 +               }
4561 +       }
4562 +}
4563 +/* }}} */
4564 +
4565 +#endif
4566 +
4567 +/* {{{ my_check_copy_function */
4568 +static int my_check_copy_function(Bucket* p, va_list args)
4569 +{
4570 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4571 +    zend_function* zf = (zend_function*)p->pData;
4572 +#ifndef ZEND_ENGINE_2
4573 +    zend_class_entry* parent = src->parent;
4574 +    zend_function* parent_fn = NULL;
4575 +#endif
4576 +
4577 +#ifdef ZEND_ENGINE_2
4578 +    return (zf->common.scope == src);
4579 +#else
4580 +       if (parent &&
4581 +        zend_hash_quick_find(&parent->function_table, p->arKey, 
4582 +            p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
4583 +        
4584 +        if((parent_fn && zf) && 
4585 +                (parent_fn->op_array.refcount == zf->op_array.refcount))
4586 +        {
4587 +            return 0;
4588 +        }
4589 +    }
4590 +    return 1;
4591 +#endif 
4592 +}
4593 +/* }}} */
4594 +
4595 +/* {{{ my_check_copy_default_property */
4596 +static int my_check_copy_default_property(Bucket* p, va_list args)
4597 +{
4598 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4599 +    zend_class_entry* parent = src->parent;
4600 +    zval ** child_prop = (zval**)p->pData;
4601 +    zval ** parent_prop = NULL;
4602 +
4603 +       if (parent &&
4604 +        zend_hash_quick_find(&parent->default_properties, p->arKey, 
4605 +            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
4606 +
4607 +        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
4608 +        {
4609 +            return 0;
4610 +        }
4611 +    }
4612 +    
4613 +    /* possibly not in the parent */
4614 +    return 1;
4615 +}
4616 +/* }}} */
4617 +
4618 +#ifdef ZEND_ENGINE_2
4619 +
4620 +/* {{{ my_check_copy_property_info */
4621 +static int my_check_copy_property_info(Bucket* p, va_list args)
4622 +{
4623 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4624 +    zend_class_entry* parent = src->parent;
4625 +    zend_property_info* child_info = (zend_property_info*)p->pData;
4626 +    zend_property_info* parent_info = NULL;
4627 +
4628 +#ifdef ZEND_ENGINE_2_2
4629 +    /* so much easier */
4630 +    return (child_info->ce == src);
4631 +#endif
4632 +
4633 +       if (parent &&
4634 +        zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength, 
4635 +            p->h, (void **) &parent_info)==SUCCESS) {
4636 +        if(parent_info->flags & ZEND_ACC_PRIVATE)
4637 +        {
4638 +            return 1;
4639 +        }
4640 +        if((parent_info->flags & ZEND_ACC_PPP_MASK) != 
4641 +            (child_info->flags & ZEND_ACC_PPP_MASK))
4642 +        {
4643 +            /* TODO: figure out whether ACC_CHANGED is more appropriate
4644 +             * here */
4645 +            return 1;
4646 +        }
4647 +        return 0;
4648 +    }
4649 +    
4650 +    /* property doesn't exist in parent, copy into cached child */
4651 +    return 1;
4652 +}
4653 +/* }}} */
4654 +
4655 +/* {{{ my_check_copy_static_member */
4656 +static int my_check_copy_static_member(Bucket* p, va_list args)
4657 +{
4658 +    zend_class_entry* src = va_arg(args, zend_class_entry*);
4659 +    HashTable * ht = va_arg(args, HashTable*);
4660 +    zend_class_entry* parent = src->parent;
4661 +    HashTable * parent_ht = NULL;
4662 +    char * member_name;
4663 +    char * class_name = NULL;
4664 +
4665 +    zend_property_info *parent_info = NULL;
4666 +    zend_property_info *child_info = NULL;
4667 +    zval ** parent_prop = NULL;
4668 +    zval ** child_prop = (zval**)(p->pData);
4669 +
4670 +    if(!parent) {
4671 +        return 1;
4672 +    }
4673 +
4674 +    /* these do not need free'ing */
4675 +#ifdef ZEND_ENGINE_2_2
4676 +    zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
4677 +#else
4678 +    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
4679 +#endif
4680 +
4681 +    /* please refer do_inherit_property_access_check in zend_compile.c
4682 +     * to understand why we lookup in properties_info.
4683 +     */
4684 +    if((zend_hash_find(&parent->properties_info, member_name, 
4685 +                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
4686 +        &&
4687 +        (zend_hash_find(&src->properties_info, member_name,
4688 +                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
4689 +    {
4690 +        if(child_info->flags & ZEND_ACC_STATIC &&    
4691 +            (parent_info->flags & ZEND_ACC_PROTECTED &&
4692 +            child_info->flags & ZEND_ACC_PUBLIC))
4693 +        {
4694 +            /* Do not copy into static_members. zend_do_inheritance
4695 +             * will automatically insert a NULL value.
4696 +             * TODO: decrement refcount or fixup when copying out for exec ? 
4697 +             */ 
4698 +            return 0;
4699 +        }
4700 +        if(ht == &(src->default_static_members))
4701 +        {
4702 +            parent_ht = &parent->default_static_members;
4703 +        }
4704 +        else
4705 +        {
4706 +            parent_ht = parent->static_members;
4707 +        }
4708 +
4709 +        if(zend_hash_quick_find(parent_ht, p->arKey,
4710 +                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
4711 +        {
4712 +            /* they point to the same zval */
4713 +            if(*parent_prop == *child_prop)
4714 +            {
4715 +                return 0;
4716 +            }
4717 +        }
4718 +    }
4719 +    
4720 +    return 1;
4721 +}
4722 +/* }}} */
4723 +#endif
4724 +
4725 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
4726 + *      register a optimizer callback function, returns the previous callback
4727 + */
4728 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
4729 +    apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
4730 +    APCG(apc_optimize_function) = optimizer;
4731 +    return old_optimizer;
4732 +}
4733 +
4734 +/*
4735 + * Local variables:
4736 + * tab-width: 4
4737 + * c-basic-offset: 4
4738 + * End:
4739 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4740 + * vim<600: expandtab sw=4 ts=4 sts=4
4741 + */
4742 diff -ruN php-5.1.6.old/ext/apc/apc_compile.h php-5.1.6/ext/APC/apc_compile.h
4743 --- php-5.1.6.old/ext/apc/apc_compile.h 1969-12-31 18:00:00.000000000 -0600
4744 +++ php-5.1.6/ext/apc/apc_compile.h     2007-04-02 18:05:30.000000000 -0500
4745 @@ -0,0 +1,134 @@
4746 +/*
4747 +  +----------------------------------------------------------------------+
4748 +  | APC                                                                  |
4749 +  +----------------------------------------------------------------------+
4750 +  | Copyright (c) 2006 The PHP Group                                     |
4751 +  +----------------------------------------------------------------------+
4752 +  | This source file is subject to version 3.01 of the PHP license,      |
4753 +  | that is bundled with this package in the file LICENSE, and is        |
4754 +  | available through the world-wide-web at the following url:           |
4755 +  | http://www.php.net/license/3_01.txt                                  |
4756 +  | If you did not receive a copy of the PHP license and are unable to   |
4757 +  | obtain it through the world-wide-web, please send a note to          |
4758 +  | license@php.net so we can mail you a copy immediately.               |
4759 +  +----------------------------------------------------------------------+
4760 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
4761 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
4762 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
4763 +  +----------------------------------------------------------------------+
4764 +
4765 +   This software was contributed to PHP by Community Connect Inc. in 2002
4766 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4767 +   Future revisions and derivatives of this source code must acknowledge
4768 +   Community Connect Inc. as the original contributor of this module by
4769 +   leaving this note intact in the source code.
4770 +
4771 +   All other licensing and usage conditions are those of the PHP Group.
4772 +
4773 + */
4774 +
4775 +/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
4776 +
4777 +#ifndef APC_COMPILE_H
4778 +#define APC_COMPILE_H
4779 +
4780 +/*
4781 + * This module encapsulates most of the complexity involved in deep-copying
4782 + * the Zend compiler data structures. The routines are allocator-agnostic, so
4783 + * the same function can be used for copying to and from shared memory.
4784 + */
4785 +
4786 +#include "apc.h"
4787 +#include "apc_php.h"
4788 +
4789 +/* {{{ struct definition: apc_function_t */
4790 +typedef struct apc_function_t apc_function_t;
4791 +struct apc_function_t {
4792 +    char* name;                 /* the function name */
4793 +    int name_len;               /* length of name */
4794 +    zend_function* function;    /* the zend function data structure */
4795 +};
4796 +/* }}} */
4797 +
4798 +/* {{{ struct definition: apc_class_t */
4799 +typedef struct apc_class_t apc_class_t;
4800 +struct apc_class_t {
4801 +    char* name;                     /* the class name */
4802 +    int name_len;                   /* length of name */
4803 +    int is_derived;                 /* true if this is a derived class */
4804 +    char* parent_name;              /* the parent class name */
4805 +    zend_class_entry* class_entry;  /* the zend class data structure */
4806 +};
4807 +/* }}} */
4808 +
4809 +/* {{{ struct definition: apc_opflags_t */
4810 +typedef struct apc_opflags_t apc_opflags_t;
4811 +struct apc_opflags_t {
4812 +    unsigned int has_jumps      : 1; /* has jump offsets */
4813 +    unsigned int deep_copy      : 1; /* needs deep copy */
4814 +
4815 +    /* autoglobal bits */
4816 +    unsigned int _POST          : 1;
4817 +    unsigned int _GET           : 1;
4818 +    unsigned int _COOKIE        : 1;
4819 +    unsigned int _SERVER        : 1;
4820 +    unsigned int _ENV           : 1;
4821 +    unsigned int _FILES         : 1;
4822 +    unsigned int _REQUEST       : 1;
4823 +    unsigned int unknown_global : 1;
4824 +};
4825 +/* }}} */
4826 +
4827 +/*
4828 + * These are the top-level copy functions.
4829 + */
4830 +
4831 +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);
4832 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
4833 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4834 +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);
4835 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
4836 +
4837 +/*
4838 + * Deallocation functions corresponding to the copy functions above.
4839 + */
4840 +
4841 +extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
4842 +extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
4843 +extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
4844 +extern void apc_free_zval(zval* src, apc_free_t deallocate);
4845 +
4846 +/*
4847 + * These "copy-for-execution" functions must be called after retrieving an
4848 + * object from the shared cache. They do the minimal amount of work necessary
4849 + * to allow multiple processes to concurrently execute the same VM data
4850 + * structures.
4851 + */
4852 +
4853 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
4854 +extern zend_function* apc_copy_function_for_execution(zend_function* src);
4855 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
4856 +
4857 +/*
4858 + * The "free-after-execution" function performs a cursory clean up of the class data
4859 + * This is required to minimize memory leak warnings and to ensure correct destructor
4860 + * ordering of some variables.
4861 + */
4862 +extern void apc_free_class_entry_after_execution(zend_class_entry* src);
4863 +
4864 +/*
4865 + * Optimization callback definition and registration function. 
4866 + */
4867 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
4868 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
4869 +
4870 +#endif
4871 +
4872 +/*
4873 + * Local variables:
4874 + * tab-width: 4
4875 + * c-basic-offset: 4
4876 + * End:
4877 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4878 + * vim<600: expandtab sw=4 ts=4 sts=4
4879 + */
4880 diff -ruN php-5.1.6.old/ext/apc/apc_debug.c php-5.1.6/ext/APC/apc_debug.c
4881 --- php-5.1.6.old/ext/apc/apc_debug.c   1969-12-31 18:00:00.000000000 -0600
4882 +++ php-5.1.6/ext/apc/apc_debug.c       2007-04-02 18:05:30.000000000 -0500
4883 @@ -0,0 +1,57 @@
4884 +/*
4885 +  +----------------------------------------------------------------------+
4886 +  | APC                                                                  |
4887 +  +----------------------------------------------------------------------+
4888 +  | Copyright (c) 2006 The PHP Group                                     |
4889 +  +----------------------------------------------------------------------+
4890 +  | This source file is subject to version 3.01 of the PHP license,      |
4891 +  | that is bundled with this package in the file LICENSE, and is        |
4892 +  | available through the world-wide-web at the following url:           |
4893 +  | http://www.php.net/license/3_01.txt                                  |
4894 +  | If you did not receive a copy of the PHP license and are unable to   |
4895 +  | obtain it through the world-wide-web, please send a note to          |
4896 +  | license@php.net so we can mail you a copy immediately.               |
4897 +  +----------------------------------------------------------------------+
4898 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
4899 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
4900 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
4901 +  +----------------------------------------------------------------------+
4902 +
4903 +   This software was contributed to PHP by Community Connect Inc. in 2002
4904 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4905 +   Future revisions and derivatives of this source code must acknowledge
4906 +   Community Connect Inc. as the original contributor of this module by
4907 +   leaving this note intact in the source code.
4908 +
4909 +   All other licensing and usage conditions are those of the PHP Group.
4910 +*/
4911 +
4912 +/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
4913 +#include "apc.h"
4914 +#include <stdio.h>
4915 +#include "zend_compile.h"
4916 +
4917 +#ifdef __DEBUG_APC__
4918 +
4919 +#include <dlfcn.h>
4920 +
4921 +/* keep track of vld_dump_oparray() signature */
4922 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
4923 +
4924 +#endif
4925 +
4926 +void dump(zend_op_array *op_array TSRMLS_DC)
4927 +{
4928 +#ifdef __DEBUG_APC__
4929 +       vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
4930 +
4931 +       if(dump_op_array)
4932 +       {
4933 +               dump_op_array(op_array TSRMLS_CC); 
4934 +       }
4935 +       else
4936 +       {
4937 +               apc_wprint("vld is not installed or something even worse.");
4938 +       }
4939 +#endif
4940 +}
4941 diff -ruN php-5.1.6.old/ext/apc/apc_debug.h php-5.1.6/ext/APC/apc_debug.h
4942 --- php-5.1.6.old/ext/apc/apc_debug.h   1969-12-31 18:00:00.000000000 -0600
4943 +++ php-5.1.6/ext/apc/apc_debug.h       2007-04-02 18:05:30.000000000 -0500
4944 @@ -0,0 +1 @@
4945 +void dump(zend_op_array * TSRMLS_DC);
4946 diff -ruN php-5.1.6.old/ext/apc/apc.dsp php-5.1.6/ext/APC/apc.dsp
4947 --- php-5.1.6.old/ext/apc/apc.dsp       1969-12-31 18:00:00.000000000 -0600
4948 +++ php-5.1.6/ext/apc/apc.dsp   2007-04-02 18:05:30.000000000 -0500
4949 @@ -0,0 +1,207 @@
4950 +# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
4951 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
4952 +# ** DO NOT EDIT **
4953 +
4954 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
4955 +
4956 +CFG=apc - Win32 Debug_TS
4957 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
4958 +!MESSAGE use the Export Makefile command and run
4959 +!MESSAGE 
4960 +!MESSAGE NMAKE /f "apc.mak".
4961 +!MESSAGE 
4962 +!MESSAGE You can specify a configuration when running NMAKE
4963 +!MESSAGE by defining the macro CFG on the command line. For example:
4964 +!MESSAGE 
4965 +!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
4966 +!MESSAGE 
4967 +!MESSAGE Possible choices for configuration are:
4968 +!MESSAGE 
4969 +!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
4970 +!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
4971 +!MESSAGE 
4972 +
4973 +# Begin Project
4974 +# PROP AllowPerConfigDependencies 0
4975 +# PROP Scc_ProjName ""
4976 +# PROP Scc_LocalPath ""
4977 +CPP=cl.exe
4978 +MTL=midl.exe
4979 +RSC=rc.exe
4980 +
4981 +!IF  "$(CFG)" == "apc - Win32 Debug_TS"
4982 +
4983 +# PROP BASE Use_MFC 0
4984 +# PROP BASE Use_Debug_Libraries 1
4985 +# PROP BASE Output_Dir "Debug_TS"
4986 +# PROP BASE Intermediate_Dir "Debug_TS"
4987 +# PROP BASE Target_Dir ""
4988 +# PROP Use_MFC 0
4989 +# PROP Use_Debug_Libraries 1
4990 +# PROP Output_Dir "Debug_TS"
4991 +# PROP Intermediate_Dir "Debug_TS"
4992 +# PROP Ignore_Export_Lib 0
4993 +# PROP Target_Dir ""
4994 +# 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
4995 +# 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
4996 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
4997 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
4998 +# ADD BASE RSC /l 0x409 /d "_DEBUG"
4999 +# ADD RSC /l 0x409 /d "_DEBUG"
5000 +BSC32=bscmake.exe
5001 +# ADD BASE BSC32 /nologo
5002 +# ADD BSC32 /nologo
5003 +LINK32=link.exe
5004 +# 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
5005 +# 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"
5006 +
5007 +!ELSEIF  "$(CFG)" == "apc - Win32 Release_TS"
5008 +
5009 +# PROP BASE Use_MFC 0
5010 +# PROP BASE Use_Debug_Libraries 0
5011 +# PROP BASE Output_Dir "Release_TS"
5012 +# PROP BASE Intermediate_Dir "Release_TS"
5013 +# PROP BASE Target_Dir ""
5014 +# PROP Use_MFC 0
5015 +# PROP Use_Debug_Libraries 0
5016 +# PROP Output_Dir "Release_TS"
5017 +# PROP Intermediate_Dir "Release_TS"
5018 +# PROP Ignore_Export_Lib 0
5019 +# PROP Target_Dir ""
5020 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5021 +# 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
5022 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5023 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5024 +# ADD BASE RSC /l 0x409 /d "NDEBUG"
5025 +# ADD RSC /l 0x409 /d "NDEBUG"
5026 +BSC32=bscmake.exe
5027 +# ADD BASE BSC32 /nologo
5028 +# ADD BSC32 /nologo
5029 +LINK32=link.exe
5030 +# 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
5031 +# 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"
5032 +
5033 +!ENDIF 
5034 +
5035 +# Begin Target
5036 +
5037 +# Name "apc - Win32 Debug_TS"
5038 +# Name "apc - Win32 Release_TS"
5039 +# Begin Group "Source Files"
5040 +
5041 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
5042 +# Begin Source File
5043 +
5044 +SOURCE=.\apc.c
5045 +# End Source File
5046 +# Begin Source File
5047 +
5048 +SOURCE=.\apc_cache.c
5049 +# End Source File
5050 +# Begin Source File
5051 +
5052 +SOURCE=.\apc_compile.c
5053 +# End Source File
5054 +# Begin Source File
5055 +
5056 +SOURCE=.\apc_debug.c
5057 +# End Source File
5058 +# Begin Source File
5059 +
5060 +SOURCE=.\apc_fcntl_win32.c
5061 +# End Source File
5062 +# Begin Source File
5063 +
5064 +SOURCE=.\apc_main.c
5065 +# End Source File
5066 +# Begin Source File
5067 +
5068 +SOURCE=.\apc_rfc1867.c
5069 +# End Source File
5070 +# Begin Source File
5071 +
5072 +SOURCE=.\apc_shm.c
5073 +# End Source File
5074 +# Begin Source File
5075 +
5076 +SOURCE=.\apc_sma.c
5077 +# End Source File
5078 +# Begin Source File
5079 +
5080 +SOURCE=.\apc_stack.c
5081 +# End Source File
5082 +# Begin Source File
5083 +
5084 +SOURCE=.\apc_zend.c
5085 +# End Source File
5086 +# Begin Source File
5087 +
5088 +SOURCE=.\php_apc.c
5089 +# End Source File
5090 +# End Group
5091 +# Begin Group "Header Files"
5092 +
5093 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
5094 +# Begin Source File
5095 +
5096 +SOURCE=.\apc.h
5097 +# End Source File
5098 +# Begin Source File
5099 +
5100 +SOURCE=.\apc_cache.h
5101 +# End Source File
5102 +# Begin Source File
5103 +
5104 +SOURCE=.\apc_compile.h
5105 +# End Source File
5106 +# Begin Source File
5107 +
5108 +SOURCE=.\apc_debug.h
5109 +# End Source File
5110 +# Begin Source File
5111 +
5112 +SOURCE=.\apc_fcntl.h
5113 +# End Source File
5114 +# Begin Source File
5115 +
5116 +SOURCE=.\apc_globals.h
5117 +# End Source File
5118 +# Begin Source File
5119 +
5120 +SOURCE=.\apc_lock.h
5121 +# End Source File
5122 +# Begin Source File
5123 +
5124 +SOURCE=.\apc_main.h
5125 +# End Source File
5126 +# Begin Source File
5127 +
5128 +SOURCE=.\apc_php.h
5129 +# End Source File
5130 +# Begin Source File
5131 +
5132 +SOURCE=.\apc_shm.h
5133 +# End Source File
5134 +# Begin Source File
5135 +
5136 +SOURCE=.\apc_sma.h
5137 +# End Source File
5138 +# Begin Source File
5139 +
5140 +SOURCE=.\apc_stack.h
5141 +# End Source File
5142 +# Begin Source File
5143 +
5144 +SOURCE=.\apc_zend.h
5145 +# End Source File
5146 +# Begin Source File
5147 +
5148 +SOURCE=.\php_apc.h
5149 +# End Source File
5150 +# End Group
5151 +# Begin Group "Resource Files"
5152 +
5153 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
5154 +# End Group
5155 +# End Target
5156 +# End Project
5157 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl.c php-5.1.6/ext/APC/apc_fcntl.c
5158 --- php-5.1.6.old/ext/apc/apc_fcntl.c   1969-12-31 18:00:00.000000000 -0600
5159 +++ php-5.1.6/ext/apc/apc_fcntl.c       2007-04-02 18:05:30.000000000 -0500
5160 @@ -0,0 +1,118 @@
5161 +/*
5162 +  +----------------------------------------------------------------------+
5163 +  | APC                                                                  |
5164 +  +----------------------------------------------------------------------+
5165 +  | Copyright (c) 2006 The PHP Group                                     |
5166 +  +----------------------------------------------------------------------+
5167 +  | This source file is subject to version 3.01 of the PHP license,      |
5168 +  | that is bundled with this package in the file LICENSE, and is        |
5169 +  | available through the world-wide-web at the following url:           |
5170 +  | http://www.php.net/license/3_01.txt                                  |
5171 +  | If you did not receive a copy of the PHP license and are unable to   |
5172 +  | obtain it through the world-wide-web, please send a note to          |
5173 +  | license@php.net so we can mail you a copy immediately.               |
5174 +  +----------------------------------------------------------------------+
5175 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5176 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5177 +  +----------------------------------------------------------------------+
5178 +
5179 +   This software was contributed to PHP by Community Connect Inc. in 2002
5180 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5181 +   Future revisions and derivatives of this source code must acknowledge
5182 +   Community Connect Inc. as the original contributor of this module by
5183 +   leaving this note intact in the source code.
5184 +
5185 +   All other licensing and usage conditions are those of the PHP Group.
5186 +
5187 + */
5188 +
5189 +/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
5190 +
5191 +#include "apc_fcntl.h"
5192 +#include "apc.h"
5193 +#include <unistd.h>
5194 +#include <fcntl.h>
5195 +
5196 +int apc_fcntl_create(const char* pathname)
5197 +{
5198 +    int fd;
5199 +    if(pathname == NULL) {
5200 +        char lock_path[] = "/tmp/.apc.XXXXXX";
5201 +        mktemp(lock_path);
5202 +        fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5203 +        if(fd > 0 ) {
5204 +            unlink(lock_path);
5205 +            return fd;
5206 +        } else {
5207 +            apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
5208 +            return -1;
5209 +        }
5210 +    }
5211 +    fd = open(pathname, O_RDWR|O_CREAT, 0666);
5212 +    if(fd > 0 ) {
5213 +        unlink(pathname);
5214 +        return fd;
5215 +    }
5216 +    apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
5217 +    return -1;
5218 +}
5219 +
5220 +void apc_fcntl_destroy(int fd)
5221 +{
5222 +    close(fd);
5223 +}
5224 +
5225 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5226 +{
5227 +  int ret;
5228 +  struct flock lock;
5229 +
5230 +  lock.l_type = type;
5231 +  lock.l_start = offset;
5232 +  lock.l_whence = whence;
5233 +  lock.l_len = len;
5234 +  lock.l_pid = 0;
5235 +
5236 +  do { ret = fcntl(fd, cmd, &lock) ; }
5237 +  while(ret < 0 && errno == EINTR);
5238 +  return(ret);
5239 +}
5240 +
5241 +void apc_fcntl_lock(int fd)
5242 +{
5243 +    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5244 +        apc_eprint("apc_fcntl_lock failed:");
5245 +    }
5246 +}
5247 +
5248 +void apc_fcntl_rdlock(int fd)
5249 +{
5250 +    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
5251 +        apc_eprint("apc_fcntl_rdlock failed:");
5252 +    }
5253 +}
5254 +
5255 +zend_bool apc_fcntl_nonblocking_lock(int fd)
5256 +{
5257 +    if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5258 +        if(errno==EACCES||errno==EAGAIN) return 0;
5259 +        else apc_eprint("apc_fcntl_lock failed:");
5260 +    }
5261 +    return 1;
5262 +}
5263 +
5264 +void apc_fcntl_unlock(int fd)
5265 +{
5266 +    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
5267 +        apc_eprint("apc_fcntl_unlock failed:");
5268 +    }
5269 +}
5270 +
5271 +/*
5272 + * Local variables:
5273 + * tab-width: 4
5274 + * c-basic-offset: 4
5275 + * End:
5276 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5277 + * vim<600: expandtab sw=4 ts=4 sts=4
5278 + */
5279 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl.h php-5.1.6/ext/APC/apc_fcntl.h
5280 --- php-5.1.6.old/ext/apc/apc_fcntl.h   1969-12-31 18:00:00.000000000 -0600
5281 +++ php-5.1.6/ext/apc/apc_fcntl.h       2007-04-02 18:05:30.000000000 -0500
5282 @@ -0,0 +1,50 @@
5283 +/*
5284 +  +----------------------------------------------------------------------+
5285 +  | APC                                                                  |
5286 +  +----------------------------------------------------------------------+
5287 +  | Copyright (c) 2006 The PHP Group                                     |
5288 +  +----------------------------------------------------------------------+
5289 +  | This source file is subject to version 3.01 of the PHP license,      |
5290 +  | that is bundled with this package in the file LICENSE, and is        |
5291 +  | available through the world-wide-web at the following url:           |
5292 +  | http://www.php.net/license/3_01.txt.                                 |
5293 +  | If you did not receive a copy of the PHP license and are unable to   |
5294 +  | obtain it through the world-wide-web, please send a note to          |
5295 +  | license@php.net so we can mail you a copy immediately.               |
5296 +  +----------------------------------------------------------------------+
5297 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5298 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5299 +  +----------------------------------------------------------------------+
5300 +
5301 +   This software was contributed to PHP by Community Connect Inc. in 2002
5302 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5303 +   Future revisions and derivatives of this source code must acknowledge
5304 +   Community Connect Inc. as the original contributor of this module by
5305 +   leaving this note intact in the source code.
5306 +
5307 +   All other licensing and usage conditions are those of the PHP Group.
5308 +
5309 + */
5310 +
5311 +/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
5312 +
5313 +#ifndef APC_FCNTL_H
5314 +#define APC_FCNTL_H
5315 +
5316 +
5317 +extern int apc_fcntl_create(const char* pathname);
5318 +extern void apc_fcntl_destroy(int fd);
5319 +extern void apc_fcntl_lock(int fd);
5320 +extern void apc_fcntl_rdlock(int fd);
5321 +extern void apc_fcntl_unlock(int fd);
5322 +extern unsigned char apc_fcntl_nonblocking_lock(int fd);
5323 +#endif
5324 +
5325 +/*
5326 + * Local variables:
5327 + * tab-width: 4
5328 + * c-basic-offset: 4
5329 + * End:
5330 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5331 + * vim<600: expandtab sw=4 ts=4 sts=4
5332 + */
5333 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl_win32.c php-5.1.6/ext/APC/apc_fcntl_win32.c
5334 --- php-5.1.6.old/ext/apc/apc_fcntl_win32.c     1969-12-31 18:00:00.000000000 -0600
5335 +++ php-5.1.6/ext/apc/apc_fcntl_win32.c 2007-04-02 18:05:30.000000000 -0500
5336 @@ -0,0 +1,117 @@
5337 +/*
5338 +  +----------------------------------------------------------------------+
5339 +  | APC                                                                  |
5340 +  +----------------------------------------------------------------------+
5341 +  | Copyright (c) 2006 The PHP Group                                     |
5342 +  +----------------------------------------------------------------------+
5343 +  | This source file is subject to version 3.01 of the PHP license,      |
5344 +  | that is bundled with this package in the file LICENSE, and is        |
5345 +  | available through the world-wide-web at the following url:           |
5346 +  | http://www.php.net/license/3_01.txt                                  |
5347 +  | If you did not receive a copy of the PHP license and are unable to   |
5348 +  | obtain it through the world-wide-web, please send a note to          |
5349 +  | license@php.net so we can mail you a copy immediately.               |
5350 +  +----------------------------------------------------------------------+
5351 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5352 +  |          Edin Kadribasic <edink@php.net>                             |
5353 +  +----------------------------------------------------------------------+
5354 +
5355 +   This software was contributed to PHP by Community Connect Inc. in 2002
5356 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5357 +   Future revisions and derivatives of this source code must acknowledge
5358 +   Community Connect Inc. as the original contributor of this module by
5359 +   leaving this note intact in the source code.
5360 +
5361 +   All other licensing and usage conditions are those of the PHP Group.
5362 +
5363 + */
5364 +
5365 +/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
5366 +
5367 +#include "apc_fcntl.h"
5368 +#include "apc.h"
5369 +#include <php.h>
5370 +#include <win32/flock.h>
5371 +#include <io.h>
5372 +#include <fcntl.h>
5373 +#include <sys/types.h>
5374 +#include <sys/stat.h>
5375 +
5376 +int apc_fcntl_create(const char* pathname)
5377 +{
5378 +       char *lock_file = emalloc(MAXPATHLEN);
5379 +       HANDLE fd;
5380 +       DWORD tmplen;
5381 +       static int i=0;
5382 +       
5383 +       tmplen = GetTempPath(MAXPATHLEN, lock_file);
5384 +       if (!tmplen) {
5385 +               efree(lock_file);
5386 +               return -1;
5387 +       }
5388 +
5389 +       snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
5390 +       
5391 +       fd = CreateFile(lock_file,
5392 +        GENERIC_READ | GENERIC_WRITE,
5393 +        FILE_SHARE_READ | FILE_SHARE_WRITE,
5394 +        NULL,
5395 +        OPEN_ALWAYS,
5396 +        FILE_ATTRIBUTE_NORMAL,
5397 +        NULL);
5398 +        
5399 +
5400 +       if (fd == INVALID_HANDLE_VALUE) {
5401 +               apc_eprint("apc_fcntl_create: could not open %s", lock_file);
5402 +               efree(lock_file);
5403 +               return -1;
5404 +       }
5405 +       
5406 +       efree(lock_file);
5407 +       return (int)fd;
5408 +}
5409 +
5410 +void apc_fcntl_destroy(int fd)
5411 +{
5412 +       CloseHandle((HANDLE)fd);
5413 +}
5414 +
5415 +void apc_fcntl_lock(int fd)
5416 +{
5417 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5418 +       
5419 +       if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
5420 +               apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
5421 +       }
5422 +}
5423 +
5424 +void apc_fcntl_rdlock(int fd)
5425 +{
5426 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5427 +       
5428 +       if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
5429 +               apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
5430 +       }
5431 +}
5432 +
5433 +void apc_fcntl_unlock(int fd)
5434 +{
5435 +       OVERLAPPED offset =     {0, 0, 0, 0, NULL};
5436 +
5437 +       if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
5438 +               DWORD error_code = GetLastError();
5439 +               /* Ignore already unlocked error */
5440 +               if (error_code != ERROR_NOT_LOCKED) {
5441 +                       apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
5442 +               }
5443 +       }
5444 +}
5445 +
5446 +/*
5447 + * Local variables:
5448 + * tab-width: 4
5449 + * c-basic-offset: 4
5450 + * End:
5451 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5452 + * vim<600: expandtab sw=4 ts=4 sts=4
5453 + */
5454 diff -ruN php-5.1.6.old/ext/apc/apc_futex.c php-5.1.6/ext/APC/apc_futex.c
5455 --- php-5.1.6.old/ext/apc/apc_futex.c   1969-12-31 18:00:00.000000000 -0600
5456 +++ php-5.1.6/ext/apc/apc_futex.c       2007-04-02 18:05:30.000000000 -0500
5457 @@ -0,0 +1,116 @@
5458 +/*
5459 +  +----------------------------------------------------------------------+
5460 +  | APC                                                                  |
5461 +  +----------------------------------------------------------------------+
5462 +  | Copyright (c) 2006 The PHP Group                                     |
5463 +  +----------------------------------------------------------------------+
5464 +  | This source file is subject to version 3.01 of the PHP license,      |
5465 +  | that is bundled with this package in the file LICENSE, and is        |
5466 +  | available through the world-wide-web at the following url:           |
5467 +  | http://www.php.net/license/3_01.txt                                  |
5468 +  | If you did not receive a copy of the PHP license and are unable to   |
5469 +  | obtain it through the world-wide-web, please send a note to          |
5470 +  | license@php.net so we can mail you a copy immediately.               |
5471 +  +----------------------------------------------------------------------+
5472 +  | Authors: Brian Shire <shire@php.net>                                 |
5473 +  +----------------------------------------------------------------------+
5474 +
5475 + */
5476 +
5477 +/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5478 +
5479 +/***************************************************************************
5480 +* Futex (Fast Userspace Mutex) support for APC
5481 +* 
5482 +* Futex support provides user space locking with system calls only
5483 +* for the contended cases.  Some required reading for this functionality is:
5484 +*
5485 +* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux' 
5486 +*  by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
5487 +*   http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
5488 +*
5489 +* 'Futexes are Tricky' by Ulrich Drepper 
5490 +*    http://people.redhat.com/drepper/futex.pdf
5491 +*
5492 +* 
5493 +* This implementation is optimized and designed for the i386 and x86_64 
5494 +* architectures.  Other architectures may require additional design 
5495 +* to efficiently and safely implement this functionality. 
5496 +*
5497 +* Lock values are:
5498 +* 0 = Unlocked
5499 +* 1 = Locked without any waiting processes
5500 +* 2 = Locked with an unknown number of waiting processes
5501 +*
5502 +***************************************************************************/
5503 +
5504 +#include "apc.h"
5505 +#include "apc_futex.h"
5506 +
5507 +#ifdef APC_FUTEX_LOCKS
5508 +
5509 +
5510 +inline int apc_futex_create()
5511 +{
5512 +    return 0;
5513 +}
5514 +
5515 +inline void apc_futex_destroy(volatile int* lock)
5516 +{
5517 +    return;
5518 +}
5519 +
5520 +void apc_futex_lock(volatile int* lock)
5521 +{
5522 +    int c;
5523 +  
5524 +    /*  Attempt to obtain a lock if not currently locked.  If the previous
5525 +     *  value was not 0 then we did not obtain the lock, and must wait.
5526 +     *  If the previous value was 1 (has no waiting processes) then we
5527 +     *  set the lock to 2 before blocking on the futex wait operation.  
5528 +     *  This implementation suffers from the possible difficulty of 
5529 +     *  efficently implementing the atomic xchg operation on some
5530 +     *  architectures, and could also cause unecessary wake operations by
5531 +     *  setting the lock to 2 when there are no additional waiters.
5532 +     */ 
5533 +    if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
5534 +        if(c != 2) {
5535 +            c = apc_xchg(lock, 2);
5536 +        }
5537 +        while(c != 0) {
5538 +            apc_futex_wait(lock, 2);
5539 +            c = apc_xchg(lock, 2);
5540 +        }
5541 +    }
5542 +    
5543 +}
5544 +
5545 +/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
5546 +inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
5547 +{
5548 +    return apc_cmpxchg(lock, 0, 1) == 0;
5549 +}
5550 +
5551 +
5552 +inline void apc_futex_unlock(volatile int* lock)
5553 +{
5554 +    /* set the lock to 0, if it's previous values was not 1 (no waiters)
5555 +     * then perform a wake operation on one process letting it know the lock 
5556 +     * is available.  This is an optimization to save wake calls if there
5557 +     * are no waiting processes for the lock 
5558 +     */
5559 +    if(apc_xchg(lock,0) != 1) {
5560 +        apc_futex_wake(lock, 1);
5561 +    }
5562 +}
5563 +
5564 +#endif
5565 +
5566 +/*
5567 + * Local variables:
5568 + * tab-width: 4
5569 + * c-basic-offset: 4
5570 + * End:
5571 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5572 + * vim<600: expandtab sw=4 ts=4 sts=4
5573 + */
5574 diff -ruN php-5.1.6.old/ext/apc/apc_futex.h php-5.1.6/ext/APC/apc_futex.h
5575 --- php-5.1.6.old/ext/apc/apc_futex.h   1969-12-31 18:00:00.000000000 -0600
5576 +++ php-5.1.6/ext/apc/apc_futex.h       2007-04-02 18:05:30.000000000 -0500
5577 @@ -0,0 +1,55 @@
5578 +/*
5579 +  +----------------------------------------------------------------------+
5580 +  | APC                                                                  |
5581 +  +----------------------------------------------------------------------+
5582 +  | Copyright (c) 2006 The PHP Group                                     |
5583 +  +----------------------------------------------------------------------+
5584 +  | This source file is subject to version 3.01 of the PHP license,      |
5585 +  | that is bundled with this package in the file LICENSE, and is        |
5586 +  | available through the world-wide-web at the following url:           |
5587 +  | http://www.php.net/license/3_01.txt                                  |
5588 +  | If you did not receive a copy of the PHP license and are unable to   |
5589 +  | obtain it through the world-wide-web, please send a note to          |
5590 +  | license@php.net so we can mail you a copy immediately.               |
5591 +  +----------------------------------------------------------------------+
5592 +  | Authors: Brian Shire <shire@php.net>                                 |
5593 +  +----------------------------------------------------------------------+
5594 +
5595 + */
5596 +
5597 +/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5598 +
5599 +#ifndef APC_FUTEX_H
5600 +#define APC_FUTEX_H
5601 +
5602 +#include "apc.h"
5603 +
5604 +#ifdef APC_FUTEX_LOCKS 
5605 +
5606 +#include <asm/types.h>
5607 +#include <unistd.h>
5608 +#include <linux/futex.h>
5609 +
5610 +#include "arch/atomic.h"
5611 +
5612 +#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
5613 +#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
5614 +#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
5615 +
5616 +int apc_futex_create();
5617 +void apc_futex_destroy(volatile int* lock);
5618 +void apc_futex_lock(volatile int* lock);
5619 +void apc_futex_unlock(volatile int* lock);
5620 +
5621 +#endif
5622 +
5623 +#endif
5624 +
5625 +/*
5626 + * Local variables:
5627 + * tab-width: 4
5628 + * c-basic-offset: 4
5629 + * End:
5630 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5631 + * vim<600: expandtab sw=4 ts=4 sts=4
5632 + */
5633 diff -ruN php-5.1.6.old/ext/apc/apc_globals.h php-5.1.6/ext/APC/apc_globals.h
5634 --- php-5.1.6.old/ext/apc/apc_globals.h 1969-12-31 18:00:00.000000000 -0600
5635 +++ php-5.1.6/ext/apc/apc_globals.h     2007-04-02 18:05:30.000000000 -0500
5636 @@ -0,0 +1,110 @@
5637 +/*
5638 +  +----------------------------------------------------------------------+
5639 +  | APC                                                                  |
5640 +  +----------------------------------------------------------------------+
5641 +  | Copyright (c) 2006 The PHP Group                                     |
5642 +  +----------------------------------------------------------------------+
5643 +  | This source file is subject to version 3.01 of the PHP license,      |
5644 +  | that is bundled with this package in the file LICENSE, and is        |
5645 +  | available through the world-wide-web at the following url:           |
5646 +  | http://www.php.net/license/3_01.txt.                                 |
5647 +  | If you did not receive a copy of the PHP license and are unable to   |
5648 +  | obtain it through the world-wide-web, please send a note to          |
5649 +  | license@php.net so we can mail you a copy immediately.               |
5650 +  +----------------------------------------------------------------------+
5651 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
5652 +  |          George Schlossnagle <george@omniti.com>                     |
5653 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5654 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
5655 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
5656 +  +----------------------------------------------------------------------+
5657 +
5658 +   This software was contributed to PHP by Community Connect Inc. in 2002
5659 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5660 +   Future revisions and derivatives of this source code must acknowledge
5661 +   Community Connect Inc. as the original contributor of this module by
5662 +   leaving this note intact in the source code.
5663 +
5664 +   All other licensing and usage conditions are those of the PHP Group.
5665 +
5666 + */
5667 +
5668 +/* $Id: apc_globals.h,v 3.59 2007/03/21 21:07:28 rasmus Exp $ */
5669 +
5670 +#ifndef APC_GLOBALS_H
5671 +#define APC_GLOBALS_H
5672 +
5673 +#define APC_VERSION "3.0.14"
5674 +
5675 +#include "apc_cache.h"
5676 +#include "apc_stack.h"
5677 +#include "apc_php.h"
5678 +
5679 +ZEND_BEGIN_MODULE_GLOBALS(apc)
5680 +    /* configuration parameters */
5681 +    zend_bool enabled;      /* if true, apc is enabled (defaults to true) */
5682 +    long shm_segments;      /* number of shared memory segments to use */
5683 +    long shm_size;          /* size of each shared memory segment (in MB) */
5684 +    long num_files_hint;    /* parameter to apc_cache_create */
5685 +    long user_entries_hint;
5686 +    long gc_ttl;            /* parameter to apc_cache_create */
5687 +    long ttl;               /* parameter to apc_cache_create */
5688 +    long user_ttl;
5689 +#if APC_MMAP
5690 +    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
5691 +#endif
5692 +    char** filters;         /* array of regex filters that prevent caching */
5693 +
5694 +    /* module variables */
5695 +    zend_bool initialized;       /* true if module was initialized */
5696 +    apc_stack_t* cache_stack;    /* the stack of cached executable code */
5697 +    zend_bool cache_by_default;  /* true if files should be cached unless filtered out */
5698 +                                 /* false if files should only be cached if filtered in */
5699 +    long slam_defense;           /* Probability of a process not caching an uncached file */
5700 +    size_t* mem_size_ptr;        /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
5701 +    long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
5702 +    zend_bool enable_cli;        /* Flag to override turning APC off for CLI */
5703 +    long max_file_size;                 /* Maximum size of file, in bytes that APC will be allowed to cache */
5704 +    long slam_rand;              /* A place to store the slam rand value for the request */
5705 +    zend_bool fpstat;            /* true if fullpath includes should be stat'ed */
5706 +    zend_bool stat_ctime;        /* true if ctime in addition to mtime should be checked */
5707 +    zend_bool write_lock;        /* true for a global write lock */
5708 +    zend_bool report_autofilter; /* true for auto-filter warnings */
5709 +    zend_bool include_once;         /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
5710 +    apc_optimize_function_t apc_optimize_function;   /* optimizer function callback */
5711 +#ifdef MULTIPART_EVENT_FORMDATA
5712 +    zend_bool rfc1867;           /* Flag to enable rfc1867 handler */
5713 +#endif
5714 +    HashTable *copied_zvals;     /* my_copy recursion detection list */
5715 +#ifdef ZEND_ENGINE_2
5716 +    int reserved_offset;         /* offset for apc info in op_array->reserved[] */
5717 +#endif
5718 +    zend_bool localcache;        /* enable local cache */
5719 +    long localcache_size;        /* size of fast cache */
5720 +    apc_local_cache_t* lcache;   /* unlocked local cache */
5721 +ZEND_END_MODULE_GLOBALS(apc)
5722 +
5723 +/* (the following declaration is defined in php_apc.c) */
5724 +ZEND_EXTERN_MODULE_GLOBALS(apc)
5725 +
5726 +#ifdef ZTS
5727 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
5728 +#else
5729 +# define APCG(v) (apc_globals.v)
5730 +#endif
5731 +
5732 +/* True globals */
5733 +extern apc_cache_t* apc_cache;       /* the global compiler cache */
5734 +extern apc_cache_t* apc_user_cache;  /* the global user content cache */
5735 +extern void* apc_compiled_filters;   /* compiled filters */
5736 +
5737 +#endif
5738 +
5739 +/*
5740 + * Local variables:
5741 + * tab-width: 4
5742 + * c-basic-offset: 4
5743 + * End:
5744 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5745 + * vim<600: expandtab sw=4 ts=4 sts=4
5746 + */
5747 diff -ruN php-5.1.6.old/ext/apc/apc.h php-5.1.6/ext/APC/apc.h
5748 --- php-5.1.6.old/ext/apc/apc.h 1969-12-31 18:00:00.000000000 -0600
5749 +++ php-5.1.6/ext/apc/apc.h     2007-04-02 18:05:30.000000000 -0500
5750 @@ -0,0 +1,126 @@
5751 +/*
5752 +  +----------------------------------------------------------------------+
5753 +  | APC                                                                  |
5754 +  +----------------------------------------------------------------------+
5755 +  | Copyright (c) 2006 The PHP Group                                     |
5756 +  +----------------------------------------------------------------------+
5757 +  | This source file is subject to version 3.01 of the PHP license,      |
5758 +  | that is bundled with this package in the file LICENSE, and is        |
5759 +  | available through the world-wide-web at the following url:           |
5760 +  | http://www.php.net/license/3_01.txt                                  |
5761 +  | If you did not receive a copy of the PHP license and are unable to   |
5762 +  | obtain it through the world-wide-web, please send a note to          |
5763 +  | license@php.net so we can mail you a copy immediately.               |
5764 +  +----------------------------------------------------------------------+
5765 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
5766 +  |          George Schlossnagle <george@omniti.com>                     |
5767 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5768 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
5769 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
5770 +  +----------------------------------------------------------------------+
5771 +
5772 +   This software was contributed to PHP by Community Connect Inc. in 2002
5773 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5774 +   Future revisions and derivatives of this source code must acknowledge
5775 +   Community Connect Inc. as the original contributor of this module by
5776 +   leaving this note intact in the source code.
5777 +
5778 +   All other licensing and usage conditions are those of the PHP Group.
5779 +
5780 + */
5781 +
5782 +/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
5783 +
5784 +#ifndef APC_H
5785 +#define APC_H
5786 +
5787 +/*
5788 + * This module defines utilities and helper functions used elsewhere in APC.
5789 + */
5790 +
5791 +/* Commonly needed C library headers. */
5792 +#include <assert.h>
5793 +#include <errno.h>
5794 +#include <stdarg.h>
5795 +#include <stdio.h>
5796 +#include <stdlib.h>
5797 +#include <string.h>
5798 +#include <time.h>
5799 +
5800 +/* UNIX headers (needed for struct stat) */
5801 +#include <sys/types.h>
5802 +#include <sys/stat.h>
5803 +#ifndef PHP_WIN32
5804 +#include <unistd.h>
5805 +#endif
5806 +
5807 +#ifdef HAVE_CONFIG_H
5808 +#include <config.h>
5809 +#endif
5810 +
5811 +#include "php.h"
5812 +
5813 +/* log levels constants (see apc_log) */
5814 +enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
5815 +
5816 +/* typedefs for extensible memory allocators */
5817 +typedef void* (*apc_malloc_t)(size_t);
5818 +typedef void  (*apc_free_t)  (void*);
5819 +
5820 +/* wrappers for memory allocation routines */
5821 +extern void* apc_emalloc(size_t n);
5822 +extern void* apc_erealloc(void* p, size_t n);
5823 +extern void apc_efree(void* p);
5824 +extern char* apc_estrdup(const char* s);
5825 +extern void* apc_xstrdup(const char* s, apc_malloc_t f);
5826 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
5827 +
5828 +/* console display functions */
5829 +extern void apc_log(int level, const char* fmt, ...);
5830 +extern void apc_eprint(const char* fmt, ...);
5831 +extern void apc_wprint(const char* fmt, ...);
5832 +extern void apc_dprint(const char* fmt, ...);
5833 +extern void apc_nprint(const char* fmt, ...);
5834 +
5835 +/* string and text manipulation */
5836 +extern char* apc_append(const char* s, const char* t);
5837 +extern char* apc_substr(const char* s, int start, int length);
5838 +extern char** apc_tokenize(const char* s, char delim);
5839 +
5840 +/* filesystem functions */
5841 +
5842 +typedef struct apc_fileinfo_t 
5843 +{
5844 +    char fullpath[MAXPATHLEN+1];
5845 +    struct stat st_buf;
5846 +} apc_fileinfo_t;
5847 +
5848 +#ifndef PHP_WIN32
5849 +#define apc_stat(f, b) stat(f, b)
5850 +#else
5851 +#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
5852 +extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
5853 +#endif
5854 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
5855 +
5856 +/* regular expression wrapper functions */
5857 +extern void* apc_regex_compile_array(char* patterns[]);
5858 +extern void apc_regex_destroy_array(void* p);
5859 +extern int apc_regex_match_array(void* p, const char* input);
5860 +
5861 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
5862 +extern unsigned int apc_crc32(const char* buf, int len);
5863 +
5864 +#define APC_NEGATIVE_MATCH 1
5865 +#define APC_POSITIVE_MATCH 2
5866 +
5867 +#endif
5868 +
5869 +/*
5870 + * Local variables:
5871 + * tab-width: 4
5872 + * c-basic-offset: 4
5873 + * End:
5874 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5875 + * vim<600: expandtab sw=4 ts=4 sts=4
5876 + */
5877 diff -ruN php-5.1.6.old/ext/apc/apc_lock.h php-5.1.6/ext/APC/apc_lock.h
5878 --- php-5.1.6.old/ext/apc/apc_lock.h    1969-12-31 18:00:00.000000000 -0600
5879 +++ php-5.1.6/ext/apc/apc_lock.h        2007-04-02 18:05:30.000000000 -0500
5880 @@ -0,0 +1,105 @@
5881 +/*
5882 +  +----------------------------------------------------------------------+
5883 +  | APC                                                                  |
5884 +  +----------------------------------------------------------------------+
5885 +  | Copyright (c) 2006 The PHP Group                                     |
5886 +  +----------------------------------------------------------------------+
5887 +  | This source file is subject to version 3.01 of the PHP license,      |
5888 +  | that is bundled with this package in the file LICENSE, and is        |
5889 +  | available through the world-wide-web at the following url:           |
5890 +  | http://www.php.net/license/3_01.txt                                  |
5891 +  | If you did not receive a copy of the PHP license and are unable to   |
5892 +  | obtain it through the world-wide-web, please send a note to          |
5893 +  | license@php.net so we can mail you a copy immediately.               |
5894 +  +----------------------------------------------------------------------+
5895 +  | Authors: George Schlossnagle <george@omniti.com>                     |
5896 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
5897 +  +----------------------------------------------------------------------+
5898 +
5899 +   This software was contributed to PHP by Community Connect Inc. in 2002
5900 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5901 +   Future revisions and derivatives of this source code must acknowledge
5902 +   Community Connect Inc. as the original contributor of this module by
5903 +   leaving this note intact in the source code.
5904 +
5905 +   All other licensing and usage conditions are those of the PHP Group.
5906 +
5907 + */
5908 +
5909 +/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
5910 +
5911 +#ifndef APC_LOCK
5912 +#define APC_LOCK
5913 +
5914 +#include "apc_sem.h"
5915 +#include "apc_fcntl.h"
5916 +#include "apc_pthreadmutex.h"
5917 +#include "apc_futex.h"
5918 +#include "apc_spin.h"
5919 +#ifdef HAVE_CONFIG_H
5920 +#include <config.h>
5921 +#endif
5922 +
5923 +#ifdef TSRM_LOCKS
5924 +#define RDLOCK_AVAILABLE 0
5925 +#define NONBLOCKING_LOCK_AVAILABLE 0
5926 +/* quick & dirty: use TSRM mutex locks for now */
5927 +#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
5928 +#define apc_lck_destroy(a)    tsrm_mutex_free((MUTEX_T)a)
5929 +#define apc_lck_lock(a)       tsrm_mutex_lock((MUTEX_T)a)
5930 +#define apc_lck_rdlock(a)     tsrm_mutex_lock((MUTEX_T)a)
5931 +#define apc_lck_unlock(a)     tsrm_mutex_unlock((MUTEX_T)a)
5932 +#elif defined(APC_SEM_LOCKS)
5933 +#define RDLOCK_AVAILABLE 0
5934 +#define NONBLOCKING_LOCK_AVAILABLE 0
5935 +#define apc_lck_t int
5936 +#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
5937 +#define apc_lck_destroy(a)    apc_sem_destroy(a)
5938 +#define apc_lck_lock(a)       apc_sem_lock(a)
5939 +#define apc_lck_rdlock(a)     apc_sem_lock(a)
5940 +#define apc_lck_unlock(a)     apc_sem_unlock(a)
5941 +#elif defined(APC_PTHREADMUTEX_LOCKS)
5942 +#define RDLOCK_AVAILABLE 0
5943 +#define NONBLOCKING_LOCK_AVAILABLE 1
5944 +#define apc_lck_t pthread_mutex_t 
5945 +#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
5946 +#define apc_lck_destroy(a)    apc_pthreadmutex_destroy(&a)
5947 +#define apc_lck_lock(a)       apc_pthreadmutex_lock(&a)
5948 +#define apc_lck_nb_lock(a)    apc_pthreadmutex_nonblocking_lock(&a)
5949 +#define apc_lck_rdlock(a)     apc_pthreadmutex_lock(&a)
5950 +#define apc_lck_unlock(a)     apc_pthreadmutex_unlock(&a)
5951 +#elif defined(APC_FUTEX_LOCKS)
5952 +#define NONBLOCKING_LOCK_AVAILABLE 1 
5953 +#define apc_lck_t int 
5954 +#define apc_lck_create(a,b,c,d) d=apc_futex_create()
5955 +#define apc_lck_destroy(a)    apc_futex_destroy(&a)
5956 +#define apc_lck_lock(a)       apc_futex_lock(&a)
5957 +#define apc_lck_nb_lock(a)    apc_futex_nonblocking_lock(&a)
5958 +#define apc_lck_rdlock(a)     apc_futex_lock(&a)
5959 +#define apc_lck_unlock(a)     apc_futex_unlock(&a)
5960 +#elif defined(APC_SPIN_LOCKS)
5961 +#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
5962 +#define apc_lck_t slock_t 
5963 +#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
5964 +#define apc_lck_destroy(a)    apc_slock_destroy(&a)
5965 +#define apc_lck_lock(a)       apc_slock_lock(&a)
5966 +#define apc_lck_nb_lock(a)    apc_slock_nonblocking_lock(&a)
5967 +#define apc_lck_rdlock(a)     apc_slock_lock(&a)
5968 +#define apc_lck_unlock(a)     apc_slock_unlock(&a)
5969 +#else
5970 +#define RDLOCK_AVAILABLE 1
5971 +#ifdef PHP_WIN32
5972 +#define NONBLOCKING_LOCK_AVAILABLE 0
5973 +#else
5974 +#define NONBLOCKING_LOCK_AVAILABLE 1
5975 +#endif
5976 +#define apc_lck_t int
5977 +#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
5978 +#define apc_lck_destroy(a)    apc_fcntl_destroy(a)
5979 +#define apc_lck_lock(a)       apc_fcntl_lock(a)
5980 +#define apc_lck_nb_lock(a)    apc_fcntl_nonblocking_lock(a)
5981 +#define apc_lck_rdlock(a)     apc_fcntl_rdlock(a)
5982 +#define apc_lck_unlock(a)     apc_fcntl_unlock(a)
5983 +#endif
5984 +
5985 +#endif
5986 diff -ruN php-5.1.6.old/ext/apc/apc_main.c php-5.1.6/ext/APC/apc_main.c
5987 --- php-5.1.6.old/ext/apc/apc_main.c    1969-12-31 18:00:00.000000000 -0600
5988 +++ php-5.1.6/ext/apc/apc_main.c        2007-04-02 18:05:30.000000000 -0500
5989 @@ -0,0 +1,681 @@
5990 +/*
5991 +  +----------------------------------------------------------------------+
5992 +  | APC                                                                  |
5993 +  +----------------------------------------------------------------------+
5994 +  | Copyright (c) 2006 The PHP Group                                     |
5995 +  +----------------------------------------------------------------------+
5996 +  | This source file is subject to version 3.01 of the PHP license,      |
5997 +  | that is bundled with this package in the file LICENSE, and is        |
5998 +  | available through the world-wide-web at the following url:           |
5999 +  | http://www.php.net/license/3_01.txt                                  |
6000 +  | If you did not receive a copy of the PHP license and are unable to   |
6001 +  | obtain it through the world-wide-web, please send a note to          |
6002 +  | license@php.net so we can mail you a copy immediately.               |
6003 +  +----------------------------------------------------------------------+
6004 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
6005 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6006 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
6007 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
6008 +  +----------------------------------------------------------------------+
6009 +
6010 +   This software was contributed to PHP by Community Connect Inc. in 2002
6011 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6012 +   Future revisions and derivatives of this source code must acknowledge
6013 +   Community Connect Inc. as the original contributor of this module by
6014 +   leaving this note intact in the source code.
6015 +
6016 +   All other licensing and usage conditions are those of the PHP Group.
6017 +
6018 + */
6019 +
6020 +/* $Id: apc_main.c,v 3.97 2007/03/22 16:03:59 gopalv Exp $ */
6021 +
6022 +#include "apc_php.h"
6023 +#include "apc_main.h"
6024 +#include "apc.h"
6025 +#include "apc_lock.h"
6026 +#include "apc_cache.h"
6027 +#include "apc_compile.h"
6028 +#include "apc_globals.h"
6029 +#include "apc_sma.h"
6030 +#include "apc_stack.h"
6031 +#include "apc_zend.h"
6032 +#include "SAPI.h"
6033 +#if PHP_API_VERSION <= 20020918
6034 +#if HAVE_APACHE
6035 +#ifdef APC_PHP4_STAT
6036 +#undef XtOffsetOf
6037 +#include "httpd.h"
6038 +#endif
6039 +#endif
6040 +#endif
6041 +
6042 +/* {{{ module variables */
6043 +
6044 +/* pointer to the original Zend engine compile_file function */
6045 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
6046 +static zend_compile_t *old_compile_file;
6047 +
6048 +/* }}} */
6049 +
6050 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
6051 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
6052 +{
6053 +    zend_compile_t *retval = old_compile_file;
6054 +
6055 +    if (ptr != NULL) old_compile_file = ptr;
6056 +    return retval;
6057 +}
6058 +/* }}} */
6059 +
6060 +/* {{{ install_function */
6061 +static int install_function(apc_function_t fn TSRMLS_DC)
6062 +{
6063 +    int status =
6064 +        zend_hash_add(EG(function_table),
6065 +                      fn.name,
6066 +                      fn.name_len+1,
6067 +                      apc_copy_function_for_execution(fn.function),
6068 +                      sizeof(fn.function[0]),
6069 +                      NULL);
6070 +
6071 +    if (status == FAILURE) {
6072 +        /* apc_eprint("Cannot redeclare %s()", fn.name); */
6073 +    }
6074 +
6075 +    return status;
6076 +}
6077 +/* }}} */
6078 +
6079 +/* {{{ install_class */
6080 +static int install_class(apc_class_t cl TSRMLS_DC)
6081 +{
6082 +    zend_class_entry* class_entry = cl.class_entry;
6083 +    zend_class_entry* parent = NULL;
6084 +    int status;
6085 +#ifdef ZEND_ENGINE_2
6086 +    zend_class_entry** allocated_ce = NULL;
6087 +#endif
6088 +
6089 +
6090 +    /* Special case for mangled names. Mangled names are unique to a file.
6091 +     * There is no way two classes with the same mangled name will occur,
6092 +     * unless a file is included twice. And if in case, a file is included
6093 +     * twice, all mangled name conflicts can be ignored and the class redeclaration
6094 +     * error may be deferred till runtime of the corresponding DECLARE_CLASS
6095 +     * calls.
6096 +     */
6097 +
6098 +    if(cl.name_len != 0 && cl.name[0] == '\0') {
6099 +        if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
6100 +            return SUCCESS;
6101 +        }
6102 +    }
6103 +    
6104 +#ifdef ZEND_ENGINE_2    
6105 +    /*
6106 +     * XXX: We need to free this somewhere...
6107 +     */
6108 +    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));    
6109 +
6110 +    if(!allocated_ce) {
6111 +        return FAILURE;
6112 +    }
6113 +
6114 +    *allocated_ce = 
6115 +#endif        
6116 +    class_entry =
6117 +        apc_copy_class_entry_for_execution(cl.class_entry,
6118 +                                           cl.is_derived);
6119 +
6120 +
6121 +    /* restore parent class pointer for compile-time inheritance */
6122 +    if (cl.parent_name != NULL) {
6123 +#ifdef ZEND_ENGINE_2    
6124 +        zend_class_entry** parent_ptr = NULL;
6125 +        /*
6126 +         * zend_lookup_class has to be due to presence of __autoload, 
6127 +         * just looking up the EG(class_table) is not enough in php5!
6128 +         * Even more dangerously, thanks to __autoload and people using
6129 +         * class names as filepaths for inclusion, this has to be case
6130 +         * sensitive. zend_lookup_class automatically does a case_fold
6131 +         * internally, but passes the case preserved version to __autoload.
6132 +         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because 
6133 +         * zend_lookup_class does it internally anyway!
6134 +         */
6135 +        status = zend_lookup_class(cl.parent_name,
6136 +                                    strlen(cl.parent_name),
6137 +                                    &parent_ptr TSRMLS_CC);
6138 +#else
6139 +        status = zend_hash_find(EG(class_table),
6140 +                                cl.parent_name,
6141 +                                strlen(cl.parent_name)+1,
6142 +                                (void**) &parent);
6143 +#endif
6144 +        if (status == FAILURE) {
6145 +            if(APCG(report_autofilter)) {
6146 +                apc_wprint("Dynamic inheritance detected for class %s", cl.name);
6147 +            }
6148 +            class_entry->parent = NULL;
6149 +            return status;
6150 +        }
6151 +        else {
6152 +#ifdef ZEND_ENGINE_2            
6153 +            parent = *parent_ptr;
6154 +#endif 
6155 +            class_entry->parent = parent;
6156 +#ifdef ZEND_ENGINE_2
6157 +            zend_do_inheritance(class_entry, parent TSRMLS_CC);
6158 +#else
6159 +            zend_do_inheritance(class_entry, parent);
6160 +#endif
6161 +        }
6162 +
6163 +
6164 +    }
6165 +
6166 +#ifdef ZEND_ENGINE_2                           
6167 +    status = zend_hash_add(EG(class_table),
6168 +                           cl.name,
6169 +                           cl.name_len+1,
6170 +                           allocated_ce,
6171 +                           sizeof(zend_class_entry*),
6172 +                           NULL);
6173 +#else                           
6174 +    status = zend_hash_add(EG(class_table),
6175 +                           cl.name,
6176 +                           cl.name_len+1,
6177 +                           class_entry,
6178 +                           sizeof(zend_class_entry),
6179 +                           NULL);
6180 +#endif                           
6181 +
6182 +    if (status == FAILURE) {
6183 +        apc_eprint("Cannot redeclare class %s", cl.name);
6184 +    } 
6185 +    return status;
6186 +}
6187 +/* }}} */
6188 +
6189 +/* {{{ uninstall_class */
6190 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
6191 +{
6192 +    int status;
6193 +
6194 +#ifdef ZEND_ENGINE_2                           
6195 +    status = zend_hash_del(EG(class_table),
6196 +                           cl.name,
6197 +                           cl.name_len+1);
6198 +#else                           
6199 +    status = zend_hash_del(EG(class_table),
6200 +                           cl.name,
6201 +                           cl.name_len+1);
6202 +#endif                           
6203 +    if (status == FAILURE) {
6204 +        apc_eprint("Cannot delete class %s", cl.name);
6205 +    } 
6206 +    return status;
6207 +}
6208 +/* }}} */
6209 +
6210 +/* {{{ compare_file_handles */
6211 +static int compare_file_handles(void* a, void* b)
6212 +{
6213 +    zend_file_handle* fh1 = (zend_file_handle*)a;
6214 +    zend_file_handle* fh2 = (zend_file_handle*)b;
6215 +    return (fh1->type == fh2->type && 
6216 +            fh1->filename == fh2->filename &&
6217 +            fh1->opened_path == fh2->opened_path);
6218 +}
6219 +/* }}} */
6220 +
6221 +/* {{{ cached_compile */
6222 +static zend_op_array* cached_compile(zend_file_handle* h,
6223 +                                        int type TSRMLS_DC)
6224 +{
6225 +    apc_cache_entry_t* cache_entry;
6226 +    int i, ii;
6227 +
6228 +    cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
6229 +    assert(cache_entry != NULL);
6230 +
6231 +    if (cache_entry->data.file.classes) {
6232 +        for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6233 +            if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
6234 +                goto default_compile;
6235 +            }
6236 +        }
6237 +    }
6238 +
6239 +    if (cache_entry->data.file.functions) {
6240 +        for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6241 +            install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
6242 +        }
6243 +    }
6244 +
6245 +
6246 +    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
6247 +
6248 +default_compile:
6249 +
6250 +    cache_entry->autofiltered = 1;
6251 +    if(APCG(report_autofilter)) {
6252 +        apc_wprint("Autofiltering %s", h->opened_path);
6253 +    }
6254 +
6255 +    if(cache_entry->data.file.classes) {
6256 +        for(ii = 0; ii < i ; ii++) {
6257 +            uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
6258 +        }
6259 +    }
6260 +    
6261 +    apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
6262 +
6263 +    /* cannot free up cache data yet, it maybe in use */
6264 +    
6265 +    zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
6266 +    
6267 +    h->type = ZEND_HANDLE_FILENAME;
6268 +    
6269 +    return old_compile_file(h, type TSRMLS_CC);
6270 +}
6271 +/* }}} */
6272 +
6273 +/* {{{ my_compile_file
6274 +   Overrides zend_compile_file */
6275 +static zend_op_array* my_compile_file(zend_file_handle* h,
6276 +                                               int type TSRMLS_DC)
6277 +{
6278 +    apc_cache_key_t key;
6279 +    apc_cache_entry_t* cache_entry;
6280 +    zend_op_array* op_array;
6281 +    int num_functions, num_classes, ret;
6282 +    zend_op_array* alloc_op_array;
6283 +    apc_function_t* alloc_functions;
6284 +    apc_class_t* alloc_classes;
6285 +    time_t t;
6286 +    char *path;
6287 +    size_t mem_size;
6288 +
6289 +    if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
6290 +               return old_compile_file(h, type TSRMLS_CC);
6291 +       }
6292 +
6293 +    /* check our regular expression filters */
6294 +    if (APCG(filters) && apc_compiled_filters) {
6295 +        int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
6296 +        if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
6297 +            return old_compile_file(h, type TSRMLS_CC);
6298 +        }
6299 +    } else if(!APCG(cache_by_default)) {
6300 +        return old_compile_file(h, type TSRMLS_CC);
6301 +    }
6302 +
6303 +#if PHP_API_VERSION <= 20041225
6304 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
6305 +    t = ((request_rec *)SG(server_context))->request_time;
6306 +#else 
6307 +    t = time(0);
6308 +#endif
6309 +#else 
6310 +    t = sapi_get_request_time(TSRMLS_C);
6311 +#endif
6312 +
6313 +#ifdef __DEBUG_APC__
6314 +    fprintf(stderr,"1. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6315 +#endif
6316 +
6317 +    /* try to create a cache key; if we fail, give up on caching */
6318 +    if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
6319 +        return old_compile_file(h, type TSRMLS_CC);
6320 +    }
6321 +
6322 +    if(APCG(localcache)) {
6323 +        /* search for the file in the local cache */
6324 +        cache_entry = apc_local_cache_find(APCG(lcache), key, t);
6325 +    } else {
6326 +        /* search for the file in the cache */
6327 +        cache_entry = apc_cache_find(apc_cache, key, t);
6328 +    }
6329 +
6330 +    if (cache_entry != NULL && !cache_entry->autofiltered) {
6331 +        int dummy = 1;
6332 +        if (h->opened_path == NULL) {
6333 +            h->opened_path = estrdup(cache_entry->data.file.filename);
6334 +        }
6335 +        zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
6336 +        zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
6337 +        apc_stack_push(APCG(cache_stack), cache_entry);
6338 +        return cached_compile(h, type TSRMLS_CC);
6339 +    }
6340 +    else if(cache_entry != NULL && cache_entry->autofiltered) {
6341 +        /* nobody else is using this cache_entry */ 
6342 +        if(cache_entry->ref_count == 1) {
6343 +            if(cache_entry->data.file.op_array) {
6344 +                apc_free_op_array(cache_entry->data.file.op_array, apc_sma_free);
6345 +                cache_entry->data.file.op_array = NULL;
6346 +            }
6347 +            if(cache_entry->data.file.functions) {
6348 +                apc_free_functions(cache_entry->data.file.functions, apc_sma_free);
6349 +                cache_entry->data.file.functions = NULL;
6350 +            }
6351 +            if(cache_entry->data.file.classes) {
6352 +                apc_free_classes(cache_entry->data.file.classes, apc_sma_free);
6353 +                cache_entry->data.file.classes = NULL;        
6354 +            }
6355 +        }
6356 +        /* We never push this into the cache_stack, so we have to do a release */
6357 +        apc_cache_release(apc_cache, cache_entry);
6358 +        return old_compile_file(h, type TSRMLS_CC);
6359 +    }
6360 +    
6361 +    if(apc_cache_busy(apc_cache) && APCG(localcache)) {
6362 +        /* possibly local cache returned NULL because cache is busy */
6363 +               return old_compile_file(h, type TSRMLS_CC);
6364 +       }
6365 +
6366 +    /* remember how many functions and classes existed before compilation */
6367 +    num_functions = zend_hash_num_elements(CG(function_table));
6368 +    num_classes   = zend_hash_num_elements(CG(class_table));
6369 +    
6370 +    /* compile the file using the default compile function */
6371 +    op_array = old_compile_file(h, type TSRMLS_CC);
6372 +    if (op_array == NULL) {
6373 +        return NULL;
6374 +    }
6375 +    /*
6376 +     * Basically this will cause a file only to be cached on a percentage 
6377 +     * of the attempts.  This is to avoid cache slams when starting up a
6378 +     * very busy server or when modifying files on a very busy live server.
6379 +     * There is no point having many processes all trying to cache the same
6380 +     * file at the same time.  By introducing a chance of being cached
6381 +     * we theoretically cut the cache slam problem by the given percentage.
6382 +     * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
6383 +     * to cache an uncached file will be ignored.
6384 +     */
6385 +    if(APCG(slam_defense)) {
6386 +        if(APCG(slam_rand)==-1) {
6387 +            APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
6388 +        }
6389 +        if(APCG(slam_rand) < APCG(slam_defense)) {
6390 +            return op_array;
6391 +        }
6392 +    }
6393 +
6394 +    HANDLE_BLOCK_INTERRUPTIONS();
6395 +
6396 +#if NONBLOCKING_LOCK_AVAILABLE
6397 +    if(APCG(write_lock)) {
6398 +        if(!apc_cache_write_lock(apc_cache)) {
6399 +            HANDLE_UNBLOCK_INTERRUPTIONS();
6400 +            return op_array;
6401 +        }
6402 +    }
6403 +#endif
6404 +
6405 +    mem_size = 0;
6406 +    APCG(mem_size_ptr) = &mem_size;
6407 +    if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6408 +        apc_cache_expunge(apc_cache,t);
6409 +        apc_cache_expunge(apc_user_cache,t);
6410 +        APCG(mem_size_ptr) = NULL;
6411 +#if NONBLOCKING_LOCK_AVAILABLE
6412 +        if(APCG(write_lock)) {
6413 +            apc_cache_write_unlock(apc_cache);
6414 +        }
6415 +#endif
6416 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6417 +        return op_array;
6418 +    }
6419 +    
6420 +    if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6421 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6422 +        apc_cache_expunge(apc_cache,t);
6423 +        apc_cache_expunge(apc_user_cache,t);
6424 +        APCG(mem_size_ptr) = NULL;
6425 +#if NONBLOCKING_LOCK_AVAILABLE
6426 +        if(APCG(write_lock)) {
6427 +            apc_cache_write_unlock(apc_cache);
6428 +        }
6429 +#endif
6430 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6431 +        return op_array;
6432 +    }
6433 +    if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6434 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6435 +        apc_free_functions(alloc_functions, apc_sma_free);
6436 +        apc_cache_expunge(apc_cache,t);
6437 +        apc_cache_expunge(apc_user_cache,t);
6438 +        APCG(mem_size_ptr) = NULL;
6439 +#if NONBLOCKING_LOCK_AVAILABLE
6440 +        if(APCG(write_lock)) {
6441 +            apc_cache_write_unlock(apc_cache);
6442 +        }
6443 +#endif
6444 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6445 +        return op_array;
6446 +    }
6447 +
6448 +    path = h->opened_path;
6449 +    if(!path) path=h->filename;
6450 +
6451 +#ifdef __DEBUG_APC__
6452 +    fprintf(stderr,"2. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6453 +#endif
6454 +
6455 +    if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
6456 +        apc_free_op_array(alloc_op_array, apc_sma_free);
6457 +        apc_free_functions(alloc_functions, apc_sma_free);
6458 +        apc_free_classes(alloc_classes, apc_sma_free);
6459 +        apc_cache_expunge(apc_cache,t);
6460 +        apc_cache_expunge(apc_user_cache,t);
6461 +        APCG(mem_size_ptr) = NULL;
6462 +#if NONBLOCKING_LOCK_AVAILABLE
6463 +        if(APCG(write_lock)) {
6464 +            apc_cache_write_unlock(apc_cache);
6465 +        }
6466 +#endif
6467 +        HANDLE_UNBLOCK_INTERRUPTIONS();
6468 +        return op_array;
6469 +    }
6470 +    APCG(mem_size_ptr) = NULL;
6471 +    cache_entry->mem_size = mem_size;
6472 +
6473 +    if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
6474 +        apc_cache_free_entry(cache_entry);
6475 +        if(ret==-1) {
6476 +            apc_cache_expunge(apc_cache,t);
6477 +            apc_cache_expunge(apc_user_cache,t);
6478 +        }
6479 +    }
6480 +
6481 +#if NONBLOCKING_LOCK_AVAILABLE
6482 +    if(APCG(write_lock)) {
6483 +        apc_cache_write_unlock(apc_cache);
6484 +    }
6485 +#endif
6486 +    HANDLE_UNBLOCK_INTERRUPTIONS();
6487 +
6488 +    return op_array;
6489 +}
6490 +/* }}} */
6491 +
6492 +/* {{{ module init and shutdown */
6493 +
6494 +int apc_module_init(int module_number TSRMLS_DC)
6495 +{
6496 +    /* apc initialization */
6497 +#if APC_MMAP
6498 +    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
6499 +#else
6500 +    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
6501 +#endif
6502 +    apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
6503 +    apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
6504 +
6505 +    apc_compiled_filters = apc_regex_compile_array(APCG(filters));
6506 +
6507 +    /* override compilation */
6508 +    old_compile_file = zend_compile_file;
6509 +    zend_compile_file = my_compile_file;
6510 +    REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
6511 +
6512 +    APCG(initialized) = 1;
6513 +    return 0;
6514 +}
6515 +
6516 +int apc_module_shutdown(TSRMLS_D)
6517 +{
6518 +    if (!APCG(initialized))
6519 +        return 0;
6520 +
6521 +    /* restore compilation */
6522 +    zend_compile_file = old_compile_file;
6523 +
6524 +    /* 
6525 +     * In case we got interrupted by a SIGTERM or something else during execution
6526 +     * we may have cache entries left on the stack that we need to check to make
6527 +     * sure that any functions or classes these may have added to the global function
6528 +     * and class tables are removed before we blow away the memory that hold them.
6529 +     * 
6530 +     * This is merely to remove memory leak warnings - as the process is terminated
6531 +     * immediately after shutdown. The following while loop can be removed without
6532 +     * affecting anything else.
6533 +     */
6534 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
6535 +        int i;
6536 +        apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6537 +        if (cache_entry->data.file.functions) {
6538 +            for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6539 +                zend_hash_del(EG(function_table),
6540 +                    cache_entry->data.file.functions[i].name,
6541 +                    cache_entry->data.file.functions[i].name_len+1);
6542 +            }
6543 +        }
6544 +        if (cache_entry->data.file.classes) {
6545 +            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6546 +                zend_hash_del(EG(class_table),
6547 +                    cache_entry->data.file.classes[i].name,
6548 +                    cache_entry->data.file.classes[i].name_len+1);
6549 +            }
6550 +        }
6551 +        apc_cache_release(apc_cache, cache_entry);
6552 +    }
6553 +
6554 +    apc_cache_destroy(apc_cache);
6555 +    apc_cache_destroy(apc_user_cache);
6556 +    apc_sma_cleanup();
6557 +
6558 +    APCG(initialized) = 0;
6559 +    return 0;
6560 +}
6561 +
6562 +/* }}} */
6563 +
6564 +/* {{{ process init and shutdown */
6565 +int apc_process_init(int module_number TSRMLS_DC)
6566 +{
6567 +    int minttl = (APCG(gc_ttl) >  APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
6568 +    int size = APCG(localcache_size);
6569 +    if(APCG(initialized) && APCG(localcache)) {
6570 +        /* TTL is 2 mins by default */
6571 +        APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120); 
6572 +    }
6573 +    return 0;
6574 +}
6575 +
6576 +int apc_process_shutdown(TSRMLS_D)
6577 +{
6578 +    if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
6579 +        apc_local_cache_destroy(APCG(lcache));
6580 +        APCG(lcache) = NULL;
6581 +    }
6582 +       return 0;
6583 +}
6584 +/* }}} */
6585 +
6586 +/* {{{ request init and shutdown */
6587 +
6588 +int apc_request_init(TSRMLS_D)
6589 +{
6590 +    apc_stack_clear(APCG(cache_stack));
6591 +    APCG(slam_rand) = -1;
6592 +    APCG(copied_zvals) = NULL;
6593 +    return 0;
6594 +}
6595 +
6596 +int apc_request_shutdown(TSRMLS_D)
6597 +{
6598 +    apc_deactivate(TSRMLS_C);
6599 +    return 0;
6600 +}
6601 +
6602 +/* }}} */
6603 +
6604 +/* {{{ apc_deactivate */
6605 +void apc_deactivate(TSRMLS_D)
6606 +{
6607 +    /* The execution stack was unwound, which prevented us from decrementing
6608 +     * the reference counts on active cache entries in `my_execute`.
6609 +     */
6610 +    while (apc_stack_size(APCG(cache_stack)) > 0) {
6611 +        int i;
6612 +        zend_class_entry* zce = NULL;
6613 +        void ** centry = (void*)(&zce);
6614 +#ifdef ZEND_ENGINE_2
6615 +        zend_class_entry** pzce = NULL;
6616 +#endif
6617 +        
6618 +        apc_cache_entry_t* cache_entry =
6619 +            (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6620 +
6621 +        if (cache_entry->data.file.functions) {
6622 +            for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6623 +                zend_hash_del(EG(function_table),
6624 +                    cache_entry->data.file.functions[i].name,
6625 +                    cache_entry->data.file.functions[i].name_len+1);
6626 +            }
6627 +        }
6628 +
6629 +        if (cache_entry->data.file.classes) {
6630 +            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6631 +#ifdef ZEND_ENGINE_2
6632 +                centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
6633 +#endif
6634 +                if(zend_hash_find(EG(class_table), 
6635 +                    cache_entry->data.file.classes[i].name,
6636 +                    cache_entry->data.file.classes[i].name_len+1,
6637 +                    (void**)centry) == FAILURE)
6638 +                {
6639 +                    /* double inclusion of conditional classes ends up failing 
6640 +                     * this lookup the second time around.
6641 +                     */
6642 +                    continue;
6643 +                }
6644 +
6645 +#ifdef ZEND_ENGINE_2
6646 +                zce = *pzce;
6647 +#endif
6648 +                zend_hash_del(EG(class_table),
6649 +                    cache_entry->data.file.classes[i].name,
6650 +                    cache_entry->data.file.classes[i].name_len+1);
6651 +                
6652 +                apc_free_class_entry_after_execution(zce);
6653 +            }
6654 +        }
6655 +        apc_cache_release(apc_cache, cache_entry);
6656 +    }
6657 +    if(APCG(localcache)) {
6658 +        apc_local_cache_cleanup(APCG(lcache)); 
6659 +    }
6660 +}
6661 +/* }}} */
6662 +
6663 +/*
6664 + * Local variables:
6665 + * tab-width: 4
6666 + * c-basic-offset: 4
6667 + * End:
6668 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6669 + * vim<600: expandtab sw=4 ts=4 sts=4
6670 + */
6671 diff -ruN php-5.1.6.old/ext/apc/apc_main.h php-5.1.6/ext/APC/apc_main.h
6672 --- php-5.1.6.old/ext/apc/apc_main.h    1969-12-31 18:00:00.000000000 -0600
6673 +++ php-5.1.6/ext/apc/apc_main.h        2007-04-02 18:05:30.000000000 -0500
6674 @@ -0,0 +1,67 @@
6675 +/*
6676 +  +----------------------------------------------------------------------+
6677 +  | APC                                                                  |
6678 +  +----------------------------------------------------------------------+
6679 +  | Copyright (c) 2006 The PHP Group                                     |
6680 +  +----------------------------------------------------------------------+
6681 +  | This source file is subject to version 3.01 of the PHP license,      |
6682 +  | that is bundled with this package in the file LICENSE, and is        |
6683 +  | available through the world-wide-web at the following url:           |
6684 +  | http://www.php.net/license/3_01.txt                                  |
6685 +  | If you did not receive a copy of the PHP license and are unable to   |
6686 +  | obtain it through the world-wide-web, please send a note to          |
6687 +  | license@php.net so we can mail you a copy immediately.               |
6688 +  +----------------------------------------------------------------------+
6689 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
6690 +  |          George Schlossnagle <george@omniti.com>                     |
6691 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6692 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
6693 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
6694 +  +----------------------------------------------------------------------+
6695 +
6696 +   This software was contributed to PHP by Community Connect Inc. in 2002
6697 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6698 +   Future revisions and derivatives of this source code must acknowledge
6699 +   Community Connect Inc. as the original contributor of this module by
6700 +   leaving this note intact in the source code.
6701 +
6702 +   All other licensing and usage conditions are those of the PHP Group.
6703 +
6704 + */
6705 +
6706 +/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
6707 +
6708 +#ifndef APC_MAIN_H
6709 +#define APC_MAIN_H
6710 +
6711 +/*
6712 + * This module provides the primary interface between PHP and APC.
6713 + */
6714 +
6715 +extern int apc_module_init(int module_number TSRMLS_DC);
6716 +extern int apc_module_shutdown(TSRMLS_D);
6717 +extern int apc_process_init(int module_number TSRMLS_DC);
6718 +extern int apc_process_shutdown(TSRMLS_D);
6719 +extern int apc_request_init(TSRMLS_D);
6720 +extern int apc_request_shutdown(TSRMLS_D);
6721 +
6722 +/*
6723 + * apc_deactivate is called by the PHP interpreter when an "exception" is
6724 + * raised (e.g., a call to the exit function) that unwinds the execution
6725 + * stack.
6726 + */
6727 +extern void apc_deactivate();
6728 +
6729 +
6730 +extern const char* apc_version();
6731 +
6732 +#endif
6733 +
6734 +/*
6735 + * Local variables:
6736 + * tab-width: 4
6737 + * c-basic-offset: 4
6738 + * End:
6739 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6740 + * vim<600: expandtab sw=4 ts=4 sts=4
6741 + */
6742 diff -ruN php-5.1.6.old/ext/apc/apc_mmap.c php-5.1.6/ext/APC/apc_mmap.c
6743 --- php-5.1.6.old/ext/apc/apc_mmap.c    1969-12-31 18:00:00.000000000 -0600
6744 +++ php-5.1.6/ext/apc/apc_mmap.c        2007-04-02 18:05:30.000000000 -0500
6745 @@ -0,0 +1,137 @@
6746 +/*
6747 +  +----------------------------------------------------------------------+
6748 +  | APC                                                                  |
6749 +  +----------------------------------------------------------------------+
6750 +  | Copyright (c) 2006 The PHP Group                                     |
6751 +  +----------------------------------------------------------------------+
6752 +  | This source file is subject to version 3.01 of the PHP license,      |
6753 +  | that is bundled with this package in the file LICENSE, and is        |
6754 +  | available through the world-wide-web at the following url:           |
6755 +  | http://www.php.net/license/3_01.txt                                  |
6756 +  | If you did not receive a copy of the PHP license and are unable to   |
6757 +  | obtain it through the world-wide-web, please send a note to          |
6758 +  | license@php.net so we can mail you a copy immediately.               |
6759 +  +----------------------------------------------------------------------+
6760 +  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
6761 +  +----------------------------------------------------------------------+
6762 +
6763 +   This software was contributed to PHP by Community Connect Inc. in 2002
6764 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6765 +   Future revisions and derivatives of this source code must acknowledge
6766 +   Community Connect Inc. as the original contributor of this module by
6767 +   leaving this note intact in the source code.
6768 +
6769 +   All other licensing and usage conditions are those of the PHP Group.
6770 +
6771 + */
6772 +
6773 +/* $Id: apc_mmap.c,v 3.5 2006/03/12 00:31:45 rasmus Exp $ */
6774 +
6775 +#include "apc.h"
6776 +
6777 +#if APC_MMAP
6778 +
6779 +#include <fcntl.h>
6780 +#include <sys/types.h>
6781 +#include <sys/mman.h>
6782 +
6783 +/* 
6784 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
6785 + * tells whatever update daemons might be running to not flush dirty
6786 + * vm pages to disk unless absolutely necessary.  My guess is that
6787 + * most systems that don't have this probably default to only synching
6788 + * to disk when absolutely necessary.
6789 + */
6790 +#ifndef MAP_NOSYNC
6791 +#define MAP_NOSYNC 0
6792 +#endif
6793 +
6794 +void *apc_mmap(char *file_mask, int size)
6795 +{
6796 +    void* shmaddr;  /* the shared memory address */
6797 +
6798 +    /* If no filename was provided, do an anonymous mmap */
6799 +    if(!file_mask || (file_mask && !strlen(file_mask))) {
6800 +        shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
6801 +    } else {
6802 +        int fd;
6803 +
6804 +        /* 
6805 +         * If the filemask contains .shm we try to do a POSIX-compliant shared memory
6806 +         * backed mmap which should avoid synchs on some platforms.  At least on
6807 +         * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
6808 +         * a file in a mounted shmfs.  For this to work on Linux you need to make sure
6809 +         * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
6810 +         * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
6811 +         * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
6812 +         * path you want here.
6813 +         */
6814 +        if(strstr(file_mask,".shm")) {
6815 +            mktemp(file_mask);
6816 +            fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
6817 +            if(fd == -1) {
6818 +                apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
6819 +                return (void *)-1;
6820 +            }
6821 +            if (ftruncate(fd, size) < 0) {
6822 +                close(fd);
6823 +                shm_unlink(file_mask);
6824 +                apc_eprint("apc_mmap: ftruncate failed:");
6825 +                return (void *)-1;
6826 +            }
6827 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6828 +            shm_unlink(file_mask);
6829 +            close(fd);
6830 +        }
6831 +        /*
6832 +         * Support anonymous mmap through the /dev/zero interface as well
6833 +         */
6834 +        else if(!strcmp(file_mask,"/dev/zero")) {
6835 +            fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
6836 +            if(fd == -1) {
6837 +                apc_eprint("apc_mmap: open on /dev/zero failed:");
6838 +                return (void *)-1;
6839 +            }
6840 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6841 +            close(fd);
6842 +        }
6843 +        /* 
6844 +         * Otherwise we do a normal filesystem mmap
6845 +         */
6846 +        else {
6847 +            fd = mkstemp(file_mask);
6848 +            if(fd == -1) {
6849 +                apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
6850 +                return (void *)-1;
6851 +            }
6852 +            if (ftruncate(fd, size) < 0) {
6853 +                close(fd);
6854 +                unlink(file_mask);
6855 +                apc_eprint("apc_mmap: ftruncate failed:");
6856 +            }
6857 +            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
6858 +            close(fd);
6859 +            unlink(file_mask);
6860 +        }
6861 +    }
6862 +    if((int)shmaddr == -1) {
6863 +        apc_eprint("apc_mmap: mmap failed:");
6864 +    }
6865 +    return shmaddr;
6866 +}
6867 +
6868 +void apc_unmap(void* shmaddr, int size)
6869 +{
6870 +    munmap(shmaddr, size);
6871 +}
6872 +
6873 +#endif
6874 +
6875 +/*
6876 + * Local variables:
6877 + * tab-width: 4
6878 + * c-basic-offset: 4
6879 + * End:
6880 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6881 + * vim<600: expandtab sw=4 ts=4 sts=4
6882 + */
6883 diff -ruN php-5.1.6.old/ext/apc/apc.php php-5.1.6/ext/APC/apc.php
6884 --- php-5.1.6.old/ext/apc/apc.php       1969-12-31 18:00:00.000000000 -0600
6885 +++ php-5.1.6/ext/apc/apc.php   2007-04-02 18:05:30.000000000 -0500
6886 @@ -0,0 +1,1313 @@
6887 +<?php
6888 +/*
6889 +  +----------------------------------------------------------------------+
6890 +  | APC                                                                  |
6891 +  +----------------------------------------------------------------------+
6892 +  | Copyright (c) 2006 The PHP Group                                     |
6893 +  +----------------------------------------------------------------------+
6894 +  | This source file is subject to version 3.01 of the PHP license,      |
6895 +  | that is bundled with this package in the file LICENSE, and is        |
6896 +  | available through the world-wide-web at the following url:           |
6897 +  | http://www.php.net/license/3_01.txt                                  |
6898 +  | If you did not receive a copy of the PHP license and are unable to   |
6899 +  | obtain it through the world-wide-web, please send a note to          |
6900 +  | license@php.net so we can mail you a copy immediately.               |
6901 +  +----------------------------------------------------------------------+
6902 +  | Authors: Ralf Becker <beckerr@php.net>                               |
6903 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
6904 +  |          Ilia Alshanetsky <ilia@prohost.org>                         |
6905 +  +----------------------------------------------------------------------+
6906 +
6907 +   All other licensing and usage conditions are those of the PHP Group.
6908 +
6909 + */
6910 +
6911 +$VERSION='$Id: apc.php,v 3.65 2006/10/27 18:32:52 shire Exp $';
6912 +
6913 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
6914 +if (file_exists("apc.conf.php")) include("apc.conf.php");
6915 +////////////////////////////////////////////////////////
6916 +
6917 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
6918 +
6919 +defaults('USE_AUTHENTICATION',1);                      // Use (internal) authentication - best choice if 
6920 +                                                                                       // no other authentication is available
6921 +                                                                                       // If set to 0:
6922 +                                                                                       //  There will be no further authentication. You 
6923 +                                                                                       //  will have to handle this by yourself!
6924 +                                                                                       // If set to 1:
6925 +                                                                                       //  You need to change ADMIN_PASSWORD to make
6926 +                                                                                       //  this work!
6927 +defaults('ADMIN_USERNAME','apc');                      // Admin Username
6928 +defaults('ADMIN_PASSWORD','password');         // Admin Password - CHANGE THIS TO ENABLE!!!
6929 +
6930 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
6931 +//           users generate a md5 or crypt password in a easy way to fill it in above
6932 +
6933 +//defaults('DATE_FORMAT', "d.m.Y H:i:s");      // German
6934 +defaults('DATE_FORMAT', 'Y/m/d H:i:s');        // US
6935 +
6936 +defaults('GRAPH_SIZE',200);                                    // Image size
6937 +
6938 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
6939 +
6940 +
6941 +// "define if not defined"
6942 +function defaults($d,$v) {
6943 +       if (!defined($d)) define($d,$v); // or just @define(...)
6944 +}
6945 +
6946 +// rewrite $PHP_SELF to block XSS attacks
6947 +//
6948 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : '';
6949 +$time = time();
6950 +$host = getenv('HOSTNAME');
6951 +if($host) { $host = '('.$host.')'; }
6952 +
6953 +// operation constants
6954 +define('OB_HOST_STATS',1);
6955 +define('OB_SYS_CACHE',2);
6956 +define('OB_USER_CACHE',3);
6957 +define('OB_SYS_CACHE_DIR',4);
6958 +define('OB_VERSION_CHECK',9);
6959 +
6960 +// check validity of input variables
6961 +$vardom=array(
6962 +       'OB'    => '/^\d+$/',                   // operational mode switch
6963 +       'CC'    => '/^[01]$/',                  // clear cache requested
6964 +       'SH'    => '/^[a-z0-9]+$/',             // shared object description
6965 +
6966 +       'IMG'   => '/^[123]$/',                 // image to generate
6967 +       'LO'    => '/^1$/',                             // login requested
6968 +
6969 +       'COUNT' => '/^\d+$/',                   // number of line displayed in list
6970 +       'SCOPE' => '/^[AD]$/',                  // list view scope
6971 +       'SORT1' => '/^[AHSMCDTZ]$/',    // first sort key
6972 +       'SORT2' => '/^[DA]$/',                  // second sort key
6973 +       'AGGR'  => '/^\d+$/',                   // aggregation by dir level
6974 +       'SEARCH'        => '/^.*$/'                     // aggregation by dir level
6975 +);
6976 +
6977 +// default cache mode
6978 +$cache_mode='opcode';
6979 +
6980 +// cache scope
6981 +$scope_list=array(
6982 +       'A' => 'cache_list',
6983 +       'D' => 'deleted_list'
6984 +);
6985 +
6986 +// handle POST and GET requests
6987 +if (empty($_REQUEST)) {
6988 +       if (!empty($_GET) && !empty($_POST)) {
6989 +               $_REQUEST = array_merge($_GET, $_POST);
6990 +       } else if (!empty($_GET)) {
6991 +               $_REQUEST = $_GET;
6992 +       } else if (!empty($_POST)) {
6993 +               $_REQUEST = $_POST;
6994 +       } else {
6995 +               $_REQUEST = array();
6996 +       }
6997 +}
6998 +
6999 +// check parameter syntax
7000 +foreach($vardom as $var => $dom) {
7001 +       if (!isset($_REQUEST[$var])) {
7002 +               $MYREQUEST[$var]=NULL;
7003 +       } else if (!is_array($_REQUEST[$var]) && preg_match($dom,$_REQUEST[$var])) {
7004 +               $MYREQUEST[$var]=$_REQUEST[$var];
7005 +       } else {
7006 +               $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
7007 +       }
7008 +}
7009 +
7010 +// check parameter sematics
7011 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
7012 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
7013 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
7014 +if (empty($MYREQUEST['OB']))   $MYREQUEST['OB']=OB_HOST_STATS;
7015 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
7016 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
7017 +
7018 +$MY_SELF=
7019 +       "$PHP_SELF".
7020 +       "?SCOPE=".$MYREQUEST['SCOPE'].
7021 +       "&SORT1=".$MYREQUEST['SORT1'].
7022 +       "&SORT2=".$MYREQUEST['SORT2'].
7023 +       "&COUNT=".$MYREQUEST['COUNT'];
7024 +$MY_SELF_WO_SORT=
7025 +       "$PHP_SELF".
7026 +       "?SCOPE=".$MYREQUEST['SCOPE'].
7027 +       "&COUNT=".$MYREQUEST['COUNT'];
7028 +
7029 +// authentication needed?
7030 +//
7031 +if (!USE_AUTHENTICATION) {
7032 +       $AUTHENTICATED=1;
7033 +} else {
7034 +       $AUTHENTICATED=0;
7035 +       if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
7036 +
7037 +               if (!isset($_SERVER['PHP_AUTH_USER']) ||
7038 +                       !isset($_SERVER['PHP_AUTH_PW']) ||
7039 +                       $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
7040 +                       $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
7041 +                       Header("WWW-Authenticate: Basic realm=\"APC Login\"");
7042 +                       Header("HTTP/1.0 401 Unauthorized");
7043 +
7044 +                       echo <<<EOB
7045 +                               <html><body>
7046 +                               <h1>Rejected!</h1>
7047 +                               <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
7048 +                               <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
7049 +                               </body></html>
7050 +EOB;
7051 +                       exit;
7052 +                       
7053 +               } else {
7054 +                       $AUTHENTICATED=1;
7055 +               }
7056 +       }
7057 +}
7058 +       
7059 +// select cache mode
7060 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
7061 +       $cache_mode='user';
7062 +}
7063 +// clear cache
7064 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
7065 +       apc_clear_cache($cache_mode);
7066 +}
7067 +
7068 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
7069 +       echo "No cache info available.  APC does not appear to be running.";
7070 +  exit;
7071 +}
7072 +
7073 +$cache_user = apc_cache_info('user', 1);  
7074 +$mem=apc_sma_info();
7075 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
7076 +
7077 +// don't cache this page
7078 +//
7079 +header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
7080 +header("Cache-Control: post-check=0, pre-check=0", false);
7081 +header("Pragma: no-cache");                                    // HTTP/1.0
7082 +
7083 +function duration($ts) {
7084 +    global $time;
7085 +    $years = (int)((($time - $ts)/(7*86400))/52.177457);
7086 +    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
7087 +    $weeks = (int)(($rem)/(7*86400));
7088 +    $days = (int)(($rem)/86400) - $weeks*7;
7089 +    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
7090 +    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
7091 +    $str = '';
7092 +    if($years==1) $str .= "$years year, ";
7093 +    if($years>1) $str .= "$years years, ";
7094 +    if($weeks==1) $str .= "$weeks week, ";
7095 +    if($weeks>1) $str .= "$weeks weeks, ";
7096 +    if($days==1) $str .= "$days day,";
7097 +    if($days>1) $str .= "$days days,";
7098 +    if($hours == 1) $str .= " $hours hour and";
7099 +    if($hours>1) $str .= " $hours hours and";
7100 +    if($mins == 1) $str .= " 1 minute";
7101 +    else $str .= " $mins minutes";
7102 +    return $str;
7103 +}
7104 +
7105 +// create graphics
7106 +//
7107 +function graphics_avail() {
7108 +       return extension_loaded('gd');
7109 +}
7110 +if (isset($MYREQUEST['IMG']))
7111 +{
7112 +       if (!graphics_avail()) {
7113 +               exit(0);
7114 +       }
7115 +
7116 +       function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
7117 +               $r=$diameter/2;
7118 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
7119 +
7120 +               
7121 +               if (function_exists("imagefilledarc")) {
7122 +                       // exists only if GD 2.0.1 is avaliable
7123 +                       imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
7124 +                       imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
7125 +                       imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
7126 +               } else {
7127 +                       imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
7128 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7129 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7130 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
7131 +                       imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
7132 +                       imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
7133 +               }
7134 +               if ($text) {
7135 +                       if ($placeindex>0) {
7136 +                               imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7137 +                               imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
7138 +                               
7139 +                       } else {
7140 +                               imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7141 +                       }
7142 +               }
7143 +       } 
7144 +
7145 +       function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
7146 +               $r=$diameter/2;
7147 +               $w=deg2rad((360+$start+($end-$start)/2)%360);
7148 +
7149 +               if ($placeindex>0) {
7150 +                       imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7151 +                       imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
7152 +                               
7153 +               } else {
7154 +                       imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7155 +               }
7156 +       } 
7157 +       
7158 +       function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
7159 +               global $col_black;
7160 +               $x1=$x+$w-1;
7161 +               $y1=$y+$h-1;
7162 +
7163 +               imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
7164 +               if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
7165 +               else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
7166 +               imagerectangle($im, $x, $y1, $x1, $y, $color1);
7167 +               if ($text) {
7168 +                       if ($placeindex>0) {
7169 +                       
7170 +                               if ($placeindex<16)
7171 +                               {
7172 +                                       $px=5;
7173 +                                       $py=$placeindex*12+6;
7174 +                                       imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
7175 +                                       imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
7176 +                                       imagestring($im,2,$px,$py-6,$text,$color1);     
7177 +                                       
7178 +                               } else {
7179 +                                       if ($placeindex<31) {
7180 +                                               $px=$x+40*2;
7181 +                                               $py=($placeindex-15)*12+6;
7182 +                                       } else {
7183 +                                               $px=$x+40*2+100*intval(($placeindex-15)/15);
7184 +                                               $py=($placeindex%15)*12+6;
7185 +                                       }
7186 +                                       imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
7187 +                                       imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
7188 +                                       imagestring($im,2,$px+2,$py-6,$text,$color1);   
7189 +                               }
7190 +                       } else {
7191 +                               imagestring($im,4,$x+5,$y1-16,$text,$color1);
7192 +                       }
7193 +               }
7194 +       }
7195 +
7196 +
7197 +       $size = GRAPH_SIZE; // image size
7198 +       if ($MYREQUEST['IMG']==3)
7199 +               $image = imagecreate(2*$size+150, $size+10);
7200 +       else
7201 +               $image = imagecreate($size+50, $size+10);
7202 +
7203 +       $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
7204 +       $col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
7205 +       $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
7206 +       $col_black = imagecolorallocate($image,   0,   0,   0);
7207 +       imagecolortransparent($image,$col_white);
7208 +
7209 +       switch ($MYREQUEST['IMG']) {
7210 +       
7211 +       case 1:
7212 +               $s=$mem['num_seg']*$mem['seg_size'];
7213 +               $a=$mem['avail_mem'];
7214 +               $x=$y=$size/2;
7215 +               $fuzz = 0.000001;
7216 +
7217 +               // This block of code creates the pie chart.  It is a lot more complex than you
7218 +               // would expect because we try to visualize any memory fragmentation as well.
7219 +               $angle_from = 0;
7220 +               $string_placement=array();
7221 +               for($i=0; $i<$mem['num_seg']; $i++) {   
7222 +                       $ptr = 0;
7223 +                       $free = $mem['block_lists'][$i];
7224 +                       foreach($free as $block) {
7225 +                               if($block['offset']!=$ptr) {       // Used block
7226 +                                       $angle_to = $angle_from+($block['offset']-$ptr)/$s;
7227 +                                       if(($angle_to+$fuzz)>1) $angle_to = 1;
7228 +                                       fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7229 +                                       if (($angle_to-$angle_from)>0.05) {
7230 +                                               array_push($string_placement, array($angle_from,$angle_to));
7231 +                                       }
7232 +                                       $angle_from = $angle_to;
7233 +                               }
7234 +                               $angle_to = $angle_from+($block['size'])/$s;
7235 +                               if(($angle_to+$fuzz)>1) $angle_to = 1;
7236 +                               fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
7237 +                               if (($angle_to-$angle_from)>0.05) {
7238 +                                       array_push($string_placement, array($angle_from,$angle_to));
7239 +                               }
7240 +                               $angle_from = $angle_to;
7241 +                               $ptr = $block['offset']+$block['size'];
7242 +                       }
7243 +                       if ($ptr < $mem['seg_size']) { // memory at the end 
7244 +                               $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
7245 +                               if(($angle_to+$fuzz)>1) $angle_to = 1;
7246 +                               fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7247 +                               if (($angle_to-$angle_from)>0.05) {
7248 +                                       array_push($string_placement, array($angle_from,$angle_to));
7249 +                               }
7250 +                       }
7251 +               }
7252 +               foreach ($string_placement as $angle) {
7253 +                       text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
7254 +               }
7255 +               break;
7256 +               
7257 +       case 2: 
7258 +               $s=$cache['num_hits']+$cache['num_misses'];
7259 +               $a=$cache['num_hits'];
7260 +               
7261 +               fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7262 +               fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7263 +               break;
7264 +               
7265 +       case 3:
7266 +               $s=$mem['num_seg']*$mem['seg_size'];
7267 +               $a=$mem['avail_mem'];
7268 +               $x=130;
7269 +               $y=1;
7270 +               $j=1;
7271 +
7272 +               // This block of code creates the bar chart.  It is a lot more complex than you
7273 +               // would expect because we try to visualize any memory fragmentation as well.
7274 +               for($i=0; $i<$mem['num_seg']; $i++) {   
7275 +                       $ptr = 0;
7276 +                       $free = $mem['block_lists'][$i];
7277 +                       foreach($free as $block) {
7278 +                               if($block['offset']!=$ptr) {       // Used block
7279 +                                       $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
7280 +                                       if ($h>0) {
7281 +                                                $j++;
7282 +                                               if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
7283 +                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
7284 +                                        }
7285 +                                       $y+=$h;
7286 +                               }
7287 +                               $h=(GRAPH_SIZE-5)*($block['size'])/$s;
7288 +                               if ($h>0) {
7289 +                                        $j++;
7290 +                                       if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
7291 +                                       else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
7292 +                                }
7293 +                               $y+=$h;
7294 +                               $ptr = $block['offset']+$block['size'];
7295 +                       }
7296 +                       if ($ptr < $mem['seg_size']) { // memory at the end 
7297 +                               $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
7298 +                               if ($h > 0) {
7299 +                                       fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
7300 +                               }
7301 +                       }
7302 +               }
7303 +               break;
7304 +       case 4: 
7305 +               $s=$cache['num_hits']+$cache['num_misses'];
7306 +               $a=$cache['num_hits'];
7307 +                       
7308 +               fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7309 +               fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7310 +               break;
7311 +       
7312 +       }
7313 +       header("Content-type: image/png");
7314 +       imagepng($image);
7315 +       exit;
7316 +}
7317 +
7318 +// pretty printer for byte values
7319 +//
7320 +function bsize($s) {
7321 +       foreach (array('','K','M','G') as $i => $k) {
7322 +               if ($s < 1024) break;
7323 +               $s/=1024;
7324 +       }
7325 +       return sprintf("%5.1f %sBytes",$s,$k);
7326 +}
7327 +
7328 +// sortable table header in "scripts for this host" view
7329 +function sortheader($key,$name,$extra='') {
7330 +       global $MYREQUEST, $MY_SELF_WO_SORT;
7331 +       
7332 +       if ($MYREQUEST['SORT1']==$key) {
7333 +               $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
7334 +       }
7335 +       return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
7336 +
7337 +}
7338 +
7339 +// create menu entry 
7340 +function menu_entry($ob,$title) {
7341 +       global $MYREQUEST,$MY_SELF;
7342 +       if ($MYREQUEST['OB']!=$ob) {
7343 +               return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7344 +       } else if (empty($MYREQUEST['SH'])) {
7345 +               return "<li><span class=active>$title</span></li>";
7346 +       } else {
7347 +               return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
7348 +       }
7349 +}
7350 +
7351 +function put_login_link($s="Login")
7352 +{
7353 +       global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
7354 +       // needs ADMIN_PASSWORD to be changed!
7355 +       //
7356 +       if (!USE_AUTHENTICATION) {
7357 +               return;
7358 +       } else if (ADMIN_PASSWORD=='password')
7359 +       {
7360 +               print <<<EOB
7361 +                       <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>
7362 +EOB;
7363 +       } else if ($AUTHENTICATED) {
7364 +               print <<<EOB
7365 +                       '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
7366 +EOB;
7367 +       } else{
7368 +               print <<<EOB
7369 +                       <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
7370 +EOB;
7371 +       }
7372 +}
7373 +
7374 +
7375 +?>
7376 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7377 +<html>
7378 +<head><title>APC INFO <?php echo $host ?></title>
7379 +<style><!--
7380 +body { background:white; font-size:100.01%; margin:0; padding:0; }
7381 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
7382 +* html body   {font-size:0.8em}
7383 +* html p      {font-size:0.8em}
7384 +* html td     {font-size:0.8em}
7385 +* html th     {font-size:0.8em}
7386 +* html input  {font-size:0.8em}
7387 +* html submit {font-size:0.8em}
7388 +td { vertical-align:top }
7389 +a { color:black; font-weight:none; text-decoration:none; }
7390 +a:hover { text-decoration:underline; }
7391 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
7392 +
7393 +
7394 +div.head div.login {
7395 +       position:absolute;
7396 +       right: 1em;
7397 +       top: 1.2em;
7398 +       color:white;
7399 +       width:6em;
7400 +       }
7401 +div.head div.login a {
7402 +       position:absolute;
7403 +       right: 0em;
7404 +       background:rgb(119,123,180);
7405 +       border:solid rgb(102,102,153) 2px;
7406 +       color:white;
7407 +       font-weight:bold;
7408 +       padding:0.1em 0.5em 0.1em 0.5em;
7409 +       text-decoration:none;
7410 +       }
7411 +div.head div.login a:hover {
7412 +       background:rgb(193,193,244);
7413 +       }
7414 +
7415 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
7416 +* html h1.apc { margin-bottom:-7px; }
7417 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
7418 +h1.apc div.logo span.logo {
7419 +       background:rgb(119,123,180);
7420 +       color:black;
7421 +       border-right: solid black 1px;
7422 +       border-bottom: solid black 1px;
7423 +       font-style:italic;
7424 +       font-size:1em;
7425 +       padding-left:1.2em;
7426 +       padding-right:1.2em;
7427 +       text-align:right;
7428 +       }
7429 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
7430 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
7431 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
7432 +hr.apc {
7433 +       background:white;
7434 +       border-bottom:solid rgb(102,102,153) 1px;
7435 +       border-style:none;
7436 +       border-top:solid rgb(102,102,153) 10px;
7437 +       height:12px;
7438 +       margin:0;
7439 +       margin-top:1px;
7440 +       padding:0;
7441 +}
7442 +
7443 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
7444 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
7445 +ol.menu a {
7446 +       background:rgb(153,153,204);
7447 +       border:solid rgb(102,102,153) 2px;
7448 +       color:white;
7449 +       font-weight:bold;
7450 +       margin-right:0em;
7451 +       padding:0.1em 0.5em 0.1em 0.5em;
7452 +       text-decoration:none;
7453 +       margin-left: 5px;
7454 +       }
7455 +ol.menu a.child_active {
7456 +       background:rgb(153,153,204);
7457 +       border:solid rgb(102,102,153) 2px;
7458 +       color:white;
7459 +       font-weight:bold;
7460 +       margin-right:0em;
7461 +       padding:0.1em 0.5em 0.1em 0.5em;
7462 +       text-decoration:none;
7463 +       border-left: solid black 5px;
7464 +       margin-left: 0px;
7465 +       }
7466 +ol.menu span.active {
7467 +       background:rgb(153,153,204);
7468 +       border:solid rgb(102,102,153) 2px;
7469 +       color:black;
7470 +       font-weight:bold;
7471 +       margin-right:0em;
7472 +       padding:0.1em 0.5em 0.1em 0.5em;
7473 +       text-decoration:none;
7474 +       border-left: solid black 5px;
7475 +       }
7476 +ol.menu span.inactive {
7477 +       background:rgb(193,193,244);
7478 +       border:solid rgb(182,182,233) 2px;
7479 +       color:white;
7480 +       font-weight:bold;
7481 +       margin-right:0em;
7482 +       padding:0.1em 0.5em 0.1em 0.5em;
7483 +       text-decoration:none;
7484 +       margin-left: 5px;
7485 +       }
7486 +ol.menu a:hover {
7487 +       background:rgb(193,193,244);
7488 +       text-decoration:none;
7489 +       }
7490 +       
7491 +       
7492 +div.info {
7493 +       background:rgb(204,204,204);
7494 +       border:solid rgb(204,204,204) 1px;
7495 +       margin-bottom:1em;
7496 +       }
7497 +div.info h2 {
7498 +       background:rgb(204,204,204);
7499 +       color:black;
7500 +       font-size:1em;
7501 +       margin:0;
7502 +       padding:0.1em 1em 0.1em 1em;
7503 +       }
7504 +div.info table {
7505 +       border:solid rgb(204,204,204) 1px;
7506 +       border-spacing:0;
7507 +       width:100%;
7508 +       }
7509 +div.info table th {
7510 +       background:rgb(204,204,204);
7511 +       color:white;
7512 +       margin:0;
7513 +       padding:0.1em 1em 0.1em 1em;
7514 +       }
7515 +div.info table th a.sortable { color:black; }
7516 +div.info table tr.tr-0 { background:rgb(238,238,238); }
7517 +div.info table tr.tr-1 { background:rgb(221,221,221); }
7518 +div.info table td { padding:0.3em 1em 0.3em 1em; }
7519 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
7520 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
7521 +div.info table td h3 {
7522 +       color:black;
7523 +       font-size:1.1em;
7524 +       margin-left:-0.3em;
7525 +       }
7526 +
7527 +div.graph { margin-bottom:1em }
7528 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
7529 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
7530 +div.graph table td.td-0 { background:rgb(238,238,238); }
7531 +div.graph table td.td-1 { background:rgb(221,221,221); }
7532 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
7533 +
7534 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
7535 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
7536 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
7537 +
7538 +div.sorting { margin:1.5em 0em 1.5em 2em }
7539 +.center { text-align:center }
7540 +.aright { position:absolute;right:1em }
7541 +.right { text-align:right }
7542 +.ok { color:rgb(0,200,0); font-weight:bold}
7543 +.failed { color:rgb(200,0,0); font-weight:bold}
7544 +
7545 +span.box {
7546 +       border: black solid 1px;
7547 +       border-right:solid black 2px;
7548 +       border-bottom:solid black 2px;
7549 +       padding:0 0.5em 0 0.5em;
7550 +       margin-right:1em;
7551 +}
7552 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
7553 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
7554 +
7555 +div.authneeded {
7556 +       background:rgb(238,238,238);
7557 +       border:solid rgb(204,204,204) 1px;
7558 +       color:rgb(200,0,0);
7559 +       font-size:1.2em;
7560 +       font-weight:bold;
7561 +       padding:2em;
7562 +       text-align:center;
7563 +       }
7564 +       
7565 +input {
7566 +       background:rgb(153,153,204);
7567 +       border:solid rgb(102,102,153) 2px;
7568 +       color:white;
7569 +       font-weight:bold;
7570 +       margin-right:1em;
7571 +       padding:0.1em 0.5em 0.1em 0.5em;
7572 +       }
7573 +//-->
7574 +</style>
7575 +</head>
7576 +<body>
7577 +<div class="head">
7578 +       <h1 class="apc">
7579 +               <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
7580 +               <div class="nameinfo">Opcode Cache</div>
7581 +       </h1>
7582 +       <div class="login">
7583 +       <?php put_login_link(); ?>
7584 +       </div>
7585 +       <hr class="apc">
7586 +</div>
7587 +<?php
7588 +
7589 +
7590 +// Display main Menu
7591 +echo <<<EOB
7592 +       <ol class=menu>
7593 +       <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
7594 +EOB;
7595 +echo
7596 +       menu_entry(1,'View Host Stats'),
7597 +       menu_entry(2,'System Cache Entries');
7598 +if ($AUTHENTICATED) {
7599 +       echo menu_entry(4,'Per-Directory Entries');
7600 +}
7601 +echo
7602 +       menu_entry(3,'User Cache Entries'),
7603 +       menu_entry(9,'Version Check');
7604 +       
7605 +if ($AUTHENTICATED) {
7606 +       echo <<<EOB
7607 +               <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>
7608 +EOB;
7609 +}
7610 +echo <<<EOB
7611 +       </ol>
7612 +EOB;
7613 +
7614 +
7615 +// CONTENT
7616 +echo <<<EOB
7617 +       <div class=content>
7618 +EOB;
7619 +
7620 +// MAIN SWITCH STATEMENT 
7621 +
7622 +switch ($MYREQUEST['OB']) {
7623 +
7624 +
7625 +
7626 +
7627 +
7628 +// -----------------------------------------------
7629 +// Host Stats
7630 +// -----------------------------------------------
7631 +case OB_HOST_STATS:
7632 +       $mem_size = $mem['num_seg']*$mem['seg_size'];
7633 +       $mem_avail= $mem['avail_mem'];
7634 +       $mem_used = $mem_size-$mem_avail;
7635 +       $seg_size = bsize($mem['seg_size']);
7636 +       $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
7637 +       $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
7638 +       $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
7639 +       $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
7640 +       $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
7641 +       $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
7642 +       $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
7643 +       $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
7644 +       $apcversion = phpversion('apc');
7645 +       $phpversion = phpversion();
7646 +       $number_files = $cache['num_entries']; 
7647 +    $size_files = bsize($cache['mem_size']);
7648 +       $number_vars = $cache_user['num_entries'];
7649 +    $size_vars = bsize($cache_user['mem_size']);
7650 +       $i=0;
7651 +       echo <<< EOB
7652 +               <div class="info div1"><h2>General Cache Information</h2>
7653 +               <table cellspacing=0><tbody>
7654 +               <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
7655 +               <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
7656 +EOB;
7657 +
7658 +       if(!empty($_SERVER['SERVER_NAME']))
7659 +               echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
7660 +       if(!empty($_SERVER['SERVER_SOFTWARE']))
7661 +               echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
7662 +
7663 +       echo <<<EOB
7664 +               <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
7665 +    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
7666 +    </td></tr>
7667 +EOB;
7668 +       echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
7669 +       echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
7670 +       echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
7671 +       echo <<<EOB
7672 +               </tbody></table>
7673 +               </div>
7674 +
7675 +               <div class="info div1"><h2>File Cache Information</h2>
7676 +               <table cellspacing=0><tbody>
7677 +               <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
7678 +               <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
7679 +               <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
7680 +               <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
7681 +               <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
7682 +               <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
7683 +               <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
7684 +               <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
7685 +               </tbody></table>
7686 +               </div>
7687 +
7688 +               <div class="info div1"><h2>User Cache Information</h2>
7689 +               <table cellspacing=0><tbody>
7690 +    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
7691 +               <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
7692 +               <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
7693 +               <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
7694 +               <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
7695 +               <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
7696 +               <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
7697 +               <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
7698 +
7699 +               </tbody></table>
7700 +               </div>
7701 +
7702 +               <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
7703 +EOB;
7704 +
7705 +       $j = 0;
7706 +       foreach (ini_get_all('apc') as $k => $v) {
7707 +               echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
7708 +               $j = 1 - $j;
7709 +       }
7710 +
7711 +       if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
7712 +               $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
7713 +       else
7714 +               $mem_note = "Memory Usage";
7715 +
7716 +       echo <<< EOB
7717 +               </tbody></table>
7718 +               </div>
7719 +
7720 +               <div class="graph div3"><h2>Host Status Diagrams</h2>
7721 +               <table cellspacing=0><tbody>
7722 +EOB;
7723 +       $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
7724 +       echo <<<EOB
7725 +               <tr>
7726 +               <td class=td-0>$mem_note</td>
7727 +               <td class=td-1>Hits &amp; Misses</td>
7728 +               </tr>
7729 +EOB;
7730 +
7731 +       echo
7732 +               graphics_avail() ? 
7733 +                         '<tr>'.
7734 +                         "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
7735 +                         "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
7736 +                       : "",
7737 +               '<tr>',
7738 +               '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
7739 +               '<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",
7740 +               '</tr>',
7741 +               '<tr>',
7742 +               '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
7743 +               '<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";
7744 +       echo <<< EOB
7745 +               </tr>
7746 +               </tbody></table>
7747 +
7748 +               <br/>
7749 +               <h2>Detailed Memory Usage and Fragmentation</h2>
7750 +               <table cellspacing=0><tbody>
7751 +               <tr>
7752 +               <td class=td-0 colspan=2><br/>
7753 +EOB;
7754 +
7755 +       // Fragementation: (freeseg - 1) / total_seg
7756 +       $nseg = $freeseg = $fragsize = $freetotal = 0;
7757 +       for($i=0; $i<$mem['num_seg']; $i++) {
7758 +               $ptr = 0;
7759 +               foreach($mem['block_lists'][$i] as $block) {
7760 +                       if ($block['offset'] != $ptr) {
7761 +                               ++$nseg;
7762 +                       }
7763 +                       $ptr = $block['offset'] + $block['size'];
7764 +                        /* Only consider blocks <5M for the fragmentation % */
7765 +                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
7766 +                        $freetotal+=$block['size'];
7767 +               }
7768 +               $freeseg += count($mem['block_lists'][$i]);
7769 +       }
7770 +       
7771 +       if ($freeseg > 1) {
7772 +               $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
7773 +       } else {
7774 +               $frag = "0%";
7775 +       }
7776 +
7777 +       if (graphics_avail()) {
7778 +               $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
7779 +               echo <<<EOB
7780 +                       <img alt="" $size src="$PHP_SELF?IMG=3&$time">
7781 +EOB;
7782 +       }
7783 +       echo <<<EOB
7784 +               </br>Fragmentation: $frag
7785 +               </td>
7786 +               </tr>
7787 +EOB;
7788 +        if(isset($mem['adist'])) {
7789 +          foreach($mem['adist'] as $i=>$v) {
7790 +            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
7791 +            if($i==0) $range = "1";
7792 +            else $range = "$cur - $nxt";
7793 +            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
7794 +          }
7795 +        }
7796 +        echo <<<EOB
7797 +               </tbody></table>
7798 +               </div>
7799 +EOB;
7800 +               
7801 +       break;
7802 +
7803 +
7804 +// -----------------------------------------------
7805 +// User Cache Entries
7806 +// -----------------------------------------------
7807 +case OB_USER_CACHE:
7808 +       if (!$AUTHENTICATED) {
7809 +               echo '<div class="authneeded">You need to login to see the user values here!<br/>&nbsp;<br/>';
7810 +               put_login_link("Login now!");
7811 +               echo '</div>';
7812 +               break;
7813 +       }
7814 +       $fieldname='info';
7815 +       $fieldheading='User Entry Label';
7816 +       $fieldkey='info';
7817 +
7818 +
7819 +// -----------------------------------------------
7820 +// System Cache Entries                
7821 +// -----------------------------------------------
7822 +case OB_SYS_CACHE:     
7823 +       if (!isset($fieldname))
7824 +       {
7825 +               $fieldname='filename';
7826 +               $fieldheading='Script Filename';
7827 +               if(ini_get("apc.stat")) $fieldkey='inode';
7828 +               else $fieldkey='filename'; 
7829 +       }
7830 +       if (!empty($MYREQUEST['SH']))
7831 +       {
7832 +               echo <<< EOB
7833 +                       <div class="info"><table cellspacing=0><tbody>
7834 +                       <tr><th>Attribute</th><th>Value</th></tr>
7835 +EOB;
7836 +
7837 +               $m=0;
7838 +               foreach($scope_list as $j => $list) {
7839 +                       foreach($cache[$list] as $i => $entry) {
7840 +                               if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
7841 +                               foreach($entry as $k => $value) {
7842 +                                       if (!$AUTHENTICATED) {
7843 +                                               // hide all path entries if not logged in
7844 +                                               $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
7845 +                                       }
7846 +
7847 +                                       if ($k == "num_hits") {
7848 +                                               $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
7849 +                                       }
7850 +                                       if ($k == 'deletion_time') {
7851 +                                               if(!$entry['deletion_time']) $value = "None";
7852 +                                       }
7853 +                                       echo
7854 +                                               "<tr class=tr-$m>",
7855 +                                               "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
7856 +                                               "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
7857 +                                               "</tr>";
7858 +                                       $m=1-$m;
7859 +                               }
7860 +                               if($fieldkey=='info') {
7861 +                                       echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
7862 +                                       $output = var_export(apc_fetch($entry[$fieldkey]),true);
7863 +                                       echo htmlspecialchars($output);
7864 +                                       echo "</pre></td></tr>\n";
7865 +                               }
7866 +                               break;
7867 +                       }
7868 +               }
7869 +
7870 +               echo <<<EOB
7871 +                       </tbody></table>
7872 +                       </div>
7873 +EOB;
7874 +               break;
7875 +       }
7876 +
7877 +       $cols=6;
7878 +       echo <<<EOB
7879 +               <div class=sorting><form>Scope:
7880 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
7881 +               <select name=SCOPE>
7882 +EOB;
7883 +       echo 
7884 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
7885 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
7886 +               "</select>",
7887 +               ", Sorting:<select name=SORT1>",
7888 +               "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
7889 +               "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
7890 +               "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
7891 +               "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
7892 +               "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
7893 +               "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
7894 +               "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
7895 +       if($fieldname=='info') echo
7896 +               "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
7897 +       echo 
7898 +               '</select>',
7899 +               '<select name=SORT2>',
7900 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
7901 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
7902 +               '</select>',
7903 +               '<select name=COUNT onChange="form.submit()">',
7904 +               '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
7905 +               '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
7906 +               '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
7907 +               '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
7908 +               '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
7909 +               '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
7910 +               '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
7911 +               '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
7912 +               '</select>',
7913 +    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
7914 +               '&nbsp;<input type=submit value="GO!">',
7915 +               '</form></div>',
7916 +
7917 +               '<div class="info"><table cellspacing=0><tbody>',
7918 +               '<tr>',
7919 +               '<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
7920 +               '<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
7921 +               '<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
7922 +               '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
7923 +               '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
7924 +               '<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
7925 +
7926 +       if($fieldname=='info') {
7927 +               $cols+=2;
7928 +                echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
7929 +       }
7930 +       echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
7931 +
7932 +       // builds list with alpha numeric sortable keys
7933 +       //
7934 +       $list = array();
7935 +       foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
7936 +               switch($MYREQUEST['SORT1']) {
7937 +                       case 'A': $k=sprintf('%015d-',$entry['access_time']);   break;
7938 +                       case 'H': $k=sprintf('%015d-',$entry['num_hits']);              break;
7939 +                       case 'Z': $k=sprintf('%015d-',$entry['mem_size']);              break;
7940 +                       case 'M': $k=sprintf('%015d-',$entry['mtime']);                 break;
7941 +                       case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
7942 +                       case 'T': $k=sprintf('%015d-',$entry['ttl']);                   break;
7943 +                       case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
7944 +                       case 'S': $k='';                                                                                break;
7945 +               }
7946 +               if (!$AUTHENTICATED) {
7947 +                       // hide all path entries if not logged in
7948 +                       $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
7949 +               } else {
7950 +                       $list[$k.$entry[$fieldname]]=$entry;
7951 +               }
7952 +       }
7953 +
7954 +       if ($list) {
7955 +               
7956 +               // sort list
7957 +               //
7958 +               switch ($MYREQUEST['SORT2']) {
7959 +                       case "A":       krsort($list);  break;
7960 +                       case "D":       ksort($list);   break;
7961 +               }
7962 +               
7963 +               // output list
7964 +               $i=0;
7965 +               foreach($list as $k => $entry) {
7966 +      if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {  
7967 +        echo
7968 +          '<tr class=tr-',$i%2,'>',
7969 +          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
7970 +          '<td class="td-n center">',$entry['num_hits'],'</td>',
7971 +          '<td class="td-n right">',$entry['mem_size'],'</td>',
7972 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
7973 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
7974 +          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
7975 +
7976 +        if($fieldname=='info') {
7977 +          if($entry['ttl'])
7978 +            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
7979 +          else
7980 +            echo '<td class="td-n center">None</td>';
7981 +        }
7982 +        echo
7983 +          '<td class="td-last center">',$entry['deletion_time'] ? date(DATE_FORMAT,$entry['deletion_time']) : '-','</td>',
7984 +          '</tr>';
7985 +        $i++;
7986 +        if ($i == $MYREQUEST['COUNT'])
7987 +          break;
7988 +      }
7989 +               }
7990 +               
7991 +       } else {
7992 +               echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
7993 +       }
7994 +       echo <<< EOB
7995 +               </tbody></table>
7996 +EOB;
7997 +
7998 +       if ($list && $i < count($list)) {
7999 +               echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8000 +       }
8001 +
8002 +       echo <<< EOB
8003 +               </div>
8004 +EOB;
8005 +       break;
8006 +
8007 +
8008 +// -----------------------------------------------
8009 +// Per-Directory System Cache Entries
8010 +// -----------------------------------------------
8011 +case OB_SYS_CACHE_DIR: 
8012 +       if (!$AUTHENTICATED) {
8013 +               break;
8014 +       }
8015 +
8016 +       echo <<<EOB
8017 +               <div class=sorting><form>Scope:
8018 +               <input type=hidden name=OB value={$MYREQUEST['OB']}>
8019 +               <select name=SCOPE>
8020 +EOB;
8021 +       echo 
8022 +               "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
8023 +               "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
8024 +               "</select>",
8025 +               ", Sorting:<select name=SORT1>",
8026 +               "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
8027 +               "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
8028 +               "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
8029 +               "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
8030 +               "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
8031 +               "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
8032 +               '</select>',
8033 +               '<select name=SORT2>',
8034 +               '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
8035 +               '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
8036 +               '</select>',
8037 +               '<select name=COUNT onChange="form.submit()">',
8038 +               '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
8039 +               '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
8040 +               '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
8041 +               '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
8042 +               '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
8043 +               '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
8044 +               '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
8045 +               '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
8046 +               '</select>',
8047 +               ", Group By Dir Level:<select name=AGGR>",
8048 +               "<option value='' selected>None</option>";
8049 +               for ($i = 1; $i < 10; $i++)
8050 +                       echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
8051 +               echo '</select>',
8052 +               '&nbsp;<input type=submit value="GO!">',
8053 +               '</form></div>',
8054 +
8055 +               '<div class="info"><table cellspacing=0><tbody>',
8056 +               '<tr>',
8057 +               '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
8058 +               '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
8059 +               '<th>',sortheader('H','Total Hits',     "&OB=".$MYREQUEST['OB']),'</th>',
8060 +               '<th>',sortheader('Z','Total Size',     "&OB=".$MYREQUEST['OB']),'</th>',
8061 +               '<th>',sortheader('C','Avg. Hits',      "&OB=".$MYREQUEST['OB']),'</th>',
8062 +               '<th>',sortheader('A','Avg. Size',      "&OB=".$MYREQUEST['OB']),'</th>',
8063 +               '</tr>';
8064 +
8065 +       // builds list with alpha numeric sortable keys
8066 +       //
8067 +       $tmp = $list = array();
8068 +       foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
8069 +               $n = dirname($entry['filename']);
8070 +               if ($MYREQUEST['AGGR'] > 0) {
8071 +                       $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
8072 +               }
8073 +               if (!isset($tmp[$n])) {
8074 +                       $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
8075 +               }
8076 +               $tmp[$n]['hits'] += $entry['num_hits'];
8077 +               $tmp[$n]['size'] += $entry['mem_size'];
8078 +               ++$tmp[$n]['ents'];
8079 +       }
8080 +
8081 +       foreach ($tmp as $k => $v) {
8082 +               switch($MYREQUEST['SORT1']) {
8083 +                       case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
8084 +                       case 'T': $kn=sprintf('%015d-',$v['ents']);             break;
8085 +                       case 'H': $kn=sprintf('%015d-',$v['hits']);             break;
8086 +                       case 'Z': $kn=sprintf('%015d-',$v['size']);             break;
8087 +                       case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
8088 +                       case 'S': $kn = $k;                                     break;
8089 +               }
8090 +               $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
8091 +       }
8092 +
8093 +       if ($list) {
8094 +               
8095 +               // sort list
8096 +               //
8097 +               switch ($MYREQUEST['SORT2']) {
8098 +                       case "A":       krsort($list);  break;
8099 +                       case "D":       ksort($list);   break;
8100 +               }
8101 +               
8102 +               // output list
8103 +               $i = 0;
8104 +               foreach($list as $entry) {
8105 +                       echo
8106 +                               '<tr class=tr-',$i%2,'>',
8107 +                               "<td class=td-0>",$entry[0],'</a></td>',
8108 +                               '<td class="td-n center">',$entry[1],'</td>',
8109 +                               '<td class="td-n center">',$entry[2],'</td>',
8110 +                               '<td class="td-n center">',$entry[3],'</td>',
8111 +                               '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
8112 +                               '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
8113 +                               '</tr>';
8114 +
8115 +                       if (++$i == $MYREQUEST['COUNT']) break;
8116 +               }
8117 +               
8118 +       } else {
8119 +               echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
8120 +       }
8121 +       echo <<< EOB
8122 +               </tbody></table>
8123 +EOB;
8124 +
8125 +       if ($list && $i < count($list)) {
8126 +               echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8127 +       }
8128 +
8129 +       echo <<< EOB
8130 +               </div>
8131 +EOB;
8132 +       break;
8133 +
8134 +// -----------------------------------------------
8135 +// Version check
8136 +// -----------------------------------------------
8137 +case OB_VERSION_CHECK:
8138 +       echo <<<EOB
8139 +               <div class="info"><h2>APC Version Information</h2>
8140 +               <table cellspacing=0><tbody>
8141 +               <tr>
8142 +               <th></th>
8143 +               </tr>
8144 +EOB;
8145 +
8146 +       $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
8147 +       if (!$rss) {
8148 +               echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
8149 +       } else {
8150 +               $apcversion = phpversion('apc');
8151 +
8152 +               preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
8153 +               echo '<tr class="tr-0 center"><td>';
8154 +               if (version_compare($apcversion, $match[1], '>=')) {
8155 +                       echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
8156 +                       $i = 3;
8157 +               } else {
8158 +                       echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
8159 +                               newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
8160 +                               http://pecl.php.net/package/APC/'.$match[1].'</a>
8161 +                               </div>';
8162 +                       $i = -1;
8163 +               }
8164 +               echo '</td></tr>';
8165 +               echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
8166 +
8167 +               preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
8168 +               next($match[2]); next($match[2]);
8169 +
8170 +               while (list(,$v) = each($match[2])) {
8171 +                       list(,$ver) = explode(' ', $v, 2);
8172 +                       if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
8173 +                               break;
8174 +                       } else if (!$i--) {
8175 +                               break;
8176 +                       }
8177 +                       echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
8178 +                       echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
8179 +                       next($match[2]);
8180 +               }
8181 +               echo '</td></tr>';
8182 +       }
8183 +       echo <<< EOB
8184 +               </tbody></table>
8185 +               </div>
8186 +EOB;
8187 +       break;
8188 +
8189 +}
8190 +
8191 +echo <<< EOB
8192 +       </div>
8193 +EOB;
8194 +
8195 +?>
8196 +
8197 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
8198 +</body>
8199 +</html>
8200 diff -ruN php-5.1.6.old/ext/apc/apc_php.h php-5.1.6/ext/APC/apc_php.h
8201 --- php-5.1.6.old/ext/apc/apc_php.h     1969-12-31 18:00:00.000000000 -0600
8202 +++ php-5.1.6/ext/apc/apc_php.h 2007-04-02 18:05:30.000000000 -0500
8203 @@ -0,0 +1,71 @@
8204 +/*
8205 +  +----------------------------------------------------------------------+
8206 +  | APC                                                                  |
8207 +  +----------------------------------------------------------------------+
8208 +  | Copyright (c) 2006 The PHP Group                                     |
8209 +  +----------------------------------------------------------------------+
8210 +  | This source file is subject to version 3.01 of the PHP license,      |
8211 +  | that is bundled with this package in the file LICENSE, and is        |
8212 +  | available through the world-wide-web at the following url:           |
8213 +  | http://www.php.net/license/3_01.txt                                  |
8214 +  | If you did not receive a copy of the PHP license and are unable to   |
8215 +  | obtain it through the world-wide-web, please send a note to          |
8216 +  | license@php.net so we can mail you a copy immediately.               |
8217 +  +----------------------------------------------------------------------+
8218 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8219 +  |          George Schlossnagle <george@omniti.com>                     |
8220 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
8221 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
8222 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
8223 +  +----------------------------------------------------------------------+
8224 +
8225 +   This software was contributed to PHP by Community Connect Inc. in 2002
8226 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8227 +   Future revisions and derivatives of this source code must acknowledge
8228 +   Community Connect Inc. as the original contributor of this module by
8229 +   leaving this note intact in the source code.
8230 +
8231 +   All other licensing and usage conditions are those of the PHP Group.
8232 +
8233 + */
8234 +
8235 +/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
8236 +
8237 +#ifndef APC_PHP_H
8238 +#define APC_PHP_H
8239 +
8240 +/*
8241 + * The purpose of this header file is to include all PHP and Zend headers that
8242 + * are typically needed elsewhere in APC. This makes it easy to insure that
8243 + * all required headers are available.
8244 + */
8245 +
8246 +#include "php.h"
8247 +#include "zend.h"
8248 +#include "zend_API.h"
8249 +#include "zend_compile.h"
8250 +#include "zend_hash.h"
8251 +#include "zend_extensions.h"
8252 +
8253 +#if ZEND_MODULE_API_NO > 20050922
8254 +#define ZEND_ENGINE_2_2
8255 +#endif
8256 +#if ZEND_MODULE_API_NO > 20050921
8257 +#define ZEND_ENGINE_2_1
8258 +#endif
8259 +#ifdef ZEND_ENGINE_2_1
8260 +#include "zend_vm.h"
8261 +#endif
8262 +
8263 +#include "rfc1867.h"
8264 +
8265 +#endif
8266 +
8267 +/*
8268 + * Local variables:
8269 + * tab-width: 4
8270 + * c-basic-offset: 4
8271 + * End:
8272 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8273 + * vim<600: expandtab sw=4 ts=4 sts=4
8274 + */
8275 diff -ruN php-5.1.6.old/ext/apc/apc_pthreadmutex.c php-5.1.6/ext/APC/apc_pthreadmutex.c
8276 --- php-5.1.6.old/ext/apc/apc_pthreadmutex.c    1969-12-31 18:00:00.000000000 -0600
8277 +++ php-5.1.6/ext/apc/apc_pthreadmutex.c        2007-04-02 18:05:30.000000000 -0500
8278 @@ -0,0 +1,104 @@
8279 +/*
8280 +  +----------------------------------------------------------------------+
8281 +  | APC                                                                  |
8282 +  +----------------------------------------------------------------------+
8283 +  | Copyright (c) 2006 The PHP Group                                     |
8284 +  +----------------------------------------------------------------------+
8285 +  | This source file is subject to version 3.01 of the PHP license,      |
8286 +  | that is bundled with this package in the file LICENSE, and is        |
8287 +  | available through the world-wide-web at the following url:           |
8288 +  | http://www.php.net/license/3_01.txt                                  |
8289 +  | If you did not receive a copy of the PHP license and are unable to   |
8290 +  | obtain it through the world-wide-web, please send a note to          |
8291 +  | license@php.net so we can mail you a copy immediately.               |
8292 +  +----------------------------------------------------------------------+
8293 +  | Authors: Brian Shire <shire@php.net>                                 |
8294 +  +----------------------------------------------------------------------+
8295 +
8296 + */
8297 +
8298 +/* $Id: apc_pthreadmutex.c,v 3.2 2007/02/15 21:40:45 shire Exp $ */
8299 +
8300 +#include "apc_pthreadmutex.h"
8301 +
8302 +#ifdef APC_PTHREADMUTEX_LOCKS
8303 +
8304 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock) 
8305 +{ 
8306 +    int result;
8307 +    pthread_mutexattr_t* attr;
8308 +    attr = malloc(sizeof(pthread_mutexattr_t));
8309 +
8310 +    result = pthread_mutexattr_init(attr);
8311 +    if(result == ENOMEM) {
8312 +        apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
8313 +    } else if(result == EINVAL) {
8314 +        apc_eprint("pthread mutex error: attr does not point to writeable memory.");
8315 +    } else if(result == EFAULT) {
8316 +        apc_eprint("pthread mutex error: attr is an invalid pointer.");
8317 +    } 
8318 +
8319 +    /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
8320 +    result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
8321 +    if(result == EINVAL) {
8322 +        apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
8323 +    } else if(result == EFAULT) {
8324 +        apc_eprint("pthread mutex error: attr is an invalid pointer.");
8325 +    } else if(result == ENOTSUP) {
8326 +        apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
8327 +    }
8328 +
8329 +    if(pthread_mutex_init(lock, attr)) { 
8330 +        apc_eprint("unable to initialize pthread lock");
8331 +    }
8332 +    return lock;
8333 +}
8334 +
8335 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
8336 +{
8337 +    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
8338 +}
8339 +
8340 +void apc_pthreadmutex_lock(pthread_mutex_t *lock)
8341 +{
8342 +    int result;
8343 +    result = pthread_mutex_lock(lock);
8344 +    if(result == EINVAL) {
8345 +        apc_eprint("unable to obtain pthread lock (EINVAL)");
8346 +    } else if(result == EDEADLK) {
8347 +        apc_eprint("unable to obtain pthread lock (EDEADLK)");
8348 +    }  
8349 +}
8350 +
8351 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
8352 +{
8353 +    if(pthread_mutex_unlock(lock)) {
8354 +        apc_eprint("unable to unlock pthread lock");
8355 +    }
8356 +}
8357 +
8358 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
8359 +{
8360 +    int rval;
8361 +    rval = pthread_mutex_trylock(lock);
8362 +    if(rval == EBUSY) {     /* Lock is already held */
8363 +        return 0;
8364 +    } else if(rval == 0) {  /* Obtained lock */
8365 +        return 1;
8366 +    } else {                /* Other error */
8367 +        apc_eprint("unable to obtain pthread trylock");
8368 +        return 0;
8369 +    }
8370 +}
8371 +
8372 +
8373 +#endif
8374 +
8375 +/*
8376 + * Local variables:
8377 + * tab-width: 4
8378 + * c-basic-offset: 4
8379 + * End:
8380 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8381 + * vim<600: expandtab sw=4 ts=4 sts=4
8382 + */
8383 diff -ruN php-5.1.6.old/ext/apc/apc_pthreadmutex.h php-5.1.6/ext/APC/apc_pthreadmutex.h
8384 --- php-5.1.6.old/ext/apc/apc_pthreadmutex.h    1969-12-31 18:00:00.000000000 -0600
8385 +++ php-5.1.6/ext/apc/apc_pthreadmutex.h        2007-04-02 18:05:30.000000000 -0500
8386 @@ -0,0 +1,48 @@
8387 +/*
8388 +  +----------------------------------------------------------------------+
8389 +  | APC                                                                  |
8390 +  +----------------------------------------------------------------------+
8391 +  | Copyright (c) 2006 The PHP Group                                     |
8392 +  +----------------------------------------------------------------------+
8393 +  | This source file is subject to version 3.01 of the PHP license,      |
8394 +  | that is bundled with this package in the file LICENSE, and is        |
8395 +  | available through the world-wide-web at the following url:           |
8396 +  | http://www.php.net/license/3_01.txt                                  |
8397 +  | If you did not receive a copy of the PHP license and are unable to   |
8398 +  | obtain it through the world-wide-web, please send a note to          |
8399 +  | license@php.net so we can mail you a copy immediately.               |
8400 +  +----------------------------------------------------------------------+
8401 +  | Authors: Brian Shire <shire@php.net>                                 |
8402 +  +----------------------------------------------------------------------+
8403 +
8404 + */
8405 +
8406 +/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
8407 +
8408 +#ifndef APC_PTHREADMUTEX_H
8409 +#define APC_PTHREADMUTEX_H
8410 +
8411 +#include "apc.h"
8412 +
8413 +#ifdef APC_PTHREADMUTEX_LOCKS 
8414 +
8415 +#include <pthread.h>
8416 +
8417 +pthread_mutex_t *apc_pthreadmutex_create();
8418 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
8419 +void apc_pthreadmutex_lock(pthread_mutex_t *lock);
8420 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
8421 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
8422 +
8423 +#endif
8424 +
8425 +#endif
8426 +
8427 +/*
8428 + * Local variables:
8429 + * tab-width: 4
8430 + * c-basic-offset: 4
8431 + * End:
8432 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8433 + * vim<600: expandtab sw=4 ts=4 sts=4
8434 + */
8435 diff -ruN php-5.1.6.old/ext/apc/apc_rfc1867.c php-5.1.6/ext/APC/apc_rfc1867.c
8436 --- php-5.1.6.old/ext/apc/apc_rfc1867.c 1969-12-31 18:00:00.000000000 -0600
8437 +++ php-5.1.6/ext/apc/apc_rfc1867.c     2007-04-02 18:05:30.000000000 -0500
8438 @@ -0,0 +1,175 @@
8439 +/*
8440 +  +----------------------------------------------------------------------+
8441 +  | APC                                                                  |
8442 +  +----------------------------------------------------------------------+
8443 +  | Copyright (c) 2006 The PHP Group                                     |
8444 +  +----------------------------------------------------------------------+
8445 +  | This source file is subject to version 3.01 of the PHP license,      |
8446 +  | that is bundled with this package in the file LICENSE, and is        |
8447 +  | available through the world-wide-web at the following url:           |
8448 +  | http://www.php.net/license/3_01.txt                                  |
8449 +  | If you did not receive a copy of the PHP license and are unable to   |
8450 +  | obtain it through the world-wide-web, please send a note to          |
8451 +  | license@php.net so we can mail you a copy immediately.               |
8452 +  +----------------------------------------------------------------------+
8453 +  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
8454 +  +----------------------------------------------------------------------+
8455 +
8456 +   This software was contributed to PHP by Community Connect Inc. in 2002
8457 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8458 +   Future revisions and derivatives of this source code must acknowledge
8459 +   Community Connect Inc. as the original contributor of this module by
8460 +   leaving this note intact in the source code.
8461 +
8462 +   All other licensing and usage conditions are those of the PHP Group.
8463 +
8464 + */
8465 +
8466 +/* $Id: apc_rfc1867.c,v 3.4 2007/02/24 11:45:29 rasmus Exp $*/
8467 +
8468 +#include "apc.h"
8469 +#include "rfc1867.h"
8470 +
8471 +#ifdef MULTIPART_EVENT_FORMDATA
8472 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8473 +
8474 +static double my_time() {
8475 +    struct timeval a;
8476 +    double t;
8477 +    gettimeofday(&a, NULL);
8478 +    t = a.tv_sec + (a.tv_usec/1000000);
8479 +    return t;
8480 +}
8481 +
8482 +void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
8483 +    static char tracking_key[64];
8484 +    static int  key_length = 0;
8485 +    static size_t content_length = 0;
8486 +    static char filename[128];
8487 +    static char name[64];
8488 +    static char *temp_filename=NULL;
8489 +    static int cancel_upload = 0;
8490 +    static double start_time;
8491 +    static size_t bytes_processed = 0;
8492 +    static double rate;
8493 +    zval *track = NULL;
8494 +
8495 +       switch (event) {
8496 +               case MULTIPART_EVENT_START:
8497 +                       {
8498 +                multipart_event_start *data = (multipart_event_start *) event_data;
8499 +                content_length = data->content_length;
8500 +                *tracking_key = '\0';
8501 +                *name = '\0';
8502 +                cancel_upload = 0;
8503 +                temp_filename = NULL;
8504 +                *filename= '\0';
8505 +                key_length = 0;
8506 +                start_time = my_time();
8507 +                bytes_processed = 0;
8508 +                rate = 0;
8509 +                       }
8510 +                       break;
8511 +
8512 +               case MULTIPART_EVENT_FORMDATA:
8513 +                       {
8514 +                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
8515 +
8516 +                               if(data->name && !strncasecmp(data->name,"apc_upload_progress",19) && data->value && data->length && data->length < 58) {
8517 +                    strlcat(tracking_key, "upload_", 63);
8518 +                    strlcat(tracking_key, *data->value, 63);
8519 +                    key_length = data->length+7;
8520 +                    bytes_processed = data->post_bytes_processed;
8521 +                               }
8522 +                       }
8523 +                       break;
8524 +
8525 +               case MULTIPART_EVENT_FILE_START:
8526 +            if(*tracking_key) {
8527 +                multipart_event_file_start *data = (multipart_event_file_start *) event_data;
8528 +
8529 +                bytes_processed = data->post_bytes_processed;
8530 +                strncpy(filename,*data->filename,127);
8531 +                temp_filename = NULL;
8532 +                strncpy(name,data->name,63);
8533 +                ALLOC_INIT_ZVAL(track);
8534 +                array_init(track);
8535 +                add_assoc_long(track, "total", content_length);
8536 +                add_assoc_long(track, "current", bytes_processed);
8537 +                add_assoc_string(track, "filename", filename, 1);
8538 +                add_assoc_string(track, "name", name, 1);
8539 +                add_assoc_long(track, "done", 0);
8540 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8541 +                zval_ptr_dtor(&track);
8542 +            }
8543 +            break;
8544 +
8545 +               case MULTIPART_EVENT_FILE_DATA:
8546 +            if(*tracking_key) {
8547 +                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
8548 +                bytes_processed = data->post_bytes_processed;
8549 +                ALLOC_INIT_ZVAL(track);
8550 +                array_init(track);
8551 +                add_assoc_long(track, "total", content_length);
8552 +                add_assoc_long(track, "current", bytes_processed);
8553 +                add_assoc_string(track, "filename", filename, 1);
8554 +                add_assoc_string(track, "name", name, 1);
8555 +                add_assoc_long(track, "done", 0);
8556 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8557 +                zval_ptr_dtor(&track);
8558 +                       }
8559 +                       break;
8560 +
8561 +               case MULTIPART_EVENT_FILE_END:
8562 +            if(*tracking_key) {
8563 +                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
8564 +                bytes_processed = data->post_bytes_processed;
8565 +                cancel_upload = data->cancel_upload;
8566 +                temp_filename = data->temp_filename;
8567 +                ALLOC_INIT_ZVAL(track);
8568 +                array_init(track);
8569 +                add_assoc_long(track, "total", content_length);
8570 +                add_assoc_long(track, "current", bytes_processed);
8571 +                add_assoc_string(track, "filename", filename, 1);
8572 +                add_assoc_string(track, "name", name, 1);
8573 +                add_assoc_string(track, "temp_filename", temp_filename, 1);
8574 +                add_assoc_long(track, "cancel_upload", cancel_upload);
8575 +                add_assoc_long(track, "done", 0);
8576 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8577 +                zval_ptr_dtor(&track);
8578 +                       }
8579 +                       break;
8580 +
8581 +               case MULTIPART_EVENT_END:
8582 +            if(*tracking_key) {
8583 +                double now = my_time(); 
8584 +                multipart_event_end *data = (multipart_event_end *) event_data;
8585 +                bytes_processed = data->post_bytes_processed;
8586 +                if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
8587 +                else rate = 8.0*bytes_processed;  /* Too quick */
8588 +                ALLOC_INIT_ZVAL(track);
8589 +                array_init(track);
8590 +                add_assoc_long(track, "total", content_length);
8591 +                add_assoc_long(track, "current", bytes_processed);
8592 +                add_assoc_double(track, "rate", rate);
8593 +                add_assoc_string(track, "filename", filename, 1);
8594 +                add_assoc_string(track, "name", name, 1);
8595 +                add_assoc_string(track, "temp_filename", temp_filename, 1);
8596 +                add_assoc_long(track, "cancel_upload", cancel_upload);
8597 +                add_assoc_long(track, "done", 1);
8598 +                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8599 +                zval_ptr_dtor(&track);
8600 +                       }
8601 +                       break;
8602 +       }
8603 +}
8604 +
8605 +#endif
8606 +/*
8607 + * Local variables:
8608 + * tab-width: 4
8609 + * c-basic-offset: 4
8610 + * End:
8611 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8612 + * vim<600: expandtab sw=4 ts=4 sts=4
8613 + */
8614 diff -ruN php-5.1.6.old/ext/apc/apc_sem.c php-5.1.6/ext/APC/apc_sem.c
8615 --- php-5.1.6.old/ext/apc/apc_sem.c     1969-12-31 18:00:00.000000000 -0600
8616 +++ php-5.1.6/ext/apc/apc_sem.c 2007-04-02 18:05:30.000000000 -0500
8617 @@ -0,0 +1,177 @@
8618 +/*
8619 +  +----------------------------------------------------------------------+
8620 +  | APC                                                                  |
8621 +  +----------------------------------------------------------------------+
8622 +  | Copyright (c) 2006 The PHP Group                                     |
8623 +  +----------------------------------------------------------------------+
8624 +  | This source file is subject to version 3.01 of the PHP license,      |
8625 +  | that is bundled with this package in the file LICENSE, and is        |
8626 +  | available through the world-wide-web at the following url:           |
8627 +  | http://www.php.net/license/3_01.txt                                  |
8628 +  | If you did not receive a copy of the PHP license and are unable to   |
8629 +  | obtain it through the world-wide-web, please send a note to          |
8630 +  | license@php.net so we can mail you a copy immediately.               |
8631 +  +----------------------------------------------------------------------+
8632 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8633 +  +----------------------------------------------------------------------+
8634 +
8635 +   This software was contributed to PHP by Community Connect Inc. in 2002
8636 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8637 +   Future revisions and derivatives of this source code must acknowledge
8638 +   Community Connect Inc. as the original contributor of this module by
8639 +   leaving this note intact in the source code.
8640 +
8641 +   All other licensing and usage conditions are those of the PHP Group.
8642 +
8643 + */
8644 +
8645 +/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
8646 +
8647 +#include "apc_sem.h"
8648 +#include "apc.h"
8649 +#include "php.h"
8650 +#include <sys/types.h>
8651 +#include <sys/ipc.h>
8652 +#include <sys/sem.h>
8653 +#include <sys/stat.h>
8654 +#include <unistd.h>
8655 +
8656 +#if HAVE_SEMUN
8657 +/* we have semun, no need to define */
8658 +#else
8659 +#undef HAVE_SEMUN
8660 +union semun {
8661 +    int val;                  /* value for SETVAL */
8662 +    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
8663 +    unsigned short *array;    /* array for GETALL, SETALL */
8664 +                              /* Linux specific part: */
8665 +    struct seminfo *__buf;    /* buffer for IPC_INFO */
8666 +};
8667 +#define HAVE_SEMUN 1
8668 +#endif
8669 +
8670 +#ifndef SEM_R
8671 +# define SEM_R 0444
8672 +#endif
8673 +#ifndef SEM_A
8674 +# define SEM_A 0222
8675 +#endif
8676 +
8677 +/* always use SEM_UNDO, otherwise we risk deadlock */
8678 +#define USE_SEM_UNDO
8679 +
8680 +#ifdef USE_SEM_UNDO
8681 +# define UNDO SEM_UNDO
8682 +#else
8683 +# define UNDO 0
8684 +#endif
8685 +
8686 +int apc_sem_create(const char* pathname, int proj, int initval)
8687 +{
8688 +    int semid;
8689 +    int perms;
8690 +    union semun arg;
8691 +    key_t key;
8692 +
8693 +    perms = 0777;
8694 +
8695 +    key = IPC_PRIVATE;
8696 +    if (pathname != NULL) {
8697 +        if ((key = ftok(pathname, proj)) < 0) {
8698 +            apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
8699 +        }
8700 +    }
8701 +    
8702 +    if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
8703 +        /* sempahore created for the first time, initialize now */
8704 +        arg.val = initval;
8705 +        if (semctl(semid, 0, SETVAL, arg) < 0) {
8706 +            apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
8707 +        }
8708 +    }
8709 +    else if (errno == EEXIST) {
8710 +        /* sempahore already exists, don't initialize */
8711 +        if ((semid = semget(key, 1, perms)) < 0) {
8712 +            apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8713 +        }
8714 +        /* insert <sleazy way to avoid race condition> here */
8715 +    }
8716 +    else {
8717 +        apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8718 +    }
8719 +
8720 +    return semid;
8721 +}
8722 +
8723 +void apc_sem_destroy(int semid)
8724 +{
8725 +    /* we expect this call to fail often, so we do not check */
8726 +    union semun arg;
8727 +    semctl(semid, 0, IPC_RMID, arg);
8728 +}
8729 +
8730 +void apc_sem_lock(int semid)
8731 +{
8732 +    struct sembuf op;
8733 +
8734 +    op.sem_num = 0;
8735 +    op.sem_op  = -1;
8736 +    op.sem_flg = UNDO;
8737 +
8738 +    if (semop(semid, &op, 1) < 0) {
8739 +        if (errno != EINTR) {
8740 +            apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
8741 +        }
8742 +    }
8743 +}
8744 +
8745 +void apc_sem_unlock(int semid)
8746 +{
8747 +    struct sembuf op;
8748 +
8749 +    op.sem_num = 0;
8750 +    op.sem_op  = 1;
8751 +    op.sem_flg = UNDO;
8752 +
8753 +    if (semop(semid, &op, 1) < 0) {
8754 +        if (errno != EINTR) {
8755 +            apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
8756 +        }
8757 +    }
8758 +}
8759 +
8760 +void apc_sem_wait_for_zero(int semid)
8761 +{
8762 +    struct sembuf op;
8763 +
8764 +    op.sem_num = 0;
8765 +    op.sem_op  = 0;
8766 +    op.sem_flg = UNDO;
8767 +
8768 +    if (semop(semid, &op, 1) < 0) {
8769 +        if (errno != EINTR) {
8770 +            apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
8771 +        }
8772 +    }
8773 +}
8774 +
8775 +int apc_sem_get_value(int semid)
8776 +{
8777 +    union semun arg;
8778 +    unsigned short val[1];
8779 +
8780 +    arg.array = val;
8781 +    if (semctl(semid, 0, GETALL, arg) < 0) {
8782 +        apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
8783 +    }
8784 +    return val[0];
8785 +}
8786 +
8787 +/*
8788 + * Local variables:
8789 + * tab-width: 4
8790 + * c-basic-offset: 4
8791 + * End:
8792 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8793 + * vim<600: expandtab sw=4 ts=4 sts=4
8794 + */
8795 diff -ruN php-5.1.6.old/ext/apc/apc_sem.h php-5.1.6/ext/APC/apc_sem.h
8796 --- php-5.1.6.old/ext/apc/apc_sem.h     1969-12-31 18:00:00.000000000 -0600
8797 +++ php-5.1.6/ext/apc/apc_sem.h 2007-04-02 18:05:30.000000000 -0500
8798 @@ -0,0 +1,51 @@
8799 +/*
8800 +  +----------------------------------------------------------------------+
8801 +  | APC                                                                  |
8802 +  +----------------------------------------------------------------------+
8803 +  | Copyright (c) 2006 The PHP Group                                     |
8804 +  +----------------------------------------------------------------------+
8805 +  | This source file is subject to version 3.01 of the PHP license,      |
8806 +  | that is bundled with this package in the file LICENSE, and is        |
8807 +  | available through the world-wide-web at the following url:           |
8808 +  | http://www.php.net/license/3_01.txt                                  |
8809 +  | If you did not receive a copy of the PHP license and are unable to   |
8810 +  | obtain it through the world-wide-web, please send a note to          |
8811 +  | license@php.net so we can mail you a copy immediately.               |
8812 +  +----------------------------------------------------------------------+
8813 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8814 +  +----------------------------------------------------------------------+
8815 +
8816 +   This software was contributed to PHP by Community Connect Inc. in 2002
8817 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8818 +   Future revisions and derivatives of this source code must acknowledge
8819 +   Community Connect Inc. as the original contributor of this module by
8820 +   leaving this note intact in the source code.
8821 +
8822 +   All other licensing and usage conditions are those of the PHP Group.
8823 +
8824 + */
8825 +
8826 +/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8827 +
8828 +#ifndef APC_SEM_H
8829 +#define APC_SEM_H
8830 +
8831 +/* Wrapper functions for SysV sempahores */
8832 +
8833 +extern int apc_sem_create(const char* pathname, int proj, int initval);
8834 +extern void apc_sem_destroy(int semid);
8835 +extern void apc_sem_lock(int semid);
8836 +extern void apc_sem_unlock(int semid);
8837 +extern void apc_sem_wait_for_zero(int semid);
8838 +extern int apc_sem_get_value(int semid);
8839 +
8840 +#endif
8841 +
8842 +/*
8843 + * Local variables:
8844 + * tab-width: 4
8845 + * c-basic-offset: 4
8846 + * End:
8847 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8848 + * vim<600: expandtab sw=4 ts=4 sts=4
8849 + */
8850 diff -ruN php-5.1.6.old/ext/apc/apc_shm.c php-5.1.6/ext/APC/apc_shm.c
8851 --- php-5.1.6.old/ext/apc/apc_shm.c     1969-12-31 18:00:00.000000000 -0600
8852 +++ php-5.1.6/ext/apc/apc_shm.c 2007-04-02 18:05:30.000000000 -0500
8853 @@ -0,0 +1,111 @@
8854 +/*
8855 +  +----------------------------------------------------------------------+
8856 +  | APC                                                                  |
8857 +  +----------------------------------------------------------------------+
8858 +  | Copyright (c) 2006 The PHP Group                                     |
8859 +  +----------------------------------------------------------------------+
8860 +  | This source file is subject to version 3.01 of the PHP license,      |
8861 +  | that is bundled with this package in the file LICENSE, and is        |
8862 +  | available through the world-wide-web at the following url:           |
8863 +  | http://www.php.net/license/3_01.txt                                  |
8864 +  | If you did not receive a copy of the PHP license and are unable to   |
8865 +  | obtain it through the world-wide-web, please send a note to          |
8866 +  | license@php.net so we can mail you a copy immediately.               |
8867 +  +----------------------------------------------------------------------+
8868 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8869 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
8870 +  +----------------------------------------------------------------------+
8871 +
8872 +   This software was contributed to PHP by Community Connect Inc. in 2002
8873 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8874 +   Future revisions and derivatives of this source code must acknowledge
8875 +   Community Connect Inc. as the original contributor of this module by
8876 +   leaving this note intact in the source code.
8877 +
8878 +   All other licensing and usage conditions are those of the PHP Group.
8879 +
8880 + */
8881 +
8882 +/* $Id: apc_shm.c,v 3.10 2006/05/31 22:24:48 rasmus Exp $ */
8883 +
8884 +#include "apc_shm.h"
8885 +#include "apc.h"
8886 +#include <sys/types.h>
8887 +#ifdef PHP_WIN32
8888 +/* shm functions are available in TSRM */
8889 +#include <tsrm/tsrm_win32.h>
8890 +#define key_t long
8891 +#else
8892 +#include <sys/ipc.h>
8893 +#include <sys/shm.h>
8894 +#include <sys/stat.h>
8895 +#endif
8896 +
8897 +#ifndef SHM_R
8898 +# define SHM_R 0444 /* read permission */
8899 +#endif
8900 +#ifndef SHM_A
8901 +# define SHM_A 0222 /* write permission */
8902 +#endif
8903 +
8904 +int apc_shm_create(const char* pathname, int proj, int size)
8905 +{
8906 +    int shmid;  /* shared memory id */
8907 +    int oflag;  /* permissions on shm */
8908 +    key_t key;  /* shm key returned by ftok */
8909 +
8910 +    key = IPC_PRIVATE;
8911 +#ifndef PHP_WIN32
8912 +       /* no ftok yet for win32 */
8913 +    if (pathname != NULL) {
8914 +        if ((key = ftok(pathname, proj)) < 0) {
8915 +            apc_eprint("apc_shm_create: ftok failed:");
8916 +        }
8917 +    }
8918 +#endif
8919 +
8920 +    oflag = IPC_CREAT | SHM_R | SHM_A;
8921 +    if ((shmid = shmget(key, size, oflag)) < 0) {
8922 +        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));
8923 +    }
8924 +
8925 +    return shmid;
8926 +}
8927 +
8928 +void apc_shm_destroy(int shmid)
8929 +{
8930 +    /* we expect this call to fail often, so we do not check */
8931 +    shmctl(shmid, IPC_RMID, 0);
8932 +}
8933 +
8934 +void* apc_shm_attach(int shmid)
8935 +{
8936 +    void* shmaddr;  /* the shared memory address */
8937 +
8938 +    if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
8939 +        apc_eprint("apc_shm_attach: shmat failed:");
8940 +    }
8941 +
8942 +    /*
8943 +     * We set the shmid for removal immediately after attaching to it. The
8944 +     * segment won't disappear until all processes have detached from it.
8945 +     */
8946 +    apc_shm_destroy(shmid);
8947 +    return shmaddr;
8948 +}
8949 +
8950 +void apc_shm_detach(void* shmaddr)
8951 +{
8952 +    if (shmdt(shmaddr) < 0) {
8953 +        apc_eprint("apc_shm_detach: shmdt failed:");
8954 +    }
8955 +}
8956 +
8957 +/*
8958 + * Local variables:
8959 + * tab-width: 4
8960 + * c-basic-offset: 4
8961 + * End:
8962 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8963 + * vim<600: expandtab sw=4 ts=4 sts=4
8964 + */
8965 diff -ruN php-5.1.6.old/ext/apc/apc_shm.h php-5.1.6/ext/APC/apc_shm.h
8966 --- php-5.1.6.old/ext/apc/apc_shm.h     1969-12-31 18:00:00.000000000 -0600
8967 +++ php-5.1.6/ext/apc/apc_shm.h 2007-04-02 18:05:30.000000000 -0500
8968 @@ -0,0 +1,49 @@
8969 +/*
8970 +  +----------------------------------------------------------------------+
8971 +  | APC                                                                  |
8972 +  +----------------------------------------------------------------------+
8973 +  | Copyright (c) 2006 The PHP Group                                     |
8974 +  +----------------------------------------------------------------------+
8975 +  | This source file is subject to version 3.01 of the PHP license,      |
8976 +  | that is bundled with this package in the file LICENSE, and is        |
8977 +  | available through the world-wide-web at the following url:           |
8978 +  | http://www.php.net/license/3_01.txt                                  |
8979 +  | If you did not receive a copy of the PHP license and are unable to   |
8980 +  | obtain it through the world-wide-web, please send a note to          |
8981 +  | license@php.net so we can mail you a copy immediately.               |
8982 +  +----------------------------------------------------------------------+
8983 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
8984 +  +----------------------------------------------------------------------+
8985 +
8986 +   This software was contributed to PHP by Community Connect Inc. in 2002
8987 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8988 +   Future revisions and derivatives of this source code must acknowledge
8989 +   Community Connect Inc. as the original contributor of this module by
8990 +   leaving this note intact in the source code.
8991 +
8992 +   All other licensing and usage conditions are those of the PHP Group.
8993 +
8994 + */
8995 +
8996 +/* $Id: apc_shm.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8997 +
8998 +#ifndef APC_SHM_H
8999 +#define APC_SHM_H
9000 +
9001 +/* Wrapper functions for unix shared memory */
9002 +
9003 +extern int apc_shm_create(const char* name, int proj, int size);
9004 +extern void apc_shm_destroy(int shmid);
9005 +extern void* apc_shm_attach(int shmid);
9006 +extern void apc_shm_detach(void* shmaddr);
9007 +
9008 +#endif
9009 +
9010 +/*
9011 + * Local variables:
9012 + * tab-width: 4
9013 + * c-basic-offset: 4
9014 + * End:
9015 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9016 + * vim<600: expandtab sw=4 ts=4 sts=4
9017 + */
9018 diff -ruN php-5.1.6.old/ext/apc/apc_sma.c php-5.1.6/ext/APC/apc_sma.c
9019 --- php-5.1.6.old/ext/apc/apc_sma.c     1969-12-31 18:00:00.000000000 -0600
9020 +++ php-5.1.6/ext/apc/apc_sma.c 2007-04-02 18:05:30.000000000 -0500
9021 @@ -0,0 +1,624 @@
9022 +/*
9023 +  +----------------------------------------------------------------------+
9024 +  | APC                                                                  |
9025 +  +----------------------------------------------------------------------+
9026 +  | Copyright (c) 2006 The PHP Group                                     |
9027 +  +----------------------------------------------------------------------+
9028 +  | This source file is subject to version 3.01 of the PHP license,      |
9029 +  | that is bundled with this package in the file LICENSE, and is        |
9030 +  | available through the world-wide-web at the following url:           |
9031 +  | http://www.php.net/license/3_01.txt                                  |
9032 +  | If you did not receive a copy of the PHP license and are unable to   |
9033 +  | obtain it through the world-wide-web, please send a note to          |
9034 +  | license@php.net so we can mail you a copy immediately.               |
9035 +  +----------------------------------------------------------------------+
9036 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9037 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
9038 +  +----------------------------------------------------------------------+
9039 +
9040 +   This software was contributed to PHP by Community Connect Inc. in 2002
9041 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9042 +   Future revisions and derivatives of this source code must acknowledge
9043 +   Community Connect Inc. as the original contributor of this module by
9044 +   leaving this note intact in the source code.
9045 +
9046 +   All other licensing and usage conditions are those of the PHP Group.
9047 +
9048 + */
9049 +
9050 +/* $Id: apc_sma.c,v 1.63 2007/04/02 09:02:57 gopalv Exp $ */
9051 +
9052 +#include "apc_sma.h"
9053 +#include "apc.h"
9054 +#include "apc_globals.h"
9055 +#include "apc_lock.h"
9056 +#include "apc_shm.h"
9057 +#include <limits.h>
9058 +#if APC_MMAP
9059 +void *apc_mmap(char *file_mask, int size);
9060 +void apc_unmap(void* shmaddr, int size);
9061 +#endif
9062 +
9063 +/* {{{ locking macros */
9064 +#define LOCK(c)         { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
9065 +#define RDLOCK(c)       { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
9066 +#define UNLOCK(c)       { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
9067 +/* }}} */
9068 +
9069 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
9070 +
9071 +static int sma_initialized = 0;     /* true if the sma has been initialized */
9072 +static unsigned int sma_numseg;     /* number of shm segments to allow */
9073 +static size_t sma_segsize;          /* size of each shm segment */
9074 +static int* sma_segments;           /* array of shm segment ids */
9075 +static void** sma_shmaddrs;         /* array of shm segment addresses */
9076 +static int sma_lastseg = 0;         /* index of MRU segment */
9077 +
9078 +typedef struct header_t header_t;
9079 +struct header_t {
9080 +    apc_lck_t sma_lock;     /* segment lock, MUST BE ALIGNED for futex locks */
9081 +    size_t segsize;         /* size of entire segment */
9082 +    size_t avail;           /* bytes available (not necessarily contiguous) */
9083 +    size_t nfoffset;        /* start next fit search from this offset       */
9084 +#if ALLOC_DISTRIBUTION
9085 +    size_t adist[30];
9086 +#endif
9087 +};
9088 +
9089 +
9090 +/* do not enable for threaded http servers */
9091 +/* #define __APC_SMA_DEBUG__ 1 */
9092 +
9093 +#ifdef __APC_SMA_DEBUG__
9094 +/* global counter for identifying blocks 
9095 + * Technically it is possible to do the same
9096 + * using offsets, but double allocations of the
9097 + * same offset can happen. */
9098 +static volatile size_t block_id = 0;
9099 +#endif
9100 +
9101 +#define APC_SMA_CANARIES 1   
9102 +
9103 +typedef struct block_t block_t;
9104 +struct block_t {
9105 +    size_t size;       /* size of this block */
9106 +    size_t next;       /* offset in segment of next free block */
9107 +#ifdef APC_SMA_CANARIES
9108 +    size_t canary;     /* canary to check for memory overwrites */
9109 +#endif
9110 +#ifdef __APC_SMA_DEBUG__
9111 +    size_t id;         /* identifier for the memory block */ 
9112 +#endif
9113 +};
9114 +
9115 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
9116 + * module. Both assume the presence of a variable shmaddr that points to the
9117 + * beginning of the shared memory segment in question. */
9118 +
9119 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
9120 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
9121 +
9122 +/* Canary macros for setting, checking and resetting memory canaries */
9123 +#ifdef APC_SMA_CANARIES
9124 +    #define SET_CANARY(v) (v)->canary = 0x42424242
9125 +    #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
9126 +    #define RESET_CANARY(v) (v)->canary = -42
9127 +#else
9128 +    #define SET_CANARY(v) 
9129 +    #define CHECK_CANARY(v)
9130 +    #define RESET_CANARY(v)
9131 +#endif
9132 +
9133 +
9134 +#ifdef max
9135 +#undef max
9136 +#endif
9137 +#define max(a, b) ((a) > (b) ? (a) : (b))
9138 +
9139 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
9140 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
9141 +#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
9142 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
9143 +/* }}} */
9144 +
9145 +/* {{{ sma_allocate: tries to allocate size bytes in a segment */
9146 +static int sma_allocate(void* shmaddr, size_t size)
9147 +{
9148 +    header_t* header;       /* header of shared memory segment */
9149 +    block_t* prv;           /* block prior to working block */
9150 +    block_t* cur;           /* working block in list */
9151 +    block_t* prvnextfit;    /* block before next fit */
9152 +    size_t realsize;        /* actual size of block needed, including header */
9153 +    size_t last_offset;     /* save the last search offset */
9154 +    int wrapped=0;
9155 +    const size_t block_size = ALIGNWORD(sizeof(struct block_t));
9156 +
9157 +    realsize = ALIGNWORD(size + block_size);
9158 +
9159 +    /*
9160 +     * First, insure that the segment contains at least realsize free bytes,
9161 +     * even if they are not contiguous.
9162 +     */
9163 +    header = (header_t*) shmaddr;
9164 +    if (header->avail < realsize) {
9165 +        return -1;
9166 +    }
9167 +
9168 +    prvnextfit = 0;     /* initially null (no fit) */
9169 +    last_offset = 0;
9170 +
9171 +    /* If we have a next fit offset, start searching from there */
9172 +    if(header->nfoffset) {
9173 +        prv = BLOCKAT(header->nfoffset);
9174 +    } else {    
9175 +        prv = BLOCKAT(sizeof(header_t));
9176 +    }
9177 +   
9178 +    CHECK_CANARY(prv);
9179 +
9180 +    while (prv->next != header->nfoffset) {
9181 +        cur = BLOCKAT(prv->next);
9182 +#ifdef __APC_SMA_DEBUG__
9183 +        CHECK_CANARY(cur);
9184 +#endif
9185 +        /* If it can fit realiszie bytes in cur block, stop searching */
9186 +        if (cur->size >= realsize) {
9187 +            prvnextfit = prv;
9188 +            break;
9189 +        }
9190 +        last_offset = prv->next;
9191 +        prv = cur;
9192 +        if(wrapped && (prv->next >= header->nfoffset)) break;
9193 +
9194 +        /* Check to see if we need to wrap around and search from the top */
9195 +        if(header->nfoffset && prv->next == 0) {
9196 +            prv = BLOCKAT(sizeof(header_t));
9197 +#ifdef __APC_SMA_DEBUG__
9198 +            CHECK_CANARY(prv);
9199 +#endif
9200 +            last_offset = 0;
9201 +            wrapped = 1;
9202 +        } 
9203 +    }
9204 +
9205 +    if (prvnextfit == 0) {
9206 +        header->nfoffset = 0;
9207 +        return -1;
9208 +    }
9209 +
9210 +    prv = prvnextfit;
9211 +    cur = BLOCKAT(prv->next);
9212 +
9213 +    CHECK_CANARY(prv);
9214 +    CHECK_CANARY(cur);
9215 +
9216 +    if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
9217 +        /* cur is big enough for realsize, but too small to split - unlink it */
9218 +        prv->next = cur->next;
9219 +    }
9220 +    else {
9221 +        block_t* nxt;      /* the new block (chopped part of cur) */
9222 +        size_t nxtoffset;  /* offset of the block currently after cur */
9223 +        size_t oldsize;    /* size of cur before split */
9224 +
9225 +        /* nextfit is too big; split it into two smaller blocks */
9226 +        nxtoffset = cur->next;
9227 +        oldsize = cur->size;
9228 +        prv->next += realsize;  /* skip over newly allocated block */
9229 +        cur->size = realsize;   /* Set the size of this new block */
9230 +        nxt = BLOCKAT(prv->next);
9231 +        nxt->next = nxtoffset;  /* Re-link the shortened block */
9232 +        nxt->size = oldsize - realsize;  /* and fix the size */
9233 +        SET_CANARY(nxt);
9234 +#ifdef __APC_SMA_DEBUG__
9235 +        nxt->id = -1;
9236 +#endif
9237 +    }
9238 +
9239 +    /* update the block header */
9240 +    header->avail -= cur->size;
9241 +#if ALLOC_DISTRIBUTION
9242 +    header->adist[(int)(log(size)/log(2))]++;
9243 +#endif
9244 +
9245 +    header->nfoffset = last_offset;
9246 +
9247 +    SET_CANARY(cur);
9248 +#ifdef __APC_SMA_DEBUG__
9249 +    cur->id = ++block_id;
9250 +    fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
9251 +#endif
9252 +
9253 +    return OFFSET(cur) + block_size;
9254 +}
9255 +/* }}} */
9256 +
9257 +/* {{{ sma_deallocate: deallocates the block at the given offset */
9258 +static int sma_deallocate(void* shmaddr, int offset)
9259 +{
9260 +    header_t* header;   /* header of shared memory segment */
9261 +    block_t* cur;       /* the new block to insert */
9262 +    block_t* prv;       /* the block before cur */
9263 +    block_t* nxt;       /* the block after cur */
9264 +    size_t size;        /* size of deallocated block */
9265 +
9266 +    offset -= ALIGNWORD(sizeof(struct block_t));
9267 +    assert(offset >= 0);
9268 +
9269 +    /* find position of new block in free list */
9270 +    cur = BLOCKAT(offset);
9271 +    prv = BLOCKAT(sizeof(header_t));
9272 +   
9273 +    CHECK_CANARY(cur);
9274 +
9275 +#ifdef __APC_SMA_DEBUG__
9276 +    CHECK_CANARY(prv);
9277 +    fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
9278 +#endif
9279 +    while (prv->next != 0 && prv->next < offset) {
9280 +        prv = BLOCKAT(prv->next);
9281 +#ifdef __APC_SMA_DEBUG__
9282 +        CHECK_CANARY(prv);
9283 +#endif
9284 +    }
9285 +    
9286 +    CHECK_CANARY(prv);
9287 +
9288 +    /* insert new block after prv */
9289 +    cur->next = prv->next;
9290 +    prv->next = offset;
9291 +
9292 +#ifdef __APC_SMA_DEBUG__
9293 +    CHECK_CANARY(cur);
9294 +    cur->id = -1;
9295 +#endif
9296 +    
9297 +    /* update the block header */
9298 +    header = (header_t*) shmaddr;
9299 +    header->avail += cur->size;
9300 +    size = cur->size;
9301 +
9302 +    if (((char *)prv) + prv->size == (char *) cur) {
9303 +        /* cur and prv share an edge, combine them */
9304 +        prv->size += cur->size;
9305 +        prv->next = cur->next;
9306 +        RESET_CANARY(cur);
9307 +        cur = prv;
9308 +    }
9309 +
9310 +    nxt = BLOCKAT(cur->next);
9311 +
9312 +    if (((char *)cur) + cur->size == (char *) nxt) {
9313 +        /* cur and nxt shared an edge, combine them */
9314 +        cur->size += nxt->size;
9315 +        cur->next = nxt->next;
9316 +#ifdef __APC_SMA_DEBUG__
9317 +        CHECK_CANARY(nxt);
9318 +        nxt->id = -1; /* assert this or set it ? */
9319 +#endif
9320 +        RESET_CANARY(nxt);
9321 +    }
9322 +    header->nfoffset = 0;  /* Reset the next fit search marker */
9323 +
9324 +    return size;
9325 +}
9326 +/* }}} */
9327 +
9328 +/* {{{ apc_sma_init */
9329 +
9330 +void apc_sma_init(int numseg, int segsize, char *mmap_file_mask)
9331 +{
9332 +    int i;
9333 +
9334 +    if (sma_initialized) {
9335 +        return;
9336 +    }
9337 +    sma_initialized = 1;
9338 +
9339 +#if APC_MMAP
9340 +    /*
9341 +     * I don't think multiple anonymous mmaps makes any sense
9342 +     * so force sma_numseg to 1 in this case
9343 +     */
9344 +    if(!mmap_file_mask || 
9345 +       (mmap_file_mask && !strlen(mmap_file_mask)) ||
9346 +       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
9347 +        sma_numseg = 1;
9348 +    } else {
9349 +        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9350 +    }
9351 +#else
9352 +    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9353 +#endif
9354 +
9355 +    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
9356 +
9357 +    sma_segments = (int*) apc_emalloc(sma_numseg*sizeof(int));
9358 +    sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
9359 +    
9360 +    for (i = 0; i < sma_numseg; i++) {
9361 +        header_t*   header;
9362 +        block_t*    block;
9363 +        void*       shmaddr;
9364 +
9365 +#if APC_MMAP
9366 +        sma_segments[i] = sma_segsize;
9367 +        sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
9368 +        if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
9369 +#else
9370 +        sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
9371 +        sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
9372 +#endif
9373 +        shmaddr = sma_shmaddrs[i];
9374 +    
9375 +        header = (header_t*) shmaddr;
9376 +        apc_lck_create(NULL, 0, 1, header->sma_lock);
9377 +        header->segsize = sma_segsize;
9378 +        header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) -
9379 +                        ALIGNWORD(sizeof(int));
9380 +        header->nfoffset = 0;
9381 +#if ALLOC_DISTRIBUTION
9382 +               {
9383 +           int j;
9384 +           for(j=0; j<30; j++) header->adist[j] = 0; 
9385 +        }
9386 +#endif 
9387 +        block = BLOCKAT(sizeof(header_t));
9388 +        block->size = 0;
9389 +        block->next = sizeof(header_t) + sizeof(block_t);
9390 +        SET_CANARY(block);
9391 +#ifdef __APC_SMA_DEBUG__
9392 +        block->id = -1;
9393 +#endif
9394 +        block = BLOCKAT(block->next);
9395 +        block->size = header->avail;
9396 +        block->next = 0;
9397 +        SET_CANARY(block);
9398 +#ifdef __APC_SMA_DEBUG__
9399 +        block->id = -1;
9400 +#endif
9401 +    }
9402 +}
9403 +/* }}} */
9404 +
9405 +/* {{{ apc_sma_cleanup */
9406 +void apc_sma_cleanup()
9407 +{
9408 +    int i;
9409 +
9410 +    assert(sma_initialized);
9411 +
9412 +    for (i = 0; i < sma_numseg; i++) {
9413 +        apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
9414 +#if APC_MMAP
9415 +        apc_unmap(sma_shmaddrs[i], sma_segments[i]);
9416 +#else
9417 +        apc_shm_detach(sma_shmaddrs[i]);
9418 +#endif
9419 +    }
9420 +    sma_initialized = 0;
9421 +    apc_efree(sma_segments);
9422 +    apc_efree(sma_shmaddrs);
9423 +}
9424 +/* }}} */
9425 +
9426 +/* {{{ apc_sma_malloc */
9427 +void* apc_sma_malloc(size_t n)
9428 +{
9429 +    int off;
9430 +    int i;
9431 +
9432 +    TSRMLS_FETCH();
9433 +    assert(sma_initialized);
9434 +    LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9435 +
9436 +    off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
9437 +    if (off != -1) {
9438 +        void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
9439 +        if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9440 +        UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9441 +        return p;
9442 +    }
9443 +    UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9444 +
9445 +    for (i = 0; i < sma_numseg; i++) {
9446 +        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9447 +        if (i == sma_lastseg) {
9448 +            continue;
9449 +        }
9450 +        off = sma_allocate(sma_shmaddrs[i], n);
9451 +        if (off != -1) {
9452 +            void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
9453 +            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9454 +            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9455 +            sma_lastseg = i;
9456 +            return p;
9457 +        }
9458 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9459 +    }
9460 +
9461 +    return NULL;
9462 +}
9463 +/* }}} */
9464 +
9465 +/* {{{ apc_sma_realloc */
9466 +void* apc_sma_realloc(void *p, size_t n)
9467 +{
9468 +    apc_sma_free(p);
9469 +    return apc_sma_malloc(n);
9470 +}
9471 +/* }}} */
9472 +
9473 +/* {{{ apc_sma_strdup */
9474 +char* apc_sma_strdup(const char* s)
9475 +{
9476 +    void* q;
9477 +    int len;
9478 +
9479 +    if(!s) return NULL;
9480 +
9481 +    len = strlen(s)+1;
9482 +    q = apc_sma_malloc(len);
9483 +    if(!q) return NULL;
9484 +    memcpy(q, s, len);
9485 +    return q;
9486 +}
9487 +/* }}} */
9488 +
9489 +/* {{{ apc_sma_free */
9490 +void apc_sma_free(void* p)
9491 +{
9492 +    int i;
9493 +    size_t offset;
9494 +    size_t d_size;
9495 +    TSRMLS_FETCH();
9496 +
9497 +    if (p == NULL) {
9498 +        return;
9499 +    }
9500 +
9501 +    assert(sma_initialized);
9502 +
9503 +    for (i = 0; i < sma_numseg; i++) {
9504 +        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9505 +        offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
9506 +        if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
9507 +            d_size = sma_deallocate(sma_shmaddrs[i], offset);
9508 +            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
9509 +            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9510 +            return;
9511 +        }
9512 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9513 +    }
9514 +
9515 +    apc_eprint("apc_sma_free: could not locate address %p", p);
9516 +}
9517 +/* }}} */
9518 +
9519 +/* {{{ apc_sma_info */
9520 +apc_sma_info_t* apc_sma_info(zend_bool limited)
9521 +{
9522 +    apc_sma_info_t* info;
9523 +    apc_sma_link_t** link;
9524 +    int i;
9525 +       char* shmaddr;
9526 +       block_t* prv;
9527 +       
9528 +    if (!sma_initialized) {
9529 +        return NULL;
9530 +    }
9531 +
9532 +    info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
9533 +    info->num_seg = sma_numseg;
9534 +    info->seg_size = sma_segsize - sizeof(header_t) - sizeof(block_t) - ALIGNWORD(sizeof(int));
9535 +
9536 +    info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
9537 +    for (i = 0; i < sma_numseg; i++) {
9538 +        info->list[i] = NULL;
9539 +    }
9540 +
9541 +    if(limited) return info;
9542 +
9543 +    /* For each segment */
9544 +    for (i = 0; i < sma_numseg; i++) {
9545 +        RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9546 +        shmaddr = sma_shmaddrs[i];
9547 +        prv = BLOCKAT(sizeof(header_t));
9548 +
9549 +        link = &info->list[i];
9550 +
9551 +        /* For each block in this segment */
9552 +        while (prv->next != 0) {
9553 +            block_t* cur = BLOCKAT(prv->next);
9554 +#ifdef __APC_SMA_DEBUG__
9555 +            CHECK_CANARY(cur);
9556 +#endif
9557 +
9558 +            *link = apc_emalloc(sizeof(apc_sma_link_t));
9559 +            (*link)->size = cur->size;
9560 +            (*link)->offset = prv->next;
9561 +            (*link)->next = NULL;
9562 +            link = &(*link)->next;
9563 +
9564 +            prv = cur;
9565 +        }
9566 +        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9567 +    }
9568 +
9569 +    return info;
9570 +}
9571 +/* }}} */
9572 +
9573 +/* {{{ apc_sma_free_info */
9574 +void apc_sma_free_info(apc_sma_info_t* info)
9575 +{
9576 +    int i;
9577 +
9578 +    for (i = 0; i < info->num_seg; i++) {
9579 +        apc_sma_link_t* p = info->list[i];
9580 +        while (p) {
9581 +            apc_sma_link_t* q = p;
9582 +            p = p->next;
9583 +            apc_efree(q);
9584 +        }
9585 +    }
9586 +    apc_efree(info->list);
9587 +    apc_efree(info);
9588 +}
9589 +/* }}} */
9590 +
9591 +/* {{{ apc_sma_get_avail_mem */
9592 +int apc_sma_get_avail_mem()
9593 +{
9594 +    int avail_mem = 0;
9595 +    int i;
9596 +    
9597 +    for (i = 0; i < sma_numseg; i++) {
9598 +        header_t* header = (header_t*) sma_shmaddrs[i];
9599 +        avail_mem += header->avail;
9600 +    }
9601 +    return avail_mem;
9602 +}
9603 +/* }}} */
9604 +
9605 +#if ALLOC_DISTRIBUTION
9606 +size_t *apc_sma_get_alloc_distribution(void) {
9607 +    header_t* header = (header_t*) sma_shmaddrs[0];
9608 +    return header->adist; 
9609 +}
9610 +#endif
9611 +
9612 +#if 0
9613 +/* {{{ apc_sma_check_integrity */
9614 +void apc_sma_check_integrity()
9615 +{
9616 +    int i;
9617 +
9618 +    /* For each segment */
9619 +    for (i = 0; i < sma_numseg; i++) {
9620 +        char* shmaddr = sma_shmaddrs[i];
9621 +        header_t* header = (header_t*) shmaddr;
9622 +        block_t* prv = BLOCKAT(sizeof(header_t));
9623 +        int avail = 0;
9624 +
9625 +        /* For each block in this segment */
9626 +        while (prv->next != 0) {
9627 +            block_t* cur = BLOCKAT(prv->next);
9628 +            avail += cur->size;
9629 +            prv = cur;
9630 +        }
9631 +
9632 +        assert(avail == header->avail);
9633 +    }
9634 +}
9635 +/* }}} */
9636 +#endif
9637 +
9638 +/*
9639 + * Local variables:
9640 + * tab-width: 4
9641 + * c-basic-offset: 4
9642 + * End:
9643 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9644 + * vim<600: expandtab sw=4 ts=4 sts=4
9645 + */
9646 diff -ruN php-5.1.6.old/ext/apc/apc_sma.h php-5.1.6/ext/APC/apc_sma.h
9647 --- php-5.1.6.old/ext/apc/apc_sma.h     1969-12-31 18:00:00.000000000 -0600
9648 +++ php-5.1.6/ext/apc/apc_sma.h 2007-04-02 18:05:30.000000000 -0500
9649 @@ -0,0 +1,82 @@
9650 +/*
9651 +  +----------------------------------------------------------------------+
9652 +  | APC                                                                  |
9653 +  +----------------------------------------------------------------------+
9654 +  | Copyright (c) 2006 The PHP Group                                     |
9655 +  +----------------------------------------------------------------------+
9656 +  | This source file is subject to version 3.01 of the PHP license,      |
9657 +  | that is bundled with this package in the file LICENSE, and is        |
9658 +  | available through the world-wide-web at the following url:           |
9659 +  | http://www.php.net/license/3_01.txt                                  |
9660 +  | If you did not receive a copy of the PHP license and are unable to   |
9661 +  | obtain it through the world-wide-web, please send a note to          |
9662 +  | license@php.net so we can mail you a copy immediately.               |
9663 +  +----------------------------------------------------------------------+
9664 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9665 +  +----------------------------------------------------------------------+
9666 +
9667 +   This software was contributed to PHP by Community Connect Inc. in 2002
9668 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9669 +   Future revisions and derivatives of this source code must acknowledge
9670 +   Community Connect Inc. as the original contributor of this module by
9671 +   leaving this note intact in the source code.
9672 +
9673 +   All other licensing and usage conditions are those of the PHP Group.
9674 +
9675 + */
9676 +
9677 +/* $Id: apc_sma.h,v 1.16 2007/02/24 11:59:40 rasmus Exp $ */
9678 +
9679 +#ifndef APC_SMA_H
9680 +#define APC_SMA_H
9681 +
9682 +#define ALLOC_DISTRIBUTION 0
9683 +
9684 +#include "apc.h"
9685 +
9686 +/* Simple shared memory allocator */
9687 +
9688 +extern void apc_sma_init(int numseg, int segsize, char *mmap_file_mask);
9689 +extern void apc_sma_cleanup();
9690 +extern void* apc_sma_malloc(size_t size);
9691 +extern void* apc_sma_realloc(void* p, size_t size);
9692 +extern char* apc_sma_strdup(const char *s);
9693 +extern void apc_sma_free(void* p);
9694 +#if ALLOC_DISTRIBUTION 
9695 +extern size_t *apc_sma_get_alloc_distribution();
9696 +#endif
9697 +
9698 +/* {{{ struct definition: apc_sma_link_t */
9699 +typedef struct apc_sma_link_t apc_sma_link_t;
9700 +struct apc_sma_link_t {
9701 +    int size;               /* size of this free block */
9702 +    int offset;             /* offset in segment of this block */
9703 +    apc_sma_link_t* next;   /* link to next free block */
9704 +};
9705 +/* }}} */
9706 +
9707 +/* {{{ struct definition: apc_sma_info_t */
9708 +typedef struct apc_sma_info_t apc_sma_info_t;
9709 +struct apc_sma_info_t {
9710 +    int num_seg;            /* number of shared memory segments */
9711 +    int seg_size;           /* size of each shared memory segment */
9712 +    apc_sma_link_t** list;  /* there is one list per segment */
9713 +};
9714 +/* }}} */
9715 +
9716 +extern apc_sma_info_t* apc_sma_info(zend_bool limited);
9717 +extern void apc_sma_free_info(apc_sma_info_t* info);
9718 +
9719 +extern int apc_sma_get_avail_mem();
9720 +extern void apc_sma_check_integrity();
9721 +
9722 +#endif
9723 +
9724 +/*
9725 + * Local variables:
9726 + * tab-width: 4
9727 + * c-basic-offset: 4
9728 + * End:
9729 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9730 + * vim<600: expandtab sw=4 ts=4 sts=4
9731 + */
9732 diff -ruN php-5.1.6.old/ext/apc/apc_spin.c php-5.1.6/ext/APC/apc_spin.c
9733 --- php-5.1.6.old/ext/apc/apc_spin.c    1969-12-31 18:00:00.000000000 -0600
9734 +++ php-5.1.6/ext/apc/apc_spin.c        2007-04-02 18:05:30.000000000 -0500
9735 @@ -0,0 +1,65 @@
9736 +/*
9737 +  +----------------------------------------------------------------------+
9738 +  | APC                                                                  |
9739 +  +----------------------------------------------------------------------+
9740 +  | Copyright (c) 2007 The PHP Group                                     |
9741 +  +----------------------------------------------------------------------+
9742 +  | This source file is subject to version 3.01 of the PHP license,      |
9743 +  | that is bundled with this package in the file LICENSE, and is        |
9744 +  | available through the world-wide-web at the following url:           |
9745 +  | http://www.php.net/license/3_01.txt                                  |
9746 +  | If you did not receive a copy of the PHP license and are unable to   |
9747 +  | obtain it through the world-wide-web, please send a note to          |
9748 +  | license@php.net so we can mail you a copy immediately.               |
9749 +  +----------------------------------------------------------------------+
9750 +  | Authors: Brian Shire <shire@php.net>                                 |
9751 +  +----------------------------------------------------------------------+
9752 +
9753 + */
9754 +
9755 +/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9756 +
9757 +#include "apc_spin.h"
9758 +
9759 +#ifdef APC_SPIN_LOCKS
9760 +
9761 +slock_t *apc_slock_create(slock_t *lock) 
9762 +{
9763 +   S_INIT_LOCK(lock); 
9764 +}
9765 +
9766 +void apc_slock_destroy(slock_t *lock)
9767 +{
9768 +    S_LOCK_FREE(lock);
9769 +}
9770 +
9771 +void apc_slock_lock(slock_t *lock)
9772 +{
9773 +    S_LOCK(lock);
9774 +}
9775 +
9776 +void apc_slock_unlock(slock_t *lock)
9777 +{
9778 +    S_UNLOCK(lock);
9779 +}
9780 +
9781 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
9782 +{
9783 +    /* Technically we aren't supposed to call this directly, but the original
9784 +     *  code provides no method for absolute non-blocking locks, so we'll call into
9785 +     *  the TAS (test and set) functionality directly 
9786 +     */
9787 +    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
9788 +}
9789 +
9790 +
9791 +#endif
9792 +
9793 +/*
9794 + * Local variables:
9795 + * tab-width: 4
9796 + * c-basic-offset: 4
9797 + * End:
9798 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9799 + * vim<600: expandtab sw=4 ts=4 sts=4
9800 + */
9801 diff -ruN php-5.1.6.old/ext/apc/apc_spin.h php-5.1.6/ext/APC/apc_spin.h
9802 --- php-5.1.6.old/ext/apc/apc_spin.h    1969-12-31 18:00:00.000000000 -0600
9803 +++ php-5.1.6/ext/apc/apc_spin.h        2007-04-02 18:05:30.000000000 -0500
9804 @@ -0,0 +1,48 @@
9805 +/*
9806 +  +----------------------------------------------------------------------+
9807 +  | APC                                                                  |
9808 +  +----------------------------------------------------------------------+
9809 +  | Copyright (c) 2007 The PHP Group                                     |
9810 +  +----------------------------------------------------------------------+
9811 +  | This source file is subject to version 3.01 of the PHP license,      |
9812 +  | that is bundled with this package in the file LICENSE, and is        |
9813 +  | available through the world-wide-web at the following url:           |
9814 +  | http://www.php.net/license/3_01.txt                                  |
9815 +  | If you did not receive a copy of the PHP license and are unable to   |
9816 +  | obtain it through the world-wide-web, please send a note to          |
9817 +  | license@php.net so we can mail you a copy immediately.               |
9818 +  +----------------------------------------------------------------------+
9819 +  | Authors: Brian Shire <shire@php.net>                                 |
9820 +  +----------------------------------------------------------------------+
9821 +
9822 + */
9823 +
9824 +/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9825 +
9826 +#ifndef APC_SPIN_H
9827 +#define APC_SPIN_H
9828 +
9829 +#include "apc.h"
9830 +
9831 +#ifdef APC_SPIN_LOCKS 
9832 +
9833 +#include "pgsql_s_lock.h"
9834 +
9835 +pthread_mutex_t *apc_spin_create();
9836 +void apc_spin_destroy(pthread_mutex_t *lock);
9837 +void apc_spin_lock(pthread_mutex_t *lock);
9838 +void apc_spin_unlock(pthread_mutex_t *lock);
9839 +zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
9840 +
9841 +#endif
9842 +
9843 +#endif
9844 +
9845 +/*
9846 + * Local variables:
9847 + * tab-width: 4
9848 + * c-basic-offset: 4
9849 + * End:
9850 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9851 + * vim<600: expandtab sw=4 ts=4 sts=4
9852 + */
9853 diff -ruN php-5.1.6.old/ext/apc/apc_stack.c php-5.1.6/ext/APC/apc_stack.c
9854 --- php-5.1.6.old/ext/apc/apc_stack.c   1969-12-31 18:00:00.000000000 -0600
9855 +++ php-5.1.6/ext/apc/apc_stack.c       2007-04-02 18:05:30.000000000 -0500
9856 @@ -0,0 +1,105 @@
9857 +/*
9858 +  +----------------------------------------------------------------------+
9859 +  | APC                                                                  |
9860 +  +----------------------------------------------------------------------+
9861 +  | Copyright (c) 2006 The PHP Group                                     |
9862 +  +----------------------------------------------------------------------+
9863 +  | This source file is subject to version 3.01 of the PHP license,      |
9864 +  | that is bundled with this package in the file LICENSE, and is        |
9865 +  | available through the world-wide-web at the following url:           |
9866 +  | http://www.php.net/license/3_01.txt                                  |
9867 +  | If you did not receive a copy of the PHP license and are unable to   |
9868 +  | obtain it through the world-wide-web, please send a note to          |
9869 +  | license@php.net so we can mail you a copy immediately.               |
9870 +  +----------------------------------------------------------------------+
9871 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9872 +  +----------------------------------------------------------------------+
9873 +
9874 +   This software was contributed to PHP by Community Connect Inc. in 2002
9875 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9876 +   Future revisions and derivatives of this source code must acknowledge
9877 +   Community Connect Inc. as the original contributor of this module by
9878 +   leaving this note intact in the source code.
9879 +
9880 +   All other licensing and usage conditions are those of the PHP Group.
9881 +
9882 + */
9883 +
9884 +/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
9885 +
9886 +#include "apc_stack.h"
9887 +#include "apc.h"
9888 +
9889 +struct apc_stack_t {
9890 +    void** data;
9891 +    int capacity;
9892 +    int size;
9893 +};
9894 +
9895 +apc_stack_t* apc_stack_create(int size_hint)
9896 +{
9897 +    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
9898 +
9899 +    stack->capacity = (size_hint > 0) ? size_hint : 10;
9900 +    stack->size = 0;
9901 +    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
9902 +
9903 +    return stack;
9904 +}
9905 +
9906 +void apc_stack_destroy(apc_stack_t* stack)
9907 +{
9908 +    if (stack != NULL) {
9909 +        apc_efree(stack->data);
9910 +        apc_efree(stack);
9911 +    }
9912 +}
9913 +
9914 +void apc_stack_clear(apc_stack_t* stack)
9915 +{
9916 +    assert(stack != NULL);
9917 +    stack->size = 0;
9918 +}
9919 +
9920 +void apc_stack_push(apc_stack_t* stack, void* item)
9921 +{
9922 +    assert(stack != NULL);
9923 +    if (stack->size == stack->capacity) {
9924 +        stack->capacity *= 2;
9925 +        stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
9926 +    }
9927 +    stack->data[stack->size++] = item;
9928 +}
9929 +
9930 +void* apc_stack_pop(apc_stack_t* stack)
9931 +{
9932 +    assert(stack != NULL && stack->size > 0);
9933 +    return stack->data[--stack->size];
9934 +}
9935 +
9936 +void* apc_stack_top(apc_stack_t* stack)
9937 +{
9938 +    assert(stack != NULL && stack->size > 0);
9939 +    return stack->data[stack->size-1];
9940 +}
9941 +
9942 +void* apc_stack_get(apc_stack_t* stack, int n)
9943 +{
9944 +    assert(stack != NULL && stack->size > n);
9945 +    return stack->data[n];
9946 +}
9947 +
9948 +int apc_stack_size(apc_stack_t* stack)
9949 +{
9950 +    assert(stack != NULL);
9951 +    return stack->size;
9952 +}
9953 +
9954 +/*
9955 + * Local variables:
9956 + * tab-width: 4
9957 + * c-basic-offset: 4
9958 + * End:
9959 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9960 + * vim<600: expandtab sw=4 ts=4 sts=4
9961 + */
9962 diff -ruN php-5.1.6.old/ext/apc/apc_stack.h php-5.1.6/ext/APC/apc_stack.h
9963 --- php-5.1.6.old/ext/apc/apc_stack.h   1969-12-31 18:00:00.000000000 -0600
9964 +++ php-5.1.6/ext/apc/apc_stack.h       2007-04-02 18:05:30.000000000 -0500
9965 @@ -0,0 +1,58 @@
9966 +/*
9967 +  +----------------------------------------------------------------------+
9968 +  | APC                                                                  |
9969 +  +----------------------------------------------------------------------+
9970 +  | Copyright (c) 2006 The PHP Group                                     |
9971 +  +----------------------------------------------------------------------+
9972 +  | This source file is subject to version 3.01 of the PHP license,      |
9973 +  | that is bundled with this package in the file LICENSE, and is        |
9974 +  | available through the world-wide-web at the following url:           |
9975 +  | http://www.php.net/license/3_01.txt                                  |
9976 +  | If you did not receive a copy of the PHP license and are unable to   |
9977 +  | obtain it through the world-wide-web, please send a note to          |
9978 +  | license@php.net so we can mail you a copy immediately.               |
9979 +  +----------------------------------------------------------------------+
9980 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
9981 +  |          George Schlossnagle <george@omniti.com>                     |
9982 +  +----------------------------------------------------------------------+
9983 +
9984 +   This software was contributed to PHP by Community Connect Inc. in 2002
9985 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9986 +   Future revisions and derivatives of this source code must acknowledge
9987 +   Community Connect Inc. as the original contributor of this module by
9988 +   leaving this note intact in the source code.
9989 +
9990 +   All other licensing and usage conditions are those of the PHP Group.
9991 +
9992 + */
9993 +
9994 +/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
9995 +
9996 +#ifndef APC_STACK_H
9997 +#define APC_STACK_H
9998 +
9999 +/* Basic stack datatype */
10000 +
10001 +#define T apc_stack_t*
10002 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
10003 +
10004 +extern T apc_stack_create(int size_hint);
10005 +extern void apc_stack_destroy(T stack);
10006 +extern void apc_stack_clear(T stack);
10007 +extern void apc_stack_push(T stack, void* item);
10008 +extern void* apc_stack_pop(T stack);
10009 +extern void* apc_stack_top(T stack);
10010 +extern void* apc_stack_get(T stack, int n);
10011 +extern int apc_stack_size(T stack);
10012 +
10013 +#undef T
10014 +#endif
10015 +
10016 +/*
10017 + * Local variables:
10018 + * tab-width: 4
10019 + * c-basic-offset: 4
10020 + * End:
10021 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10022 + * vim<600: expandtab sw=4 ts=4 sts=4
10023 + */
10024 diff -ruN php-5.1.6.old/ext/apc/apc_zend.c php-5.1.6/ext/APC/apc_zend.c
10025 --- php-5.1.6.old/ext/apc/apc_zend.c    1969-12-31 18:00:00.000000000 -0600
10026 +++ php-5.1.6/ext/apc/apc_zend.c        2007-04-02 18:05:30.000000000 -0500
10027 @@ -0,0 +1,277 @@
10028 +/*
10029 +  +----------------------------------------------------------------------+
10030 +  | APC                                                                  |
10031 +  +----------------------------------------------------------------------+
10032 +  | Copyright (c) 2006 The PHP Group                                     |
10033 +  +----------------------------------------------------------------------+
10034 +  | This source file is subject to version 3.01 of the PHP license,      |
10035 +  | that is bundled with this package in the file LICENSE, and is        |
10036 +  | available through the world-wide-web at the following url:           |
10037 +  | http://www.php.net/license/3_01.txt                                  |
10038 +  | If you did not receive a copy of the PHP license and are unable to   |
10039 +  | obtain it through the world-wide-web, please send a note to          |
10040 +  | license@php.net so we can mail you a copy immediately.               |
10041 +  +----------------------------------------------------------------------+
10042 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10043 +  +----------------------------------------------------------------------+
10044 +
10045 +   This software was contributed to PHP by Community Connect Inc. in 2002
10046 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10047 +   Future revisions and derivatives of this source code must acknowledge
10048 +   Community Connect Inc. as the original contributor of this module by
10049 +   leaving this note intact in the source code.
10050 +
10051 +   All other licensing and usage conditions are those of the PHP Group.
10052 +
10053 + */
10054 +
10055 +/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
10056 +
10057 +#include "apc_zend.h"
10058 +#include "apc_globals.h"
10059 +
10060 +void* apc_php_malloc(size_t n)
10061 +{
10062 +    return emalloc(n);
10063 +}
10064 +
10065 +void apc_php_free(void* p)
10066 +{
10067 +    efree(p);
10068 +}
10069 +
10070 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
10071 +# define ZEND_VM_KIND_CALL     1
10072 +#endif
10073 +
10074 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
10075 +# define ZEND_VM_KIND  ZEND_VM_KIND_CALL
10076 +#endif
10077 +
10078 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
10079 +# define APC_OPCODE_OVERRIDE
10080 +#endif
10081 +
10082 +#ifdef APC_OPCODE_OVERRIDE
10083 +
10084 +#ifdef ZEND_ENGINE_2_1
10085 +/* Taken from Zend/zend_vm_execute.h */
10086 +#define _CONST_CODE  0
10087 +#define _TMP_CODE    1
10088 +#define _VAR_CODE    2
10089 +#define _UNUSED_CODE 3
10090 +#define _CV_CODE     4
10091 +static inline int _apc_opcode_handler_decode(zend_op *opline)
10092 +{
10093 +       static const int apc_vm_decode[] = {
10094 +               _UNUSED_CODE, /* 0              */
10095 +               _CONST_CODE,  /* 1 = IS_CONST   */
10096 +               _TMP_CODE,    /* 2 = IS_TMP_VAR */
10097 +               _UNUSED_CODE, /* 3              */
10098 +               _VAR_CODE,    /* 4 = IS_VAR     */
10099 +               _UNUSED_CODE, /* 5              */
10100 +               _UNUSED_CODE, /* 6              */
10101 +               _UNUSED_CODE, /* 7              */
10102 +               _UNUSED_CODE, /* 8 = IS_UNUSED  */
10103 +               _UNUSED_CODE, /* 9              */
10104 +               _UNUSED_CODE, /* 10             */
10105 +               _UNUSED_CODE, /* 11             */
10106 +               _UNUSED_CODE, /* 12             */
10107 +               _UNUSED_CODE, /* 13             */
10108 +               _UNUSED_CODE, /* 14             */
10109 +               _UNUSED_CODE, /* 15             */
10110 +               _CV_CODE      /* 16 = IS_CV     */
10111 +       };
10112 +       return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
10113 +}
10114 +
10115 +# define APC_ZEND_OPLINE                                       zend_op *opline = execute_data->opline;
10116 +# define APC_OPCODE_HANDLER_DECODE(opline)     _apc_opcode_handler_decode(opline)
10117 +# if PHP_MAJOR_VERSION >= 6
10118 +#  define APC_OPCODE_HANDLER_COUNT                     ((25 * 152) + 1)
10119 +# else
10120 +#  define APC_OPCODE_HANDLER_COUNT                     ((25 * 151) + 1)
10121 +# endif
10122 +# 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; }
10123 +
10124 +#else /* ZE2.0 */
10125 +# define APC_ZEND_ONLINE
10126 +# define APC_OPCODE_HANDLER_DECODE(opline)     (opline->opcode)
10127 +# define APC_OPCODE_HANDLER_COUNT                      512
10128 +# define APC_REPLACE_OPCODE(opname)                    zend_opcode_handlers[opname] = apc_op_##opname;
10129 +#endif
10130 +
10131 +static opcode_handler_t *apc_original_opcode_handlers;
10132 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
10133 +
10134 +#define APC_EX_T(offset)                                       (*(temp_variable *)((char*)execute_data->Ts + offset))
10135 +
10136 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
10137 +{
10138 +       *freeval = NULL;
10139 +
10140 +       switch (node->op_type) {
10141 +               case IS_CONST:
10142 +                       return &(node->u.constant);
10143 +               case IS_VAR:
10144 +                       return APC_EX_T(node->u.var).var.ptr;
10145 +               case IS_TMP_VAR:
10146 +                       return (*freeval = &APC_EX_T(node->u.var).tmp_var);
10147 +#ifdef ZEND_ENGINE_2_1
10148 +               case IS_CV:
10149 +               {
10150 +                       zval ***ret = &execute_data->CVs[node->u.var];
10151 +
10152 +                       if (!*ret) {
10153 +                               zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
10154 +
10155 +                               if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
10156 +                                       apc_nprint("Undefined variable: %s", cv->name);
10157 +                                       return &EG(uninitialized_zval);
10158 +                               }
10159 +                       }
10160 +                       return **ret;
10161 +               }
10162 +#endif
10163 +               case IS_UNUSED:
10164 +               default:
10165 +                       return NULL;
10166 +       }
10167 +}
10168 +
10169 +static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
10170 +{
10171 +       APC_ZEND_OPLINE
10172 +       zval *freeop1 = NULL;
10173 +       zval *inc_filename = NULL, tmp_inc_filename;
10174 +       char realpath[MAXPATHLEN];
10175 +       php_stream_wrapper *wrapper;
10176 +       char *path_for_open;
10177 +       int ret = 0;
10178 +       #ifdef ZEND_ENGINE_2
10179 +       apc_opflags_t* flags = NULL;
10180 +       #endif
10181 +
10182 +       if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
10183 +               Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
10184 +               return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10185 +       }
10186 +
10187 +       inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
10188 +       if (Z_TYPE_P(inc_filename) != IS_STRING) {
10189 +               tmp_inc_filename = *inc_filename;
10190 +               zval_copy_ctor(&tmp_inc_filename);
10191 +               convert_to_string(&tmp_inc_filename);
10192 +               inc_filename = &tmp_inc_filename;
10193 +       }
10194 +
10195 +       wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
10196 +       if (wrapper != &php_plain_files_wrapper ||
10197 +               !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
10198 +               !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
10199 +               /* Fallback to original handler */
10200 +               if (inc_filename == &tmp_inc_filename) {
10201 +                       zval_dtor(&tmp_inc_filename);
10202 +               }
10203 +               return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10204 +       }
10205 +
10206 +       if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
10207 +               if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
10208 +                       ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
10209 +                       ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
10210 +               }
10211 +               if (inc_filename == &tmp_inc_filename) {
10212 +                       zval_dtor(&tmp_inc_filename);
10213 +               }
10214 +               if (freeop1) {
10215 +                       zval_dtor(freeop1);
10216 +               }
10217 +               execute_data->opline++;
10218 +               return 0;
10219 +       }
10220 +
10221 +       if (inc_filename == &tmp_inc_filename) {
10222 +               zval_dtor(&tmp_inc_filename);
10223 +       }
10224 +
10225 +       if(APCG(reserved_offset) != -1) {
10226 +               /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
10227 +               flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
10228 +       }
10229 +
10230 +#ifdef ZEND_ENGINE_2
10231 +       if(flags && flags->deep_copy == 1) {
10232 +               /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily 
10233 +                * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
10234 +                */
10235 +               Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
10236 +               ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10237 +               Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
10238 +#else 
10239 +       if(0) {
10240 +               /* do nothing, have nothing, be nothing */
10241 +#endif
10242 +       } else {
10243 +               ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10244 +       }
10245 +
10246 +       return ret;
10247 +}
10248 +
10249 +void apc_zend_init(TSRMLS_D)
10250 +{
10251 +    zend_extension dummy_ext;
10252 +#ifdef ZEND_ENGINE_2
10253 +    APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext); 
10254 +    assert(APCG(reserved_offset) == dummy_ext.resource_number);
10255 +    assert(APCG(reserved_offset) != -1);
10256 +    assert(sizeof(apc_opflags_t) <= sizeof(void*));
10257 +#endif
10258 +       if (!APCG(include_once)) {
10259 +               /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
10260 +               return;
10261 +       }
10262 +
10263 +       memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
10264 +
10265 +       /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
10266 +#ifdef ZEND_ENGINE_2_1
10267 +       apc_original_opcode_handlers = zend_opcode_handlers;
10268 +       zend_opcode_handlers = apc_opcode_handlers;
10269 +#else
10270 +       apc_original_opcode_handlers = apc_opcode_handlers;
10271 +#endif
10272 +
10273 +       APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
10274 +}
10275 +
10276 +void apc_zend_shutdown(TSRMLS_D)
10277 +{
10278 +       if (!APCG(include_once)) {
10279 +               /* Nothing changed, nothing to restore */
10280 +               return;
10281 +       }
10282 +
10283 +#ifdef ZEND_ENGINE_2_1
10284 +       zend_opcode_handlers = apc_original_opcode_handlers;
10285 +#else
10286 +       memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
10287 +#endif
10288 +}
10289 +
10290 +#else /* Opcode Overrides unavailable */
10291 +
10292 +void apc_zend_init(TSRMLS_D) { }
10293 +void apc_zend_shutdown(TSRMLS_D) { }
10294 +
10295 +#endif /* APC_OPCODE_OVERRIDE */
10296 +
10297 +/*
10298 + * Local variables:
10299 + * tab-width: 4
10300 + * c-basic-offset: 4
10301 + * End:
10302 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10303 + * vim<600: expandtab sw=4 ts=4 sts=4
10304 + */
10305 diff -ruN php-5.1.6.old/ext/apc/apc_zend.h php-5.1.6/ext/APC/apc_zend.h
10306 --- php-5.1.6.old/ext/apc/apc_zend.h    1969-12-31 18:00:00.000000000 -0600
10307 +++ php-5.1.6/ext/apc/apc_zend.h        2007-04-02 18:05:30.000000000 -0500
10308 @@ -0,0 +1,53 @@
10309 +/*
10310 +  +----------------------------------------------------------------------+
10311 +  | APC                                                                  |
10312 +  +----------------------------------------------------------------------+
10313 +  | Copyright (c) 2006 The PHP Group                                     |
10314 +  +----------------------------------------------------------------------+
10315 +  | This source file is subject to version 3.01 of the PHP license,      |
10316 +  | that is bundled with this package in the file LICENSE, and is        |
10317 +  | available through the world-wide-web at the following url:           |
10318 +  | http://www.php.net/license/3_01.txt                                  |
10319 +  | If you did not receive a copy of the PHP license and are unable to   |
10320 +  | obtain it through the world-wide-web, please send a note to          |
10321 +  | license@php.net so we can mail you a copy immediately.               |
10322 +  +----------------------------------------------------------------------+
10323 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
10324 +  +----------------------------------------------------------------------+
10325 +
10326 +   This software was contributed to PHP by Community Connect Inc. in 2002
10327 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10328 +   Future revisions and derivatives of this source code must acknowledge
10329 +   Community Connect Inc. as the original contributor of this module by
10330 +   leaving this note intact in the source code.
10331 +
10332 +   All other licensing and usage conditions are those of the PHP Group.
10333 +
10334 + */
10335 +
10336 +/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
10337 +
10338 +#ifndef APC_ZEND_H
10339 +#define APC_ZEND_H
10340 +
10341 +/* Utilities for interfacing with the zend engine */
10342 +
10343 +#include "apc.h"
10344 +#include "apc_php.h"
10345 +
10346 +extern void* apc_php_malloc(size_t n);
10347 +extern void apc_php_free(void* p);
10348 +
10349 +extern void apc_zend_init(TSRMLS_D);
10350 +extern void apc_zend_shutdown(TSRMLS_D);
10351 +
10352 +#endif
10353 +
10354 +/*
10355 + * Local variables:
10356 + * tab-width: 4
10357 + * c-basic-offset: 4
10358 + * End:
10359 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10360 + * vim<600: expandtab sw=4 ts=4 sts=4
10361 + */
10362 diff -ruN php-5.1.6.old/ext/apc/CHANGELOG php-5.1.6/ext/APC/CHANGELOG
10363 --- php-5.1.6.old/ext/apc/CHANGELOG     1969-12-31 18:00:00.000000000 -0600
10364 +++ php-5.1.6/ext/apc/CHANGELOG 2007-04-02 18:05:30.000000000 -0500
10365 @@ -0,0 +1,192 @@
10366 +3.0.14: 2007-03-21
10367 +- Build fix (Shire)
10368 +- Don't hook the upload hook if APC is disabled (Rasmus)
10369 +- Local shadow cache support (Gopal)
10370 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
10371 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
10372 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
10373 +- Allocator fixes to reduce fragmentation (Gopal)
10374 +
10375 +3.0.13: 2007-02-24
10376 +- File upload progress (Rasmus)
10377 +- Pthread mutex and spin locks (Shire)
10378 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
10379 +- apc.stat_ctime flag for ctime checks (Rasmus)
10380 +- Multiple key fetches with apc_fetch (Shire)
10381 +- Canary checks for shm memory deallocation (Gopal)
10382 +- Add hooks for external optimizer (Shire)
10383 +- Obsolete and remove apc optimizer (Gopal)
10384 +- APC info changes - cache insert rate, hit and miss rates (Shire)
10385 +- Fix apc_load_constants (Gopal)
10386 +- Rewrite dump opcode code to use vld (Gopal)
10387 +- Use apc_[ewn]print functions for error reporting (Shire) 
10388 +- Auto global fixes and refactoring (Gopal, Shire)
10389 +- Fix memory leaks in object serialization (Ilia)
10390 +- Memory cleanup code for destructor order (Gopal)
10391 +- Win32 build fixes (Ilia, Wez)
10392 +- ZTS and Php 4 build fixes (Bjori)
10393 +- Add apc_add() function (Rasmus)
10394 +- Add optional limited flag to apc_sma_info() (Rasmus)
10395 +
10396 +3.0.12p2: 2006-09-05
10397 +- Package version up
10398 +
10399 +3.0,12p1: 2006-09-05
10400 +- PHP4 build fixes
10401 +
10402 +3.0.12: 2006-09-05
10403 +- PHP 5.2 compatibility (Gopal)
10404 +- TSRM fixes (Gopal)
10405 +- Add extra flags to op_array->reserved to improve op array 
10406 +  processing code (Gopal)
10407 +- Fix crashes in optimizer and cli mode (Ilia)
10408 +- Optimizer fixes for PHP5 (Ilia, Gopal)
10409 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
10410 +- Php 4 function table and properties fixes (Gopal)
10411 +- Fix memory leaks in apc_cache_info (Gopal)
10412 +
10413 +3.0.11: 2006-08-16
10414 +- Made --enable-apc-mmap the default compile option (for real this time)
10415 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
10416 +  only fetch header information to make it useful when you have tens of
10417 +  thousands of entries.  (Brian Shire)
10418 +- 64-bit fixes (George)
10419 +- Don't mix Full Path and Inode keys (George)
10420 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
10421 +  require_once() and include_once() statements. (Sara)
10422 +- Add a non-blocking write_lock for cache inserts.  This is a better approach
10423 +  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
10424 +- A bit of work on the optimizer.  (Sara)
10425 +- Various memory issues resolved. (Gopal)
10426 +
10427 +3.0.10: 2006-03-11
10428 +- Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
10429 +  includes will not be stat'ed for any changes.  You will have to restart the server if you
10430 +  change anything.  This mode increases performance quite a bit, especially if you have a
10431 +  lot of includes.
10432 +
10433 +- Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
10434 +  than it solves.  I'll need to revisit locking and signal handling at some point soon.
10435 +
10436 +3.0.9: 2006-03-04
10437 +- Eliminate rand() call when slam_defense is not set (Rasmus)
10438 +- Fix for __isset problem (Gopal)
10439 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
10440 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
10441 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
10442 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
10443 +- Add automatic serialization of objects in apc_store() (Marcus)
10444 +- 64-bit .ini flag fix (Rasmus)
10445 +- Static members fix (Gopal)
10446 +- sma_cleanup() mem leak fix (Rasmus)
10447 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
10448 +- Fix autoglobals JIT bug (Gopal)
10449 +- Fix instance bug (Gopal)
10450 +- Add a lock cleanup safety net to request shutdown (Rasmus)
10451 +- Fix apc.slam_defense edge-case bug (Rasmus)
10452 +- User entry memory usage tracking support (Ilia)
10453 +- 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)
10454 +
10455 +3.0.8: 2005-08-24
10456 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
10457 +Cache corruption fix in cache-full cleanup code (Gopal)
10458 +
10459 +3.0.7: 2005-08-16
10460 +- Fix to apc.php to show final segment in frag chart. (Ilia)
10461 +- A couple of win32 fixes. (Frank)
10462 +- Add apc.enable_cli ini directive. (Rasmus)
10463 +- Add test cases. (Marcus)
10464 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
10465 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
10466 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
10467 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
10468 +
10469 +3.0.6: 2005-07-30
10470 +- Added apc.php to package.xml file.
10471 +- Track per-entry memory usage. (Val)
10472 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
10473 +- fcntl locking robustness fixes. (Rasmus)
10474 +- Shared read-locks where possible. (Rasmus)
10475 +- Added file_update_protection configuration parameter. (Rasmus)
10476 +- Windows ZTS fixes (Frank)
10477 +
10478 +3.0.5: 2005-07-27
10479 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
10480 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
10481 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
10482 +- Segfault in cache cleanup code (Ilia, Rasmus)
10483 +
10484 +3.0.4: 2005-07-18
10485 +- Add win32 support (Edin )
10486 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
10487 +- A couple of other minor fixes
10488 +
10489 +3.0.3: 2005-07-05
10490 +- Fix compile problem against PHP 5.0.x
10491 +
10492 +3.0.2: 2005-07-05
10493 +- Better shm error message
10494 +
10495 +3.0.1: 2005-07-05
10496 +- PHP4 build fix
10497 +
10498 +3.0: 2005-06-23
10499 +- PHP 5.1 support (Arun, Gopal, Rasmus)
10500 +- Major Inheritance bug fix (Arun, Gopal)
10501 +
10502 +2.0: 2003-02-10
10503 +- ground-up rewrite sharing none of the original source code (djc)
10504 +
10505 +1.0.10:
10506 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
10507 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
10508 +  this parameter to your php.ini file to activate apc shm or mmap caching
10509 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
10510 +  2001-05-15]
10511 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
10512 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
10513 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
10514 +- fixed regex support [gws 2001-05-16]
10515 +- enhanced reader-writer lock support [rg 2001-05-07]
10516 +
10517 +1.0.9:
10518 +- fixed (?) memory alignment bug on 64 bit archiecures 
10519 +- added many cache visibiliy functions 
10520 +- added opional fcntl locks under shm version 
10521 +- numerous bug fixes 
10522 +
10523 +1.0.8:
10524 +- added ability to detect and decompile compiled files placed as 'source'
10525 +  [gws,dw 2001-01-30]
10526 +- fixed apc_rstat bug [gws 2001-01-29]
10527 +- added hack to support included urls [gws 2001-01-30]
10528 +- fixed apc_cache_index [mb 2001-01-31]
10529 +- added multiple regex support [gs 2001-02-03]
10530 +- added apc_cache_info [mb,gs 2001-02-03]
10531 +
10532 +1.0.7:
10533 +- partially fixed for Solaris [gws 2001-01-29]
10534 +- fixed mtime support for relative includes [gws 2001-01-29]
10535 +- code cleanup [yg,ta,gws 2001-01-29]
10536 +
10537 +1.0.6:
10538 +- support for mtime in mmap [yg,gws 2001-01-27]
10539 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
10540 +
10541 +1.0.5:
10542 +- support for relative include paths [djc,gws 2001-01-19]
10543 +- class member array support fixed [djc 2001-01-18]
10544 +- added apc_cache_index [gws 2001-01-18]
10545 +
10546 +1.0.4:
10547 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
10548 +
10549 +1.0.3:
10550 +- fixed support for class inheritance [djc 2001-01-16]
10551 +
10552 +1.0.2:
10553 +- support for inherited classes [gws 2001-01-15]
10554 +- support for intialization of class variables and objects [gws 2001-01-13]
10555 +
10556 +1.0.1:
10557 +- added optional file modification time check [djc 2001-01-12]
10558 diff -ruN php-5.1.6.old/ext/apc/config.m4 php-5.1.6/ext/APC/config.m4
10559 --- php-5.1.6.old/ext/apc/config.m4     1969-12-31 18:00:00.000000000 -0600
10560 +++ php-5.1.6/ext/apc/config.m4 2007-04-02 18:05:30.000000000 -0500
10561 @@ -0,0 +1,214 @@
10562 +dnl
10563 +dnl $Id: config.m4,v 3.25 2007/02/24 15:57:59 rasmus Exp $
10564 +dnl
10565 +
10566 +AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
10567 +AC_ARG_WITH(apxs,
10568 +[  --with-apxs[=FILE]      Get compiler flags from apxs -q.  Provide the
10569 +                          pathname to the Apache apxs tool; defaults to "apxs".],[
10570 +  if test "$withval" != "no"; then
10571 +    if test "$withval" = "yes"; then
10572 +      APXS=apxs
10573 +      $APXS -q CFLAGS >/dev/null 2>&1
10574 +      if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
10575 +        APXS=/usr/sbin/apxs
10576 +      elif test -x /usr/bin/apxs2;  then
10577 +        APXS=/usr/bin/apxs2
10578 +      elif test -x /usr/sbin/apxs2; then
10579 +        APXS=/usr/sbin/apxs2
10580 +      fi
10581 +    else
10582 +      PHP_EXPAND_PATH($withval, APXS)
10583 +    fi
10584 +
10585 +    $APXS -q CFLAGS >/dev/null 2>&1
10586 +    if test "$?" != "0"; then
10587 +      AC_MSG_RESULT()
10588 +      AC_MSG_RESULT()
10589 +      AC_MSG_RESULT([Sorry, I was not able to successfully run APXS.  Possible reasons:])
10590 +      AC_MSG_RESULT()
10591 +      AC_MSG_RESULT([1.  Perl is not installed;])
10592 +      AC_MSG_RESULT([2.  Apache was not compiled with DSO support (--enable-module=so);])
10593 +      AC_MSG_RESULT([3.  'apxs' is not in your path.  Try to use --with-apxs=/path/to/apxs])
10594 +      AC_MSG_RESULT([The output of $APXS follows])
10595 +      $APXS -q CFLAGS
10596 +      AC_MSG_ERROR([Aborting])
10597 +    fi
10598 +
10599 +    APC_CFLAGS=`$APXS -q CFLAGS`
10600 +    AC_MSG_RESULT(yes)
10601 +  else
10602 +    AC_MSG_RESULT(no)
10603 +  fi
10604 +],[
10605 +  AC_MSG_RESULT(no)
10606 +])
10607 +
10608 +PHP_ARG_ENABLE(apc, whether to enable APC support,
10609 +[  --enable-apc           Enable APC support])
10610 +
10611 +AC_MSG_CHECKING(Checking whether we should use mmap)
10612 +AC_ARG_ENABLE(apc-mmap,
10613 +[  --disable-apc-mmap
10614 +                          Disable mmap support and use IPC shm instead],
10615 +[
10616 +  PHP_APC_MMAP=$enableval
10617 +  AC_MSG_RESULT($enableval)
10618 +], [
10619 +  PHP_APC_MMAP=yes
10620 +  AC_MSG_RESULT(yes)
10621 +])
10622 +
10623 +AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
10624 +AC_ARG_ENABLE(apc-sem,
10625 +[  --enable-apc-sem
10626 +                          Enable semaphore locks instead of fcntl],
10627 +[
10628 +  PHP_APC_SEM=$enableval
10629 +  AC_MSG_RESULT($enableval)
10630 +], [
10631 +  PHP_APC_SEM=no
10632 +  AC_MSG_RESULT(no)
10633 +])
10634 +
10635 +AC_MSG_CHECKING(Checking whether we should use futex locking)
10636 +AC_ARG_ENABLE(apc-futex,
10637 +[  --enable-apc-futex
10638 +                          Enable linux futex based locks  EXPERIMENTAL ],
10639 +[
10640 +  PHP_APC_FUTEX=$enableval
10641 +  AC_MSG_RESULT($enableval)
10642 +],
10643 +[
10644 +  PHP_APC_FUTEX=no
10645 +  AC_MSG_RESULT(no)
10646 +])
10647 +
10648 +if test "$PHP_APC_FUTEX" != "no"; then
10649 +       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.]); ] )
10650 +fi
10651 +
10652 +AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
10653 +AC_ARG_ENABLE(apc-pthreadmutex,
10654 +[  --enable-apc-pthreadmutex
10655 +                          Enable pthread mutex locking  EXPERIMENTAL ],
10656 +[
10657 +  PHP_APC_PTHREADMUTEX=$enableval
10658 +  AC_MSG_RESULT($enableval)
10659 +],
10660 +[
10661 +  PHP_APC_PTHREADMUTEX=no
10662 +  AC_MSG_RESULT(no)
10663 +])
10664 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
10665 +       orig_LIBS="$LIBS"
10666 +       LIBS="$LIBS -lpthread"
10667 +       AC_TRY_RUN(
10668 +                       [
10669 +                               #include <sys/types.h>
10670 +                               #include <pthread.h>
10671 +                                main() {
10672 +                               pthread_mutex_t mutex;
10673 +                               pthread_mutexattr_t attr;       
10674 +
10675 +                               if(pthread_mutexattr_init(&attr)) { 
10676 +                                       puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
10677 +                                       return -1; 
10678 +                               }
10679 +                               if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { 
10680 +                                       puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's which are required. (if you're using threads you should just use the built-in php thread locking).");
10681 +                                       return -1; 
10682 +                               }       
10683 +                               if(pthread_mutex_init(&mutex, &attr)) { 
10684 +                                       puts("Unable to initialize the mutex (pthread_mutex_init).");
10685 +                                       return -1; 
10686 +                               }
10687 +                               if(pthread_mutexattr_destroy(&attr)) { 
10688 +                                       puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
10689 +                                       return -1; 
10690 +                               }
10691 +                               if(pthread_mutex_destroy(&mutex)) { 
10692 +                                       puts("Unable to destroy mutex (pthread_mutex_destroy).");
10693 +                                       return -1; 
10694 +                               }
10695 +
10696 +                               puts("pthread mutex's are supported!");
10697 +                               return 0;
10698 +                                }
10699 +                       ],
10700 +                       [ dnl -Success-
10701 +                               PHP_ADD_LIBRARY(pthread)
10702 +                       ],
10703 +                       [ dnl -Failure-
10704 +                               AC_MSG_ERROR([It doesn't appear that pthread mutex's are supported on your system, please try a different configuration])
10705 +                       ],
10706 +                       [
10707 +                               PHP_ADD_LIBRARY(pthread)
10708 +                       ]
10709 +       )
10710 +       LIBS="$orig_LIBS"
10711 +fi
10712 +
10713 +AC_MSG_CHECKING(Checking whether we should use spin locks)
10714 +AC_ARG_ENABLE(apc-spinlocks,
10715 +[  --enable-apc-spinlocks
10716 +                          Enable spin locks  EXPERIMENTAL ],
10717 +[
10718 +  PHP_APC_SPINLOCKS=$enableval
10719 +  AC_MSG_RESULT($enableval)
10720 +],
10721 +[
10722 +  PHP_APC_SPINLOCKS=no
10723 +  AC_MSG_RESULT(no)
10724 +])
10725 +
10726 +if test "$PHP_APC" != "no"; then
10727 +  test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
10728 +  test "$PHP_APC_SEM"  != "no" && AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
10729 +  test "$PHP_APC_FUTEX" != "no" && AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
10730 +  test "$PHP_APC_PTHREADMUTEX" != "no" && AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
10731 +  test "$PHP_APC_SPINLOCKS" != "no" && AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) 
10732 +
10733 +  AC_CACHE_CHECK(for union semun, php_cv_semun,
10734 +  [
10735 +    AC_TRY_COMPILE([
10736 +#include <sys/types.h>
10737 +#include <sys/ipc.h>
10738 +#include <sys/sem.h>
10739 +    ], [union semun x;], [
10740 +      php_cv_semun=yes
10741 +    ],[
10742 +      php_cv_semun=no
10743 +    ])
10744 +  ])
10745 +  if test "$php_cv_semun" = "yes"; then
10746 +    AC_DEFINE(HAVE_SEMUN, 1, [ ])
10747 +  else
10748 +    AC_DEFINE(HAVE_SEMUN, 0, [ ])
10749 +  fi
10750 +
10751 +  apc_sources="apc.c php_apc.c \
10752 +               apc_cache.c \
10753 +               apc_compile.c \
10754 +               apc_debug.c \
10755 +               apc_fcntl.c \
10756 +               apc_main.c \
10757 +               apc_mmap.c \
10758 +               apc_sem.c \
10759 +               apc_shm.c \
10760 +               apc_futex.c \
10761 +               apc_pthreadmutex.c \
10762 +                          apc_spin.c \
10763 +                          pgsql_s_lock.c \
10764 +               apc_sma.c \
10765 +               apc_stack.c \
10766 +               apc_zend.c \
10767 +               apc_rfc1867.c "
10768 +
10769 +  PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
10770 +  PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
10771 +  PHP_SUBST(APC_SHARED_LIBADD)
10772 +  PHP_SUBST(APC_CFLAGS)
10773 +  AC_DEFINE(HAVE_APC, 1, [ ])
10774 +fi
10775 +
10776 diff -ruN php-5.1.6.old/ext/apc/INSTALL php-5.1.6/ext/APC/INSTALL
10777 --- php-5.1.6.old/ext/apc/INSTALL       1969-12-31 18:00:00.000000000 -0600
10778 +++ php-5.1.6/ext/apc/INSTALL   2007-04-02 18:05:30.000000000 -0500
10779 @@ -0,0 +1,405 @@
10780 +Installation Instructions for APC
10781 +---------------------------------
10782 +
10783 +This version of APC should work on PHP 4.3.0 - 4.4.x and
10784 +5.1.0 - 5.2.x.  Yes, that means PHP 5.0.x is no longer 
10785 +supported.  Upgrade to PHP 5.1.x or 5.2.x and you will 
10786 +notice all sorts of performance increases.
10787 +
10788 +CVS Instructions
10789 +----------------
10790 +Building from CVS can be done like this:
10791 +
10792 +  cvs -d :pserver:cvsread@cvs.php.net:/repository login
10793 +  Password: phpfi
10794 +  cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
10795 +  cd pecl/apc
10796 +  phpize
10797 +  ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10798 +  make
10799 +  make install
10800 +
10801 +Suggested Configuration (in your php.ini file)
10802 +----------------------------------------------
10803 +  extension=apc.so
10804 +  apc.enabled=1
10805 +  apc.shm_segments=1
10806 +  apc.shm_size=128
10807 +  apc.ttl=7200
10808 +  apc.user_ttl=7200
10809 +  apc.num_files_hint=1024
10810 +  apc.mmap_file_mask=/tmp/apc.XXXXXX
10811 +  apc.enable_cli=1
10812 +
10813 +These are fully described at the bottom of this file.
10814 +
10815 +PHP 4 Optimization
10816 +------------------
10817 +If you are trying to get every little bit of speed out of PHP4+APC, you need
10818 +to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
10819 +your CPPFLAGS.  (if you don't have httpd.h, install the apache_dev package 
10820 +for your OS) and do:
10821 +  export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
10822 +  setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
10823 +and then re-run your configure script.
10824 +
10825 +This optimization saves a stat syscall on the main script file.  In PHP5 this
10826 +optimization is automatic and doesn't need any special build flags.
10827 +
10828 +The second thing you are going to want to do to save another syscall is to 
10829 +compile using the --with-apxs configure switch.  This should work for both
10830 +Apache1 and Apache2.  Point it directly at your apxs2 script for Apache2.
10831 +eg. --with-apxs=/usr/local/bin/apxs2
10832 +
10833 ++---------------------+
10834 +| QUICK INSTALL (DSO) |
10835 ++---------------------+
10836 +
10837 +These instructions assume your PHP installation is located in /usr/local/php and you
10838 +want Apache optimizations (--with-apxs).
10839 +
10840 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10841 +$ cd apc_x.y
10842 +$ /usr/local/php/bin/phpize
10843 +$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10844 +$ make
10845 +$ make install
10846 +
10847 +You will probably need to run the final command (make install) as root.
10848 +
10849 +The above sequence of commands will install a .so file in your PHP
10850 +installation extension directory. The output of make install should display
10851 +that path to the screen.
10852 +
10853 +Next you must edit your php.ini file, which is normally located in
10854 +/usr/local/php/lib/php.ini, and add the following line:
10855 +
10856 +    extension="apc.so"
10857 +
10858 +Replace "/path/to/php/extensions" with whatever path was displayed when you
10859 +ran make install above.
10860 +
10861 +Then restart your web server and consult the output of phpinfo(). If there is
10862 +an informational section for APC, the installation was successful.
10863 +
10864 ++------------------------+
10865 +| QUICK INSTALL (Static) |
10866 ++------------------------+
10867 +
10868 +APC will not successfully compile on all systems as a DSO. If you run into
10869 +problems using the DSO quick install, you can try to compile it statically
10870 +into PHP. (The DSO install is recommended, though.)
10871 +
10872 +These instructions assume the current directory is the root of the PHP source
10873 +tree, and that you have already configured PHP by running its bundled
10874 +configure script.
10875 +
10876 +$ cd ext
10877 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10878 +$ cd ..
10879 +$ ./buildconf
10880 +$ ./config.nice
10881 +$ make
10882 +$ make install
10883 +
10884 +Once this is complete, simply restart your web server. You do not need to
10885 +modify your php.ini file to enable APC.
10886 +
10887 ++-----------------+
10888 +| VERBOSE INSTALL |
10889 ++-----------------+
10890 +
10891 +These instructions assume your PHP installation is located in /usr/local/php.
10892 +
10893 +1.  Unpack your distribution file.
10894 +
10895 +    You will have downloaded a file named something like apc_x.y.tar.gz.
10896 +    Unzip this file with a command like
10897 +    
10898 +        gunzip apc_x.y.tar.gz
10899 +    
10900 +    Next you have to untar it with
10901 +    
10902 +        tar xvf apc_x.y.tar
10903 +
10904 +    This will create an apc_x.y directory. cd into this new directory:
10905 +
10906 +        cd apc_x.y
10907 +
10908 +2.  Run phpize.
10909 +
10910 +    phpize is a script that should have been installed with PHP, and is
10911 +    normally located in /usr/local/php/bin assuming you installed PHP in
10912 +    /usr/local/php. (If you do not have the phpize script, you must reinstall
10913 +    PHP and be sure not to disable PEAR.)
10914 +
10915 +    Run the phpize command:
10916 +    
10917 +        /usr/local/php/bin/phpize
10918 +
10919 +    Its output should resemble this:
10920 +
10921 +        autoheader: `config.h.in' is created
10922 +        You should update your `aclocal.m4' by running aclocal.
10923 +        Configuring for:
10924 +          PHP Api Version:   20020918
10925 +          Zend Module Api No:   20020429
10926 +          Zend Extension Api No:   20021010
10927
10928 +    phpize should create a configure script in the current directory. If you
10929 +    get errors instead, you might be missing some required development tools,
10930 +    such as autoconf or libtool. You can try downloading the latest versions
10931 +    of those tools and running phpize again.
10932
10933 +3.  Run the configure script.
10934
10935 +    phpize creates a configure script. The only option you need to specify is
10936 +    the location of your php-config script:
10937 +
10938 +        ./configure --enable-apc
10939 +
10940 +    php-config should be located in the same directory as phpize.
10941 +
10942 +    If you prefer to use mmap instead of the default IPC shared memory support,
10943 +    add --enable-apc-mmap to your configure line. 
10944 +
10945 +       If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
10946 +       --enable-sem to your configure line.  If you don't have a problem
10947 +       with your server segaulting, or any other unnatural accumulation of
10948 +       semaphores on your system, the semaphore based locking is slightly faster.
10949 +
10950 +4.  Compile and install the files. Simply type: make install
10951 +
10952 +    (You may need to be root in order to install)
10953 +
10954 +    If you encounter errors from libtool or gcc during this step, please
10955 +    contact the project maintainer (dcowgill@php.net).
10956 +
10957 +5.  Edit your php.ini
10958 +
10959 +    make install should have printed a line resembling the following:
10960 +
10961 +        Installing shared extensions: /path/to/extension/
10962 +
10963 +    Copy the path /path/to/extension/ and add the following line to your
10964 +    php.ini file (normally located in /usr/local/php/lib/php.ini):
10965 +
10966 +        extension="apc.so"
10967 +
10968 +    If you don't have a php.ini file in that location, you can create it now.
10969 +
10970 +6.  Restart the web server and test the installation.
10971 +
10972 +    Restart your web server now (for apache, it's apachectl restart) and
10973 +    create a small test PHP file in your document root. The file should
10974 +    contain just the following line:
10975 +
10976 +        <?php phpinfo() ?>
10977 +
10978 +    Request that file in a web browser. If there is an entry for APC in the
10979 +    list of installed modules, the installation was successful.
10980 +
10981 +    If APC is not listed, consult your web server error log. If it contains an
10982 +    error message saying that it can't load the APC extension, your system
10983 +    might not be able to load shared libraries created with PHP's build
10984 +    system. One alternative would be to compile APC statically into PHP. See
10985 +    the Quick Install (Static) instructions above.
10986 +
10987 +    You should consult your error log anyway to see if APC generated any
10988 +    errors. On BSD-based platforms, it is typical for APC to be unable to
10989 +    allocate the default-sized shared memory segment. See below for hints on
10990 +    raising your system's shared memory limitations.
10991 +
10992 ++-----------------+
10993 +| CONFIGURING APC |
10994 ++-----------------+
10995 +
10996 +Although the default APC settings are fine for many installations, serious
10997 +users should consider tuning the following parameters:
10998 +
10999 +    OPTION                  DESCRIPTION
11000 +    ------------------      --------------------------------------------------
11001 +    apc.enabled             This can be set to 0 to disable APC. This is
11002 +                            primarily useful when APC is statically compiled
11003 +                            into PHP, since there is no other way to disable
11004 +                            it (when compiled as a DSO, the zend_extension
11005 +                            line can just be commented-out).
11006 +                            (Default: 1)
11007 +                            
11008 +    apc.shm_segments        The number of shared memory segments to allocate
11009 +                            for the compiler cache. If APC is running out of
11010 +                            shared memory but you have already set
11011 +                            apc.shm_size as high as your system allows, you
11012 +                            can try raising this value.  Setting this to a
11013 +                            value other than 1 has no effect in mmap mode
11014 +                            since mmap'ed shm segments don't have size limits.
11015 +                            (Default: 1)
11016 +                            
11017 +    apc.shm_size            The size of each shared memory segment in MB.
11018 +                            By default, some systems (including most BSD
11019 +                            variants) have very low limits on the size of a
11020 +                            shared memory segment.
11021 +                            (Default: 30)
11022 +                            
11023 +    apc.optimization        This option has been deprecated.
11024 +                            (Default: 0)
11025 +    
11026 +    apc.num_files_hint      A "hint" about the number of distinct source files
11027 +                            that will be included or requested on your web
11028 +                            server. Set to zero or omit if you're not sure;
11029 +                            this setting is mainly useful for sites that have
11030 +                            many thousands of source files.
11031 +                            (Default: 1000)
11032 +
11033 +    apc.user_entries_hint   Just like num_files_hint, a "hint" about the number
11034 +                            of distinct user cache variables to store. 
11035 +                            Set to zero or omit if you're not sure;
11036 +                            (Default: 4096)
11037 +
11038 +    apc.ttl                 The number of seconds a cache entry is allowed to
11039 +                            idle in a slot in case this cache entry slot is 
11040 +                            needed by another entry.  Leaving this at zero
11041 +                            means that your cache could potentially fill up
11042 +                            with stale entries while newer entries won't be
11043 +                            cached.  
11044 +                            (Default: 0)
11045 +
11046 +    apc.user_ttl            The number of seconds a user cache entry is allowed 
11047 +                            to idle in a slot in case this cache entry slot is 
11048 +                            needed by another entry.  Leaving this at zero
11049 +                            means that your cache could potentially fill up
11050 +                            with stale entries while newer entries won't be
11051 +                            cached.  
11052 +                            (Default: 0)
11053 +
11054 +
11055 +    apc.gc_ttl              The number of seconds that a cache entry may
11056 +                            remain on the garbage-collection list. This value
11057 +                            provides a failsafe in the event that a server
11058 +                            process dies while executing a cached source file;
11059 +                            if that source file is modified, the memory
11060 +                            allocated for the old version will not be
11061 +                            reclaimed until this TTL reached. Set to zero to
11062 +                            disable this feature.
11063 +                            (Default: 3600)
11064 +
11065 +    apc.cache_by_default    On by default, but can be set to off and used in
11066 +                            conjunction with positive apc.filters so that files
11067 +                            are only cached if matched by a positive filter.
11068 +                            (Default: On)
11069 +
11070 +    apc.filters             A comma-separated list of POSIX extended regular
11071 +                            expressions. If any pattern matches the source
11072 +                            filename, the file will not be cached. Note that
11073 +                            the filename used for matching is the one passed
11074 +                            to include/require, not the absolute path.  If the
11075 +                            first character of the expression is a + then the
11076 +                            expression will be additive in the sense that any
11077 +                            files matched by the expression will be cached, and
11078 +                            if the first character is a - then anything matched
11079 +                            will not be cached.  The - case is the default, so
11080 +                            it can be left off.
11081 +                            (Default: "")
11082 +
11083 +    apc.mmap_file_mask      If compiled with MMAP support by using --enable-mmap
11084 +                            this is the mktemp-style file_mask to pass to the
11085 +                            mmap module for determing whether your mmap'ed memory
11086 +                            region is going to be file-backed or shared memory
11087 +                            backed.  For straight file-backed mmap, set it to
11088 +                            something like /tmp/apc.XXXXXX (exactly 6 X's).
11089 +                            To use POSIX-style shm_open/mmap put a ".shm"
11090 +                            somewhere in your mask.  eg.  "/apc.shm.XXXXXX"
11091 +                            You can also set it to "/dev/zero" to use your 
11092 +                            kernel's /dev/zero interface to anonymous mmap'ed 
11093 +                            memory.  Leaving it undefined will force an 
11094 +                            anonymous mmap.
11095 +                            (Default: "")
11096 +
11097 +    apc.slam_defense        ** DEPRECATED - Use apc.write_lock instead **
11098 +                            On very busy servers whenever you start the server or
11099 +                            modify files you can create a race of many processes
11100 +                            all trying to cache the same file at the same time.
11101 +                            This option sets the percentage of processes that will
11102 +                            skip trying to cache an uncached file.  Or think of it
11103 +                            as the probability of a single process to skip caching.
11104 +                            For example, setting this to 75 would mean that there is
11105 +                            a 75% chance that the process will not cache an uncached
11106 +                            file.  So the higher the setting the greater the defense
11107 +                            against cache slams.  Setting this to 0 disables this
11108 +                            feature.
11109 +                            (Default: 0)
11110 +
11111 +    apc.file_update_protection
11112 +                            When you modify a file on a live web server you really
11113 +                            should do so in an atomic manner.  That is, write to a
11114 +                            temporary file and rename (mv) the file into its permanent
11115 +                            position when it is ready.  Many text editors, cp, tar and
11116 +                            other such programs don't do this.  This means that there
11117 +                            is a chance that a file is accessed (and cached) while it
11118 +                            is still being written to.  This file_update_protection
11119 +                            setting puts a delay on caching brand new files.  The
11120 +                            default is 2 seconds which means that if the modification
11121 +                            timestamp (mtime) on a file shows that it is less than 2
11122 +                            seconds old when it is accessed, it will not be cached.  
11123 +                            The unfortunate person who accessed this half-written file
11124 +                            will still see weirdness, but at least it won't persist.
11125 +                            If you are certain you always atomically update your files
11126 +                            by using something like rsync which does this correctly, you
11127 +                            can turn this protection off by setting it to 0.  If you
11128 +                            have a system that is flooded with io causing some update
11129 +                            procedure to take longer than 2 seconds, you may want to
11130 +                            increase this a bit.
11131 +                            (Default: 2)
11132 +
11133 +    apc.enable_cli          Mostly for testing and debugging.  Setting this enables APC
11134 +                            for the CLI version of PHP.  Normally you wouldn't want to
11135 +                            create, populate and tear down the APC cache on every CLI
11136 +                            request, but for various test scenarios it is handy to be
11137 +                            able to enable APC for the CLI version of APC easily.
11138 +                            (Default: 0)
11139 +
11140 +    apc.max_file_size       Prevents large files from being cached.  
11141 +                            (Default: 1M)
11142 +
11143 +    apc.stat                Whether to stat the main script file and the fullpath
11144 +                            includes.  If you turn this off you will need to restart
11145 +                            your server in order to update scripts.
11146 +                            (Default: 1)
11147 +
11148 +    apc.write_lock          On busy servers when you first start up the server, or when
11149 +                            many files are modified, you can end up with all your processes
11150 +                            trying to compile and cache the same files.  With write_lock 
11151 +                            enabled, only one process at a time will try to compile an
11152 +                            uncached script while the other processes will run uncached
11153 +                            instead of sitting around waiting on a lock.
11154 +                            (Default: 1)
11155 +
11156 +    apc.report_autofilter   Logs any scripts that were automatically excluded from being
11157 +                            cached due to early/late binding issues.
11158 +                            (Default: 0)
11159 +
11160 +    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
11161 +                            if you compiled APC against PHP 5.2.0 or later.  When enabled
11162 +                            any file uploads which includes a field called 
11163 +                            APC_UPLOAD_PROGRESS before the file field in an upload form
11164 +                            will cause APC to automatically create an upload_<key>
11165 +                            user cache entry where <key> is the value of the 
11166 +                            APC_UPLOAD_PROGRESS form entry.
11167 +
11168 +                            Note that the file upload tracking is not threadsafe at this
11169 +                            point, so new uploads that happen while a previous one is 
11170 +                            still going will disable the tracking for the previous.
11171 +                            (Default: 0)
11172 +
11173 +    apc.localcache          This enables a lock-free local process shadow-cache which 
11174 +                            reduces lock contention when the cache is being written to.
11175 +                            (Default: 0)
11176 +                            
11177 +    apc.localcache.size     The size of the local process shadow-cache, should be set to 
11178 +                            a sufficently large value, approximately half of num_files_hint.
11179 +                            (Default: 512)
11180 +    
11181 +    apc.include_once_override 
11182 +                            Optimize include_once and require_once calls and avoid the 
11183 +                            expensive system calls used.
11184 +                            (Default: 0)
11185 diff -ruN php-5.1.6.old/ext/apc/LICENSE php-5.1.6/ext/APC/LICENSE
11186 --- php-5.1.6.old/ext/apc/LICENSE       1969-12-31 18:00:00.000000000 -0600
11187 +++ php-5.1.6/ext/apc/LICENSE   2007-04-02 18:05:30.000000000 -0500
11188 @@ -0,0 +1,68 @@
11189 +-------------------------------------------------------------------- 
11190 +                  The PHP License, version 3.01
11191 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
11192 +-------------------------------------------------------------------- 
11193 +
11194 +Redistribution and use in source and binary forms, with or without
11195 +modification, is permitted provided that the following conditions
11196 +are met:
11197 +
11198 +  1. Redistributions of source code must retain the above copyright
11199 +     notice, this list of conditions and the following disclaimer.
11200
11201 +  2. Redistributions in binary form must reproduce the above copyright
11202 +     notice, this list of conditions and the following disclaimer in
11203 +     the documentation and/or other materials provided with the
11204 +     distribution.
11205
11206 +  3. The name "PHP" must not be used to endorse or promote products
11207 +     derived from this software without prior written permission. For
11208 +     written permission, please contact group@php.net.
11209 +  
11210 +  4. Products derived from this software may not be called "PHP", nor
11211 +     may "PHP" appear in their name, without prior written permission
11212 +     from group@php.net.  You may indicate that your software works in
11213 +     conjunction with PHP by saying "Foo for PHP" instead of calling
11214 +     it "PHP Foo" or "phpfoo"
11215
11216 +  5. The PHP Group may publish revised and/or new versions of the
11217 +     license from time to time. Each version will be given a
11218 +     distinguishing version number.
11219 +     Once covered code has been published under a particular version
11220 +     of the license, you may always continue to use it under the terms
11221 +     of that version. You may also choose to use such covered code
11222 +     under the terms of any subsequent version of the license
11223 +     published by the PHP Group. No one other than the PHP Group has
11224 +     the right to modify the terms applicable to covered code created
11225 +     under this License.
11226 +
11227 +  6. Redistributions of any form whatsoever must retain the following
11228 +     acknowledgment:
11229 +     "This product includes PHP software, freely available from
11230 +     <http://www.php.net/software/>".
11231 +
11232 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 
11233 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
11234 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
11235 +PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP
11236 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
11237 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
11238 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
11239 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11240 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
11241 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11242 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11243 +OF THE POSSIBILITY OF SUCH DAMAGE.
11244 +
11245 +-------------------------------------------------------------------- 
11246 +
11247 +This software consists of voluntary contributions made by many
11248 +individuals on behalf of the PHP Group.
11249 +
11250 +The PHP Group can be contacted via Email at group@php.net.
11251 +
11252 +For more information on the PHP Group and the PHP project, 
11253 +please see <http://www.php.net>.
11254 +
11255 +PHP includes the Zend Engine, freely available at
11256 +<http://www.zend.com>.
11257 diff -ruN php-5.1.6.old/ext/apc/NOTICE php-5.1.6/ext/APC/NOTICE
11258 --- php-5.1.6.old/ext/apc/NOTICE        1969-12-31 18:00:00.000000000 -0600
11259 +++ php-5.1.6/ext/apc/NOTICE    2007-04-02 18:05:30.000000000 -0500
11260 @@ -0,0 +1,43 @@
11261 +This is the NOTICE file that holds acknowledgements and stuff.
11262 +
11263 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
11264 +This extension is being released under the PHP License for complete compliance
11265 +with PHP and to encourage wide-spread use.  It is our intention that this
11266 +project be kept open source and that all commercial spin-offs contribute their
11267 +modifications back into the public source-tree.
11268 +
11269 +Creators:
11270 +    Daniel Cowgill
11271 +    George Schlossnagle
11272 +
11273 +PHP5 support and major features by:
11274 +    Arun C. Murthy 
11275 +    Gopal Vijayaraghavan
11276 +    Rasmus Lerdorf
11277 +
11278 +This software was contributed to PHP by Community Connect Inc. in 2002
11279 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11280 +Future revisions and derivatives of this source code must acknowledge
11281 +Community Connect Inc. as the original contributor of this module by
11282 +leaving this note intact in the source code.
11283 +
11284 +All other licensing and usage conditions are those of the PHP Group.
11285 +
11286 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting 
11287 +this project and providing a challenging and stimulating environment in 
11288 +which exciting projects can happen.
11289 +
11290 +Contributors:
11291 +    Mike Bretz          bug fixes, GUI, and lots of work
11292 +    Ricardo Galli       changed read-write locks to prefer readers
11293 +    Yann Grossel        bug fixes
11294 +    Thies Arntzen       bug fixes
11295 +    Sara Golemon        optimizer work
11296 +
11297 +Special Thanks:
11298 +    Florian Baumert     help debugging phplib problems
11299 +    Thomas Duffey       help debugging inheritance issues
11300 +    Vibol Hou           help debugging phplib problems
11301 +    Angel Li            diffs for ANSI comment compliance
11302 +    Christian Rishøj    help debugging phplib problems
11303 +    Sascha Schumann     memory error bug fix
11304 diff -ruN php-5.1.6.old/ext/apc/pgsql_s_lock.c php-5.1.6/ext/APC/pgsql_s_lock.c
11305 --- php-5.1.6.old/ext/apc/pgsql_s_lock.c        1969-12-31 18:00:00.000000000 -0600
11306 +++ php-5.1.6/ext/apc/pgsql_s_lock.c    2007-04-02 18:05:30.000000000 -0500
11307 @@ -0,0 +1,481 @@
11308 +/*
11309 +  +----------------------------------------------------------------------+
11310 +  | APC                                                                  |
11311 +  +----------------------------------------------------------------------+
11312 +  | Copyright (c) 2007 The PHP Group                                     |
11313 +  +----------------------------------------------------------------------+
11314 +  | This source file is subject to version 3.01 of the PHP license,      |
11315 +  | that is bundled with this package in the file LICENSE, and is        |
11316 +  | available through the world-wide-web at the following url:           |
11317 +  | http://www.php.net/license/3_01.txt                                  |
11318 +  | If you did not receive a copy of the PHP license and are unable to   |
11319 +  | obtain it through the world-wide-web, please send a note to          |
11320 +  | license@php.net so we can mail you a copy immediately.               |
11321 +  +----------------------------------------------------------------------+
11322 +  | The following code was ported from the PostgreSQL project, please    |
11323 +  |  see appropriate copyright notices that follow.                      |
11324 +  | Initial conversion by Brian Shire <shire@php.net>                    |
11325 +  +----------------------------------------------------------------------+
11326 +
11327 + */
11328 +
11329 +/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
11330 +
11331 +/*-------------------------------------------------------------------------
11332 + *
11333 + * s_lock.c
11334 + *        Hardware-dependent implementation of spinlocks.
11335 + *
11336 + *
11337 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11338 + * Portions Copyright (c) 1994, Regents of the University of California
11339 + *
11340 + *
11341 + * IDENTIFICATION
11342 + *       $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
11343 + *
11344 + *-------------------------------------------------------------------------
11345 + */
11346 +/* #include "postgres.h"  -- Removed for APC */
11347 +
11348 +/* -- Added for APC -- */
11349 +#include "apc.h"
11350 +#ifdef APC_SPIN_LOCKS
11351 +
11352 +#ifdef S_LOCK_TEST
11353 +#include <stdio.h>
11354 +#endif
11355 +#ifndef WIN32
11356 +#include <sys/select.h>
11357 +#endif
11358 +/* ---- */
11359 +
11360 +#include <time.h>
11361 +#include <unistd.h>
11362 +
11363 +/* #include "storage/s_lock.h" -- Removed for APC */
11364 +#include "pgsql_s_lock.h"
11365 +
11366 +static int     spins_per_delay = DEFAULT_SPINS_PER_DELAY;
11367 +
11368 +
11369 +/* -- APC specific additions ------------------------------*/
11370 +/* The following dependencies have been copied from 
11371 + * other pgsql source files.  The original locations 
11372 + * have been noted.
11373 + */
11374 +
11375 +/* -- from include/c.h -- */
11376 +#ifndef TRUE
11377 +#define TRUE  1
11378 +#endif
11379 +
11380 +#ifndef FALSE
11381 +#define FALSE 0
11382 +#endif
11383 +
11384 +/* -- from include/pg_config_manual.h -- */
11385 +#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
11386 +
11387 +/*
11388 + * Max
11389 + *    Return the maximum of two numbers.
11390 + */
11391 +#define Max(x, y)   ((x) > (y) ? (x) : (y))
11392 +
11393 +/* -- from include/c.h -- */
11394 +/*
11395 + * Min
11396 + *    Return the minimum of two numbers.
11397 + */
11398 +#define Min(x, y)   ((x) < (y) ? (x) : (y))
11399 +
11400 +
11401 +/* -- from backend/port/win32/signal.c -- */
11402 +/*
11403 + * pg_usleep --- delay the specified number of microseconds.
11404 + *
11405 + * NOTE: although the delay is specified in microseconds, the effective
11406 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen.  Expect
11407 + * the requested delay to be rounded up to the next resolution boundary.
11408 + *
11409 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
11410 + */
11411 +void
11412 +pg_usleep(long microsec)
11413 +{
11414 +       if (microsec > 0)
11415 +       {
11416 +#ifndef WIN32
11417 +               struct timeval delay;
11418 +
11419 +               delay.tv_sec = microsec / 1000000L;
11420 +               delay.tv_usec = microsec % 1000000L;
11421 +               (void) select(0, NULL, NULL, NULL, &delay);
11422 +#else
11423 +               SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
11424 +#endif
11425 +       }
11426 +}
11427 +
11428 +/* -- End APC specific additions ------------------------------*/
11429 +
11430 +
11431 +/*
11432 + * s_lock_stuck() - complain about a stuck spinlock
11433 + */
11434 +static void
11435 +s_lock_stuck(volatile slock_t *lock, const char *file, int line)
11436 +{
11437 +#if defined(S_LOCK_TEST)
11438 +       fprintf(stderr,
11439 +                       "\nStuck spinlock (%p) detected at %s:%d.\n",
11440 +                       lock, file, line);
11441 +       exit(1);
11442 +#else
11443 +  /* -- Removed for APC
11444 +       elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
11445 +                lock, file, line);
11446 +  */
11447 +  apc_eprint("Stuck spinlock (%p) detected", lock);
11448 +#endif
11449 +}
11450 +
11451 +
11452 +/*
11453 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
11454 + */
11455 +void
11456 +s_lock(volatile slock_t *lock, const char *file, int line)
11457 +{
11458 +       /*
11459 +        * We loop tightly for awhile, then delay using pg_usleep() and try again.
11460 +        * Preferably, "awhile" should be a small multiple of the maximum time we
11461 +        * expect a spinlock to be held.  100 iterations seems about right as an
11462 +        * initial guess.  However, on a uniprocessor the loop is a waste of
11463 +        * cycles, while in a multi-CPU scenario it's usually better to spin a bit
11464 +        * longer than to call the kernel, so we try to adapt the spin loop count
11465 +        * depending on whether we seem to be in a uniprocessor or multiprocessor.
11466 +        *
11467 +        * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
11468 +        * be wrong; there are platforms where that can result in a "stuck
11469 +        * spinlock" failure.  This has been seen particularly on Alphas; it seems
11470 +        * that the first TAS after returning from kernel space will always fail
11471 +        * on that hardware.
11472 +        *
11473 +        * Once we do decide to block, we use randomly increasing pg_usleep()
11474 +        * delays. The first delay is 1 msec, then the delay randomly increases to
11475 +        * about one second, after which we reset to 1 msec and start again.  The
11476 +        * idea here is that in the presence of heavy contention we need to
11477 +        * increase the delay, else the spinlock holder may never get to run and
11478 +        * release the lock.  (Consider situation where spinlock holder has been
11479 +        * nice'd down in priority by the scheduler --- it will not get scheduled
11480 +        * until all would-be acquirers are sleeping, so if we always use a 1-msec
11481 +        * sleep, there is a real possibility of starvation.)  But we can't just
11482 +        * clamp the delay to an upper bound, else it would take a long time to
11483 +        * make a reasonable number of tries.
11484 +        *
11485 +        * We time out and declare error after NUM_DELAYS delays (thus, exactly
11486 +        * that many tries).  With the given settings, this will usually take 2 or
11487 +        * so minutes.  It seems better to fix the total number of tries (and thus
11488 +        * the probability of unintended failure) than to fix the total time
11489 +        * spent.
11490 +        *
11491 +        * The pg_usleep() delays are measured in milliseconds because 1 msec is a
11492 +        * common resolution limit at the OS level for newer platforms. On older
11493 +        * platforms the resolution limit is usually 10 msec, in which case the
11494 +        * total delay before timeout will be a bit more.
11495 +        */
11496 +#define MIN_SPINS_PER_DELAY 10
11497 +#define MAX_SPINS_PER_DELAY 1000
11498 +#define NUM_DELAYS                     1000
11499 +#define MIN_DELAY_MSEC         1
11500 +#define MAX_DELAY_MSEC         1000
11501 +
11502 +       int                     spins = 0;
11503 +       int                     delays = 0;
11504 +       int                     cur_delay = 0;
11505 +  
11506 +       while (TAS(lock))
11507 +       {
11508 +               /* CPU-specific delay each time through the loop */
11509 +               SPIN_DELAY();
11510 +
11511 +               /* Block the process every spins_per_delay tries */
11512 +               if (++spins >= spins_per_delay)
11513 +               {
11514 +                       if (++delays > NUM_DELAYS)
11515 +                               s_lock_stuck(lock, file, line);
11516 +
11517 +                       if (cur_delay == 0) /* first time to delay? */
11518 +                               cur_delay = MIN_DELAY_MSEC;
11519 +
11520 +                       pg_usleep(cur_delay * 1000L);
11521 +
11522 +#if defined(S_LOCK_TEST)
11523 +                       fprintf(stdout, "*");
11524 +                       fflush(stdout);
11525 +#endif
11526 +
11527 +                       /* increase delay by a random fraction between 1X and 2X */
11528 +                       cur_delay += (int) (cur_delay *
11529 +                                         ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
11530 +                       /* wrap back to minimum delay when max is exceeded */
11531 +                       if (cur_delay > MAX_DELAY_MSEC)
11532 +                               cur_delay = MIN_DELAY_MSEC;
11533 +
11534 +                       spins = 0;
11535 +               }
11536 +       }
11537 +
11538 +       /*
11539 +        * If we were able to acquire the lock without delaying, it's a good
11540 +        * indication we are in a multiprocessor.  If we had to delay, it's a sign
11541 +        * (but not a sure thing) that we are in a uniprocessor. Hence, we
11542 +        * decrement spins_per_delay slowly when we had to delay, and increase it
11543 +        * rapidly when we didn't.  It's expected that spins_per_delay will
11544 +        * converge to the minimum value on a uniprocessor and to the maximum
11545 +        * value on a multiprocessor.
11546 +        *
11547 +        * Note: spins_per_delay is local within our current process. We want to
11548 +        * average these observations across multiple backends, since it's
11549 +        * relatively rare for this function to even get entered, and so a single
11550 +        * backend might not live long enough to converge on a good value.      That
11551 +        * is handled by the two routines below.
11552 +        */
11553 +       if (cur_delay == 0)
11554 +       {
11555 +               /* we never had to delay */
11556 +               if (spins_per_delay < MAX_SPINS_PER_DELAY)
11557 +                       spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
11558 +       }
11559 +       else
11560 +       {
11561 +               if (spins_per_delay > MIN_SPINS_PER_DELAY)
11562 +                       spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
11563 +       }
11564 +}
11565 +
11566 +
11567 +#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
11568 +/*
11569 + * Set local copy of spins_per_delay during backend startup.
11570 + *
11571 + * NB: this has to be pretty fast as it is called while holding a spinlock
11572 + */
11573 +void
11574 +set_spins_per_delay(int shared_spins_per_delay)
11575 +{
11576 +       spins_per_delay = shared_spins_per_delay;
11577 +}
11578 +
11579 +/*
11580 + * Update shared estimate of spins_per_delay during backend exit.
11581 + *
11582 + * NB: this has to be pretty fast as it is called while holding a spinlock
11583 + */
11584 +int
11585 +update_spins_per_delay(int shared_spins_per_delay)
11586 +{
11587 +       /*
11588 +        * We use an exponential moving average with a relatively slow adaption
11589 +        * rate, so that noise in any one backend's result won't affect the shared
11590 +        * value too much.      As long as both inputs are within the allowed range,
11591 +        * the result must be too, so we need not worry about clamping the result.
11592 +        *
11593 +        * We deliberately truncate rather than rounding; this is so that single
11594 +        * adjustments inside a backend can affect the shared estimate (see the
11595 +        * asymmetric adjustment rules above).
11596 +        */
11597 +       return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
11598 +}
11599 +#endif
11600 +
11601 +/*
11602 + * Various TAS implementations that cannot live in s_lock.h as no inline
11603 + * definition exists (yet).
11604 + * In the future, get rid of tas.[cso] and fold it into this file.
11605 + *
11606 + * If you change something here, you will likely need to modify s_lock.h too,
11607 + * because the definitions for these are split between this file and s_lock.h.
11608 + */
11609 +
11610 +
11611 +#ifdef HAVE_SPINLOCKS                  /* skip spinlocks if requested */
11612 +
11613 +
11614 +#if defined(__GNUC__)
11615 +
11616 +/*
11617 + * All the gcc flavors that are not inlined
11618 + */
11619 +
11620 +
11621 +/*
11622 + * Note: all the if-tests here probably ought to be testing gcc version
11623 + * rather than platform, but I don't have adequate info to know what to
11624 + * write.  Ideally we'd flush all this in favor of the inline version.
11625 + */
11626 +#if defined(__m68k__) && !defined(__linux__)
11627 +/* really means: extern int tas(slock_t* **lock); */
11628 +static void
11629 +tas_dummy()
11630 +{
11631 +       __asm__         __volatile__(
11632 +#if defined(__NetBSD__) && defined(__ELF__)
11633 +/* no underscore for label and % for registers */
11634 +                                                                                "\
11635 +.global                tas                             \n\
11636 +tas:                                                   \n\
11637 +                       movel   %sp@(0x4),%a0   \n\
11638 +                       tas     %a0@            \n\
11639 +                       beq     _success        \n\
11640 +                       moveq   #-128,%d0       \n\
11641 +                       rts                             \n\
11642 +_success:                                              \n\
11643 +                       moveq   #0,%d0          \n\
11644 +                       rts                             \n"
11645 +#else
11646 +                                                                                "\
11647 +.global                _tas                            \n\
11648 +_tas:                                                  \n\
11649 +                       movel   sp@(0x4),a0     \n\
11650 +                       tas     a0@                     \n\
11651 +                       beq     _success        \n\
11652 +                       moveq   #-128,d0        \n\
11653 +                       rts                                     \n\
11654 +_success:                                              \n\
11655 +                       moveq   #0,d0           \n\
11656 +                       rts                                     \n"
11657 +#endif   /* __NetBSD__ && __ELF__ */
11658 +       );
11659 +}
11660 +#endif   /* __m68k__ && !__linux__ */
11661 +#else                                                  /* not __GNUC__ */
11662 +
11663 +/*
11664 + * All non gcc
11665 + */
11666 +
11667 +
11668 +#if defined(sun3)
11669 +static void
11670 +tas_dummy()                                            /* really means: extern int tas(slock_t
11671 +                                                                * *lock); */
11672 +{
11673 +       asm("LLA0:");
11674 +       asm("   .data");
11675 +       asm("   .text");
11676 +       asm("|#PROC# 04");
11677 +       asm("   .globl  _tas");
11678 +       asm("_tas:");
11679 +       asm("|#PROLOGUE# 1");
11680 +       asm("   movel   sp@(0x4),a0");
11681 +       asm("   tas a0@");
11682 +       asm("   beq LLA1");
11683 +       asm("   moveq   #-128,d0");
11684 +       asm("   rts");
11685 +       asm("LLA1:");
11686 +       asm("   moveq   #0,d0");
11687 +       asm("   rts");
11688 +       asm("   .data");
11689 +}
11690 +#endif   /* sun3 */
11691 +#endif   /* not __GNUC__ */
11692 +#endif   /* HAVE_SPINLOCKS */
11693 +
11694 +
11695 +
11696 +/*****************************************************************************/
11697 +#if defined(S_LOCK_TEST)
11698 +
11699 +/*
11700 + * test program for verifying a port's spinlock support.
11701 + */
11702 +
11703 +struct test_lock_struct
11704 +{
11705 +       char            pad1;
11706 +       slock_t         lock;
11707 +       char            pad2;
11708 +};
11709 +
11710 +volatile struct test_lock_struct test_lock;
11711 +
11712 +int
11713 +main()
11714 +{
11715 +       srandom((unsigned int) time(NULL));
11716 +
11717 +       test_lock.pad1 = test_lock.pad2 = 0x44;
11718 +
11719 +       S_INIT_LOCK(&test_lock.lock);
11720 +
11721 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11722 +       {
11723 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11724 +               return 1;
11725 +       }
11726 +
11727 +       if (!S_LOCK_FREE(&test_lock.lock))
11728 +       {
11729 +               printf("S_LOCK_TEST: failed, lock not initialized\n");
11730 +               return 1;
11731 +       }
11732 +
11733 +       S_LOCK(&test_lock.lock);
11734 +
11735 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11736 +       {
11737 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11738 +               return 1;
11739 +       }
11740 +
11741 +       if (S_LOCK_FREE(&test_lock.lock))
11742 +       {
11743 +               printf("S_LOCK_TEST: failed, lock not locked\n");
11744 +               return 1;
11745 +       }
11746 +
11747 +       S_UNLOCK(&test_lock.lock);
11748 +
11749 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11750 +       {
11751 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11752 +               return 1;
11753 +       }
11754 +
11755 +       if (!S_LOCK_FREE(&test_lock.lock))
11756 +       {
11757 +               printf("S_LOCK_TEST: failed, lock not unlocked\n");
11758 +               return 1;
11759 +       }
11760 +
11761 +       S_LOCK(&test_lock.lock);
11762 +
11763 +       if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11764 +       {
11765 +               printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11766 +               return 1;
11767 +       }
11768 +
11769 +       if (S_LOCK_FREE(&test_lock.lock))
11770 +       {
11771 +               printf("S_LOCK_TEST: failed, lock not re-locked\n");
11772 +               return 1;
11773 +       }
11774 +
11775 +       printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
11776 +       printf("             exit with a 'stuck spinlock' message\n");
11777 +       printf("             if S_LOCK() and TAS() are working.\n");
11778 +       fflush(stdout);
11779 +
11780 +       s_lock(&test_lock.lock, __FILE__, __LINE__);
11781 +
11782 +       printf("S_LOCK_TEST: failed, lock not locked\n");
11783 +       return 1;
11784 +}
11785 +
11786 +#endif   /* S_LOCK_TEST */
11787 +
11788 +#endif /* APC_SPIN_LOCKS */
11789 diff -ruN php-5.1.6.old/ext/apc/pgsql_s_lock.h php-5.1.6/ext/APC/pgsql_s_lock.h
11790 --- php-5.1.6.old/ext/apc/pgsql_s_lock.h        1969-12-31 18:00:00.000000000 -0600
11791 +++ php-5.1.6/ext/apc/pgsql_s_lock.h    2007-04-02 18:05:30.000000000 -0500
11792 @@ -0,0 +1,928 @@
11793 +/*
11794 +  +----------------------------------------------------------------------+
11795 +  | APC                                                                  |
11796 +  +----------------------------------------------------------------------+
11797 +  | Copyright (c) 2007 The PHP Group                                     |
11798 +  +----------------------------------------------------------------------+
11799 +  | This source file is subject to version 3.01 of the PHP license,      |
11800 +  | that is bundled with this package in the file LICENSE, and is        |
11801 +  | available through the world-wide-web at the following url:           |
11802 +  | http://www.php.net/license/3_01.txt                                  |
11803 +  | If you did not receive a copy of the PHP license and are unable to   |
11804 +  | obtain it through the world-wide-web, please send a note to          |
11805 +  | license@php.net so we can mail you a copy immediately.               |
11806 +  +----------------------------------------------------------------------+
11807 +  | The following code was ported from the PostgreSQL project, please    |
11808 +  |  see appropriate copyright notices that follow.                      |
11809 +  | Initial conversion by Brian Shire <shire@php.net>                    |
11810 +  +----------------------------------------------------------------------+
11811 +
11812 + */
11813 +
11814 +/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
11815 +
11816 +/*-------------------------------------------------------------------------
11817 + *
11818 + * s_lock.h
11819 + *        Hardware-dependent implementation of spinlocks.
11820 + *
11821 + *     NOTE: none of the macros in this file are intended to be called directly.
11822 + *     Call them through the hardware-independent macros in spin.h.
11823 + *
11824 + *     The following hardware-dependent macros must be provided for each
11825 + *     supported platform:
11826 + *
11827 + *     void S_INIT_LOCK(slock_t *lock)
11828 + *             Initialize a spinlock (to the unlocked state).
11829 + *
11830 + *     void S_LOCK(slock_t *lock)
11831 + *             Acquire a spinlock, waiting if necessary.
11832 + *             Time out and abort() if unable to acquire the lock in a
11833 + *             "reasonable" amount of time --- typically ~ 1 minute.
11834 + *
11835 + *     void S_UNLOCK(slock_t *lock)
11836 + *             Unlock a previously acquired lock.
11837 + *
11838 + *     bool S_LOCK_FREE(slock_t *lock)
11839 + *             Tests if the lock is free. Returns TRUE if free, FALSE if locked.
11840 + *             This does *not* change the state of the lock.
11841 + *
11842 + *     void SPIN_DELAY(void)
11843 + *             Delay operation to occur inside spinlock wait loop.
11844 + *
11845 + *     Note to implementors: there are default implementations for all these
11846 + *     macros at the bottom of the file.  Check if your platform can use
11847 + *     these or needs to override them.
11848 + *
11849 + *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
11850 + *     TAS():
11851 + *
11852 + *     int TAS(slock_t *lock)
11853 + *             Atomic test-and-set instruction.  Attempt to acquire the lock,
11854 + *             but do *not* wait.      Returns 0 if successful, nonzero if unable
11855 + *             to acquire the lock.
11856 + *
11857 + *     TAS() is NOT part of the API, and should never be called directly.
11858 + *
11859 + *     CAUTION: on some platforms TAS() may sometimes report failure to acquire
11860 + *     a lock even when the lock is not locked.  For example, on Alpha TAS()
11861 + *     will "fail" if interrupted.  Therefore TAS() should always be invoked
11862 + *     in a retry loop, even if you are certain the lock is free.
11863 + *
11864 + *     ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
11865 + *     points, ie, loads and stores of other values must not be moved across
11866 + *     a lock or unlock.  In most cases it suffices to make the operation be
11867 + *     done through a "volatile" pointer.
11868 + *
11869 + *     On most supported platforms, TAS() uses a tas() function written
11870 + *     in assembly language to execute a hardware atomic-test-and-set
11871 + *     instruction.  Equivalent OS-supplied mutex routines could be used too.
11872 + *
11873 + *     If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
11874 + *     defined), then we fall back on an emulation that uses SysV semaphores
11875 + *     (see spin.c).  This emulation will be MUCH MUCH slower than a proper TAS()
11876 + *     implementation, because of the cost of a kernel call per lock or unlock.
11877 + *     An old report is that Postgres spends around 40% of its time in semop(2)
11878 + *     when using the SysV semaphore code.
11879 + *
11880 + *
11881 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11882 + * Portions Copyright (c) 1994, Regents of the University of California
11883 + *
11884 + *       $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
11885 + *
11886 + *-------------------------------------------------------------------------
11887 + */
11888 +#ifndef S_LOCK_H
11889 +#define S_LOCK_H
11890 +
11891 +/** APC namespace protection ************************************************/
11892 +/* hack to protect against any possible runtime namespace collisions...*/
11893 +#define pg_usleep               apc_spin_pg_usleep
11894 +#define s_lock                  apc_spin_s_lock
11895 +#define spins_per_delay         apc_spin_spins_per_delay
11896 +/****************************************************************************/
11897 +
11898 +
11899 +/* #include "storage/pg_sema.h"   -- Removed for APC */
11900 +
11901 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
11902 +
11903 +#ifdef HAVE_SPINLOCKS  /* skip spinlocks if requested */
11904 +
11905 +
11906 +#if defined(__GNUC__) || defined(__ICC)
11907 +/*************************************************************************
11908 + * All the gcc inlines
11909 + * Gcc consistently defines the CPU as __cpu__.
11910 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
11911 + */
11912 +
11913 +/*----------
11914 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
11915 +
11916 +       __asm__ __volatile__(
11917 +               "       instruction     \n"
11918 +               "       instruction     \n"
11919 +               "       instruction     \n"
11920 +:              "=r"(_res), "+m"(*lock)         // return register, in/out lock value
11921 +:              "r"(lock)                                       // lock pointer, in input register
11922 +:              "memory", "cc");                        // show clobbered registers here
11923 +
11924 + * The output-operands list (after first colon) should always include
11925 + * "+m"(*lock), whether or not the asm code actually refers to this
11926 + * operand directly.  This ensures that gcc believes the value in the
11927 + * lock variable is used and set by the asm code.  Also, the clobbers
11928 + * list (after third colon) should always include "memory"; this prevents
11929 + * gcc from thinking it can cache the values of shared-memory fields
11930 + * across the asm code.  Add "cc" if your asm code changes the condition
11931 + * code register, and also list any temp registers the code uses.
11932 + *----------
11933 + */
11934 +
11935 +
11936 +#ifdef __i386__                /* 32-bit i386 */
11937 +#define HAS_TEST_AND_SET
11938 +
11939 +typedef unsigned char slock_t;
11940 +
11941 +#define TAS(lock) tas(lock)
11942 +
11943 +static __inline__ int
11944 +tas(volatile slock_t *lock)
11945 +{
11946 +       register slock_t _res = 1;
11947 +
11948 +       /*
11949 +        * Use a non-locking test before asserting the bus lock.  Note that the
11950 +        * extra test appears to be a small loss on some x86 platforms and a small
11951 +        * win on others; it's by no means clear that we should keep it.
11952 +        */
11953 +       __asm__ __volatile__(
11954 +               "       cmpb    $0,%1   \n"
11955 +               "       jne             1f              \n"
11956 +               "       lock                    \n"
11957 +               "       xchgb   %0,%1   \n"
11958 +               "1: \n"
11959 +:              "+q"(_res), "+m"(*lock)
11960 +:
11961 +:              "memory", "cc");
11962 +       return (int) _res;
11963 +}
11964 +
11965 +#define SPIN_DELAY() spin_delay()
11966 +
11967 +static __inline__ void
11968 +spin_delay(void)
11969 +{
11970 +       /*
11971 +        * This sequence is equivalent to the PAUSE instruction ("rep" is
11972 +        * ignored by old IA32 processors if the following instruction is
11973 +        * not a string operation); the IA-32 Architecture Software
11974 +        * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
11975 +        * PAUSE in the inner loop of a spin lock is necessary for good
11976 +        * performance:
11977 +        *
11978 +        *     The PAUSE instruction improves the performance of IA-32
11979 +        *     processors supporting Hyper-Threading Technology when
11980 +        *     executing spin-wait loops and other routines where one
11981 +        *     thread is accessing a shared lock or semaphore in a tight
11982 +        *     polling loop. When executing a spin-wait loop, the
11983 +        *     processor can suffer a severe performance penalty when
11984 +        *     exiting the loop because it detects a possible memory order
11985 +        *     violation and flushes the core processor's pipeline. The
11986 +        *     PAUSE instruction provides a hint to the processor that the
11987 +        *     code sequence is a spin-wait loop. The processor uses this
11988 +        *     hint to avoid the memory order violation and prevent the
11989 +        *     pipeline flush. In addition, the PAUSE instruction
11990 +        *     de-pipelines the spin-wait loop to prevent it from
11991 +        *     consuming execution resources excessively.
11992 +        */
11993 +       __asm__ __volatile__(
11994 +               " rep; nop                      \n");
11995 +}
11996 +
11997 +#endif  /* __i386__ */
11998 +
11999 +
12000 +#ifdef __x86_64__              /* AMD Opteron, Intel EM64T */
12001 +#define HAS_TEST_AND_SET
12002 +
12003 +typedef unsigned char slock_t;
12004 +
12005 +#define TAS(lock) tas(lock)
12006 +
12007 +static __inline__ int
12008 +tas(volatile slock_t *lock)
12009 +{
12010 +       register slock_t _res = 1;
12011 +
12012 +       /*
12013 +        * On Opteron, using a non-locking test before the locking instruction
12014 +        * is a huge loss.  On EM64T, it appears to be a wash or small loss,
12015 +        * so we needn't bother to try to distinguish the sub-architectures.
12016 +        */
12017 +       __asm__ __volatile__(
12018 +               "       lock                    \n"
12019 +               "       xchgb   %0,%1   \n"
12020 +:              "+q"(_res), "+m"(*lock)
12021 +:
12022 +:              "memory", "cc");
12023 +       return (int) _res;
12024 +}
12025 +
12026 +#define SPIN_DELAY() spin_delay()
12027 +
12028 +static __inline__ void
12029 +spin_delay(void)
12030 +{
12031 +       /*
12032 +        * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
12033 +        * Opteron, but it may be of some use on EM64T, so we keep it.
12034 +        */
12035 +       __asm__ __volatile__(
12036 +               " rep; nop                      \n");
12037 +}
12038 +
12039 +#endif  /* __x86_64__ */
12040 +
12041 +
12042 +#if defined(__ia64__) || defined(__ia64)       /* Intel Itanium */
12043 +#define HAS_TEST_AND_SET
12044 +
12045 +typedef unsigned int slock_t;
12046 +
12047 +#define TAS(lock) tas(lock)
12048 +
12049 +#ifndef __INTEL_COMPILER
12050 +
12051 +static __inline__ int
12052 +tas(volatile slock_t *lock)
12053 +{
12054 +       long int        ret;
12055 +
12056 +       __asm__ __volatile__(
12057 +               "       xchg4   %0=%1,%2        \n"
12058 +:              "=r"(ret), "+m"(*lock)
12059 +:              "r"(1)
12060 +:              "memory");
12061 +       return (int) ret;
12062 +}
12063 +
12064 +#else /* __INTEL_COMPILER */
12065 +
12066 +static __inline__ int
12067 +tas(volatile slock_t *lock)
12068 +{
12069 +       int             ret;
12070 +
12071 +       ret = _InterlockedExchange(lock,1);     /* this is a xchg asm macro */
12072 +
12073 +       return ret;
12074 +}
12075 +
12076 +#endif /* __INTEL_COMPILER */
12077 +#endif  /* __ia64__ || __ia64 */
12078 +
12079 +
12080 +#if defined(__arm__) || defined(__arm)
12081 +#define HAS_TEST_AND_SET
12082 +
12083 +typedef unsigned char slock_t;
12084 +
12085 +#define TAS(lock) tas(lock)
12086 +
12087 +static __inline__ int
12088 +tas(volatile slock_t *lock)
12089 +{
12090 +       register slock_t _res = 1;
12091 +
12092 +       __asm__ __volatile__(
12093 +               "       swpb    %0, %0, [%2]    \n"
12094 +:              "+r"(_res), "+m"(*lock)
12095 +:              "r"(lock)
12096 +:              "memory");
12097 +       return (int) _res;
12098 +}
12099 +
12100 +#endif  /* __arm__ */
12101 +
12102 +
12103 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
12104 +#if defined(__s390__) || defined(__s390x__)
12105 +#define HAS_TEST_AND_SET
12106 +
12107 +typedef unsigned int slock_t;
12108 +
12109 +#define TAS(lock)         tas(lock)
12110 +
12111 +static __inline__ int
12112 +tas(volatile slock_t *lock)
12113 +{
12114 +       int                     _res = 0;
12115 +
12116 +       __asm__ __volatile__(
12117 +               "       cs      %0,%3,0(%2)             \n"
12118 +:              "+d"(_res), "+m"(*lock)
12119 +:              "a"(lock), "d"(1)
12120 +:              "memory", "cc");
12121 +       return _res;
12122 +}
12123 +
12124 +#endif  /* __s390__ || __s390x__ */
12125 +
12126 +
12127 +#if defined(__sparc__)         /* Sparc */
12128 +#define HAS_TEST_AND_SET
12129 +
12130 +typedef unsigned char slock_t;
12131 +
12132 +#define TAS(lock) tas(lock)
12133 +
12134 +static __inline__ int
12135 +tas(volatile slock_t *lock)
12136 +{
12137 +       register slock_t _res;
12138 +
12139 +       /*
12140 +        *      See comment in /pg/backend/port/tas/solaris_sparc.s for why this
12141 +        *      uses "ldstub", and that file uses "cas".  gcc currently generates
12142 +        *      sparcv7-targeted binaries, so "cas" use isn't possible.
12143 +        */
12144 +       __asm__ __volatile__(
12145 +               "       ldstub  [%2], %0        \n"
12146 +:              "=r"(_res), "+m"(*lock)
12147 +:              "r"(lock)
12148 +:              "memory");
12149 +       return (int) _res;
12150 +}
12151 +
12152 +#endif  /* __sparc__ */
12153 +
12154 +
12155 +/* PowerPC */
12156 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
12157 +#define HAS_TEST_AND_SET
12158 +
12159 +#if defined(__ppc64__) || defined(__powerpc64__)
12160 +typedef unsigned long slock_t;
12161 +#else
12162 +typedef unsigned int slock_t;
12163 +#endif
12164 +
12165 +#define TAS(lock) tas(lock)
12166 +/*
12167 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
12168 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
12169 + */
12170 +static __inline__ int
12171 +tas(volatile slock_t *lock)
12172 +{
12173 +       slock_t _t;
12174 +       int _res;
12175 +
12176 +       __asm__ __volatile__(
12177 +"      lwarx   %0,0,%3         \n"
12178 +"      cmpwi   %0,0            \n"
12179 +"      bne     1f                      \n"
12180 +"      addi    %0,%0,1         \n"
12181 +"      stwcx.  %0,0,%3         \n"
12182 +"      beq     2f              \n"
12183 +"1:    li      %1,1            \n"
12184 +"      b               3f                      \n"
12185 +"2:                                            \n"
12186 +"      isync                           \n"
12187 +"      li      %1,0            \n"
12188 +"3:                                            \n"
12189 +
12190 +:      "=&r"(_t), "=r"(_res), "+m"(*lock)
12191 +:      "r"(lock)
12192 +:      "memory", "cc");
12193 +       return _res;
12194 +}
12195 +
12196 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
12197 +#define S_UNLOCK(lock) \
12198 +do \
12199 +{ \
12200 +       __asm__ __volatile__ (" sync \n"); \
12201 +       *((volatile slock_t *) (lock)) = 0; \
12202 +} while (0)
12203 +
12204 +#endif /* powerpc */
12205 +
12206 +
12207 +/* Linux Motorola 68k */
12208 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
12209 +#define HAS_TEST_AND_SET
12210 +
12211 +typedef unsigned char slock_t;
12212 +
12213 +#define TAS(lock) tas(lock)
12214 +
12215 +static __inline__ int
12216 +tas(volatile slock_t *lock)
12217 +{
12218 +       register int rv;
12219 +
12220 +       __asm__ __volatile__(
12221 +               "       clrl    %0              \n"
12222 +               "       tas             %1              \n"
12223 +               "       sne             %0              \n"
12224 +:              "=d"(rv), "+m"(*lock)
12225 +:
12226 +:              "memory", "cc");
12227 +       return rv;
12228 +}
12229 +
12230 +#endif  /* (__mc68000__ || __m68k__) && __linux__ */
12231 +
12232 +
12233 +/*
12234 + * VAXen -- even multiprocessor ones
12235 + * (thanks to Tom Ivar Helbekkmo)
12236 + */
12237 +#if defined(__vax__)
12238 +#define HAS_TEST_AND_SET
12239 +
12240 +typedef unsigned char slock_t;
12241 +
12242 +#define TAS(lock) tas(lock)
12243 +
12244 +static __inline__ int
12245 +tas(volatile slock_t *lock)
12246 +{
12247 +       register int    _res;
12248 +
12249 +       __asm__ __volatile__(
12250 +               "       movl    $1, %0                  \n"
12251 +               "       bbssi   $0, (%2), 1f    \n"
12252 +               "       clrl    %0                              \n"
12253 +               "1: \n"
12254 +:              "=&r"(_res), "+m"(*lock)
12255 +:              "r"(lock)
12256 +:              "memory");
12257 +       return _res;
12258 +}
12259 +
12260 +#endif  /* __vax__ */
12261 +
12262 +
12263 +#if defined(__ns32k__)         /* National Semiconductor 32K */
12264 +#define HAS_TEST_AND_SET
12265 +
12266 +typedef unsigned char slock_t;
12267 +
12268 +#define TAS(lock) tas(lock)
12269 +
12270 +static __inline__ int
12271 +tas(volatile slock_t *lock)
12272 +{
12273 +       register int    _res;
12274 +
12275 +       __asm__ __volatile__(
12276 +               "       sbitb   0, %1   \n"
12277 +               "       sfsd    %0              \n"
12278 +:              "=r"(_res), "+m"(*lock)
12279 +:
12280 +:              "memory");
12281 +       return _res;
12282 +}
12283 +
12284 +#endif  /* __ns32k__ */
12285 +
12286 +
12287 +#if defined(__alpha) || defined(__alpha__)     /* Alpha */
12288 +/*
12289 + * Correct multi-processor locking methods are explained in section 5.5.3
12290 + * of the Alpha AXP Architecture Handbook, which at this writing can be
12291 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
12292 + * For gcc we implement the handbook's code directly with inline assembler.
12293 + */
12294 +#define HAS_TEST_AND_SET
12295 +
12296 +typedef unsigned long slock_t;
12297 +
12298 +#define TAS(lock)  tas(lock)
12299 +
12300 +static __inline__ int
12301 +tas(volatile slock_t *lock)
12302 +{
12303 +       register slock_t _res;
12304 +
12305 +       __asm__ __volatile__(
12306 +               "       ldq             $0, %1  \n"
12307 +               "       bne             $0, 2f  \n"
12308 +               "       ldq_l   %0, %1  \n"
12309 +               "       bne             %0, 2f  \n"
12310 +               "       mov             1,  $0  \n"
12311 +               "       stq_c   $0, %1  \n"
12312 +               "       beq             $0, 2f  \n"
12313 +               "       mb                              \n"
12314 +               "       br              3f              \n"
12315 +               "2:     mov             1, %0   \n"
12316 +               "3:                                     \n"
12317 +:              "=&r"(_res), "+m"(*lock)
12318 +:
12319 +:              "memory", "0");
12320 +       return (int) _res;
12321 +}
12322 +
12323 +#define S_UNLOCK(lock) \
12324 +do \
12325 +{\
12326 +       __asm__ __volatile__ (" mb \n"); \
12327 +       *((volatile slock_t *) (lock)) = 0; \
12328 +} while (0)
12329 +
12330 +#endif /* __alpha || __alpha__ */
12331 +
12332 +
12333 +#if defined(__mips__) && !defined(__sgi)       /* non-SGI MIPS */
12334 +/* Note: on SGI we use the OS' mutex ABI, see below */
12335 +/* Note: R10000 processors require a separate SYNC */
12336 +#define HAS_TEST_AND_SET
12337 +
12338 +typedef unsigned int slock_t;
12339 +
12340 +#define TAS(lock) tas(lock)
12341 +
12342 +static __inline__ int
12343 +tas(volatile slock_t *lock)
12344 +{
12345 +       register volatile slock_t *_l = lock;
12346 +       register int _res;
12347 +       register int _tmp;
12348 +
12349 +       __asm__ __volatile__(
12350 +               "       .set push           \n"
12351 +               "       .set mips2          \n"
12352 +               "       .set noreorder      \n"
12353 +               "       .set nomacro        \n"
12354 +               "       ll      %0, %2      \n"
12355 +               "       or      %1, %0, 1   \n"
12356 +               "       sc      %1, %2      \n"
12357 +               "       xori    %1, 1       \n"
12358 +               "       or      %0, %0, %1  \n"
12359 +               "       sync                \n"
12360 +               "       .set pop              "
12361 +:              "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
12362 +:
12363 +:              "memory");
12364 +       return _res;
12365 +}
12366 +
12367 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
12368 +#define S_UNLOCK(lock) \
12369 +do \
12370 +{ \
12371 +       __asm__ __volatile__( \
12372 +               "       .set push           \n" \
12373 +               "       .set mips2          \n" \
12374 +               "       .set noreorder      \n" \
12375 +               "       .set nomacro        \n" \
12376 +               "       sync                \n" \
12377 +               "       .set pop              "); \
12378 +       *((volatile slock_t *) (lock)) = 0; \
12379 +} while (0)
12380 +
12381 +#endif /* __mips__ && !__sgi */
12382 +
12383 +
12384 +/* These live in s_lock.c, but only for gcc */
12385 +
12386 +
12387 +#if defined(__m68k__) && !defined(__linux__)   /* non-Linux Motorola 68k */
12388 +#define HAS_TEST_AND_SET
12389 +
12390 +typedef unsigned char slock_t;
12391 +#endif
12392 +
12393 +
12394 +#endif /* __GNUC__ */
12395 +
12396 +
12397 +
12398 +/*
12399 + * ---------------------------------------------------------------------
12400 + * Platforms that use non-gcc inline assembly:
12401 + * ---------------------------------------------------------------------
12402 + */
12403 +
12404 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
12405 +
12406 +
12407 +#if defined(USE_UNIVEL_CC)             /* Unixware compiler */
12408 +#define HAS_TEST_AND_SET
12409 +
12410 +typedef unsigned char slock_t;
12411 +
12412 +#define TAS(lock)      tas(lock)
12413 +
12414 +asm int
12415 +tas(volatile slock_t *s_lock)
12416 +{
12417 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
12418 +%mem s_lock
12419 +       pushl %ebx
12420 +       movl s_lock, %ebx
12421 +       movl $255, %eax
12422 +       lock
12423 +       xchgb %al, (%ebx)
12424 +       popl %ebx
12425 +}
12426 +
12427 +#endif  /* defined(USE_UNIVEL_CC) */
12428 +
12429 +
12430 +#if defined(__alpha) || defined(__alpha__)     /* Tru64 Unix Alpha compiler */
12431 +/*
12432 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
12433 + * have some builtin functions that accomplish much the same results.
12434 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
12435 + * regardless of the compiler in use.  LOCK_LONG and UNLOCK_LONG only
12436 + * operate on an int (ie, longword), but that's OK as long as we define
12437 + * S_INIT_LOCK to zero out the whole quadword.
12438 + */
12439 +#define HAS_TEST_AND_SET
12440 +
12441 +typedef unsigned long slock_t;
12442 +
12443 +#include <alpha/builtins.h>
12444 +#define S_INIT_LOCK(lock)  (*(lock) = 0)
12445 +#define TAS(lock)                 (__LOCK_LONG_RETRY((lock), 1) == 0)
12446 +#define S_UNLOCK(lock)    __UNLOCK_LONG(lock)
12447 +
12448 +#endif  /* __alpha || __alpha__ */
12449 +
12450 +
12451 +#if defined(__hppa) || defined(__hppa__)       /* HP PA-RISC, GCC and HP compilers */
12452 +/*
12453 + * HP's PA-RISC
12454 + *
12455 + * See src/backend/port/hpux/tas.c.template for details about LDCWX.  Because
12456 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
12457 + * struct.  The active word in the struct is whichever has the aligned address;
12458 + * the other three words just sit at -1.
12459 + *
12460 + * When using gcc, we can inline the required assembly code.
12461 + */
12462 +#define HAS_TEST_AND_SET
12463 +
12464 +typedef struct
12465 +{
12466 +       int                     sema[4];
12467 +} slock_t;
12468 +
12469 +#define TAS_ACTIVE_WORD(lock)  ((volatile int *) (((long) (lock) + 15) & ~15))
12470 +
12471 +#if defined(__GNUC__)
12472 +
12473 +static __inline__ int
12474 +tas(volatile slock_t *lock)
12475 +{
12476 +       volatile int *lockword = TAS_ACTIVE_WORD(lock);
12477 +       register int lockval;
12478 +
12479 +       __asm__ __volatile__(
12480 +               "       ldcwx   0(0,%2),%0      \n"
12481 +:              "=r"(lockval), "+m"(*lockword)
12482 +:              "r"(lockword)
12483 +:              "memory");
12484 +       return (lockval == 0);
12485 +}
12486 +
12487 +#endif /* __GNUC__ */
12488 +
12489 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
12490 +
12491 +#define S_INIT_LOCK(lock) \
12492 +       do { \
12493 +               volatile slock_t *lock_ = (lock); \
12494 +               lock_->sema[0] = -1; \
12495 +               lock_->sema[1] = -1; \
12496 +               lock_->sema[2] = -1; \
12497 +               lock_->sema[3] = -1; \
12498 +       } while (0)
12499 +
12500 +#define S_LOCK_FREE(lock)      (*TAS_ACTIVE_WORD(lock) != 0)
12501 +
12502 +#endif  /* __hppa || __hppa__ */
12503 +
12504 +
12505 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
12506 +
12507 +#define HAS_TEST_AND_SET
12508 +
12509 +typedef unsigned int slock_t;
12510 +
12511 +#include <ia64/sys/inline.h>
12512 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
12513 +
12514 +#endif /* HPUX on IA64, non gcc */
12515 +
12516 +
12517 +#if defined(__sgi)     /* SGI compiler */
12518 +/*
12519 + * SGI IRIX 5
12520 + * slock_t is defined as a unsigned long. We use the standard SGI
12521 + * mutex API.
12522 + *
12523 + * The following comment is left for historical reasons, but is probably
12524 + * not a good idea since the mutex ABI is supported.
12525 + *
12526 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
12527 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
12528 + * for the R3000 chips out there.
12529 + */
12530 +#define HAS_TEST_AND_SET
12531 +
12532 +typedef unsigned long slock_t;
12533 +
12534 +#include "mutex.h"
12535 +#define TAS(lock)      (test_and_set(lock,1))
12536 +#define S_UNLOCK(lock) (test_then_and(lock,0))
12537 +#define S_INIT_LOCK(lock)      (test_then_and(lock,0))
12538 +#define S_LOCK_FREE(lock)      (test_then_add(lock,0) == 0)
12539 +#endif  /* __sgi */
12540 +
12541 +
12542 +#if defined(sinix)             /* Sinix */
12543 +/*
12544 + * SINIX / Reliant UNIX
12545 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
12546 + * member. (Basically same as SGI)
12547 + */
12548 +#define HAS_TEST_AND_SET
12549 +
12550 +#include "abi_mutex.h"
12551 +typedef abilock_t slock_t;
12552 +
12553 +#define TAS(lock)      (!acquire_lock(lock))
12554 +#define S_UNLOCK(lock) release_lock(lock)
12555 +#define S_INIT_LOCK(lock)      init_lock(lock)
12556 +#define S_LOCK_FREE(lock)      (stat_lock(lock) == UNLOCKED)
12557 +#endif  /* sinix */
12558 +
12559 +
12560 +#if defined(_AIX)      /* AIX */
12561 +/*
12562 + * AIX (POWER)
12563 + */
12564 +#define HAS_TEST_AND_SET
12565 +
12566 +typedef unsigned int slock_t;
12567 +
12568 +#define TAS(lock)                      _check_lock(lock, 0, 1)
12569 +#define S_UNLOCK(lock)         _clear_lock(lock, 0)
12570 +#endif  /* _AIX */
12571 +
12572 +
12573 +#if defined (nextstep)         /* Nextstep */
12574 +#define HAS_TEST_AND_SET
12575 +
12576 +typedef struct mutex slock_t;
12577 +
12578 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
12579 +
12580 +#define S_LOCK(lock)   mutex_lock(lock)
12581 +#define S_UNLOCK(lock) mutex_unlock(lock)
12582 +#define S_INIT_LOCK(lock)      mutex_init(lock)
12583 +/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
12584 +#define S_LOCK_FREE(alock)     ((alock)->lock == 0)
12585 +#endif  /* nextstep */
12586 +
12587 +
12588 +/* These are in s_lock.c */
12589 +
12590 +
12591 +#if defined(sun3)              /* Sun3 */
12592 +#define HAS_TEST_AND_SET
12593 +
12594 +typedef unsigned char slock_t;
12595 +#endif
12596 +
12597 +
12598 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
12599 +#define HAS_TEST_AND_SET
12600 +
12601 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
12602 +typedef unsigned int slock_t;
12603 +#else
12604 +typedef unsigned char slock_t;
12605 +#endif
12606 +
12607 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
12608 +                                                                         slock_t cmp);
12609 +
12610 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
12611 +#endif
12612 +
12613 +
12614 +#ifdef WIN32_ONLY_COMPILER
12615 +typedef LONG slock_t;
12616 +
12617 +#define HAS_TEST_AND_SET
12618 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
12619 +
12620 +#define SPIN_DELAY() spin_delay()
12621 +
12622 +static __forceinline void
12623 +spin_delay(void)
12624 +{
12625 +       /* See comment for gcc code. Same code, MASM syntax */
12626 +       __asm rep nop;
12627 +}
12628 +
12629 +#endif
12630 +
12631 +  
12632 +#endif /* !defined(HAS_TEST_AND_SET) */
12633 +
12634 +
12635 +/* Blow up if we didn't have any way to do spinlocks */
12636 +#ifndef HAS_TEST_AND_SET
12637 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
12638 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
12639 +/* #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. */ 
12640 +#endif
12641 +
12642 +
12643 +#else  /* !HAVE_SPINLOCKS */
12644 +
12645 +
12646 +/*
12647 + * Fake spinlock implementation using semaphores --- slow and prone
12648 + * to fall foul of kernel limits on number of semaphores, so don't use this
12649 + * unless you must!  The subroutines appear in spin.c.
12650 + */
12651 +
12652 +/* -- Removed for APC
12653 +typedef PGSemaphoreData slock_t;
12654 +
12655 +extern bool s_lock_free_sema(volatile slock_t *lock);
12656 +extern void s_unlock_sema(volatile slock_t *lock);
12657 +extern void s_init_lock_sema(volatile slock_t *lock);
12658 +extern int     tas_sema(volatile slock_t *lock);
12659 +
12660 +#define S_LOCK_FREE(lock)      s_lock_free_sema(lock)
12661 +#define S_UNLOCK(lock)  s_unlock_sema(lock)
12662 +#define S_INIT_LOCK(lock)      s_init_lock_sema(lock)
12663 +#define TAS(lock)      tas_sema(lock)
12664 +*/
12665 +
12666 +#endif /* HAVE_SPINLOCKS */
12667 +
12668 +
12669 +/*
12670 + * Default Definitions - override these above as needed.
12671 + */
12672 +
12673 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
12674 +
12675 +#if !defined(S_LOCK)
12676 +#define S_LOCK(lock) \
12677 +       do { \
12678 +               if (TAS(lock)) \
12679 +                       s_lock((lock), __FILE__, __LINE__); \
12680 +       } while (0)
12681 +#endif  /* S_LOCK */
12682 +
12683 +#if !defined(S_LOCK_FREE)
12684 +#define S_LOCK_FREE(lock)      (*(lock) == 0)
12685 +#endif  /* S_LOCK_FREE */
12686 +
12687 +#if !defined(S_UNLOCK)
12688 +#define S_UNLOCK(lock)         (*((volatile slock_t *) (lock)) = 0)
12689 +#endif  /* S_UNLOCK */
12690 +
12691 +#if !defined(S_INIT_LOCK)
12692 +#define S_INIT_LOCK(lock)      S_UNLOCK(lock)
12693 +#endif  /* S_INIT_LOCK */
12694 +
12695 +#if !defined(SPIN_DELAY)
12696 +#define SPIN_DELAY()   ((void) 0)
12697 +#endif  /* SPIN_DELAY */
12698 +
12699 +#if !defined(TAS)
12700 +extern int     tas(volatile slock_t *lock);            /* in port/.../tas.s, or
12701 +                                                                                                * s_lock.c */
12702 +
12703 +#define TAS(lock)              tas(lock)
12704 +#endif  /* TAS */
12705 +
12706 +
12707 +/*
12708 + * Platform-independent out-of-line support routines
12709 + */
12710 +extern void s_lock(volatile slock_t *lock, const char *file, int line);
12711 +
12712 +/* Support for dynamic adjustment of spins_per_delay */
12713 +#define DEFAULT_SPINS_PER_DELAY  100
12714 +
12715 +#if 0  /* -- Removed from APC use -- */
12716 +extern void set_spins_per_delay(int shared_spins_per_delay);
12717 +extern int     update_spins_per_delay(int shared_spins_per_delay);
12718 +#endif
12719 +
12720 +#endif  /* S_LOCK_H */
12721 diff -ruN php-5.1.6.old/ext/apc/php_apc.c php-5.1.6/ext/APC/php_apc.c
12722 --- php-5.1.6.old/ext/apc/php_apc.c     1969-12-31 18:00:00.000000000 -0600
12723 +++ php-5.1.6/ext/apc/php_apc.c 2007-04-02 18:05:30.000000000 -0500
12724 @@ -0,0 +1,957 @@
12725 +/*
12726 +  +----------------------------------------------------------------------+
12727 +  | APC                                                                  |
12728 +  +----------------------------------------------------------------------+
12729 +  | Copyright (c) 2006 The PHP Group                                     |
12730 +  +----------------------------------------------------------------------+
12731 +  | This source file is subject to version 3.01 of the PHP license,      |
12732 +  | that is bundled with this package in the file LICENSE, and is        |
12733 +  | available through the world-wide-web at the following url:           |
12734 +  | http://www.php.net/license/3_01.txt                                  |
12735 +  | If you did not receive a copy of the PHP license and are unable to   |
12736 +  | obtain it through the world-wide-web, please send a note to          |
12737 +  | license@php.net so we can mail you a copy immediately.               |
12738 +  +----------------------------------------------------------------------+
12739 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
12740 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
12741 +  +----------------------------------------------------------------------+
12742 +
12743 +   This software was contributed to PHP by Community Connect Inc. in 2002
12744 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12745 +   Future revisions and derivatives of this source code must acknowledge
12746 +   Community Connect Inc. as the original contributor of this module by
12747 +   leaving this note intact in the source code.
12748 +
12749 +   All other licensing and usage conditions are those of the PHP Group.
12750 +
12751 + */
12752 +
12753 +/* $Id: php_apc.c,v 3.140 2007/03/28 07:14:54 gopalv Exp $ */
12754 +
12755 +#include "apc_zend.h"
12756 +#include "apc_cache.h"
12757 +#include "apc_main.h"
12758 +#include "apc_sma.h"
12759 +#include "apc_lock.h"
12760 +#include "php_globals.h"
12761 +#include "php_ini.h"
12762 +#include "ext/standard/info.h"
12763 +#include "SAPI.h"
12764 +#include "rfc1867.h"
12765 +#include "php_apc.h"
12766 +#if PHP_API_VERSION <= 20020918
12767 +#if HAVE_APACHE
12768 +#ifdef APC_PHP4_STAT
12769 +#undef XtOffsetOf
12770 +#include "httpd.h"
12771 +#endif
12772 +#endif
12773 +#endif
12774 +
12775 +/* {{{ PHP_FUNCTION declarations */
12776 +PHP_FUNCTION(apc_cache_info);
12777 +PHP_FUNCTION(apc_clear_cache);
12778 +PHP_FUNCTION(apc_sma_info);
12779 +PHP_FUNCTION(apc_store);
12780 +PHP_FUNCTION(apc_fetch);
12781 +PHP_FUNCTION(apc_delete);
12782 +PHP_FUNCTION(apc_compile_file);
12783 +PHP_FUNCTION(apc_define_constants);
12784 +PHP_FUNCTION(apc_load_constants);
12785 +PHP_FUNCTION(apc_add);
12786 +/* }}} */
12787 +
12788 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
12789 +ZEND_DECLARE_MODULE_GLOBALS(apc)
12790 +
12791 +/* True globals */
12792 +apc_cache_t* apc_cache = NULL;       
12793 +apc_cache_t* apc_user_cache = NULL;
12794 +void* apc_compiled_filters = NULL;
12795 +
12796 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12797 +{
12798 +    apc_globals->filters = NULL;
12799 +    apc_globals->initialized = 0;
12800 +    apc_globals->cache_stack = apc_stack_create(0);
12801 +    apc_globals->cache_by_default = 1;
12802 +    apc_globals->slam_defense = 0;
12803 +    apc_globals->mem_size_ptr = NULL;
12804 +    apc_globals->fpstat = 1;
12805 +    apc_globals->stat_ctime = 0;
12806 +    apc_globals->write_lock = 1;
12807 +    apc_globals->report_autofilter = 0;
12808 +    apc_globals->apc_optimize_function = NULL;
12809 +#ifdef MULTIPART_EVENT_FORMDATA
12810 +    apc_globals->rfc1867 = 0;
12811 +#endif
12812 +    apc_globals->copied_zvals = NULL;
12813 +#ifdef ZEND_ENGINE_2
12814 +    apc_globals->reserved_offset = -1;
12815 +#endif
12816 +    apc_globals->localcache = 0;
12817 +    apc_globals->localcache_size = 0;
12818 +    apc_globals->lcache = NULL;
12819 +}
12820 +
12821 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12822 +{
12823 +    /* deallocate the ignore patterns */
12824 +    if (apc_globals->filters != NULL) {
12825 +        int i;
12826 +        for (i=0; apc_globals->filters[i] != NULL; i++) {
12827 +            apc_efree(apc_globals->filters[i]);
12828 +        }
12829 +        apc_efree(apc_globals->filters);
12830 +    }
12831 +
12832 +    /* the stack should be empty */
12833 +    assert(apc_stack_size(apc_globals->cache_stack) == 0); 
12834 +
12835 +    /* apc cleanup */
12836 +    apc_stack_destroy(apc_globals->cache_stack);
12837 +
12838 +    /* the rest of the globals are cleaned up in apc_module_shutdown() */
12839 +}
12840 +
12841 +/* }}} */
12842 +
12843 +/* {{{ PHP_INI */
12844 +
12845 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
12846 +{
12847 +    APCG(filters) = apc_tokenize(new_value, ',');
12848 +    return SUCCESS;
12849 +}
12850 +/* }}} */
12851 +
12852 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
12853 +{
12854 +#if APC_MMAP
12855 +    if(atoi(new_value)!=1) {
12856 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
12857 +    }
12858 +    APCG(shm_segments) = 1; 
12859 +#else
12860 +    APCG(shm_segments) = atoi(new_value);
12861 +#endif
12862 +    return SUCCESS;
12863 +}
12864 +/* }}} */
12865 +
12866 +
12867 +#ifdef ZEND_ENGINE_2
12868 +#define OnUpdateInt OnUpdateLong
12869 +#endif
12870 +
12871 +PHP_INI_BEGIN()
12872 +STD_PHP_INI_BOOLEAN("apc.enabled",      "1",    PHP_INI_SYSTEM, OnUpdateBool,              enabled,         zend_apc_globals, apc_globals)
12873 +STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    PHP_INI_SYSTEM, OnUpdateShmSegments,       shm_segments,    zend_apc_globals, apc_globals)
12874 +STD_PHP_INI_ENTRY("apc.shm_size",       "30",   PHP_INI_SYSTEM, OnUpdateInt,            shm_size,        zend_apc_globals, apc_globals)
12875 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool,     include_once,    zend_apc_globals, apc_globals)
12876 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt,            num_files_hint,  zend_apc_globals, apc_globals)
12877 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt,          user_entries_hint, zend_apc_globals, apc_globals)
12878 +STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", PHP_INI_SYSTEM, OnUpdateInt,            gc_ttl,           zend_apc_globals, apc_globals)
12879 +STD_PHP_INI_ENTRY("apc.ttl",            "0",    PHP_INI_SYSTEM, OnUpdateInt,            ttl,              zend_apc_globals, apc_globals)
12880 +STD_PHP_INI_ENTRY("apc.user_ttl",       "0",    PHP_INI_SYSTEM, OnUpdateInt,            user_ttl,         zend_apc_globals, apc_globals)
12881 +#if APC_MMAP
12882 +STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
12883 +#endif
12884 +PHP_INI_ENTRY("apc.filters",        NULL,     PHP_INI_SYSTEM, OnUpdate_filters)
12885 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1",  PHP_INI_ALL, OnUpdateBool,         cache_by_default, zend_apc_globals, apc_globals)
12886 +STD_PHP_INI_ENTRY("apc.slam_defense", "0",      PHP_INI_SYSTEM, OnUpdateInt,            slam_defense,     zend_apc_globals, apc_globals)
12887 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection,  zend_apc_globals, apc_globals)
12888 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0",      PHP_INI_SYSTEM, OnUpdateBool,           enable_cli,       zend_apc_globals, apc_globals)
12889 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M",    PHP_INI_SYSTEM, OnUpdateInt,            max_file_size,    zend_apc_globals, apc_globals)
12890 +STD_PHP_INI_BOOLEAN("apc.stat", "1",            PHP_INI_SYSTEM, OnUpdateBool,           fpstat,           zend_apc_globals, apc_globals)
12891 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0",      PHP_INI_SYSTEM, OnUpdateBool,           stat_ctime,       zend_apc_globals, apc_globals)
12892 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1",      PHP_INI_SYSTEM, OnUpdateBool,           write_lock,       zend_apc_globals, apc_globals)
12893 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool,         report_autofilter,zend_apc_globals, apc_globals)
12894 +#ifdef MULTIPART_EVENT_FORMDATA
12895 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
12896 +#endif
12897 +STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
12898 +STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size,  zend_apc_globals, apc_globals)
12899 +PHP_INI_END()
12900 +
12901 +/* }}} */
12902 +
12903 +/* {{{ PHP_MINFO_FUNCTION(apc) */
12904 +static PHP_MINFO_FUNCTION(apc)
12905 +{
12906 +    php_info_print_table_start();
12907 +    php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
12908 +    php_info_print_table_row(2, "Version", APC_VERSION);
12909 +#if APC_MMAP
12910 +    php_info_print_table_row(2, "MMAP Support", "Enabled");
12911 +    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
12912 +#else
12913 +    php_info_print_table_row(2, "MMAP Support", "Disabled");
12914 +#endif
12915 +#if APC_SEM_LOCKS
12916 +    php_info_print_table_row(2, "Locking type", "IPC Semaphore");
12917 +#elif APC_FUTEX_LOCKS
12918 +    php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
12919 +#elif APC_PTHREADMUTEX_LOCKS
12920 +    php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
12921 +#elif APC_SPIN_LOCKS
12922 +    php_info_print_table_row(2, "Locking type", "spin Locks");
12923 +#else
12924 +    php_info_print_table_row(2, "Locking type", "File Locks");
12925 +#endif
12926 +    php_info_print_table_row(2, "Revision", "$Revision: 3.140 $");
12927 +    php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
12928 +    php_info_print_table_end();
12929 +    DISPLAY_INI_ENTRIES();
12930 +}
12931 +/* }}} */
12932 +
12933 +#ifdef MULTIPART_EVENT_FORMDATA
12934 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
12935 +#endif
12936 +
12937 +/* {{{ PHP_MINIT_FUNCTION(apc) */
12938 +static PHP_MINIT_FUNCTION(apc)
12939 +{
12940 +    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
12941 +
12942 +    REGISTER_INI_ENTRIES();
12943 +
12944 +    /* Disable APC in cli mode unless overridden by apc.enable_cli */
12945 +    if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
12946 +        APCG(enabled) = 0;
12947 +    }
12948 +
12949 +    if (APCG(enabled)) {
12950 +        if(APCG(initialized)) {
12951 +            apc_process_init(module_number TSRMLS_CC);
12952 +        } else {
12953 +            apc_module_init(module_number TSRMLS_CC);
12954 +            apc_zend_init(TSRMLS_C);
12955 +            apc_process_init(module_number TSRMLS_CC);
12956 +#ifdef MULTIPART_EVENT_FORMDATA
12957 +            /* File upload progress tracking */
12958 +            if(APCG(rfc1867)) {
12959 +                php_rfc1867_callback = apc_rfc1867_progress;
12960 +            }
12961 +#endif
12962 +        }
12963 +    }
12964 +
12965 +    return SUCCESS;
12966 +}
12967 +/* }}} */
12968 +
12969 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
12970 +static PHP_MSHUTDOWN_FUNCTION(apc)
12971 +{
12972 +    if(APCG(enabled)) {
12973 +        apc_process_shutdown(TSRMLS_C);
12974 +        apc_zend_shutdown(TSRMLS_C);
12975 +        apc_module_shutdown(TSRMLS_C);
12976 +#ifndef ZTS
12977 +        php_apc_shutdown_globals(&apc_globals);
12978 +#endif
12979 +    }
12980 +#ifdef ZTS
12981 +    ts_free_id(apc_globals_id);
12982 +#endif
12983 +    UNREGISTER_INI_ENTRIES();
12984 +    return SUCCESS;
12985 +}
12986 +/* }}} */
12987 +
12988 +/* {{{ PHP_RINIT_FUNCTION(apc) */
12989 +static PHP_RINIT_FUNCTION(apc)
12990 +{
12991 +    if(APCG(enabled)) {
12992 +        apc_request_init(TSRMLS_C);
12993 +    }
12994 +    return SUCCESS;
12995 +}
12996 +/* }}} */
12997 +
12998 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
12999 +static PHP_RSHUTDOWN_FUNCTION(apc)
13000 +{
13001 +    if(APCG(enabled)) {
13002 +        apc_request_shutdown(TSRMLS_C);
13003 +    }
13004 +    return SUCCESS;
13005 +}
13006 +/* }}} */
13007 +
13008 +/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
13009 +PHP_FUNCTION(apc_cache_info)
13010 +{
13011 +    apc_cache_info_t* info;
13012 +    apc_cache_link_t* p;
13013 +    zval* list;
13014 +    char *cache_type;
13015 +    int ct_len;
13016 +    zend_bool limited=0;
13017 +
13018 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
13019 +        return;
13020 +    }
13021 +
13022 +    if(ZEND_NUM_ARGS()) {
13023 +        if(!strcasecmp(cache_type,"user")) {
13024 +            info = apc_cache_info(apc_user_cache, limited);
13025 +        } else {
13026 +            info = apc_cache_info(apc_cache, limited);
13027 +        }
13028 +    } else info = apc_cache_info(apc_cache, limited);
13029 +
13030 +    if(!info) {
13031 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available.  Perhaps APC is not enabled? Check apc.enabled in your ini file");
13032 +        RETURN_FALSE;
13033 +    }
13034 +
13035 +    array_init(return_value);
13036 +    add_assoc_long(return_value, "num_slots", info->num_slots);
13037 +    add_assoc_long(return_value, "ttl", info->ttl);
13038 +    add_assoc_long(return_value, "num_hits", info->num_hits);
13039 +    add_assoc_long(return_value, "num_misses", info->num_misses);
13040 +    add_assoc_long(return_value, "start_time", info->start_time);
13041 +    add_assoc_long(return_value, "expunges", info->expunges);
13042 +    add_assoc_long(return_value, "mem_size", info->mem_size);
13043 +    add_assoc_long(return_value, "num_entries", info->num_entries);
13044 +    add_assoc_long(return_value, "num_inserts", info->num_inserts);
13045 +#ifdef MULTIPART_EVENT_FORMDATA
13046 +    add_assoc_long(return_value, "file_upload_progress", 1);
13047 +#else
13048 +    add_assoc_long(return_value, "file_upload_progress", 0);
13049 +#endif
13050 +#if APC_MMAP
13051 +    add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
13052 +#else
13053 +    add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
13054 +#endif
13055 +#if APC_SEM_LOCKS
13056 +    add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
13057 +#elif APC_FUTEX_LOCKS
13058 +    add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
13059 +#elif APC_PTHREADMUTEX_LOCKS
13060 +    add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
13061 +#elif APC_SPIN_LOCKS
13062 +    add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
13063 +#else
13064 +    add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
13065 +#endif
13066 +    if(limited) {
13067 +        apc_cache_free_info(info);
13068 +        return;
13069 +    }
13070 +    
13071 +    ALLOC_INIT_ZVAL(list);
13072 +    array_init(list);
13073 +
13074 +    for (p = info->list; p != NULL; p = p->next) {
13075 +        zval* link;
13076 +
13077 +        ALLOC_INIT_ZVAL(link);
13078 +        array_init(link);
13079 +
13080 +        if(p->type == APC_CACHE_ENTRY_FILE) {
13081 +            add_assoc_string(link, "filename", p->data.file.filename, 1);
13082 +            add_assoc_long(link, "device", p->data.file.device);
13083 +            add_assoc_long(link, "inode", p->data.file.inode);
13084 +            add_assoc_string(link, "type", "file", 1);
13085 +        } else if(p->type == APC_CACHE_ENTRY_USER) {
13086 +            add_assoc_string(link, "info", p->data.user.info, 1);
13087 +            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13088 +            add_assoc_string(link, "type", "user", 1);
13089 +        }
13090 +        add_assoc_long(link, "num_hits", p->num_hits);
13091 +        add_assoc_long(link, "mtime", p->mtime);
13092 +        add_assoc_long(link, "creation_time", p->creation_time);
13093 +        add_assoc_long(link, "deletion_time", p->deletion_time);
13094 +        add_assoc_long(link, "access_time", p->access_time);
13095 +        add_assoc_long(link, "ref_count", p->ref_count);
13096 +        add_assoc_long(link, "mem_size", p->mem_size);
13097 +        add_next_index_zval(list, link);
13098 +    }
13099 +    add_assoc_zval(return_value, "cache_list", list);
13100 +
13101 +    ALLOC_INIT_ZVAL(list);
13102 +    array_init(list);
13103 +
13104 +    for (p = info->deleted_list; p != NULL; p = p->next) {
13105 +        zval* link;
13106 +
13107 +        ALLOC_INIT_ZVAL(link);
13108 +        array_init(link);
13109 +
13110 +        if(p->type == APC_CACHE_ENTRY_FILE) {
13111 +            add_assoc_string(link, "filename", p->data.file.filename, 1);
13112 +            add_assoc_long(link, "device", p->data.file.device);
13113 +            add_assoc_long(link, "inode", p->data.file.inode);
13114 +            add_assoc_string(link, "type", "file", 1);
13115 +        } else if(p->type == APC_CACHE_ENTRY_USER) {
13116 +            add_assoc_string(link, "info", p->data.user.info, 1);
13117 +            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13118 +            add_assoc_string(link, "type", "user", 1);
13119 +        }
13120 +        add_assoc_long(link, "num_hits", p->num_hits);
13121 +        add_assoc_long(link, "mtime", p->mtime);
13122 +        add_assoc_long(link, "creation_time", p->creation_time);
13123 +        add_assoc_long(link, "deletion_time", p->deletion_time);
13124 +        add_assoc_long(link, "access_time", p->access_time);
13125 +        add_assoc_long(link, "ref_count", p->ref_count);
13126 +        add_assoc_long(link, "mem_size", p->mem_size);
13127 +        add_next_index_zval(list, link);
13128 +    }
13129 +    add_assoc_zval(return_value, "deleted_list", list);
13130 +
13131 +    apc_cache_free_info(info);
13132 +}
13133 +/* }}} */
13134 +
13135 +/* {{{ proto void apc_clear_cache() */
13136 +PHP_FUNCTION(apc_clear_cache)
13137 +{
13138 +    char *cache_type;
13139 +    int ct_len;
13140 +
13141 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
13142 +        return;
13143 +    }
13144 +
13145 +    if(ZEND_NUM_ARGS()) {
13146 +        if(!strcasecmp(cache_type,"user")) {
13147 +            apc_cache_clear(apc_user_cache);
13148 +            RETURN_TRUE;
13149 +        }
13150 +    }
13151 +    apc_cache_clear(apc_cache);
13152 +}
13153 +/* }}} */
13154 +
13155 +/* {{{ proto array apc_sma_info([bool limited]) */
13156 +PHP_FUNCTION(apc_sma_info)
13157 +{
13158 +    apc_sma_info_t* info;
13159 +    zval* block_lists;
13160 +    int i;
13161 +    zend_bool limited = 0;
13162 +
13163 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
13164 +        return;
13165 +    }
13166 +
13167 +    info = apc_sma_info(limited);
13168 +
13169 +    if(!info) {
13170 +        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
13171 +        RETURN_FALSE;
13172 +    }
13173 +
13174 +    array_init(return_value);
13175 +    add_assoc_long(return_value, "num_seg", info->num_seg);
13176 +    add_assoc_long(return_value, "seg_size", info->seg_size);
13177 +    add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
13178 +
13179 +    if(limited) {
13180 +        apc_sma_free_info(info);
13181 +        return;
13182 +    }
13183 +
13184 +#if ALLOC_DISTRIBUTION
13185 +    {
13186 +        size_t *adist = apc_sma_get_alloc_distribution();
13187 +        zval* list;
13188 +        ALLOC_INIT_ZVAL(list);
13189 +        array_init(list);
13190 +        for(i=0; i<30; i++) {
13191 +            add_next_index_long(list, adist[i]);
13192 +        }
13193 +        add_assoc_zval(return_value, "adist", list);
13194 +    }
13195 +#endif
13196 +    ALLOC_INIT_ZVAL(block_lists);
13197 +    array_init(block_lists);
13198 +
13199 +    for (i = 0; i < info->num_seg; i++) {
13200 +        apc_sma_link_t* p;
13201 +        zval* list;
13202 +
13203 +        ALLOC_INIT_ZVAL(list);
13204 +        array_init(list);
13205 +
13206 +        for (p = info->list[i]; p != NULL; p = p->next) {
13207 +            zval* link;
13208 +
13209 +            ALLOC_INIT_ZVAL(link);
13210 +            array_init(link);
13211 +
13212 +            add_assoc_long(link, "size", p->size);
13213 +            add_assoc_long(link, "offset", p->offset);
13214 +            add_next_index_zval(list, link);
13215 +        }
13216 +        add_next_index_zval(block_lists, list);
13217 +    }
13218 +    add_assoc_zval(return_value, "block_lists", block_lists);
13219 +    apc_sma_free_info(info);
13220 +}
13221 +/* }}} */
13222 +
13223 +/* {{{ _apc_store */
13224 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
13225 +    apc_cache_entry_t *entry;
13226 +    apc_cache_key_t key;
13227 +    time_t t;
13228 +    size_t mem_size = 0;
13229 +
13230 +#if PHP_API_VERSION <= 20041225
13231 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13232 +    t = ((request_rec *)SG(server_context))->request_time;
13233 +#else
13234 +    t = time(0);
13235 +#endif
13236 +#else
13237 +    t = sapi_get_request_time(TSRMLS_C);
13238 +#endif
13239 +
13240 +    if(!APCG(enabled)) return 0;
13241 +
13242 +    HANDLE_BLOCK_INTERRUPTIONS();
13243 +
13244 +    APCG(mem_size_ptr) = &mem_size;
13245 +    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
13246 +        APCG(mem_size_ptr) = NULL;
13247 +        apc_cache_expunge(apc_cache,t);
13248 +        apc_cache_expunge(apc_user_cache,t);
13249 +        HANDLE_UNBLOCK_INTERRUPTIONS();
13250 +        return 0;
13251 +    }
13252 +
13253 +    if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
13254 +        APCG(mem_size_ptr) = NULL;
13255 +        apc_cache_free_entry(entry);
13256 +        apc_cache_expunge(apc_cache,t);
13257 +        apc_cache_expunge(apc_user_cache,t);
13258 +        HANDLE_UNBLOCK_INTERRUPTIONS();
13259 +        return 0;
13260 +    }
13261 +
13262 +    if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
13263 +        APCG(mem_size_ptr) = NULL;
13264 +        apc_cache_free_entry(entry);
13265 +        apc_cache_expunge(apc_cache,t);
13266 +        apc_cache_expunge(apc_user_cache,t);
13267 +        HANDLE_UNBLOCK_INTERRUPTIONS();
13268 +        return 0;
13269 +    }
13270 +
13271 +    APCG(mem_size_ptr) = NULL;
13272 +
13273 +    HANDLE_UNBLOCK_INTERRUPTIONS();
13274 +
13275 +    return 1;
13276 +}
13277 +/* }}} */
13278 +
13279 +/* {{{ proto int apc_store(string key, zval var [, ttl ])
13280 + */
13281 +PHP_FUNCTION(apc_store) {
13282 +    zval *val;
13283 +    char *strkey;
13284 +    int strkey_len;
13285 +    long ttl = 0L;
13286 +
13287 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13288 +        return;
13289 +    }
13290 +
13291 +    if(!strkey_len) RETURN_FALSE;
13292 +
13293 +    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
13294 +    RETURN_FALSE;
13295 +}
13296 +/* }}} */
13297 +
13298 +/* {{{ proto int apc_add(string key, zval var [, ttl ])
13299 + */
13300 +PHP_FUNCTION(apc_add) {
13301 +    zval *val;
13302 +    char *strkey;
13303 +    int strkey_len;
13304 +    long ttl = 0L;
13305 +
13306 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13307 +        return;
13308 +    }
13309 +
13310 +    if(!strkey_len) RETURN_FALSE;
13311 +
13312 +    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
13313 +    RETURN_FALSE;
13314 +}
13315 +/* }}} */
13316 +
13317 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
13318 +    return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
13319 +}
13320 +
13321 +/* {{{ RETURN_ZVAL for php4 */
13322 +#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
13323 +#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } 
13324 +#define RETVAL_ZVAL(zv, copy, dtor)     ZVAL_ZVAL(return_value, zv, copy, dtor)
13325 +#define ZVAL_ZVAL(z, zv, copy, dtor) {  \
13326 +        int is_ref, refcount;           \
13327 +        is_ref = (z)->is_ref;           \
13328 +        refcount = (z)->refcount;       \
13329 +        *(z) = *(zv);                   \
13330 +        if (copy) {                     \
13331 +            zval_copy_ctor(z);          \
13332 +        }                               \
13333 +        if (dtor) {                     \
13334 +            if (!copy) {                \
13335 +                ZVAL_NULL(zv);          \
13336 +            }                           \
13337 +            zval_ptr_dtor(&zv);         \
13338 +        }                               \
13339 +        (z)->is_ref = is_ref;           \
13340 +        (z)->refcount = refcount;       \
13341 +    }
13342 +#endif
13343 +/* }}} */
13344 +
13345 +/* {{{ proto mixed apc_fetch(mixed key)
13346 + */
13347 +PHP_FUNCTION(apc_fetch) {
13348 +    zval *key;
13349 +    HashTable *hash;
13350 +    HashPosition hpos;
13351 +    zval **hentry;
13352 +    zval *result;
13353 +    zval *result_entry;
13354 +    char *strkey;
13355 +    int strkey_len;
13356 +    apc_cache_entry_t* entry;
13357 +    time_t t;
13358 +
13359 +    if(!APCG(enabled)) RETURN_FALSE;
13360 +
13361 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
13362 +        return;
13363 +    }
13364 +
13365 +#if PHP_API_VERSION <= 20041225
13366 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13367 +    t = ((request_rec *)SG(server_context))->request_time;
13368 +#else 
13369 +    t = time(0);
13370 +#endif
13371 +#else
13372 +    t = sapi_get_request_time(TSRMLS_C);
13373 +#endif
13374 +
13375 +    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
13376 +        convert_to_string(key);
13377 +    }
13378 +    
13379 +    if(Z_TYPE_P(key) == IS_STRING) {
13380 +        strkey = Z_STRVAL_P(key);
13381 +        strkey_len = Z_STRLEN_P(key);
13382 +        if(!strkey_len) RETURN_FALSE;
13383 +        entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13384 +        if(entry) {
13385 +            /* deep-copy returned shm zval to emalloc'ed return_value */
13386 +            apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
13387 +            apc_cache_release(apc_user_cache, entry);
13388 +        } else {
13389 +            RETURN_FALSE;
13390 +        }
13391 +    } else if(Z_TYPE_P(key) == IS_ARRAY) {
13392 +        hash = Z_ARRVAL_P(key);
13393 +        MAKE_STD_ZVAL(result);
13394 +        array_init(result); 
13395 +        zend_hash_internal_pointer_reset_ex(hash, &hpos);
13396 +        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
13397 +            if(Z_TYPE_PP(hentry) != IS_STRING) {
13398 +                apc_wprint("apc_fetch() expects a string or array of strings.");
13399 +                RETURN_FALSE;
13400 +            }
13401 +            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
13402 +            if(entry) {
13403 +                /* deep-copy returned shm zval to emalloc'ed return_value */
13404 +                MAKE_STD_ZVAL(result_entry);
13405 +                apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
13406 +                apc_cache_release(apc_user_cache, entry);
13407 +                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
13408 +            } /* don't set values we didn't find */
13409 +            zend_hash_move_forward_ex(hash, &hpos);
13410 +        }
13411 +        RETURN_ZVAL(result, 0, 1);
13412 +    } else {
13413 +        apc_wprint("apc_fetch() expects a string or array of strings.");
13414 +        RETURN_FALSE;
13415 +    }
13416 +
13417 +    return;
13418 +}
13419 +/* }}} */
13420 +
13421 +/* {{{ proto mixed apc_delete(string key)
13422 + */
13423 +PHP_FUNCTION(apc_delete) {
13424 +    char *strkey;
13425 +    int strkey_len;
13426 +
13427 +    if(!APCG(enabled)) RETURN_FALSE;
13428 +
13429 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
13430 +        return;
13431 +    }
13432 +
13433 +    if(!strkey_len) RETURN_FALSE;
13434 +
13435 +    if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
13436 +        RETURN_TRUE;
13437 +    } else {
13438 +        RETURN_FALSE;
13439 +    }
13440 +}
13441 +/* }}} */
13442 +
13443 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
13444 +    char *const_key;
13445 +    unsigned int const_key_len;
13446 +    zval **entry;
13447 +    HashPosition pos;
13448 +
13449 +    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
13450 +    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
13451 +        zend_constant c;
13452 +        int key_type;
13453 +        ulong num_key;
13454 +
13455 +        key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
13456 +        if(key_type != HASH_KEY_IS_STRING) {
13457 +            zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13458 +            continue;
13459 +        }
13460 +        switch(Z_TYPE_PP(entry)) {
13461 +            case IS_LONG:
13462 +            case IS_DOUBLE:
13463 +            case IS_STRING:
13464 +            case IS_BOOL:
13465 +            case IS_RESOURCE:
13466 +            case IS_NULL:
13467 +                break;
13468 +            default:
13469 +                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13470 +                continue;
13471 +        }
13472 +        c.value = **entry;
13473 +        zval_copy_ctor(&c.value);
13474 +        c.flags = case_sensitive;
13475 +        c.name = zend_strndup(const_key, const_key_len);
13476 +        c.name_len = const_key_len;
13477 +#ifdef ZEND_ENGINE_2
13478 +        c.module_number = PHP_USER_CONSTANT;
13479 +#endif
13480 +        zend_register_constant(&c TSRMLS_CC);
13481 +
13482 +        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13483 +    }
13484 +}
13485 +
13486 +/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
13487 + */
13488 +PHP_FUNCTION(apc_define_constants) {
13489 +    char *strkey;
13490 +    int strkey_len;
13491 +    zval *constants = NULL;
13492 +    zend_bool case_sensitive = 1;
13493 +    int argc = ZEND_NUM_ARGS();
13494 +
13495 +    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
13496 +        return;
13497 +    }
13498 +
13499 +    if(!strkey_len) RETURN_FALSE;
13500 +
13501 +    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
13502 +    if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
13503 +    RETURN_FALSE;
13504 +} /* }}} */
13505 +
13506 +/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
13507 + */
13508 +PHP_FUNCTION(apc_load_constants) {
13509 +    char *strkey;
13510 +    int strkey_len;
13511 +    apc_cache_entry_t* entry;
13512 +    time_t t;
13513 +    zend_bool case_sensitive = 1;
13514 +
13515 +    if(!APCG(enabled)) RETURN_FALSE;
13516 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
13517 +        return;
13518 +    }
13519 +
13520 +    if(!strkey_len) RETURN_FALSE;
13521 +
13522 +#if PHP_API_VERSION <= 20041225
13523 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13524 +    t = ((request_rec *)SG(server_context))->request_time;
13525 +#else 
13526 +    t = time(0);
13527 +#endif
13528 +#else 
13529 +    t = sapi_get_request_time(TSRMLS_C);
13530 +#endif
13531 +
13532 +    entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13533 +
13534 +    if(entry) {
13535 +        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
13536 +        apc_cache_release(apc_user_cache, entry);
13537 +        RETURN_TRUE;
13538 +    } else {
13539 +        RETURN_FALSE;
13540 +    }
13541 +}
13542 +/* }}} */
13543 +
13544 +/* {{{ proto boolean apc_compile_file(string filename)
13545 + */
13546 +PHP_FUNCTION(apc_compile_file) {
13547 +    char *filename;
13548 +    int filename_len;
13549 +    zend_file_handle file_handle;
13550 +    zend_op_array *op_array;
13551 +    long slam_defense = 0;
13552 +    char** filters = NULL;
13553 +    zend_bool cache_by_default = 1;
13554 +    HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
13555 +    HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
13556 +
13557 +    if(!APCG(enabled)) RETURN_FALSE;
13558 +
13559 +    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
13560 +        return;
13561 +    }
13562 +
13563 +    if(!filename) RETURN_FALSE;
13564 +
13565 +    /* If slam defense is active, temporarily disable */
13566 +    if(APCG(slam_defense)) {
13567 +        slam_defense = APCG(slam_defense);
13568 +        APCG(slam_defense) = 0;
13569 +    }
13570 +   
13571 +    /* If filter is active, temporarily disable */
13572 +    if(APCG(filters) != NULL) {
13573 +        filters = APCG(filters);
13574 +        APCG(filters) = NULL;
13575 +    }
13576 +
13577 +    /* If cache_by_default is off, temporarily enable */
13578 +    if(!APCG(cache_by_default)) {
13579 +        cache_by_default = APCG(cache_by_default);
13580 +        APCG(cache_by_default) = 1;
13581 +    }
13582 +
13583 +    /* Replace function/class tables to avoid namespace conflicts */
13584 +    zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13585 +    cg_orig_function_table = CG(function_table);
13586 +    CG(function_table) = &cg_function_table;
13587 +    zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13588 +    cg_orig_class_table = CG(class_table);
13589 +    CG(class_table) = &cg_class_table;
13590 +    zend_hash_init_ex(&eg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13591 +    eg_orig_function_table = EG(function_table);
13592 +    EG(function_table) = &eg_function_table;
13593 +    zend_hash_init_ex(&eg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13594 +    eg_orig_class_table = EG(class_table);
13595 +    EG(class_table) = &eg_class_table;
13596 +    
13597 +    /* Compile the file, loading it into the cache */
13598 +    file_handle.type = ZEND_HANDLE_FILENAME;
13599 +    file_handle.filename = filename;
13600 +    file_handle.free_filename = 0;
13601 +    file_handle.opened_path = NULL;
13602 +    zend_try {
13603 +        op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
13604 +    } zend_catch {
13605 +        apc_eprint("Error compiling %s in apc_compile_file.", filename);
13606 +        op_array = NULL;
13607 +    } zend_end_try();
13608 +
13609 +    /* Return class/function tables to previous states, destroy temp tables */
13610 +    CG(function_table) = cg_orig_function_table;
13611 +    zend_hash_destroy(&cg_function_table);
13612 +    CG(class_table) = cg_orig_class_table;
13613 +    zend_hash_destroy(&cg_class_table);
13614 +    EG(function_table) = eg_orig_function_table;
13615 +    zend_hash_destroy(&eg_function_table);
13616 +    EG(class_table) = eg_orig_class_table;
13617 +    zend_hash_destroy(&eg_class_table);
13618 +    
13619 +    /* Restore global settings */
13620 +    APCG(slam_defense) = slam_defense;
13621 +    APCG(filters) = filters;
13622 +    APCG(cache_by_default) = cache_by_default;
13623 +
13624 +    if(op_array == NULL) { RETURN_FALSE; }
13625 +
13626 +    /* Free up everything */
13627 +    zend_destroy_file_handle(&file_handle TSRMLS_CC);
13628 +#ifdef ZEND_ENGINE_2
13629 +    destroy_op_array(op_array TSRMLS_CC);
13630 +#else
13631 +    destroy_op_array(op_array);
13632 +#endif
13633 +    efree(op_array);
13634 +
13635 +    RETURN_TRUE;
13636 +}
13637 +/* }}} */
13638 +
13639 +/* {{{ apc_functions[] */
13640 +function_entry apc_functions[] = {
13641 +       PHP_FE(apc_cache_info,          NULL)
13642 +       PHP_FE(apc_clear_cache,         NULL)
13643 +       PHP_FE(apc_sma_info,            NULL)
13644 +       PHP_FE(apc_store,               NULL)
13645 +       PHP_FE(apc_fetch,               NULL)
13646 +       PHP_FE(apc_delete,              NULL)
13647 +       PHP_FE(apc_define_constants,    NULL)
13648 +       PHP_FE(apc_load_constants,      NULL)
13649 +       PHP_FE(apc_compile_file,        NULL)
13650 +       {NULL,          NULL,                           NULL}
13651 +};
13652 +/* }}} */
13653 +
13654 +/* {{{ module definition structure */
13655 +
13656 +zend_module_entry apc_module_entry = {
13657 +       STANDARD_MODULE_HEADER,
13658 +       "apc",
13659 +       apc_functions,
13660 +       PHP_MINIT(apc),
13661 +       PHP_MSHUTDOWN(apc),
13662 +       PHP_RINIT(apc),
13663 +       PHP_RSHUTDOWN(apc),
13664 +       PHP_MINFO(apc),
13665 +       APC_VERSION,
13666 +       STANDARD_MODULE_PROPERTIES
13667 +};
13668 +
13669 +#ifdef COMPILE_DL_APC
13670 +ZEND_GET_MODULE(apc)
13671 +#endif
13672 +/* }}} */
13673 +
13674 +/*
13675 + * Local variables:
13676 + * tab-width: 4
13677 + * c-basic-offset: 4
13678 + * End:
13679 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13680 + * vim<600: expandtab sw=4 ts=4 sts=4
13681 + */
13682 diff -ruN php-5.1.6.old/ext/apc/php_apc.h php-5.1.6/ext/APC/php_apc.h
13683 --- php-5.1.6.old/ext/apc/php_apc.h     1969-12-31 18:00:00.000000000 -0600
13684 +++ php-5.1.6/ext/apc/php_apc.h 2007-04-02 18:05:30.000000000 -0500
13685 @@ -0,0 +1,52 @@
13686 +/*
13687 +  +----------------------------------------------------------------------+
13688 +  | APC                                                                  |
13689 +  +----------------------------------------------------------------------+
13690 +  | Copyright (c) 2006 The PHP Group                                     |
13691 +  +----------------------------------------------------------------------+
13692 +  | This source file is subject to version 3.01 of the PHP license,      |
13693 +  | that is bundled with this package in the file LICENSE, and is        |
13694 +  | available through the world-wide-web at the following url:           |
13695 +  | http://www.php.net/license/3_01.txt                                  |
13696 +  | If you did not receive a copy of the PHP license and are unable to   |
13697 +  | obtain it through the world-wide-web, please send a note to          |
13698 +  | license@php.net so we can mail you a copy immediately.               |
13699 +  +----------------------------------------------------------------------+
13700 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
13701 +  |          George Schlossnagle <george@omniti.com>                     |
13702 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
13703 +  +----------------------------------------------------------------------+
13704 +
13705 +   This software was contributed to PHP by Community Connect Inc. in 2002
13706 +   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13707 +   Future revisions and derivatives of this source code must acknowledge
13708 +   Community Connect Inc. as the original contributor of this module by
13709 +   leaving this note intact in the source code.
13710 +
13711 +   All other licensing and usage conditions are those of the PHP Group.
13712 +
13713 + */
13714 +
13715 +/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
13716 +
13717 +#ifndef PHP_APC_H
13718 +#define PHP_APC_H
13719 +
13720 +#include "apc_php.h"
13721 +#include "apc_globals.h"
13722 +
13723 +extern zend_module_entry apc_module_entry;
13724 +#define apc_module_ptr &apc_module_entry
13725 +
13726 +#define phpext_apc_ptr apc_module_ptr
13727 +
13728 +#endif /* PHP_APC_H */
13729 +
13730 +/*
13731 + * Local variables:
13732 + * tab-width: 4
13733 + * c-basic-offset: 4
13734 + * End:
13735 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13736 + * vim<600: expandtab sw=4 ts=4 sts=4
13737 + */
13738 diff -ruN php-5.1.6.old/ext/apc/TECHNOTES.txt php-5.1.6/ext/APC/TECHNOTES.txt
13739 --- php-5.1.6.old/ext/apc/TECHNOTES.txt 1969-12-31 18:00:00.000000000 -0600
13740 +++ php-5.1.6/ext/apc/TECHNOTES.txt     2007-04-02 18:05:30.000000000 -0500
13741 @@ -0,0 +1,357 @@
13742 +APC Quick-Start Braindump
13743 +
13744 +This is a rapidly written braindump of how APC currently works in the
13745 +form of a quick-start guide to start hacking on APC.
13746 +
13747 +1. Install and use APC a bit so you know what it does from the end-user's
13748 +   perspective.  
13749 +   user-space functions are all explained here: 
13750 +
13751 +2. Grab the current APC code from CVS:
13752 +    
13753 +    cvs -d:pserver:cvsread@cvs.php.net:/repository login
13754 +    Password: phpfi
13755 +    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
13756 +
13757 +   apc/php_apc.c has most of the code for the user-visible stuff.  It is
13758 +   also a regular PHP extension in the sense that there are MINIT, MINFO, 
13759 +   MSHUTDOWN, RSHUTDOWN, etc. functions.  
13760 +
13761 +3. Build it.
13762 +
13763 +   cd pecl/apc
13764 +   phpize
13765 +   ./configure --enable-apc --enable-mmap
13766 +   make
13767 +   cp modules/apc.so /usr/local/lib/php
13768 +   apachectl restart
13769 +
13770 +4. Debugging Hints
13771 +
13772 +     apachectl stop
13773 +     gdb /usr/bin/httpd
13774 +     break ??
13775 +     run -X
13776 +
13777 +   Grab the .gdbinit from the PHP source tree and have a look at the macros.
13778 +
13779 +5. Look through apc/apc_sma.c
13780 +   It is a pretty standard memory allocator.
13781 +
13782 +   apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
13783 +   caller just like malloc, realloc, strdup and free
13784 +
13785 +   On server startup the MINIT hook in php_apc.c calls apc_module_init() in
13786 +   apc_main.c which in turn calls apc_sma_init().  apc_sma_init calls into
13787 +   apc_mmap.c to mmap the specified sized segment (I tend to just use a single
13788 +   segment).  apc_mmap.c should be self-explanatory.  It mmaps a temp file and
13789 +   then unlinks that file right after the mmap to provide automatic shared memory
13790 +   cleanup in case the process dies.
13791 +
13792 +   Once the region has been initialized we stick a header_t at the beginning
13793 +   of the region.  It contains the total size in header->segsize and the number 
13794 +   of bytes available in header->avail.  
13795 +
13796 +   After the header comes a bit of a hack.  A zero-sized block is inserted just
13797 +   to make things easier later on.  And then a huge block that is basically
13798 +   the size of the entire segment minus the two (for the 0-sized block, and this one)
13799 +   block headers.
13800 +
13801 +   The code for this is:
13802 +
13803 +     header = (header_t*) shmaddr;
13804 +     header->segsize = sma_segsize;
13805 +     header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
13806 +     memset(&header->lock,0,sizeof(header->lock));
13807 +     sma_lock = &header->lock;
13808 +     block = BLOCKAT(sizeof(header_t));
13809 +     block->size = 0;
13810 +     block->next = sizeof(header_t) + sizeof(block_t);
13811 +     block = BLOCKAT(block->next);
13812 +     block->size = header->avail;
13813 +     block->next = 0;
13814 +
13815 +   So the shared memory looks like this:
13816 +
13817 +     +--------+-------+---------------------------------+
13818 +     | header | block |             block               |
13819 +     +--------+-------+---------------------------------+
13820 +
13821 +   sma_shmaddrs[0] gives you the address of header
13822 +
13823 +   The blocks are just a simple offset-based linked list (so no pointers):
13824 +
13825 +     typedef struct block_t block_t;
13826 +     struct block_t {
13827 +         int size;       /* size of this block */
13828 +         int next;       /* offset in segment of next free block */
13829 +     };
13830 +
13831 +   The BLOCKAT macro turns an offset into an actual address for you:
13832 +
13833 +     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
13834 +
13835 +   where shmaddr = sma_shaddrs[0]
13836 +
13837 +   And the OFFSET macro goes the other way:
13838 +
13839 +     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
13840 +
13841 +   Allocating a block with a call to apc_sma_allocate() walks through the
13842 +   linked list of blocks until it finds one that is >= to the requested size.
13843 +   The first call to apc_sma_allocate() will hit the second block.  We then
13844 +   chop up that block so it looks like this:
13845 +
13846 +     +--------+-------+-------+-------------------------+
13847 +     | header | block | block |         block           |
13848 +     +--------+-------+-------+-------------------------+
13849 +
13850 +   Then we unlink that block from the linked list so it won't show up
13851 +   as an available block on the next allocate.  So we actually have:
13852 +
13853 +     +--------+-------+       +-------------------------+
13854 +     | header | block |------>|         block           |
13855 +     +--------+-------+       +-------------------------+
13856 +
13857 +   And header->avail along with block->size of the remaining large
13858 +   block are updated accordingly.  The arrow there representing the
13859 +   link which now points to a block with an offset further along in
13860 +   the segment.
13861 +
13862 +   When the block is freed using apc_sma_deallocate() the steps are
13863 +   basically just reversed.  The block is put back and then the deallocate
13864 +   code looks at the block before and after to see if the block immediately
13865 +   before and after are free and if so the blocks are combined.  So you never
13866 +   have 2 free blocks next to each other, apart from at the front with that
13867 +   0-sized dummy block.  This mostly prevents fragmentation.  I have been
13868 +   toying with the idea of always allocating block at 2^n boundaries to make
13869 +   it more likely that they will be re-used to cut down on fragmentation further.
13870 +   That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
13871 +  
13872 +   Of course, anytime we fiddle with our shared memory segment we lock using
13873 +   the locking macros, LOCK() and UNLOCK().
13874 +
13875 +   That should mostly take care of the low-level shared memory handling.
13876 +
13877 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
13878 +   cache logic.
13879 +
13880 +   The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
13881 +   and apc_cache.c for actual cache manipulation.  
13882 +  
13883 +   After the shared memory segment is created and the caches are initialized,
13884 +   apc_module_init() installs the my_compile_file() function overriding Zend's
13885 +   version.  I'll talk about my_compile_file() and the rest of apc_compile.c
13886 +   in the next section.  For now I will stick with apc_main.c and apc_cache.c
13887 +   and talk about the actual caches.  A cache consists of a block of shared
13888 +   memory returned by apc_sma_allocate() via apc_sma_malloc().  You will 
13889 +   notice references to apc_emalloc().  apc_emalloc() is just a thin wrapper
13890 +   around PHP's own emalloc() function which allocates per-process memory from
13891 +   PHP's pool-based memory allocator.  Don't confuse apc_emalloc() and 
13892 +   apc_sma_malloc() as the first is per-process and the second is shared memory.
13893 +
13894 +   The cache is stored in/described by this struct allocated locally using
13895 +   emalloc():
13896 +
13897 +     struct apc_cache_t {
13898 +         void* shmaddr;              /* process (local) address of shared cache */
13899 +         header_t* header;           /* cache header (stored in SHM) */
13900 +         slot_t** slots;             /* array of cache slots (stored in SHM) */
13901 +         int num_slots;              /* number of slots in cache */
13902 +         int gc_ttl;                 /* maximum time on GC list for a slot */
13903 +         int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
13904 +     };
13905 +
13906 +   Whenever you see functions that take a 'cache' argument, this is what they
13907 +   take.  And apc_cache_create() returns a pointer to this populated struct.
13908 +
13909 +   At the beginning of the cache we have a header.  Remember, we are down a level now
13910 +   from the sma stuff.  The sma stuff is the low-level shared-memory allocator which
13911 +   has its own header which is completely separate and invisible to apc_cache.c.  
13912 +   As far as apc_cache.c is concerned the block of memory it is working with could 
13913 +   have come from a call to malloc().
13914 +
13915 +   The header looks like this:
13916 +
13917 +     typedef struct header_t header_t;
13918 +     struct header_t {
13919 +         int num_hits;               /* total successful hits in cache */
13920 +         int num_misses;             /* total unsuccessful hits in cache */
13921 +         slot_t* deleted_list;       /* linked list of to-be-deleted slots */
13922 +     };
13923 +
13924 +   Since this is at the start of the shared memory segment, these values are accessible
13925 +   across all the yapache processes and hence access to them has to be locked.
13926 +
13927 +   After the header we have an array of slots.  The number of slots is user-defined
13928 +   through the apc.num_slots ini hint.  Each slot is described by:
13929 +
13930 +     typedef struct slot_t slot_t;
13931 +     struct slot_t {
13932 +         apc_cache_key_t key;        /* slot key */
13933 +         apc_cache_entry_t* value;   /* slot value */
13934 +         slot_t* next;               /* next slot in linked list */
13935 +         int num_hits;               /* number of hits to this bucket */
13936 +        time_t creation_time;       /* time slot was initialized */
13937 +        time_t deletion_time;       /* time slot was removed from cache */
13938 +        time_t access_time;         /* time slot was last accessed */
13939 +     };
13940 +
13941 +   The slot_t *next there is a linked list to other slots that happened to hash to the
13942 +   same array position.
13943 +
13944 +   apc_cache_insert() shows what happens on a new cache insert.
13945 +
13946 +     slot = &cache->slots[hash(key) % cache->num_slots];
13947 +
13948 +   cache->slots is our array of slots in the segment.  hash() is simply:
13949 +
13950 +     static unsigned int hash(apc_cache_key_t key)
13951 +     {
13952 +         return key.data.file.device + key.data.file.inode;
13953 +     }
13954 +
13955 +   That is, we use the file's device and inode to uniquely identify it.  Initially
13956 +   we had used the file's full path, but getting that requires a realpath() call which
13957 +   is amazingly expensive since it has to stat each component of the path to resolve
13958 +   symlinks and get rid of relative path components.  By using the device+inode we
13959 +   can uniquely identify a file with a single stat.
13960 +
13961 +   So, on an insert we find the array position in the slots array by hasing the device+inode.
13962 +   If there are currently no other slots there, we just create the slot and stick it into
13963 +   the array:
13964 +
13965 +     *slot = make_slot(key, value, *slot, t)
13966 +
13967 +   If there are other slots already at this position we walk the link list to get to
13968 +   the end.  Here is the loop:
13969 +
13970 +     while (*slot) {
13971 +         if (key_equals((*slot)->key.data.file, key.data.file)) {
13972 +            /* If existing slot for the same device+inode is different, remove it and insert the new version */
13973 +            if ((*slot)->key.mtime != key.mtime) {
13974 +                remove_slot(cache, slot);
13975 +                break;
13976 +            }
13977 +            UNLOCK(cache);
13978 +            return 0;
13979 +        } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
13980 +             remove_slot(cache, slot);
13981 +             continue;
13982 +         }
13983 +         slot = &(*slot)->next;
13984 +     }
13985 +
13986 +   That first key_equals() check sees if we have an exact match meaning the file
13987 +   is already in the cache.  Since we try to find the file in the cache before doing
13988 +   an insert, this will generally only happen if another process managed to beat us
13989 +   to inserting it.  If we have a newer version of the file at this point we remove
13990 +   it an insert the new version.  If our version is not newer we just return without
13991 +   doing anything.
13992 +
13993 +   While walking the linked list we also check to see if the cache has a TTL defined.
13994 +   If while walking the linked list we see a slot that has expired, we remove it
13995 +   since we are right there looking at it.  This is the only place we remove stale
13996 +   entries unless the shared memory segment fills up and we force a full expunge via
13997 +   apc_cache_expunge().  apc_cache_expunge() walks the entire slots array and walks
13998 +   down every linked list removing stale slots to free up room.  This is obviously
13999 +   slow and thus only happens when we have run out of room.
14000 +
14001 +   apc_cache_find() simply hashes and returns the entry if it is there.  If it is there
14002 +   but older than the mtime in the entry we are looking for, we delete the one that is
14003 +   there and return indicating we didn't find it.
14004 +
14005 +   Next we need to understand what an actual cache entry looks like.  Have a look at
14006 +   apc_cache.h for the structs.  I sort of glossed over the key part earlier saying
14007 +   that we just used the device+inode to find a hash slot.  It is actually a bit more
14008 +   complex than that because we have two kinds of caches.  We have the standard file
14009 +   cache containing opcode arrays, but we also have a user-controlled cache that the
14010 +   user can insert whatever they want into via apc_store().  For the user cache we
14011 +   obviously don't have a device+inode.  The actual identifier is provided by the user
14012 +   as a char *.  So the key is actually a union that looks like this:
14013 +
14014 +     typedef union _apc_cache_key_data_t {
14015 +         struct {
14016 +             int device;             /* the filesystem device */
14017 +             int inode;              /* the filesystem inode */
14018 +         } file;
14019 +         struct {
14020 +             char *identifier;
14021 +         } user;
14022 +     } apc_cache_key_data_t;
14023 +
14024 +     struct apc_cache_key_t {
14025 +         apc_cache_key_data_t data;
14026 +         int mtime;                  /* the mtime of this cached entry */
14027 +     };   
14028 +
14029 +   And we have two sets of functions to do inserts and finds.  apc_cache_user_find() 
14030 +   and apc_cache_user_insert() operate on the user cache.
14031 +
14032 +   Ok, on to the actual cache entry.  Again, because we have two kinds of caches, we
14033 +   also have the corresponding two kinds of cache entries described by this union:
14034 +
14035 +     typedef union _apc_cache_entry_value_t {
14036 +         struct {
14037 +             char *filename;             /* absolute path to source file */
14038 +             zend_op_array* op_array;    /* op_array allocated in shared memory */
14039 +             apc_function_t* functions;  /* array of apc_function_t's */
14040 +             apc_class_t* classes;       /* array of apc_class_t's */
14041 +         } file;
14042 +         struct {
14043 +             char *info;
14044 +             zval *val;
14045 +             unsigned int ttl;
14046 +         } user;
14047 +     } apc_cache_entry_value_t;
14048 +
14049 +   And then the actual cache entry:
14050 +
14051 +     struct apc_cache_entry_t {
14052 +         apc_cache_entry_value_t data;
14053 +         unsigned char type;
14054 +         int ref_count;
14055 +     };
14056 +
14057 +   The user entry is pretty simple and not all that important for now.  I will
14058 +   concentrate on the file entries since that is what holds the actual compiled
14059 +   opcode arrays along with the functions and classes required by the executor.
14060 +
14061 +   apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
14062 +   The main thing to understand here is that we need more than just the opcode
14063 +   array, we also need the functions and classes created by the compiler when it
14064 +   created the opcode array.  As far as the executor is concerned, it doesn't know
14065 +   that it isn't operating in normal mode being called right after the parse/compile
14066 +   phase, so we need to recreate everything so it looks exactly like it would at
14067 +   that point. 
14068 +
14069 +7. my_compile_file() and apc_compile.c
14070 +
14071 +   my_compile_file() in apc_main.c controls where we get the opcodes from.  If
14072 +   the user-specified filters exclude the file from being cached, then we just
14073 +   call the original compile function and return.  Otherwise we fetch the request
14074 +   time from Apache to avoid an extra syscall, create the key so we can look up
14075 +   the file in the cache.  If we find it we stick it on a local stack which we
14076 +   use at cleanup time to make sure we return everything back to normal after a 
14077 +   request and call cached_compile() which installs the functions and classes
14078 +   associated with the op_array in this entry and then copy the op_array down
14079 +   into our memory space for execution.
14080 +
14081 +   If we didn't find the file in the cache, we need to compile it and insert it.
14082 +   To compile it we simply call the original compile function:
14083 +
14084 +      op_array = old_compile_file(h, type TSRMLS_CC);
14085 +
14086 +   To do the insert we need to copy the functions, classes and the opcode array
14087 +   the compile phase created into shared memory.  This all happens in apc_compile.c
14088 +   in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
14089 +   functions.  Then we make the file entry and do the insert.  Both of these
14090 +   operations were described in the previous section.  
14091 +
14092 +8. The Optimizer
14093 +   
14094 +   The optimizer has been deprecated.
14095 +
14096 +If you made it to the end of this, you should have a pretty good idea of where things are in
14097 +the code.  I skimmed over a lot of things, so plan on spending some time reading through the code.
14098 +
14099 diff -ruN php-5.1.6.old/ext/apc/tests/apc_001.phpt php-5.1.6/ext/APC/tests/apc_001.phpt
14100 --- php-5.1.6.old/ext/apc/tests/apc_001.phpt    1969-12-31 18:00:00.000000000 -0600
14101 +++ php-5.1.6/ext/apc/tests/apc_001.phpt        2007-04-02 18:05:30.000000000 -0500
14102 @@ -0,0 +1,27 @@
14103 +--TEST--
14104 +APC: apc_store/fetch with strings
14105 +--SKIPIF--
14106 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14107 +--INI--
14108 +apc.enabled=1
14109 +apc.enable_cli=1
14110 +apc.file_update_protection=0
14111 +--FILE--
14112 +<?php
14113 +
14114 +$foo = 'hello world';
14115 +var_dump($foo);
14116 +apc_store('foo',$foo);
14117 +$bar = apc_fetch('foo');
14118 +var_dump($bar);
14119 +$bar = 'nice';
14120 +var_dump($bar);
14121 +
14122 +?>
14123 +===DONE===
14124 +<?php exit(0); ?>
14125 +--EXPECTF--
14126 +string(11) "hello world"
14127 +string(11) "hello world"
14128 +string(4) "nice"
14129 +===DONE===
14130 diff -ruN php-5.1.6.old/ext/apc/tests/apc_002.phpt php-5.1.6/ext/APC/tests/apc_002.phpt
14131 --- php-5.1.6.old/ext/apc/tests/apc_002.phpt    1969-12-31 18:00:00.000000000 -0600
14132 +++ php-5.1.6/ext/apc/tests/apc_002.phpt        2007-04-02 18:05:30.000000000 -0500
14133 @@ -0,0 +1,34 @@
14134 +--TEST--
14135 +APC: apc_store/fetch with objects
14136 +--SKIPIF--
14137 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14138 +--INI--
14139 +apc.enabled=1
14140 +apc.enable_cli=1
14141 +apc.file_update_protection=0
14142 +--FILE--
14143 +<?php
14144 +
14145 +class foo { }
14146 +$foo = new foo;
14147 +var_dump($foo);
14148 +apc_store('foo',$foo);
14149 +unset($foo);
14150 +$bar = apc_fetch('foo');
14151 +var_dump($bar);
14152 +$bar->a = true;
14153 +var_dump($bar);
14154 +
14155 +?>
14156 +===DONE===
14157 +<?php exit(0); ?>
14158 +--EXPECTF--
14159 +object(foo)#%d (0) {
14160 +}
14161 +object(foo)#%d (0) {
14162 +}
14163 +object(foo)#%d (1) {
14164 +  ["a"]=>
14165 +  bool(true)
14166 +}
14167 +===DONE===
14168 diff -ruN php-5.1.6.old/ext/apc/tests/apc_003.phpt php-5.1.6/ext/APC/tests/apc_003.phpt
14169 --- php-5.1.6.old/ext/apc/tests/apc_003.phpt    1969-12-31 18:00:00.000000000 -0600
14170 +++ php-5.1.6/ext/apc/tests/apc_003.phpt        2007-04-02 18:05:30.000000000 -0500
14171 @@ -0,0 +1,112 @@
14172 +--TEST--
14173 +APC: apc_store/fetch with objects
14174 +--SKIPIF--
14175 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14176 +--INI--
14177 +apc.enabled=1
14178 +apc.enable_cli=1
14179 +apc.file_update_protection=0
14180 +--FILE--
14181 +<?php
14182 +
14183 +class foo { }
14184 +$foo = new foo;
14185 +var_dump($foo);
14186 +apc_store('foo',$foo);
14187 +unset($foo);
14188 +$bar = apc_fetch('foo');
14189 +var_dump($bar);
14190 +$bar->a = true;
14191 +var_dump($bar);
14192 +
14193 +class bar extends foo
14194 +{
14195 +       public    $pub = 'bar';
14196 +       protected $pro = 'bar';
14197 +       private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
14198 +       
14199 +       function __construct()
14200 +       {
14201 +               $this->bar = true;
14202 +       }
14203 +       
14204 +       function change()
14205 +       {
14206 +               $this->pri = 'mod';
14207 +       }
14208 +}
14209 +
14210 +class baz extends bar
14211 +{
14212 +       private $pri = 'baz';
14213 +
14214 +       function __construct()
14215 +       {
14216 +               parent::__construct();
14217 +               $this->baz = true;
14218 +       }
14219 +}
14220 +
14221 +$baz = new baz;
14222 +var_dump($baz);
14223 +$baz->change();
14224 +var_dump($baz);
14225 +apc_store('baz', $baz);
14226 +unset($baz);
14227 +var_dump(apc_fetch('baz'));
14228 +
14229 +?>
14230 +===DONE===
14231 +<?php exit(0); ?>
14232 +--EXPECTF--
14233 +object(foo)#%d (0) {
14234 +}
14235 +object(foo)#%d (0) {
14236 +}
14237 +object(foo)#%d (1) {
14238 +  ["a"]=>
14239 +  bool(true)
14240 +}
14241 +object(baz)#%d (6) {
14242 +  ["pri:private"]=>
14243 +  string(3) "baz"
14244 +  ["pub"]=>
14245 +  string(3) "bar"
14246 +  ["pro:protected"]=>
14247 +  string(3) "bar"
14248 +  ["pri:private"]=>
14249 +  string(3) "bar"
14250 +  ["bar"]=>
14251 +  bool(true)
14252 +  ["baz"]=>
14253 +  bool(true)
14254 +}
14255 +object(baz)#%d (6) {
14256 +  ["pri:private"]=>
14257 +  string(3) "baz"
14258 +  ["pub"]=>
14259 +  string(3) "bar"
14260 +  ["pro:protected"]=>
14261 +  string(3) "bar"
14262 +  ["pri:private"]=>
14263 +  string(3) "mod"
14264 +  ["bar"]=>
14265 +  bool(true)
14266 +  ["baz"]=>
14267 +  bool(true)
14268 +}
14269 +object(baz)#%d (6) {
14270 +  ["pri:private"]=>
14271 +  string(3) "baz"
14272 +  ["pub"]=>
14273 +  string(3) "bar"
14274 +  ["pro:protected"]=>
14275 +  string(3) "bar"
14276 +  ["pri:private"]=>
14277 +  string(3) "mod"
14278 +  ["bar"]=>
14279 +  bool(true)
14280 +  ["baz"]=>
14281 +  bool(true)
14282 +}
14283 +===DONE===
14284 diff -ruN php-5.1.6.old/ext/apc/tests/skipif.inc php-5.1.6/ext/APC/tests/skipif.inc
14285 --- php-5.1.6.old/ext/apc/tests/skipif.inc      1969-12-31 18:00:00.000000000 -0600
14286 +++ php-5.1.6/ext/apc/tests/skipif.inc  2007-04-02 18:05:30.000000000 -0500
14287 @@ -0,0 +1,6 @@
14288 +<?php
14289 +
14290 +if (!extension_loaded("apc")) die("skip");
14291 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
14292 +
14293 +?>
14294 diff -ruN php-5.1.6.old/ext/apc/TODO php-5.1.6/ext/APC/TODO
14295 --- php-5.1.6.old/ext/apc/TODO  1969-12-31 18:00:00.000000000 -0600
14296 +++ php-5.1.6/ext/apc/TODO      2007-04-02 18:05:30.000000000 -0500
14297 @@ -0,0 +1,30 @@
14298 +Known Bugs
14299
14300 +1.   Gallery2 doesn't work with PHP5+APC.  There is something wrong
14301 +     with the way methods are restored in some edge case I haven't
14302 +     been able to figure out yet.
14303 +     To reproduce install gallery2 and click down to an individual photo.
14304 +
14305 +2.   apc_store() probably needs some checks to skip trying to store
14306 +     internal classes.  Something along the lines of:
14307 +
14308 +     if(Z_TYPE_P(val) == IS_OBJECT) {
14309 +        zend_class_entry *ce = Z_OBJCE_P(val);
14310 +        if(ce->type == ZEND_INTERNAL_CLASS) {
14311 +            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
14312 +            RETURN_FALSE;
14313 +        }
14314 +     }
14315 +
14316 +     in the apc_store() function in php_apc.c but I am wondering if it needs to do more
14317 +     than that.
14318 +
14319 +Enhancements
14320 +
14321 +1.   Some faster platform-specific locking mechanisms wouldd be nice.  futex support
14322 +     for the 2.6 Linux kernels, and/or x86-specific spinlock support.
14323 +
14324 +2.   The optimizer needs a lot of work.  
14325 +
14326 +3.   Assert() elimination in the optimizer when some debug flag somewhere isn't set.
14327 +