8eb204e1c06e3a3d5ec7f7d10aec9f4d1d3bafbe
[openwrt/svn-archive/archive.git] / lang / php5 / patches / 005-APC.patch
1 diff -ubrN php-5.2.5-orig/ext/apc/apc.c php-5.2.5/ext/apc/apc.c
2 --- php-5.2.5-orig/ext/apc/apc.c 1969-12-31 18:00:00.000000000 -0600
3 +++ php-5.2.5/ext/apc/apc.c 2007-12-26 16:51:32.000000000 -0600
4 @@ -0,0 +1,554 @@
5 +/*
6 + +----------------------------------------------------------------------+
7 + | APC |
8 + +----------------------------------------------------------------------+
9 + | Copyright (c) 2006 The PHP Group |
10 + +----------------------------------------------------------------------+
11 + | This source file is subject to version 3.01 of the PHP license, |
12 + | that is bundled with this package in the file LICENSE, and is |
13 + | available through the world-wide-web at the following url: |
14 + | http://www.php.net/license/3_01.txt |
15 + | If you did not receive a copy of the PHP license and are unable to |
16 + | obtain it through the world-wide-web, please send a note to |
17 + | license@php.net so we can mail you a copy immediately. |
18 + +----------------------------------------------------------------------+
19 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
20 + | George Schlossnagle <george@omniti.com> |
21 + | Rasmus Lerdorf <rasmus@php.net> |
22 + | Arun C. Murthy <arunc@yahoo-inc.com> |
23 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
24 + +----------------------------------------------------------------------+
25 +
26 + This software was contributed to PHP by Community Connect Inc. in 2002
27 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
28 + Future revisions and derivatives of this source code must acknowledge
29 + Community Connect Inc. as the original contributor of this module by
30 + leaving this note intact in the source code.
31 +
32 + All other licensing and usage conditions are those of the PHP Group.
33 +
34 + */
35 +
36 +/* $Id: apc.c,v 3.18 2007/11/29 22:15:53 shire Exp $ */
37 +
38 +#include "apc.h"
39 +#include <regex.h> /* for POSIX regular expressions */
40 +#include "php.h"
41 +
42 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
43 +
44 +/* {{{ memory allocation wrappers */
45 +
46 +void* apc_emalloc(size_t n)
47 +{
48 + void* p = malloc(n);
49 + if (p == NULL) {
50 + apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
51 + }
52 + return p;
53 +}
54 +
55 +void* apc_erealloc(void* p, size_t n)
56 +{
57 + p = realloc(p, n);
58 + if (p == NULL) {
59 + apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
60 + }
61 + return p;
62 +}
63 +
64 +void apc_efree(void* p)
65 +{
66 + if (p == NULL) {
67 + apc_eprint("apc_efree: attempt to free null pointer");
68 + }
69 + free(p);
70 +}
71 +
72 +char* apc_estrdup(const char* s)
73 +{
74 + int len;
75 + char* dup;
76 +
77 + if (s == NULL) {
78 + return NULL;
79 + }
80 + len = strlen(s);
81 + dup = (char*) malloc(len+1);
82 + if (dup == NULL) {
83 + apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
84 + }
85 + memcpy(dup, s, len);
86 + dup[len] = '\0';
87 + return dup;
88 +}
89 +
90 +void* apc_xstrdup(const char* s, apc_malloc_t f)
91 +{
92 + return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
93 +}
94 +
95 +void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
96 +{
97 + void* q;
98 +
99 + if (p != NULL && (q = f(n)) != NULL) {
100 + memcpy(q, p, n);
101 + return q;
102 + }
103 + return NULL;
104 +}
105 +
106 +/* }}} */
107 +
108 +/* {{{ console display functions */
109 +
110 +static void my_log(int level, const char* fmt, va_list args)
111 +{
112 + static const char* level_strings[] = {
113 + "apc-debug",
114 + "apc-notice",
115 + "apc-warning",
116 + "apc-error"
117 + };
118 + static const int num_levels = NELEMS(level_strings);
119 +
120 + time_t now;
121 + char* buf; /* for ctime */
122 +
123 + fflush(stdout);
124 +
125 + if (level < 0)
126 + level = 0;
127 + else if (level >= num_levels)
128 + level = num_levels-1;
129 +
130 + now = time(0);
131 + buf = ctime(&now); /* TODO: replace with reentrant impl */
132 + buf[24] = '\0';
133 +
134 + fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
135 + vfprintf(stderr, fmt, args);
136 +
137 + if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
138 + fprintf(stderr, " %s", strerror(errno));
139 + }
140 + fprintf(stderr, "\n");
141 +
142 + if (level == APC_ERROR) {
143 + exit(2);
144 + }
145 +}
146 +
147 +void apc_log(int level, const char* fmt, ...)
148 +{
149 + va_list args;
150 + va_start(args, fmt);
151 + my_log(level, fmt, args);
152 + va_end(args);
153 +}
154 +
155 +void apc_eprint(const char* fmt, ...)
156 +{
157 + va_list args;
158 + va_start(args, fmt);
159 + my_log(APC_ERROR, fmt, args);
160 + va_end(args);
161 +}
162 +
163 +void apc_wprint(const char* fmt, ...)
164 +{
165 + va_list args;
166 + va_start(args, fmt);
167 + my_log(APC_WARNING, fmt, args);
168 + va_end(args);
169 +}
170 +
171 +void apc_nprint(const char* fmt, ...)
172 +{
173 + va_list args;
174 + va_start(args, fmt);
175 + my_log(APC_NOTICE, fmt, args);
176 + va_end(args);
177 +}
178 +
179 +void apc_dprint(const char* fmt, ...)
180 +{
181 +#ifdef APC_DEBUG
182 + va_list args;
183 + va_start(args, fmt);
184 + my_log(APC_DBG, fmt, args);
185 + va_end(args);
186 +#endif
187 +}
188 +
189 +/* }}} */
190 +
191 +/* {{{ string and text manipulation */
192 +
193 +char* apc_append(const char* s, const char* t)
194 +{
195 + int slen;
196 + int tlen;
197 + char* p;
198 +
199 + slen = strlen(s);
200 + tlen = strlen(t);
201 +
202 + p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
203 + memcpy(p, s, slen);
204 + memcpy(p + slen, t, tlen + 1);
205 +
206 + return p;
207 +}
208 +
209 +char* apc_substr(const char* s, int start, int length)
210 +{
211 + char* substr;
212 + int src_len = strlen(s);
213 +
214 + /* bring start into range */
215 + if (start < 0) {
216 + start = 0;
217 + }
218 + else if (start >= src_len) {
219 + start = src_len - 1;
220 + }
221 +
222 + /* bring length into range */
223 + if (length < 0 || src_len - start < length) {
224 + length = src_len - start;
225 + }
226 +
227 + /* create the substring */
228 + substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
229 + substr[length] = '\0';
230 + return substr;
231 +}
232 +
233 +char** apc_tokenize(const char* s, char delim)
234 +{
235 + char** tokens; /* array of tokens, NULL terminated */
236 + int size; /* size of tokens array */
237 + int n; /* index of next token in tokens array */
238 + int cur; /* current position in input string */
239 + int end; /* final legal position in input string */
240 + int next; /* position of next delimiter in input */
241 +
242 + if (!s) {
243 + return NULL;
244 + }
245 +
246 + size = 2;
247 + n = 0;
248 + cur = 0;
249 + end = strlen(s) - 1;
250 +
251 + tokens = (char**) apc_emalloc(size * sizeof(char*));
252 + tokens[n] = NULL;
253 +
254 + while (cur <= end) {
255 + /* search for the next delimiter */
256 + char* p = strchr(s + cur, delim);
257 + next = p ? p-s : end+1;
258 +
259 + /* resize token array if necessary */
260 + if (n == size-1) {
261 + size *= 2;
262 + tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
263 + }
264 +
265 + /* save the current token */
266 + tokens[n] = apc_substr(s, cur, next-cur);
267 +
268 + tokens[++n] = NULL;
269 + cur = next + 1;
270 + }
271 +
272 + return tokens;
273 +}
274 +
275 +/* }}} */
276 +
277 +/* {{{ filesystem functions */
278 +
279 +#ifdef PHP_WIN32
280 +int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
281 +{
282 + char rpath[MAXPATHLEN];
283 + BY_HANDLE_FILE_INFORMATION fi;
284 + HANDLE f;
285 +
286 + if (VCWD_STAT(path, buf)) {
287 + return -1;
288 + }
289 +
290 + VCWD_REALPATH(path, rpath);
291 + f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
292 + GetFileInformationByHandle(f, &fi);
293 + buf->st_ino = (ino_t)fi.nFileIndexLow;
294 + CloseHandle (f);
295 + return 0;
296 +}
297 +#endif
298 +
299 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
300 +{
301 + char** paths;
302 + char *exec_fname;
303 + int exec_fname_length;
304 + int found = 0;
305 + int i;
306 + TSRMLS_FETCH();
307 +
308 + assert(filename && fileinfo);
309 +
310 + if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
311 + strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
312 + return 0;
313 + }
314 +
315 + paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
316 + if (!paths)
317 + return -1;
318 +
319 + /* for each directory in paths, look for filename inside */
320 + for (i = 0; paths[i]; i++) {
321 + snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
322 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
323 + found = 1;
324 + break;
325 + }
326 + }
327 +
328 + /* check in path of the calling scripts' current working directory */
329 + /* modified from main/streams/plain_wrapper.c */
330 + if(!found && zend_is_executing(TSRMLS_C)) {
331 + exec_fname = zend_get_executed_filename(TSRMLS_C);
332 + exec_fname_length = strlen(exec_fname);
333 + while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
334 + if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
335 + /* not: [no active file] or no path */
336 + memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
337 + fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
338 + strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
339 + /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
340 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
341 + found = 1;
342 + }
343 + }
344 + }
345 +
346 + /* free the value returned by apc_tokenize */
347 + for (i = 0; paths[i]; i++) {
348 + apc_efree(paths[i]);
349 + }
350 + apc_efree(paths);
351 +
352 + return found ? 0 : -1;
353 +}
354 +
355 +/* }}} */
356 +
357 +/* {{{ regular expression wrapper functions */
358 +
359 +typedef struct {
360 + regex_t *reg;
361 + unsigned char type;
362 +} apc_regex;
363 +
364 +void* apc_regex_compile_array(char* patterns[])
365 +{
366 + apc_regex** regs;
367 + int npat;
368 + int i;
369 +
370 + if (!patterns)
371 + return NULL;
372 +
373 + /* count the number of patterns in patterns */
374 + for (npat = 0; patterns[npat] != NULL; npat++) {}
375 +
376 + if (npat == 0)
377 + return NULL;
378 +
379 + /* allocate the array of compiled expressions */
380 + regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
381 + for (i = 0; i <= npat; i++) {
382 + regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
383 + regs[i]->reg = NULL;
384 + regs[i]->type = APC_NEGATIVE_MATCH;
385 + }
386 +
387 + /* compile the expressions */
388 + for (i = 0; i < npat; i++) {
389 + char *pattern = patterns[i];
390 + if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
391 + else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
392 +
393 + regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
394 +
395 + if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
396 + apc_wprint("apc_regex_compile_array: invalid expression '%s'",
397 + pattern);
398 +
399 + apc_regex_destroy_array(regs);
400 +
401 + return NULL;
402 + }
403 + }
404 +
405 + return (void*) regs;
406 +}
407 +
408 +void apc_regex_destroy_array(void* p)
409 +{
410 + if (p != NULL) {
411 + apc_regex** regs = (apc_regex**) p;
412 + int i;
413 +
414 + for (i = 0; regs[i]->reg != NULL; i++) {
415 + regfree(regs[i]->reg);
416 + apc_efree(regs[i]->reg);
417 + apc_efree(regs[i]);
418 + }
419 + apc_efree(regs);
420 + }
421 +}
422 +
423 +int apc_regex_match_array(void* p, const char* input)
424 +{
425 + apc_regex** regs;
426 + int i;
427 +
428 + if (!p)
429 + return 0;
430 +
431 + regs = (apc_regex**) p;
432 + for (i = 0; regs[i]->reg != NULL; i++)
433 + if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
434 + return (int)(regs[i]->type);
435 +
436 + return 0;
437 +}
438 +
439 +/* }}} */
440 +
441 +/* {{{ crc32 implementation */
442 +
443 +/* this table was generated by crc32gen() */
444 +static unsigned int crc32tab[] = {
445 + /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
446 + /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
447 + /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
448 + /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
449 + /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
450 + /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
451 + /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
452 + /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
453 + /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
454 + /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
455 + /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
456 + /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
457 + /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
458 + /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
459 + /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
460 + /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
461 + /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
462 + /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
463 + /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
464 + /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
465 + /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
466 + /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
467 + /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
468 + /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
469 + /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
470 + /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
471 + /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
472 + /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
473 + /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
474 + /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
475 + /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
476 + /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
477 + /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
478 + /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
479 + /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
480 + /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
481 + /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
482 + /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
483 + /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
484 + /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
485 + /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
486 + /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
487 + /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
488 + /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
489 + /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
490 + /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
491 + /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
492 + /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
493 + /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
494 + /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
495 + /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
496 + /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
497 + /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
498 + /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
499 + /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
500 + /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
501 + /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
502 + /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
503 + /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
504 + /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
505 + /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
506 + /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
507 + /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
508 + /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
509 +};
510 +
511 +unsigned int apc_crc32(const char* buf, int len)
512 +{
513 + int i;
514 + int k;
515 + unsigned int crc;
516 +
517 + /* preconditioning */
518 + crc = 0xFFFFFFFF;
519 +
520 + for (i = 0; i < len; i++) {
521 + k = (crc ^ buf[i]) & 0x000000FF;
522 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
523 + }
524 +
525 + /* postconditioning */
526 + return ~crc;
527 +}
528 +
529 +/* crc32gen: generate the nth (0..255) crc32 table value */
530 +#if 0
531 +static unsigned long crc32gen(int n)
532 +{
533 + int i;
534 + unsigned long crc;
535 +
536 + crc = n;
537 + for (i = 8; i >= 0; i--) {
538 + if (crc & 1) {
539 + crc = (crc >> 1) ^ 0xEDB88320;
540 + }
541 + else {
542 + crc >>= 1;
543 + }
544 + }
545 + return crc;
546 +}
547 +#endif
548 +
549 +/* }}} */
550 +
551 +/*
552 + * Local variables:
553 + * tab-width: 4
554 + * c-basic-offset: 4
555 + * End:
556 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
557 + * vim<600: expandtab sw=4 ts=4 sts=4
558 + */
559 diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.c php-5.2.5/ext/apc/apc_cache.c
560 --- php-5.2.5-orig/ext/apc/apc_cache.c 1969-12-31 18:00:00.000000000 -0600
561 +++ php-5.2.5/ext/apc/apc_cache.c 2007-12-26 16:51:32.000000000 -0600
562 @@ -0,0 +1,1343 @@
563 +/*
564 + +----------------------------------------------------------------------+
565 + | APC |
566 + +----------------------------------------------------------------------+
567 + | Copyright (c) 2006 The PHP Group |
568 + +----------------------------------------------------------------------+
569 + | This source file is subject to version 3.01 of the PHP license, |
570 + | that is bundled with this package in the file LICENSE, and is |
571 + | available through the world-wide-web at the following url: |
572 + | http://www.php.net/license/3_01.txt |
573 + | If you did not receive a copy of the PHP license and are unable to |
574 + | obtain it through the world-wide-web, please send a note to |
575 + | license@php.net so we can mail you a copy immediately. |
576 + +----------------------------------------------------------------------+
577 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
578 + | Rasmus Lerdorf <rasmus@php.net> |
579 + | Arun C. Murthy <arunc@yahoo-inc.com> |
580 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
581 + +----------------------------------------------------------------------+
582 +
583 + This software was contributed to PHP by Community Connect Inc. in 2002
584 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
585 + Future revisions and derivatives of this source code must acknowledge
586 + Community Connect Inc. as the original contributor of this module by
587 + leaving this note intact in the source code.
588 +
589 + All other licensing and usage conditions are those of the PHP Group.
590 +
591 + */
592 +
593 +/* $Id: apc_cache.c,v 3.145 2007/10/05 23:06:56 gopalv Exp $ */
594 +
595 +#include "apc_cache.h"
596 +#include "apc_lock.h"
597 +#include "apc_sma.h"
598 +#include "apc_globals.h"
599 +#include "SAPI.h"
600 +#include "ext/standard/php_var.h"
601 +#include "ext/standard/php_smart_str.h"
602 +
603 +/* TODO: rehash when load factor exceeds threshold */
604 +
605 +#define CHECK(p) { if ((p) == NULL) return NULL; }
606 +
607 +/* {{{ locking macros */
608 +#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock)
609 +#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
610 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
611 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
612 +#define UNLOCK(c) { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
613 +/* }}} */
614 +
615 +/* {{{ struct definition: slot_t */
616 +typedef struct slot_t slot_t;
617 +struct slot_t {
618 + apc_cache_key_t key; /* slot key */
619 + apc_cache_entry_t* value; /* slot value */
620 + slot_t* next; /* next slot in linked list */
621 + int num_hits; /* number of hits to this bucket */
622 + time_t creation_time; /* time slot was initialized */
623 + time_t deletion_time; /* time slot was removed from cache */
624 + time_t access_time; /* time slot was last accessed */
625 +};
626 +/* }}} */
627 +
628 +/* {{{ struct definition: header_t
629 + Any values that must be shared among processes should go in here. */
630 +typedef struct header_t header_t;
631 +struct header_t {
632 + apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */
633 + apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */
634 + int num_hits; /* total successful hits in cache */
635 + int num_misses; /* total unsuccessful hits in cache */
636 + int num_inserts; /* total successful inserts in cache */
637 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
638 + time_t start_time; /* time the above counters were reset */
639 + int expunges; /* total number of expunges */
640 + zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */
641 + int num_entries; /* Statistic on the number of entries */
642 + size_t mem_size; /* Statistic on the memory size used by this cache */
643 +};
644 +/* }}} */
645 +
646 +/* {{{ struct definition: apc_cache_t */
647 +struct apc_cache_t {
648 + void* shmaddr; /* process (local) address of shared cache */
649 + header_t* header; /* cache header (stored in SHM) */
650 + slot_t** slots; /* array of cache slots (stored in SHM) */
651 + int num_slots; /* number of slots in cache */
652 + int gc_ttl; /* maximum time on GC list for a slot */
653 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
654 +};
655 +/* }}} */
656 +
657 +/* {{{ struct definition local_slot_t */
658 +typedef struct local_slot_t local_slot_t;
659 +struct local_slot_t {
660 + slot_t *original; /* the original slot in shm */
661 + int num_hits; /* number of hits */
662 + time_t creation_time; /* creation time */
663 + apc_cache_entry_t *value; /* shallow copy of slot->value */
664 + local_slot_t *next; /* only for dead list */
665 +};
666 +/* }}} */
667 +/* {{{ struct definition apc_local_cache_t */
668 +struct apc_local_cache_t {
669 + apc_cache_t* shmcache; /* the real cache in shm */
670 + local_slot_t* slots; /* process (local) cache of objects */
671 + local_slot_t* dead_list; /* list of objects pending removal */
672 + int num_slots; /* number of slots in cache */
673 + int ttl; /* time to live */
674 + int num_hits; /* number of hits */
675 + int generation; /* every generation lives between expunges */
676 +};
677 +/* }}} */
678 +
679 +/* {{{ key_equals */
680 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
681 +/* }}} */
682 +
683 +/* {{{ hash */
684 +static unsigned int hash(apc_cache_key_t key)
685 +{
686 + return key.data.file.device + key.data.file.inode;
687 +}
688 +/* }}} */
689 +
690 +/* {{{ string_nhash_8 */
691 +static unsigned int string_nhash_8(const char *s, size_t len)
692 +{
693 + register const unsigned int *iv = (const unsigned int *)s;
694 + register unsigned int h = 0;
695 + register const unsigned int *e = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
696 +
697 + for(;iv<e;iv++) {
698 + h += *iv;
699 + h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
700 + }
701 + s = (const char *)iv;
702 + for(len %= sizeof(unsigned int);len;len--) {
703 + h += *(s++);
704 + }
705 + h ^= (h >> 13);
706 + h ^= (h >> 7);
707 + return h;
708 +}
709 +/* }}} */
710 +
711 +/* {{{ make_slot */
712 +slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
713 +{
714 + slot_t* p = apc_sma_malloc(sizeof(slot_t));
715 + if (!p) return NULL;
716 +
717 + if(value->type == APC_CACHE_ENTRY_USER) {
718 + char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
719 + if (!identifier) {
720 + apc_sma_free(p);
721 + return NULL;
722 + }
723 + key.data.user.identifier = identifier;
724 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
725 + char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
726 + if (!fullpath) {
727 + apc_sma_free(p);
728 + return NULL;
729 + }
730 + key.data.fpfile.fullpath = fullpath;
731 + }
732 + p->key = key;
733 + p->value = value;
734 + p->next = next;
735 + p->num_hits = 0;
736 + p->creation_time = t;
737 + p->access_time = t;
738 + p->deletion_time = 0;
739 + return p;
740 +}
741 +/* }}} */
742 +
743 +/* {{{ free_slot */
744 +static void free_slot(slot_t* slot)
745 +{
746 + if(slot->value->type == APC_CACHE_ENTRY_USER) {
747 + apc_sma_free((char *)slot->key.data.user.identifier);
748 + } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
749 + apc_sma_free((char *)slot->key.data.fpfile.fullpath);
750 + }
751 + apc_cache_free_entry(slot->value);
752 + apc_sma_free(slot);
753 +}
754 +/* }}} */
755 +
756 +/* {{{ remove_slot */
757 +static void remove_slot(apc_cache_t* cache, slot_t** slot)
758 +{
759 + slot_t* dead = *slot;
760 + *slot = (*slot)->next;
761 +
762 + cache->header->mem_size -= dead->value->mem_size;
763 + cache->header->num_entries--;
764 + if (dead->value->ref_count <= 0) {
765 + free_slot(dead);
766 + }
767 + else {
768 + dead->next = cache->header->deleted_list;
769 + dead->deletion_time = time(0);
770 + cache->header->deleted_list = dead;
771 + }
772 +}
773 +/* }}} */
774 +
775 +/* {{{ process_pending_removals */
776 +static void process_pending_removals(apc_cache_t* cache)
777 +{
778 + slot_t** slot;
779 + time_t now;
780 +
781 + /* This function scans the list of removed cache entries and deletes any
782 + * entry whose reference count is zero (indicating that it is no longer
783 + * being executed) or that has been on the pending list for more than
784 + * cache->gc_ttl seconds (we issue a warning in the latter case).
785 + */
786 +
787 + if (!cache->header->deleted_list)
788 + return;
789 +
790 + slot = &cache->header->deleted_list;
791 + now = time(0);
792 +
793 + while (*slot != NULL) {
794 + int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
795 +
796 + if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
797 + slot_t* dead = *slot;
798 +
799 + if (dead->value->ref_count > 0) {
800 + switch(dead->value->type) {
801 + case APC_CACHE_ENTRY_FILE:
802 + apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
803 + "was on gc-list for %d seconds", dead->value->data.file.filename,
804 + dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
805 + break;
806 + case APC_CACHE_ENTRY_USER:
807 + apc_log(APC_WARNING, "GC cache entry '%s' "
808 + "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
809 + break;
810 + }
811 + }
812 + *slot = dead->next;
813 + free_slot(dead);
814 + }
815 + else {
816 + slot = &(*slot)->next;
817 + }
818 + }
819 +}
820 +/* }}} */
821 +
822 +/* {{{ prevent_garbage_collection */
823 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
824 +{
825 + /* set reference counts on zend objects to an arbitrarily high value to
826 + * prevent garbage collection after execution */
827 +
828 + enum { BIG_VALUE = 1000 };
829 +
830 + if(entry->data.file.op_array) {
831 + entry->data.file.op_array->refcount[0] = BIG_VALUE;
832 + }
833 + if (entry->data.file.functions) {
834 + int i;
835 + apc_function_t* fns = entry->data.file.functions;
836 + for (i=0; fns[i].function != NULL; i++) {
837 +#ifdef ZEND_ENGINE_2
838 + *(fns[i].function->op_array.refcount) = BIG_VALUE;
839 +#else
840 + fns[i].function->op_array.refcount[0] = BIG_VALUE;
841 +#endif
842 + }
843 + }
844 + if (entry->data.file.classes) {
845 + int i;
846 + apc_class_t* classes = entry->data.file.classes;
847 + for (i=0; classes[i].class_entry != NULL; i++) {
848 +#ifdef ZEND_ENGINE_2
849 + classes[i].class_entry->refcount = BIG_VALUE;
850 +#else
851 + classes[i].class_entry->refcount[0] = BIG_VALUE;
852 +#endif
853 + }
854 + }
855 +}
856 +/* }}} */
857 +
858 +/* {{{ apc_cache_create */
859 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
860 +{
861 + apc_cache_t* cache;
862 + int cache_size;
863 + int num_slots;
864 + int i;
865 +
866 + num_slots = size_hint > 0 ? size_hint*2 : 2000;
867 +
868 + cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
869 + cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
870 +
871 + cache->shmaddr = apc_sma_malloc(cache_size);
872 + if(!cache->shmaddr) {
873 + apc_eprint("Unable to allocate shared memory for cache structures. (Perhaps your shared memory size isn't large enough?). ");
874 + }
875 + memset(cache->shmaddr, 0, cache_size);
876 +
877 + cache->header = (header_t*) cache->shmaddr;
878 + cache->header->num_hits = 0;
879 + cache->header->num_misses = 0;
880 + cache->header->deleted_list = NULL;
881 + cache->header->start_time = time(NULL);
882 + cache->header->expunges = 0;
883 + cache->header->busy = 0;
884 +
885 + cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
886 + cache->num_slots = num_slots;
887 + cache->gc_ttl = gc_ttl;
888 + cache->ttl = ttl;
889 + CREATE_LOCK(cache->header->lock);
890 +#if NONBLOCKING_LOCK_AVAILABLE
891 + CREATE_LOCK(cache->header->wrlock);
892 +#endif
893 + for (i = 0; i < num_slots; i++) {
894 + cache->slots[i] = NULL;
895 + }
896 +
897 + return cache;
898 +}
899 +/* }}} */
900 +
901 +/* {{{ apc_cache_destroy */
902 +void apc_cache_destroy(apc_cache_t* cache)
903 +{
904 + DESTROY_LOCK(cache);
905 + apc_efree(cache);
906 +}
907 +/* }}} */
908 +
909 +/* {{{ apc_cache_clear */
910 +void apc_cache_clear(apc_cache_t* cache)
911 +{
912 + int i;
913 +
914 + if(!cache) return;
915 +
916 + LOCK(cache);
917 + cache->header->busy = 1;
918 + cache->header->num_hits = 0;
919 + cache->header->num_misses = 0;
920 + cache->header->start_time = time(NULL);
921 + cache->header->expunges = 0;
922 +
923 + for (i = 0; i < cache->num_slots; i++) {
924 + slot_t* p = cache->slots[i];
925 + while (p) {
926 + remove_slot(cache, &p);
927 + }
928 + cache->slots[i] = NULL;
929 + }
930 +
931 + cache->header->busy = 0;
932 + UNLOCK(cache);
933 +}
934 +/* }}} */
935 +
936 +/* {{{ apc_cache_expunge */
937 +void apc_cache_expunge(apc_cache_t* cache, time_t t)
938 +{
939 + int i;
940 +
941 + if(!cache) return;
942 +
943 + if(!cache->ttl) {
944 + /*
945 + * If cache->ttl is not set, we wipe out the entire cache when
946 + * we run out of space.
947 + */
948 + LOCK(cache);
949 + cache->header->busy = 1;
950 + cache->header->expunges++;
951 + for (i = 0; i < cache->num_slots; i++) {
952 + slot_t* p = cache->slots[i];
953 + while (p) {
954 + remove_slot(cache, &p);
955 + }
956 + cache->slots[i] = NULL;
957 + }
958 + cache->header->busy = 0;
959 + UNLOCK(cache);
960 + } else {
961 + slot_t **p;
962 +
963 + /*
964 + * If the ttl for the cache is set we walk through and delete stale
965 + * entries. For the user cache that is slightly confusing since
966 + * we have the individual entry ttl's we can look at, but that would be
967 + * too much work. So if you want the user cache expunged, set a high
968 + * default apc.user_ttl and still provide a specific ttl for each entry
969 + * on insert
970 + */
971 +
972 + LOCK(cache);
973 + cache->header->busy = 1;
974 + cache->header->expunges++;
975 + for (i = 0; i < cache->num_slots; i++) {
976 + p = &cache->slots[i];
977 + while(*p) {
978 + /*
979 + * For the user cache we look at the individual entry ttl values
980 + * and if not set fall back to the default ttl for the user cache
981 + */
982 + if((*p)->value->type == APC_CACHE_ENTRY_USER) {
983 + if((*p)->value->data.user.ttl) {
984 + if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
985 + remove_slot(cache, p);
986 + continue;
987 + }
988 + } else if(cache->ttl) {
989 + if((*p)->creation_time + cache->ttl < t) {
990 + remove_slot(cache, p);
991 + continue;
992 + }
993 + }
994 + } else if((*p)->access_time < (t - cache->ttl)) {
995 + remove_slot(cache, p);
996 + continue;
997 + }
998 + p = &(*p)->next;
999 + }
1000 + }
1001 + cache->header->busy = 0;
1002 + UNLOCK(cache);
1003 + }
1004 +}
1005 +/* }}} */
1006 +
1007 +/* {{{ apc_cache_insert */
1008 +int apc_cache_insert(apc_cache_t* cache,
1009 + apc_cache_key_t key,
1010 + apc_cache_entry_t* value,
1011 + time_t t)
1012 +{
1013 + slot_t** slot;
1014 +
1015 + if (!value) {
1016 + return 0;
1017 + }
1018 +
1019 +#ifdef __DEBUG_APC__
1020 + fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
1021 +#endif
1022 +
1023 + LOCK(cache);
1024 + process_pending_removals(cache);
1025 +
1026 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1027 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1028 +
1029 + while(*slot) {
1030 + if(key.type == (*slot)->key.type) {
1031 + if(key.type == APC_CACHE_KEY_FILE) {
1032 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1033 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
1034 + if ((*slot)->key.mtime != key.mtime) {
1035 + remove_slot(cache, slot);
1036 + break;
1037 + }
1038 + UNLOCK(cache);
1039 + return 0;
1040 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1041 + remove_slot(cache, slot);
1042 + continue;
1043 + }
1044 + } else { /* APC_CACHE_KEY_FPFILE */
1045 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1046 + /* Hrm.. it's already here, remove it and insert new one */
1047 + remove_slot(cache, slot);
1048 + break;
1049 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1050 + remove_slot(cache, slot);
1051 + continue;
1052 + }
1053 + }
1054 + }
1055 + slot = &(*slot)->next;
1056 + }
1057 +
1058 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1059 + UNLOCK(cache);
1060 + return -1;
1061 + }
1062 +
1063 + cache->header->mem_size += value->mem_size;
1064 + cache->header->num_entries++;
1065 + cache->header->num_inserts++;
1066 +
1067 + UNLOCK(cache);
1068 + return 1;
1069 +}
1070 +/* }}} */
1071 +
1072 +/* {{{ apc_cache_user_insert */
1073 +int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC)
1074 +{
1075 + slot_t** slot;
1076 + size_t* mem_size_ptr = NULL;
1077 +
1078 + if (!value) {
1079 + return 0;
1080 + }
1081 +
1082 + LOCK(cache);
1083 + process_pending_removals(cache);
1084 +
1085 + slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
1086 +
1087 + if (APCG(mem_size_ptr) != NULL) {
1088 + mem_size_ptr = APCG(mem_size_ptr);
1089 + APCG(mem_size_ptr) = NULL;
1090 + }
1091 +
1092 + while (*slot) {
1093 + if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
1094 + /*
1095 + * At this point we have found the user cache entry. If we are doing
1096 + * an exclusive insert (apc_add) we are going to bail right away if
1097 + * the user entry already exists and it has no ttl, or
1098 + * there is a ttl and the entry has not timed out yet.
1099 + */
1100 + if(exclusive && ( !(*slot)->value->data.user.ttl ||
1101 + ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t )
1102 + ) ) {
1103 + UNLOCK(cache);
1104 + return 0;
1105 + }
1106 + remove_slot(cache, slot);
1107 + break;
1108 + } else
1109 + /*
1110 + * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of
1111 + * slot entries so we don't always have to skip past a bunch of stale entries. We check
1112 + * for staleness here and get rid of them by first checking to see if the cache has a global
1113 + * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
1114 + * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
1115 + */
1116 + if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) ||
1117 + ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
1118 + remove_slot(cache, slot);
1119 + continue;
1120 + }
1121 + slot = &(*slot)->next;
1122 + }
1123 +
1124 + if (mem_size_ptr != NULL) {
1125 + APCG(mem_size_ptr) = mem_size_ptr;
1126 + }
1127 +
1128 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1129 + UNLOCK(cache);
1130 + return 0;
1131 + }
1132 + if (APCG(mem_size_ptr) != NULL) {
1133 + value->mem_size = *APCG(mem_size_ptr);
1134 + cache->header->mem_size += *APCG(mem_size_ptr);
1135 + }
1136 + cache->header->num_entries++;
1137 + cache->header->num_inserts++;
1138 +
1139 + UNLOCK(cache);
1140 + return 1;
1141 +}
1142 +/* }}} */
1143 +
1144 +/* {{{ apc_cache_find_slot */
1145 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1146 +{
1147 + slot_t** slot;
1148 + volatile slot_t* retval = NULL;
1149 +
1150 + LOCK(cache);
1151 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1152 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1153 +
1154 + while (*slot) {
1155 + if(key.type == (*slot)->key.type) {
1156 + if(key.type == APC_CACHE_KEY_FILE) {
1157 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1158 + if((*slot)->key.mtime != key.mtime) {
1159 + remove_slot(cache, slot);
1160 + cache->header->num_misses++;
1161 + UNLOCK(cache);
1162 + return NULL;
1163 + }
1164 + (*slot)->num_hits++;
1165 + (*slot)->value->ref_count++;
1166 + (*slot)->access_time = t;
1167 + prevent_garbage_collection((*slot)->value);
1168 + cache->header->num_hits++;
1169 + retval = *slot;
1170 + UNLOCK(cache);
1171 + return (slot_t*)retval;
1172 + }
1173 + } else { /* APC_CACHE_KEY_FPFILE */
1174 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1175 + /* TTL Check ? */
1176 + (*slot)->num_hits++;
1177 + (*slot)->value->ref_count++;
1178 + (*slot)->access_time = t;
1179 + prevent_garbage_collection((*slot)->value);
1180 + cache->header->num_hits++;
1181 + retval = *slot;
1182 + UNLOCK(cache);
1183 + return (slot_t*)retval;
1184 + }
1185 + }
1186 + }
1187 + slot = &(*slot)->next;
1188 + }
1189 + cache->header->num_misses++;
1190 + UNLOCK(cache);
1191 + return NULL;
1192 +}
1193 +/* }}} */
1194 +
1195 +/* {{{ apc_cache_find */
1196 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1197 +{
1198 + slot_t * slot = apc_cache_find_slot(cache, key, t);
1199 + return (slot) ? slot->value : NULL;
1200 +}
1201 +/* }}} */
1202 +
1203 +/* {{{ apc_cache_user_find */
1204 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
1205 +{
1206 + slot_t** slot;
1207 + volatile apc_cache_entry_t* value = NULL;
1208 +
1209 + LOCK(cache);
1210 +
1211 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1212 +
1213 + while (*slot) {
1214 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1215 + /* Check to make sure this entry isn't expired by a hard TTL */
1216 + if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
1217 + remove_slot(cache, slot);
1218 + UNLOCK(cache);
1219 + return NULL;
1220 + }
1221 + /* Otherwise we are fine, increase counters and return the cache entry */
1222 + (*slot)->num_hits++;
1223 + (*slot)->value->ref_count++;
1224 + (*slot)->access_time = t;
1225 +
1226 + cache->header->num_hits++;
1227 + value = (*slot)->value;
1228 + UNLOCK(cache);
1229 + return (apc_cache_entry_t*)value;
1230 + }
1231 + slot = &(*slot)->next;
1232 + }
1233 +
1234 + UNLOCK(cache);
1235 + return NULL;
1236 +}
1237 +/* }}} */
1238 +
1239 +/* {{{ apc_cache_user_delete */
1240 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
1241 +{
1242 + slot_t** slot;
1243 +
1244 + LOCK(cache);
1245 +
1246 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1247 +
1248 + while (*slot) {
1249 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1250 + remove_slot(cache, slot);
1251 + UNLOCK(cache);
1252 + return 1;
1253 + }
1254 + slot = &(*slot)->next;
1255 + }
1256 +
1257 + UNLOCK(cache);
1258 + return 0;
1259 +}
1260 +/* }}} */
1261 +
1262 +/* {{{ apc_cache_release */
1263 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
1264 +{
1265 + /* local cache refcount-- is done in apc_local_cache_cleanup */
1266 + if(entry->local) return;
1267 +
1268 + LOCK(cache);
1269 + entry->ref_count--;
1270 + UNLOCK(cache);
1271 +}
1272 +/* }}} */
1273 +
1274 +/* {{{ apc_cache_make_file_key */
1275 +int apc_cache_make_file_key(apc_cache_key_t* key,
1276 + const char* filename,
1277 + const char* include_path,
1278 + time_t t
1279 + TSRMLS_DC)
1280 +{
1281 + struct stat *tmp_buf=NULL;
1282 + struct apc_fileinfo_t fileinfo = { {0}, };
1283 + int len;
1284 +
1285 + assert(key != NULL);
1286 +
1287 + if (!filename || !SG(request_info).path_translated) {
1288 +#ifdef __DEBUG_APC__
1289 + fprintf(stderr,"No filename and no path_translated - bailing\n");
1290 +#endif
1291 + return 0;
1292 + }
1293 +
1294 + len = strlen(filename);
1295 + if(APCG(fpstat)==0) {
1296 + if(IS_ABSOLUTE_PATH(filename,len)) {
1297 + key->data.fpfile.fullpath = filename;
1298 + key->data.fpfile.fullpath_len = len;
1299 + key->mtime = t;
1300 + key->type = APC_CACHE_KEY_FPFILE;
1301 + } else {
1302 + if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1303 + apc_wprint("apc failed to locate %s - bailing", filename);
1304 + return 0;
1305 + }
1306 +
1307 + if(!realpath(fileinfo.fullpath, APCG(canon_path))) {
1308 + apc_wprint("realpath failed to canonicalize %s - bailing", filename);
1309 + return 0;
1310 + }
1311 +
1312 + key->data.fpfile.fullpath = APCG(canon_path);
1313 + key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
1314 + key->mtime = t;
1315 + key->type = APC_CACHE_KEY_FPFILE;
1316 + }
1317 + return 1;
1318 + }
1319 +
1320 + if(!strcmp(SG(request_info).path_translated, filename)) {
1321 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
1322 + }
1323 + if(tmp_buf) {
1324 + fileinfo.st_buf = *tmp_buf;
1325 + } else {
1326 + if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1327 +#ifdef __DEBUG_APC__
1328 + fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
1329 +#endif
1330 + return 0;
1331 + }
1332 + }
1333 +
1334 + if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
1335 +#ifdef __DEBUG_APC__
1336 + fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
1337 +#endif
1338 + return 0;
1339 + }
1340 +
1341 + /*
1342 + * This is a bit of a hack.
1343 + *
1344 + * Here I am checking to see if the file is at least 2 seconds old.
1345 + * The idea is that if the file is currently being written to then its
1346 + * mtime is going to match or at most be 1 second off of the current
1347 + * request time and we want to avoid caching files that have not been
1348 + * completely written. Of course, people should be using atomic
1349 + * mechanisms to push files onto live web servers, but adding this
1350 + * tiny safety is easier than educating the world. This is now
1351 + * configurable, but the default is still 2 seconds.
1352 + */
1353 + if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) {
1354 +#ifdef __DEBUG_APC__
1355 + fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
1356 +#endif
1357 + return 0;
1358 + }
1359 +
1360 + key->data.file.device = fileinfo.st_buf.st_dev;
1361 + key->data.file.inode = fileinfo.st_buf.st_ino;
1362 + /*
1363 + * If working with content management systems that like to munge the mtime,
1364 + * it might be appropriate to key off of the ctime to be immune to systems
1365 + * that try to backdate a template. If the mtime is set to something older
1366 + * than the previous mtime of a template we will obviously never see this
1367 + * "older" template. At some point the Smarty templating system did this.
1368 + * I generally disagree with using the ctime here because you lose the
1369 + * ability to warm up new content by saving it to a temporary file, hitting
1370 + * it once to cache it and then renaming it into its permanent location so
1371 + * set the apc.stat_ctime=true to enable this check.
1372 + */
1373 + if(APCG(stat_ctime)) {
1374 + key->mtime = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime;
1375 + } else {
1376 + key->mtime = fileinfo.st_buf.st_mtime;
1377 + }
1378 + key->type = APC_CACHE_KEY_FILE;
1379 + return 1;
1380 +}
1381 +/* }}} */
1382 +
1383 +/* {{{ apc_cache_make_user_key */
1384 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
1385 +{
1386 + assert(key != NULL);
1387 +
1388 + if (!identifier)
1389 + return 0;
1390 +
1391 + key->data.user.identifier = identifier;
1392 + key->data.user.identifier_len = identifier_len;
1393 + key->mtime = t;
1394 + key->type = APC_CACHE_KEY_USER;
1395 + return 1;
1396 +}
1397 +/* }}} */
1398 +
1399 +/* {{{ apc_cache_make_file_entry */
1400 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
1401 + zend_op_array* op_array,
1402 + apc_function_t* functions,
1403 + apc_class_t* classes)
1404 +{
1405 + apc_cache_entry_t* entry;
1406 +
1407 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1408 + if (!entry) return NULL;
1409 +
1410 + entry->data.file.filename = apc_xstrdup(filename, apc_sma_malloc);
1411 + if(!entry->data.file.filename) {
1412 +#ifdef __DEBUG_APC__
1413 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
1414 +#endif
1415 + apc_sma_free(entry);
1416 + return NULL;
1417 + }
1418 +#ifdef __DEBUG_APC__
1419 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
1420 +#endif
1421 + entry->data.file.op_array = op_array;
1422 + entry->data.file.functions = functions;
1423 + entry->data.file.classes = classes;
1424 + entry->type = APC_CACHE_ENTRY_FILE;
1425 + entry->ref_count = 0;
1426 + entry->mem_size = 0;
1427 + entry->local = 0;
1428 + return entry;
1429 +}
1430 +/* }}} */
1431 +
1432 +/* {{{ apc_cache_store_zval */
1433 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1434 +{
1435 + smart_str buf = {0};
1436 + php_serialize_data_t var_hash;
1437 + TSRMLS_FETCH();
1438 +
1439 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1440 + if(!dst) {
1441 + CHECK(dst = (zval*) allocate(sizeof(zval)));
1442 + }
1443 +
1444 + PHP_VAR_SERIALIZE_INIT(var_hash);
1445 + php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
1446 + PHP_VAR_SERIALIZE_DESTROY(var_hash);
1447 +
1448 + dst->type = IS_NULL; /* in case we fail */
1449 + if(buf.c) {
1450 + dst->type = src->type & ~IS_CONSTANT_INDEX;
1451 + dst->value.str.len = buf.len;
1452 + CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
1453 + dst->type = src->type;
1454 + smart_str_free(&buf);
1455 + }
1456 + return dst;
1457 + } else {
1458 +
1459 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1460 + HashTable *old = APCG(copied_zvals);
1461 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1462 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1463 +
1464 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1465 +
1466 + if(APCG(copied_zvals)) {
1467 + zend_hash_destroy(APCG(copied_zvals));
1468 + efree(APCG(copied_zvals));
1469 + }
1470 +
1471 + APCG(copied_zvals) = old;
1472 +
1473 + return dst;
1474 + }
1475 +}
1476 +/* }}} */
1477 +
1478 +/* {{{ apc_cache_fetch_zval */
1479 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1480 +{
1481 + TSRMLS_FETCH();
1482 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1483 + php_unserialize_data_t var_hash;
1484 + const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
1485 +
1486 + PHP_VAR_UNSERIALIZE_INIT(var_hash);
1487 + if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
1488 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1489 + zval_dtor(dst);
1490 + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
1491 + dst->type = IS_NULL;
1492 + }
1493 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1494 + return dst;
1495 + } else {
1496 +
1497 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1498 + HashTable *old = APCG(copied_zvals);
1499 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1500 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1501 +
1502 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1503 +
1504 + if(APCG(copied_zvals)) {
1505 + zend_hash_destroy(APCG(copied_zvals));
1506 + efree(APCG(copied_zvals));
1507 + }
1508 +
1509 + APCG(copied_zvals) = old;
1510 +
1511 + return dst;
1512 + }
1513 +}
1514 +/* }}} */
1515 +
1516 +/* {{{ apc_cache_free_zval */
1517 +void apc_cache_free_zval(zval* src, apc_free_t deallocate)
1518 +{
1519 + TSRMLS_FETCH();
1520 + if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1521 + if (src->value.str.val) {
1522 + deallocate(src->value.str.val);
1523 + }
1524 + deallocate(src);
1525 + } else {
1526 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1527 + HashTable *old = APCG(copied_zvals);
1528 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1529 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1530 +
1531 + apc_free_zval(src, deallocate);
1532 +
1533 + if(APCG(copied_zvals)) {
1534 + zend_hash_destroy(APCG(copied_zvals));
1535 + efree(APCG(copied_zvals));
1536 + }
1537 +
1538 + APCG(copied_zvals) = old;
1539 + }
1540 +}
1541 +/* }}} */
1542 +
1543 +/* {{{ apc_cache_make_user_entry */
1544 +apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
1545 +{
1546 + apc_cache_entry_t* entry;
1547 +
1548 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1549 + if (!entry) return NULL;
1550 +
1551 + entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
1552 + entry->data.user.info_len = info_len;
1553 + if(!entry->data.user.info) {
1554 + apc_sma_free(entry);
1555 + return NULL;
1556 + }
1557 + entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
1558 + if(!entry->data.user.val) {
1559 + apc_sma_free(entry->data.user.info);
1560 + apc_sma_free(entry);
1561 + return NULL;
1562 + }
1563 + INIT_PZVAL(entry->data.user.val);
1564 + entry->data.user.ttl = ttl;
1565 + entry->type = APC_CACHE_ENTRY_USER;
1566 + entry->ref_count = 0;
1567 + entry->mem_size = 0;
1568 + entry->local = 0;
1569 + return entry;
1570 +}
1571 +/* }}} */
1572 +
1573 +/* {{{ apc_cache_free_entry */
1574 +void apc_cache_free_entry(apc_cache_entry_t* entry)
1575 +{
1576 + if (entry != NULL) {
1577 + assert(entry->ref_count == 0);
1578 + switch(entry->type) {
1579 + case APC_CACHE_ENTRY_FILE:
1580 + apc_sma_free(entry->data.file.filename);
1581 + apc_free_op_array(entry->data.file.op_array, apc_sma_free);
1582 + apc_free_functions(entry->data.file.functions, apc_sma_free);
1583 + apc_free_classes(entry->data.file.classes, apc_sma_free);
1584 + break;
1585 + case APC_CACHE_ENTRY_USER:
1586 + apc_sma_free(entry->data.user.info);
1587 + apc_cache_free_zval(entry->data.user.val, apc_sma_free);
1588 + break;
1589 + }
1590 + apc_sma_free(entry);
1591 + }
1592 +}
1593 +/* }}} */
1594 +
1595 +/* {{{ apc_cache_info */
1596 +apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
1597 +{
1598 + apc_cache_info_t* info;
1599 + slot_t* p;
1600 + int i;
1601 +
1602 + if(!cache) return NULL;
1603 +
1604 + LOCK(cache);
1605 +
1606 + info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
1607 + if(!info) {
1608 + UNLOCK(cache);
1609 + return NULL;
1610 + }
1611 + info->num_slots = cache->num_slots;
1612 + info->ttl = cache->ttl;
1613 + info->num_hits = cache->header->num_hits;
1614 + info->num_misses = cache->header->num_misses;
1615 + info->list = NULL;
1616 + info->deleted_list = NULL;
1617 + info->start_time = cache->header->start_time;
1618 + info->expunges = cache->header->expunges;
1619 + info->mem_size = cache->header->mem_size;
1620 + info->num_entries = cache->header->num_entries;
1621 + info->num_inserts = cache->header->num_inserts;
1622 +
1623 + if(!limited) {
1624 + /* For each hashtable slot */
1625 + for (i = 0; i < info->num_slots; i++) {
1626 + p = cache->slots[i];
1627 + for (; p != NULL; p = p->next) {
1628 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1629 +
1630 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1631 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1632 + link->data.file.device = p->key.data.file.device;
1633 + link->data.file.inode = p->key.data.file.inode;
1634 + link->type = APC_CACHE_ENTRY_FILE;
1635 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1636 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1637 + link->data.user.ttl = p->value->data.user.ttl;
1638 + link->type = APC_CACHE_ENTRY_USER;
1639 + }
1640 + link->num_hits = p->num_hits;
1641 + link->mtime = p->key.mtime;
1642 + link->creation_time = p->creation_time;
1643 + link->deletion_time = p->deletion_time;
1644 + link->access_time = p->access_time;
1645 + link->ref_count = p->value->ref_count;
1646 + link->mem_size = p->value->mem_size;
1647 + link->next = info->list;
1648 + info->list = link;
1649 + }
1650 + }
1651 +
1652 + /* For each slot pending deletion */
1653 + for (p = cache->header->deleted_list; p != NULL; p = p->next) {
1654 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1655 +
1656 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1657 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1658 + if(p->key.type == APC_CACHE_KEY_FILE) {
1659 + link->data.file.device = p->key.data.file.device;
1660 + link->data.file.inode = p->key.data.file.inode;
1661 + } else { /* This is a no-stat fullpath file entry */
1662 + link->data.file.device = 0;
1663 + link->data.file.inode = 0;
1664 + }
1665 + link->type = APC_CACHE_ENTRY_FILE;
1666 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1667 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1668 + link->data.user.ttl = p->value->data.user.ttl;
1669 + link->type = APC_CACHE_ENTRY_USER;
1670 + }
1671 + link->num_hits = p->num_hits;
1672 + link->mtime = p->key.mtime;
1673 + link->creation_time = p->creation_time;
1674 + link->deletion_time = p->deletion_time;
1675 + link->access_time = p->access_time;
1676 + link->ref_count = p->value->ref_count;
1677 + link->mem_size = p->value->mem_size;
1678 + link->next = info->deleted_list;
1679 + info->deleted_list = link;
1680 + }
1681 + }
1682 +
1683 + UNLOCK(cache);
1684 + return info;
1685 +}
1686 +/* }}} */
1687 +
1688 +/* {{{ apc_cache_free_info */
1689 +void apc_cache_free_info(apc_cache_info_t* info)
1690 +{
1691 + apc_cache_link_t* p = info->list;
1692 + apc_cache_link_t* q = NULL;
1693 + while (p != NULL) {
1694 + q = p;
1695 + p = p->next;
1696 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1697 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1698 + apc_efree(q);
1699 + }
1700 + p = info->deleted_list;
1701 + while (p != NULL) {
1702 + q = p;
1703 + p = p->next;
1704 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1705 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1706 + apc_efree(q);
1707 + }
1708 + apc_efree(info);
1709 +}
1710 +/* }}} */
1711 +
1712 +/* {{{ apc_cache_unlock */
1713 +void apc_cache_unlock(apc_cache_t* cache)
1714 +{
1715 + UNLOCK(cache);
1716 +}
1717 +/* }}} */
1718 +
1719 +/* {{{ apc_cache_busy */
1720 +zend_bool apc_cache_busy(apc_cache_t* cache)
1721 +{
1722 + return cache->header->busy;
1723 +}
1724 +/* }}} */
1725 +
1726 +#if NONBLOCKING_LOCK_AVAILABLE
1727 +/* {{{ apc_cache_write_lock */
1728 +zend_bool apc_cache_write_lock(apc_cache_t* cache)
1729 +{
1730 + return apc_lck_nb_lock(cache->header->wrlock);
1731 +}
1732 +/* }}} */
1733 +
1734 +/* {{{ apc_cache_write_unlock */
1735 +void apc_cache_write_unlock(apc_cache_t* cache)
1736 +{
1737 + apc_lck_unlock(cache->header->wrlock);
1738 +}
1739 +/* }}} */
1740 +#endif
1741 +
1742 +/* {{{ make_local_slot */
1743 +static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot, time_t t)
1744 +{
1745 + apc_cache_entry_t* value;
1746 +
1747 + value = apc_emalloc(sizeof(apc_cache_entry_t));
1748 + memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
1749 + value->local = 1;
1750 +
1751 + lslot->original = slot;
1752 + lslot->value = value;
1753 + lslot->num_hits = 0;
1754 + lslot->creation_time = t;
1755 +
1756 + return lslot; /* for what joy ? ... consistency */
1757 +}
1758 +/* }}} */
1759 +
1760 +/* {{{ free_local_slot */
1761 +static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot)
1762 +{
1763 + local_slot_t * dead = NULL;
1764 + if(!lslot->original) return;
1765 +
1766 + /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
1767 + dead = apc_emalloc(sizeof(local_slot_t));
1768 + memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
1769 +
1770 + lslot->original = NULL;
1771 + lslot->value = NULL;
1772 +
1773 + dead->next = cache->dead_list;
1774 + cache->dead_list = dead;
1775 +}
1776 +/* }}} */
1777 +
1778 +/* {{{ apc_local_cache_create */
1779 +apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
1780 +{
1781 + apc_local_cache_t* cache = NULL;
1782 +
1783 + cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
1784 +
1785 + cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
1786 + memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
1787 +
1788 + cache->shmcache = shmcache;
1789 + cache->num_slots = num_slots;
1790 + cache->ttl = ttl;
1791 + cache->num_hits = 0;
1792 + cache->generation = shmcache->header->expunges;
1793 + cache->dead_list = NULL;
1794 +
1795 + return cache;
1796 +}
1797 +/* }}} */
1798 +
1799 +/* {{{ apc_local_cache_cleanup */
1800 +void apc_local_cache_cleanup(apc_local_cache_t* cache) {
1801 + local_slot_t * lslot;
1802 + time_t t = time(0);
1803 +
1804 + int i;
1805 + for(i = 0; i < cache->num_slots; i++) {
1806 + lslot = &cache->slots[i];
1807 + /* every slot lives for exactly TTL seconds */
1808 + if((lslot->original && lslot->creation_time < (t - cache->ttl)) ||
1809 + cache->generation != cache->shmcache->header->expunges) {
1810 + free_local_slot(cache, lslot);
1811 + }
1812 + }
1813 +
1814 + LOCK(cache->shmcache);
1815 + for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
1816 + lslot->original->num_hits += lslot->num_hits;
1817 + lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
1818 + apc_efree(lslot->value);
1819 + }
1820 + UNLOCK(cache->shmcache);
1821 +
1822 + cache->dead_list = NULL;
1823 +}
1824 +/* }}} */
1825 +
1826 +/* {{{ apc_local_cache_destroy */
1827 +void apc_local_cache_destroy(apc_local_cache_t* cache)
1828 +{
1829 + int i;
1830 + for(i = 0; i < cache->num_slots; i++) {
1831 + free_local_slot(cache, &cache->slots[i]);
1832 + }
1833 +
1834 + apc_local_cache_cleanup(cache);
1835 +
1836 + LOCK(cache->shmcache);
1837 + cache->shmcache->header->num_hits += cache->num_hits;
1838 + UNLOCK(cache->shmcache);
1839 +
1840 + apc_efree(cache->slots);
1841 + apc_efree(cache);
1842 +}
1843 +/* }}} */
1844 +
1845 +/* {{{ apc_local_cache_find */
1846 +apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
1847 +{
1848 + slot_t* slot;
1849 + local_slot_t* lslot;
1850 +
1851 + if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
1852 + else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1853 +
1854 + slot = lslot->original;
1855 +
1856 + if(slot && key.type == slot->key.type) {
1857 + if(slot->access_time < (t - cache->ttl)) {
1858 + goto not_found;
1859 + }
1860 + if(key.type == APC_CACHE_KEY_FILE &&
1861 + key_equals(slot->key.data.file, key.data.file)) {
1862 + if(slot->key.mtime != key.mtime) {
1863 + free_local_slot(cache, lslot);
1864 + goto not_found;
1865 + }
1866 + cache->num_hits++;
1867 + lslot->num_hits++;
1868 + lslot->original->access_time = t; /* unlocked write, but last write wins */
1869 + return lslot->value;
1870 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
1871 + if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1872 + cache->num_hits++;
1873 + lslot->num_hits++;
1874 + lslot->original->access_time = t; /* unlocked write, but last write wins */
1875 + return lslot->value;
1876 + }
1877 + }
1878 + }
1879 +not_found:
1880 + if(apc_cache_busy(cache->shmcache)) {
1881 + return NULL;
1882 + }
1883 +
1884 + slot = apc_cache_find_slot(cache->shmcache, key, t);
1885 +
1886 + if(!slot) return NULL;
1887 +
1888 + /* i.e maintain a sort of top list */
1889 + if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits) < slot->num_hits) {
1890 + free_local_slot(cache, lslot);
1891 + make_local_slot(cache, lslot, slot, t);
1892 + return lslot->value;
1893 + }
1894 + return slot->value;
1895 +}
1896 +/* }}} */
1897 +
1898 +/*
1899 + * Local variables:
1900 + * tab-width: 4
1901 + * c-basic-offset: 4
1902 + * End:
1903 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1904 + * vim<600: expandtab sw=4 ts=4 sts=4
1905 + */
1906 diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.h php-5.2.5/ext/apc/apc_cache.h
1907 --- php-5.2.5-orig/ext/apc/apc_cache.h 1969-12-31 18:00:00.000000000 -0600
1908 +++ php-5.2.5/ext/apc/apc_cache.h 2007-12-26 16:51:32.000000000 -0600
1909 @@ -0,0 +1,312 @@
1910 +/*
1911 + +----------------------------------------------------------------------+
1912 + | APC |
1913 + +----------------------------------------------------------------------+
1914 + | Copyright (c) 2006 The PHP Group |
1915 + +----------------------------------------------------------------------+
1916 + | This source file is subject to version 3.01 of the PHP license, |
1917 + | that is bundled with this package in the file LICENSE, and is |
1918 + | available through the world-wide-web at the following url: |
1919 + | http://www.php.net/license/3_01.txt. |
1920 + | If you did not receive a copy of the PHP license and are unable to |
1921 + | obtain it through the world-wide-web, please send a note to |
1922 + | license@php.net so we can mail you a copy immediately. |
1923 + +----------------------------------------------------------------------+
1924 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
1925 + | Rasmus Lerdorf <rasmus@php.net> |
1926 + +----------------------------------------------------------------------+
1927 +
1928 + This software was contributed to PHP by Community Connect Inc. in 2002
1929 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1930 + Future revisions and derivatives of this source code must acknowledge
1931 + Community Connect Inc. as the original contributor of this module by
1932 + leaving this note intact in the source code.
1933 +
1934 + All other licensing and usage conditions are those of the PHP Group.
1935 +
1936 + */
1937 +
1938 +/* $Id: apc_cache.h,v 3.46 2007/10/05 23:06:56 gopalv Exp $ */
1939 +
1940 +#ifndef APC_CACHE_H
1941 +#define APC_CACHE_H
1942 +
1943 +/*
1944 + * This module defines the shared memory file cache. Basically all of the
1945 + * logic for storing and retrieving cache entries lives here.
1946 + */
1947 +
1948 +#include "apc.h"
1949 +#include "apc_compile.h"
1950 +
1951 +#define APC_CACHE_ENTRY_FILE 1
1952 +#define APC_CACHE_ENTRY_USER 2
1953 +
1954 +#define APC_CACHE_KEY_FILE 1
1955 +#define APC_CACHE_KEY_USER 2
1956 +#define APC_CACHE_KEY_FPFILE 3
1957 +
1958 +/* {{{ struct definition: apc_cache_key_t */
1959 +#define T apc_cache_t*
1960 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
1961 +
1962 +typedef union _apc_cache_key_data_t {
1963 + struct {
1964 + dev_t device; /* the filesystem device */
1965 + ino_t inode; /* the filesystem inode */
1966 + } file;
1967 + struct {
1968 + const char *identifier;
1969 + int identifier_len;
1970 + } user;
1971 + struct {
1972 + const char *fullpath;
1973 + int fullpath_len;
1974 + } fpfile;
1975 +} apc_cache_key_data_t;
1976 +
1977 +typedef struct apc_cache_key_t apc_cache_key_t;
1978 +struct apc_cache_key_t {
1979 + apc_cache_key_data_t data;
1980 + time_t mtime; /* the mtime of this cached entry */
1981 + unsigned char type;
1982 +};
1983 +/* }}} */
1984 +
1985 +/* {{{ struct definition: apc_cache_entry_t */
1986 +typedef union _apc_cache_entry_value_t {
1987 + struct {
1988 + char *filename; /* absolute path to source file */
1989 + zend_op_array* op_array; /* op_array allocated in shared memory */
1990 + apc_function_t* functions; /* array of apc_function_t's */
1991 + apc_class_t* classes; /* array of apc_class_t's */
1992 + } file;
1993 + struct {
1994 + char *info;
1995 + int info_len;
1996 + zval *val;
1997 + unsigned int ttl;
1998 + } user;
1999 +} apc_cache_entry_value_t;
2000 +
2001 +typedef struct apc_cache_entry_t apc_cache_entry_t;
2002 +struct apc_cache_entry_t {
2003 + apc_cache_entry_value_t data;
2004 + unsigned char type;
2005 + unsigned char local;
2006 + int ref_count;
2007 + size_t mem_size;
2008 +};
2009 +/* }}} */
2010 +
2011 +/*
2012 + * apc_cache_create creates the shared memory compiler cache. This function
2013 + * should be called just once (ideally in the web server parent process, e.g.
2014 + * in apache), otherwise you will end up with multiple caches (which won't
2015 + * necessarily break anything). Returns a pointer to the cache object.
2016 + *
2017 + * size_hint is a "hint" at the total number of source files that will be
2018 + * cached. It determines the physical size of the hash table. Passing 0 for
2019 + * this argument will use a reasonable default value.
2020 + *
2021 + * gc_ttl is the maximum time a cache entry may speed on the garbage
2022 + * collection list. This is basically a work around for the inherent
2023 + * unreliability of our reference counting mechanism (see apc_cache_release).
2024 + *
2025 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
2026 + * is needed. This helps in cleaning up the cache and ensuring that entries
2027 + * hit frequently stay cached and ones not hit very often eventually disappear.
2028 + */
2029 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
2030 +
2031 +/*
2032 + * apc_cache_destroy releases any OS resources associated with a cache object.
2033 + * Under apache, this function can be safely called by the child processes
2034 + * when they exit.
2035 + */
2036 +extern void apc_cache_destroy(T cache);
2037 +
2038 +/*
2039 + * apc_cache_clear empties a cache. This can safely be called at any time,
2040 + * even while other server processes are executing cached source files.
2041 + */
2042 +extern void apc_cache_clear(T cache);
2043 +
2044 +/*
2045 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
2046 + * Internally, the filename is translated to a canonical representation, so
2047 + * that relative and absolute filenames will map to a single key. Returns
2048 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
2049 + * returned, the caller must free the cache entry by calling
2050 + * apc_cache_free_entry (see below).
2051 + *
2052 + * key is the value created by apc_cache_make_file_key for file keys.
2053 + *
2054 + * value is a cache entry returned by apc_cache_make_entry (see below).
2055 + */
2056 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
2057 + apc_cache_entry_t* value, time_t t);
2058 +
2059 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
2060 + apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
2061 +
2062 +/*
2063 + * apc_cache_find searches for a cache entry by filename, and returns a
2064 + * pointer to the entry if found, NULL otherwise.
2065 + *
2066 + * key is a value created by apc_cache_make_file_key for file keys.
2067 + */
2068 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
2069 +
2070 +/*
2071 + * apc_cache_user_find searches for a cache entry by its hashed identifier,
2072 + * and returns a pointer to the entry if found, NULL otherwise.
2073 + *
2074 + */
2075 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
2076 +
2077 +/*
2078 + * apc_cache_user_delete finds an entry in the user cache and deletes it.
2079 + */
2080 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
2081 +
2082 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
2083 + * zval from it.
2084 + *
2085 + */
2086 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
2087 +
2088 +/*
2089 + * apc_cache_release decrements the reference count associated with a cache
2090 + * entry. Calling apc_cache_find automatically increments the reference count,
2091 + * and this function must be called post-execution to return the count to its
2092 + * original value. Failing to do so will prevent the entry from being
2093 + * garbage-collected.
2094 + *
2095 + * entry is the cache entry whose ref count you want to decrement.
2096 + */
2097 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
2098 +
2099 +/*
2100 + * apc_cache_make_file_key creates a key object given a relative or absolute
2101 + * filename and an optional list of auxillary paths to search. include_path is
2102 + * searched if the filename cannot be found relative to the current working
2103 + * directory.
2104 + *
2105 + * key points to caller-allocated storage (must not be null).
2106 + *
2107 + * filename is the path to the source file.
2108 + *
2109 + * include_path is a colon-separated list of directories to search.
2110 + *
2111 + * and finally we pass in the current request time so we can avoid
2112 + * caching files with a current mtime which tends to indicate that
2113 + * they are still being written to.
2114 + */
2115 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
2116 + const char* filename,
2117 + const char* include_path,
2118 + time_t t
2119 + TSRMLS_DC);
2120 +
2121 +/*
2122 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
2123 + * and the compilation results returned by the PHP compiler.
2124 + */
2125 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2126 + zend_op_array* op_array,
2127 + apc_function_t* functions,
2128 + apc_class_t* classes);
2129 +/*
2130 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
2131 + * and the zval to be stored.
2132 + */
2133 +extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
2134 +
2135 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
2136 +
2137 +/*
2138 + * Frees all memory associated with an object returned by apc_cache_make_entry
2139 + * (see above).
2140 + */
2141 +extern void apc_cache_free_entry(apc_cache_entry_t* entry);
2142 +
2143 +/* {{{ struct definition: apc_cache_link_data_t */
2144 +typedef union _apc_cache_link_data_t {
2145 + struct {
2146 + char *filename;
2147 + dev_t device;
2148 + ino_t inode;
2149 + } file;
2150 + struct {
2151 + char *info;
2152 + unsigned int ttl;
2153 + } user;
2154 +} apc_cache_link_data_t;
2155 +/* }}} */
2156 +
2157 +/* {{{ struct definition: apc_cache_link_t */
2158 +typedef struct apc_cache_link_t apc_cache_link_t;
2159 +struct apc_cache_link_t {
2160 + apc_cache_link_data_t data;
2161 + unsigned char type;
2162 + int num_hits;
2163 + time_t mtime;
2164 + time_t creation_time;
2165 + time_t deletion_time;
2166 + time_t access_time;
2167 + int ref_count;
2168 + size_t mem_size;
2169 + apc_cache_link_t* next;
2170 +};
2171 +/* }}} */
2172 +
2173 +/* {{{ struct definition: apc_cache_info_t */
2174 +typedef struct apc_cache_info_t apc_cache_info_t;
2175 +struct apc_cache_info_t {
2176 + int num_slots;
2177 + int num_hits;
2178 + int num_misses;
2179 + int ttl;
2180 + apc_cache_link_t* list;
2181 + apc_cache_link_t* deleted_list;
2182 + time_t start_time;
2183 + int expunges;
2184 + int num_entries;
2185 + int num_inserts;
2186 + size_t mem_size;
2187 +};
2188 +/* }}} */
2189 +
2190 +extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
2191 +extern void apc_cache_free_info(apc_cache_info_t* info);
2192 +extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
2193 +extern void apc_cache_unlock(apc_cache_t* cache);
2194 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
2195 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
2196 +extern void apc_cache_write_unlock(apc_cache_t* cache);
2197 +
2198 +/*
2199 + * Process local cache, which keeps a refcount hungry version of the slots
2200 + * for quick access without a lock - as long as the entry exists in local
2201 + * cache, the refcount of the shm version will be +1 more than required.
2202 + * It holds no data, only a shallow copy of apc_cache_entry.
2203 + */
2204 +typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */
2205 +
2206 +extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
2207 +extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
2208 +extern void apc_local_cache_destroy(apc_local_cache_t* cache);
2209 +extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
2210 +
2211 +#undef T
2212 +#endif
2213 +
2214 +/*
2215 + * Local variables:
2216 + * tab-width: 4
2217 + * c-basic-offset: 4
2218 + * End:
2219 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
2220 + * vim<600: expandtab sw=4 ts=4 sts=4
2221 + */
2222 diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.c php-5.2.5/ext/apc/apc_compile.c
2223 --- php-5.2.5-orig/ext/apc/apc_compile.c 1969-12-31 18:00:00.000000000 -0600
2224 +++ php-5.2.5/ext/apc/apc_compile.c 2007-12-26 16:51:32.000000000 -0600
2225 @@ -0,0 +1,2529 @@
2226 +/*
2227 + +----------------------------------------------------------------------+
2228 + | APC |
2229 + +----------------------------------------------------------------------+
2230 + | Copyright (c) 2006 The PHP Group |
2231 + +----------------------------------------------------------------------+
2232 + | This source file is subject to version 3.01 of the PHP license, |
2233 + | that is bundled with this package in the file LICENSE, and is |
2234 + | available through the world-wide-web at the following url: |
2235 + | http://www.php.net/license/3_01.txt. |
2236 + | If you did not receive a copy of the PHP license and are unable to |
2237 + | obtain it through the world-wide-web, please send a note to |
2238 + | license@php.net so we can mail you a copy immediately. |
2239 + +----------------------------------------------------------------------+
2240 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
2241 + | Rasmus Lerdorf <rasmus@php.net> |
2242 + | Arun C. Murthy <arunc@yahoo-inc.com> |
2243 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
2244 + +----------------------------------------------------------------------+
2245 +
2246 + This software was contributed to PHP by Community Connect Inc. in 2002
2247 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
2248 + Future revisions and derivatives of this source code must acknowledge
2249 + Community Connect Inc. as the original contributor of this module by
2250 + leaving this note intact in the source code.
2251 +
2252 + All other licensing and usage conditions are those of the PHP Group.
2253 +
2254 + */
2255 +
2256 +/* $Id: apc_compile.c,v 3.87 2007/08/25 13:09:13 gopalv Exp $ */
2257 +
2258 +#include "apc_compile.h"
2259 +#include "apc_globals.h"
2260 +#include "apc_zend.h"
2261 +
2262 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
2263 +typedef void (*ht_free_fun_t)(void*, apc_free_t);
2264 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
2265 +
2266 +#ifdef ZEND_ENGINE_2
2267 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
2268 +#endif
2269 +
2270 +#define CHECK(p) { if ((p) == NULL) return NULL; }
2271 +
2272 +/* {{{ internal function declarations */
2273 +
2274 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
2275 +
2276 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
2277 +
2278 +/*
2279 + * The "copy" functions perform deep-copies on a particular data structure
2280 + * (passed as the second argument). They also optionally allocate space for
2281 + * the destination data structure if the first argument is null.
2282 + */
2283 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
2284 +static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
2285 +static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
2286 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
2287 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
2288 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
2289 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
2290 +static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, ht_free_fun_t, int, apc_malloc_t, apc_free_t, ht_check_copy_fun_t, ...);
2291 +#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
2292 + my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
2293 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
2294 +#ifdef ZEND_ENGINE_2
2295 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
2296 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
2297 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
2298 +#endif
2299 +/*
2300 + * The "destroy" functions free the memory associated with a particular data
2301 + * structure but do not free the pointer to the data structure.
2302 + *
2303 + * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
2304 + * the zval* has other references elsewhere
2305 + */
2306 +static int my_destroy_zval(zval*, apc_free_t);
2307 +static void my_destroy_zval_ptr(zval**, apc_free_t);
2308 +static void my_destroy_zend_op(zend_op*, apc_free_t);
2309 +static void my_destroy_znode(znode*, apc_free_t);
2310 +static void my_destroy_function(zend_function*, apc_free_t);
2311 +static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
2312 +static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
2313 +static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2314 +static void my_destroy_op_array(zend_op_array*, apc_free_t);
2315 +#ifdef ZEND_ENGINE_2
2316 +static void my_destroy_property_info(zend_property_info*, apc_free_t);
2317 +static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
2318 +static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
2319 +#endif
2320 +
2321 +/*
2322 + * The "free" functions work exactly like their "destroy" counterparts (see
2323 + * above) but also free the pointer to the data structure.
2324 + */
2325 +static void my_free_zval_ptr(zval**, apc_free_t);
2326 +static void my_free_function(zend_function*, apc_free_t);
2327 +static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2328 +#ifdef ZEND_ENGINE_2
2329 +static void my_free_property_info(zend_property_info* src, apc_free_t);
2330 +static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
2331 +static void my_free_arg_info(zend_arg_info*, apc_free_t);
2332 +#endif
2333 +
2334 +/*
2335 + * The "fixup" functions need for ZEND_ENGINE_2
2336 + */
2337 +#ifdef ZEND_ENGINE_2
2338 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2339 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
2340 +/* my_fixup_function_for_execution is the same as my_fixup_function
2341 + * but named differently for clarity
2342 + */
2343 +#define my_fixup_function_for_execution my_fixup_function
2344 +
2345 +#ifdef ZEND_ENGINE_2_2
2346 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2347 +#define my_fixup_property_info_for_execution my_fixup_property_info
2348 +#endif
2349 +
2350 +#endif
2351 +
2352 +/*
2353 + * These functions return "1" if the member/function is
2354 + * defined/overridden in the 'current' class and not inherited.
2355 + */
2356 +static int my_check_copy_function(Bucket* src, va_list args);
2357 +static int my_check_copy_default_property(Bucket* p, va_list args);
2358 +#ifdef ZEND_ENGINE_2
2359 +static int my_check_copy_property_info(Bucket* src, va_list args);
2360 +static int my_check_copy_static_member(Bucket* src, va_list args);
2361 +#endif
2362 +
2363 +/* }}} */
2364 +
2365 +/* {{{ check_op_array_integrity */
2366 +#if 0
2367 +static void check_op_array_integrity(zend_op_array* src)
2368 +{
2369 + int i, j;
2370 +
2371 + /* These sorts of checks really aren't particularly effective, but they
2372 + * can provide a welcome sanity check when debugging. Just don't enable
2373 + * for production use! */
2374 +
2375 + assert(src->refcount != NULL);
2376 + assert(src->opcodes != NULL);
2377 + assert(src->last > 0);
2378 +
2379 + for (i = 0; i < src->last; i++) {
2380 + zend_op* op = &src->opcodes[i];
2381 + znode* nodes[] = { &op->result, &op->op1, &op->op2 };
2382 + for (j = 0; j < 3; j++) {
2383 + assert(nodes[j]->op_type == IS_CONST ||
2384 + nodes[j]->op_type == IS_VAR ||
2385 + nodes[j]->op_type == IS_TMP_VAR ||
2386 + nodes[j]->op_type == IS_UNUSED);
2387 +
2388 + if (nodes[j]->op_type == IS_CONST) {
2389 + int type = nodes[j]->u.constant.type;
2390 + assert(type == IS_RESOURCE ||
2391 + type == IS_BOOL ||
2392 + type == IS_LONG ||
2393 + type == IS_DOUBLE ||
2394 + type == IS_NULL ||
2395 + type == IS_CONSTANT ||
2396 + type == IS_STRING ||
2397 + type == FLAG_IS_BC ||
2398 + type == IS_ARRAY ||
2399 + type == IS_CONSTANT_ARRAY ||
2400 + type == IS_OBJECT);
2401 + }
2402 + }
2403 + }
2404 +}
2405 +#endif
2406 +/* }}} */
2407 +
2408 +/* {{{ is_derived_class */
2409 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
2410 +{
2411 + int i;
2412 +
2413 + /*
2414 + * Scan the op_array for execution-time class declarations of derived
2415 + * classes. If we find one whose key matches our current class key, we
2416 + * know the current class is a derived class.
2417 + *
2418 + * This check is exceedingly inefficient (fortunately it only has to occur
2419 + * once, when the source file is first compiled and cached), but the
2420 + * compiler should save this information for us -- definitely a candidate
2421 + * for a Zend Engine patch.
2422 + *
2423 + * XXX checking for derived classes provides a minimal (albeit measurable)
2424 + * speed up. It may not be worth the added complexity -- considere
2425 + * removing this optimization.
2426 + */
2427 +
2428 + for (i = 0; i < op_array->last; i++) {
2429 + zend_op* op = &op_array->opcodes[i];
2430 +
2431 +#ifdef ZEND_ENGINE_2
2432 + if (op->opcode == ZEND_DECLARE_CLASS &&
2433 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2434 +#else
2435 + if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
2436 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2437 +#endif
2438 + {
2439 + if (op->op1.u.constant.value.str.len == key_size &&
2440 + !memcmp(op->op1.u.constant.value.str.val, key, key_size))
2441 + {
2442 + return 1;
2443 + }
2444 + }
2445 + }
2446 +
2447 + return 0;
2448 +}
2449 +/* }}} */
2450 +
2451 +/* {{{ my_bitwise_copy_function */
2452 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
2453 +{
2454 + assert(src != NULL);
2455 +
2456 + if (!dst) {
2457 + CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
2458 + }
2459 +
2460 + /* We only need to do a bitwise copy */
2461 + memcpy(dst, src, sizeof(src[0]));
2462 +
2463 + return dst;
2464 +}
2465 +/* }}} */
2466 +
2467 +/* {{{ my_copy_zval_ptr */
2468 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
2469 +{
2470 + int local_dst_alloc = 0;
2471 + zval* dst_new;
2472 +
2473 + assert(src != NULL);
2474 +
2475 + if (!dst) {
2476 + CHECK(dst = (zval**) allocate(sizeof(zval*)));
2477 + local_dst_alloc = 1;
2478 + }
2479 +
2480 + if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
2481 + if(local_dst_alloc) deallocate(dst);
2482 + return NULL;
2483 + }
2484 + dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
2485 + if(dst_new != *dst) {
2486 + deallocate(*dst);
2487 + *dst = dst_new;
2488 + }
2489 +
2490 + (*dst)->refcount = (*src)->refcount;
2491 + (*dst)->is_ref = (*src)->is_ref;
2492 +
2493 + return dst;
2494 +}
2495 +/* }}} */
2496 +
2497 +/* {{{ my_copy_zval */
2498 +static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
2499 +{
2500 + zval **tmp;
2501 + TSRMLS_FETCH();
2502 +
2503 + assert(dst != NULL);
2504 + assert(src != NULL);
2505 +
2506 + memcpy(dst, src, sizeof(src[0]));
2507 +
2508 + switch (src->type & ~IS_CONSTANT_INDEX) {
2509 + case IS_RESOURCE:
2510 + case IS_BOOL:
2511 + case IS_LONG:
2512 + case IS_DOUBLE:
2513 + case IS_NULL:
2514 + break;
2515 +
2516 + case IS_CONSTANT:
2517 + case IS_STRING:
2518 +#ifndef ZEND_ENGINE_2
2519 + case FLAG_IS_BC:
2520 +#endif
2521 + if (src->value.str.val) {
2522 + CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
2523 + src->value.str.len+1,
2524 + allocate));
2525 + }
2526 + break;
2527 +
2528 + case IS_ARRAY:
2529 +
2530 + if(APCG(copied_zvals)) {
2531 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
2532 + (*tmp)->refcount++;
2533 + return *tmp;
2534 + }
2535 +
2536 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
2537 + }
2538 + /* fall through */
2539 +
2540 + case IS_CONSTANT_ARRAY:
2541 +
2542 + CHECK(dst->value.ht =
2543 + my_copy_hashtable(NULL,
2544 + src->value.ht,
2545 + (ht_copy_fun_t) my_copy_zval_ptr,
2546 + (ht_free_fun_t) my_free_zval_ptr,
2547 + 1,
2548 + allocate, deallocate));
2549 + break;
2550 +
2551 + case IS_OBJECT:
2552 +#ifndef ZEND_ENGINE_2
2553 + CHECK(dst->value.obj.ce =
2554 + my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
2555 +
2556 + if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
2557 + src->value.obj.properties,
2558 + (ht_copy_fun_t) my_copy_zval_ptr,
2559 + (ht_free_fun_t) my_free_zval_ptr,
2560 + 1,
2561 + allocate, deallocate))) {
2562 + my_destroy_class_entry(dst->value.obj.ce, deallocate);
2563 + return NULL;
2564 + }
2565 + break;
2566 +#else
2567 + dst->type = IS_NULL;
2568 +#endif
2569 + break;
2570 +
2571 + default:
2572 + assert(0);
2573 + }
2574 +
2575 + return dst;
2576 +}
2577 +/* }}} */
2578 +
2579 +/* {{{ my_copy_znode */
2580 +static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
2581 +{
2582 + assert(dst != NULL);
2583 + assert(src != NULL);
2584 +
2585 + memcpy(dst, src, sizeof(src[0]));
2586 +
2587 +#ifdef IS_CV
2588 + assert(dst ->op_type == IS_CONST ||
2589 + dst ->op_type == IS_VAR ||
2590 + dst ->op_type == IS_CV ||
2591 + dst ->op_type == IS_TMP_VAR ||
2592 + dst ->op_type == IS_UNUSED);
2593 +#else
2594 + assert(dst ->op_type == IS_CONST ||
2595 + dst ->op_type == IS_VAR ||
2596 + dst ->op_type == IS_TMP_VAR ||
2597 + dst ->op_type == IS_UNUSED);
2598 +#endif
2599 +
2600 + if (src->op_type == IS_CONST) {
2601 + if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
2602 + return NULL;
2603 + }
2604 + }
2605 +
2606 + return dst;
2607 +}
2608 +/* }}} */
2609 +
2610 +/* {{{ my_copy_zend_op */
2611 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
2612 +{
2613 + assert(dst != NULL);
2614 + assert(src != NULL);
2615 +
2616 + memcpy(dst, src, sizeof(src[0]));
2617 +
2618 + if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL
2619 + || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
2620 + || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
2621 + {
2622 + return NULL;
2623 + }
2624 +
2625 + return dst;
2626 +}
2627 +/* }}} */
2628 +
2629 +/* {{{ my_copy_function */
2630 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
2631 +{
2632 + int local_dst_alloc = 0;
2633 + TSRMLS_FETCH();
2634 +
2635 + assert(src != NULL);
2636 +
2637 + if(!dst) local_dst_alloc = 1;
2638 + CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
2639 +
2640 + switch (src->type) {
2641 + case ZEND_INTERNAL_FUNCTION:
2642 + case ZEND_OVERLOADED_FUNCTION:
2643 + /* shallow copy because op_array is internal */
2644 + dst->op_array = src->op_array;
2645 + break;
2646 +
2647 + case ZEND_USER_FUNCTION:
2648 + case ZEND_EVAL_CODE:
2649 + if(!apc_copy_op_array(&dst->op_array,
2650 + &src->op_array,
2651 + allocate, deallocate TSRMLS_CC)) {
2652 + if(local_dst_alloc) deallocate(dst);
2653 + return NULL;
2654 + }
2655 + break;
2656 +
2657 + default:
2658 + assert(0);
2659 + }
2660 +#ifdef ZEND_ENGINE_2
2661 + /*
2662 + * op_array bitwise copying overwrites what ever you modified
2663 + * before apc_copy_op_array - which is why this code is outside
2664 + * my_bitwise_copy_function.
2665 + */
2666 +
2667 + /* zend_do_inheritance will re-look this up, because the pointers
2668 + * in prototype are from a function table of another class. It just
2669 + * helps if that one is from EG(class_table).
2670 + */
2671 + dst->common.prototype = NULL;
2672 +
2673 + /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
2674 + * have to carry around a prototype. Thankfully zend_do_inheritance
2675 + * sets this properly as well
2676 + */
2677 + dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
2678 +#endif
2679 +
2680 +
2681 + return dst;
2682 +}
2683 +/* }}} */
2684 +
2685 +/* {{{ my_copy_function_entry */
2686 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2687 +{
2688 + int local_dst_alloc = 0;
2689 + assert(src != NULL);
2690 +
2691 + if (!dst) {
2692 + CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
2693 + local_dst_alloc = 1;
2694 + }
2695 +
2696 + /* Start with a bitwise copy */
2697 + memcpy(dst, src, sizeof(src[0]));
2698 +
2699 + dst->fname = NULL;
2700 +#ifdef ZEND_ENGINE_2
2701 + dst->arg_info = NULL;
2702 +#else
2703 + dst->func_arg_types = NULL;
2704 +#endif
2705 +
2706 + if (src->fname) {
2707 + if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
2708 + goto cleanup;
2709 + }
2710 + }
2711 +
2712 +#ifdef ZEND_ENGINE_2
2713 + if (src->arg_info) {
2714 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
2715 + src->arg_info,
2716 + src->num_args,
2717 + allocate,
2718 + deallocate))) {
2719 + goto cleanup;
2720 + }
2721 + }
2722 +#else
2723 + if (src->func_arg_types) {
2724 + if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
2725 + src->func_arg_types[0]+1,
2726 + allocate))) {
2727 + goto cleanup;
2728 + }
2729 + }
2730 +#endif
2731 +
2732 + return dst;
2733 +
2734 +cleanup:
2735 + if(dst->fname) deallocate(dst->fname);
2736 + if(local_dst_alloc) deallocate(dst);
2737 + return NULL;
2738 +}
2739 +/* }}} */
2740 +
2741 +#ifdef ZEND_ENGINE_2
2742 +/* {{{ my_copy_property_info */
2743 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2744 +{
2745 + int local_dst_alloc = 0;
2746 +
2747 + assert(src != NULL);
2748 +
2749 + if (!dst) {
2750 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2751 + local_dst_alloc = 1;
2752 + }
2753 +
2754 + /* Start with a bitwise copy */
2755 + memcpy(dst, src, sizeof(*src));
2756 +
2757 + dst->name = NULL;
2758 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2759 + dst->doc_comment = NULL;
2760 +#endif
2761 +
2762 + if (src->name) {
2763 + /* private members are stored inside property_info as a mangled
2764 + * string of the form:
2765 + * \0<classname>\0<membername>\0
2766 + */
2767 + if(!(dst->name =
2768 + apc_xmemcpy(src->name, src->name_length+1, allocate))) {
2769 + goto cleanup;
2770 + }
2771 + }
2772 +
2773 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2774 + if (src->doc_comment) {
2775 + if( !(dst->doc_comment =
2776 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
2777 + goto cleanup;
2778 + }
2779 + }
2780 +#endif
2781 +
2782 + return dst;
2783 +
2784 +cleanup:
2785 + if(dst->name) deallocate(dst->name);
2786 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2787 + if(dst->doc_comment) deallocate(dst->doc_comment);
2788 +#endif
2789 + if(local_dst_alloc) deallocate(dst);
2790 + return NULL;
2791 +}
2792 +/* }}} */
2793 +
2794 +/* {{{ my_copy_property_info_for_execution */
2795 +static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2796 +{
2797 + int local_dst_alloc = 0;
2798 +
2799 + assert(src != NULL);
2800 +
2801 + if (!dst) {
2802 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2803 + local_dst_alloc = 1;
2804 + }
2805 +
2806 + /* We need only a shallow copy */
2807 + memcpy(dst, src, sizeof(*src));
2808 +
2809 + return dst;
2810 +}
2811 +/* }}} */
2812 +
2813 +/* {{{ my_copy_arg_info_array */
2814 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, zend_arg_info* src, uint num_args, apc_malloc_t allocate, apc_free_t deallocate)
2815 +{
2816 + int local_dst_alloc = 0;
2817 + int i = 0;
2818 +
2819 +
2820 + if (!dst) {
2821 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
2822 + local_dst_alloc = 1;
2823 + }
2824 +
2825 + /* Start with a bitwise copy */
2826 + memcpy(dst, src, sizeof(*src)*num_args);
2827 +
2828 + for(i=0; i < num_args; i++) {
2829 + if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {
2830 + if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
2831 + if(local_dst_alloc) deallocate(dst);
2832 + return NULL;
2833 + }
2834 + }
2835 +
2836 + return dst;
2837 +}
2838 +/* }}} */
2839 +
2840 +/* {{{ my_copy_arg_info */
2841 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2842 +{
2843 + int local_dst_alloc = 0;
2844 +
2845 + assert(src != NULL);
2846 +
2847 + if (!dst) {
2848 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
2849 + local_dst_alloc = 1;
2850 + }
2851 +
2852 + /* Start with a bitwise copy */
2853 + memcpy(dst, src, sizeof(*src));
2854 +
2855 + dst->name = NULL;
2856 + dst->class_name = NULL;
2857 +
2858 + if (src->name) {
2859 + if(!(dst->name =
2860 + apc_xmemcpy(src->name, src->name_len+1, allocate))) {
2861 + goto cleanup;
2862 + }
2863 + }
2864 +
2865 + if (src->class_name) {
2866 + if(!(dst->class_name =
2867 + apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
2868 + goto cleanup;
2869 + }
2870 + }
2871 +
2872 + return dst;
2873 +
2874 +cleanup:
2875 + if(dst->name) deallocate(dst->name);
2876 + if(dst->class_name) deallocate(dst->name);
2877 + if(local_dst_alloc) deallocate(dst);
2878 + return NULL;
2879 +}
2880 +/* }}} */
2881 +#endif
2882 +
2883 +/* {{{ my_copy_class_entry */
2884 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2885 +{
2886 + int local_dst_alloc = 0;
2887 + int i = 0;
2888 +
2889 + assert(src != NULL);
2890 +
2891 + if (!dst) {
2892 + CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
2893 + local_dst_alloc = 1;
2894 + }
2895 +
2896 + /* Start with a bitwise copy */
2897 + memcpy(dst, src, sizeof(*src));
2898 +
2899 + dst->name = NULL;
2900 + dst->builtin_functions = NULL;
2901 + memset(&dst->function_table, 0, sizeof(dst->function_table));
2902 + memset(&dst->default_properties, 0, sizeof(dst->default_properties));
2903 +#ifndef ZEND_ENGINE_2
2904 + dst->refcount = NULL;
2905 +#else
2906 + dst->static_members = NULL;
2907 + dst->doc_comment = NULL;
2908 + dst->filename = NULL;
2909 + memset(&dst->properties_info, 0, sizeof(dst->properties_info));
2910 + memset(&dst->constants_table, 0, sizeof(dst->constants_table));
2911 + memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
2912 +#endif
2913 +
2914 + if (src->name) {
2915 + if(!(dst->name = apc_xstrdup(src->name, allocate))) {
2916 + goto cleanup;
2917 + }
2918 + }
2919 +
2920 +#ifndef ZEND_ENGINE_2
2921 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
2922 + sizeof(src->refcount[0]),
2923 + allocate))) {
2924 + goto cleanup;
2925 + }
2926 +#endif
2927 +
2928 + if(!(my_copy_hashtable_ex(&dst->function_table,
2929 + &src->function_table,
2930 + (ht_copy_fun_t) my_copy_function,
2931 + (ht_free_fun_t) my_free_function,
2932 + 0,
2933 + allocate, deallocate,
2934 + (ht_check_copy_fun_t) my_check_copy_function,
2935 + src))) {
2936 + goto cleanup;
2937 + }
2938 +
2939 +#ifdef ZEND_ENGINE_2
2940 +
2941 + /* the interfaces are populated at runtime using ADD_INTERFACE */
2942 + dst->interfaces = NULL;
2943 +
2944 + /* the current count includes inherited interfaces as well,
2945 + the real dynamic ones are the first <n> which are zero'd
2946 + out in zend_do_end_class_declaration */
2947 + for(i = 0 ; i < src->num_interfaces ; i++) {
2948 + if(src->interfaces[i])
2949 + {
2950 + dst->num_interfaces = i;
2951 + break;
2952 + }
2953 + }
2954 +
2955 + /* these will either be set inside my_fixup_hashtable or
2956 + * they will be copied out from parent inside zend_do_inheritance
2957 + */
2958 + dst->constructor = NULL;
2959 + dst->destructor = NULL;
2960 + dst->clone = NULL;
2961 + dst->__get = NULL;
2962 + dst->__set = NULL;
2963 + dst->__unset = NULL;
2964 + dst->__isset = NULL;
2965 + dst->__call = NULL;
2966 +#ifdef ZEND_ENGINE_2_2
2967 + dst->__tostring = NULL;
2968 +#endif
2969 +
2970 + /* unset function proxies */
2971 + dst->serialize_func = NULL;
2972 + dst->unserialize_func = NULL;
2973 +
2974 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
2975 +#endif
2976 +
2977 + if(!(my_copy_hashtable_ex(&dst->default_properties,
2978 + &src->default_properties,
2979 + (ht_copy_fun_t) my_copy_zval_ptr,
2980 + (ht_free_fun_t) my_free_zval_ptr,
2981 + 1,
2982 + allocate,deallocate,
2983 + (ht_check_copy_fun_t) my_check_copy_default_property,
2984 + src))) {
2985 + goto cleanup;
2986 + }
2987 +
2988 +#ifdef ZEND_ENGINE_2
2989 +
2990 + if(!(my_copy_hashtable_ex(&dst->properties_info,
2991 + &src->properties_info,
2992 + (ht_copy_fun_t) my_copy_property_info,
2993 + (ht_free_fun_t) my_free_property_info,
2994 + 0,
2995 + allocate, deallocate,
2996 + (ht_check_copy_fun_t) my_check_copy_property_info,
2997 + src))) {
2998 + goto cleanup;
2999 + }
3000 +
3001 +#ifdef ZEND_ENGINE_2_2
3002 + /* php5.2 introduced a scope attribute for property info */
3003 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
3004 +#endif
3005 +
3006 + if(!my_copy_hashtable_ex(&dst->default_static_members,
3007 + &src->default_static_members,
3008 + (ht_copy_fun_t) my_copy_zval_ptr,
3009 + (ht_free_fun_t) my_free_zval_ptr,
3010 + 1,
3011 + allocate, deallocate,
3012 + (ht_check_copy_fun_t) my_check_copy_static_member,
3013 + src,
3014 + &src->default_static_members)) {
3015 + goto cleanup;
3016 + }
3017 + if(src->static_members != &src->default_static_members)
3018 + {
3019 + if(!(dst->static_members = my_copy_hashtable_ex(NULL,
3020 + src->static_members,
3021 + (ht_copy_fun_t) my_copy_zval_ptr,
3022 + (ht_free_fun_t) my_free_zval_ptr,
3023 + 1,
3024 + allocate, deallocate,
3025 + (ht_check_copy_fun_t) my_check_copy_static_member,
3026 + src,
3027 + src->static_members))) {
3028 + goto cleanup;
3029 + }
3030 + }
3031 + else
3032 + {
3033 + dst->static_members = &dst->default_static_members;
3034 + }
3035 +
3036 + if(!(my_copy_hashtable(&dst->constants_table,
3037 + &src->constants_table,
3038 + (ht_copy_fun_t) my_copy_zval_ptr,
3039 + (ht_free_fun_t) my_free_zval_ptr,
3040 + 1,
3041 + allocate, deallocate))) {
3042 + goto cleanup;
3043 + }
3044 +
3045 + if (src->doc_comment) {
3046 + if(!(dst->doc_comment =
3047 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3048 + goto cleanup;
3049 + }
3050 + }
3051 +#endif
3052 +
3053 + if (src->builtin_functions) {
3054 + int i, n;
3055 +
3056 + for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
3057 +
3058 + if(!(dst->builtin_functions =
3059 + (zend_function_entry*)
3060 + allocate((n + 1) * sizeof(zend_function_entry)))) {
3061 + goto cleanup;
3062 + }
3063 +
3064 +
3065 + for (i = 0; i < n; i++) {
3066 + if(!my_copy_function_entry(&dst->builtin_functions[i],
3067 + &src->builtin_functions[i],
3068 + allocate, deallocate)) {
3069 + int ii;
3070 +
3071 + for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
3072 + goto cleanup;
3073 + }
3074 + }
3075 + dst->builtin_functions[n].fname = NULL;
3076 + }
3077 +
3078 +#ifdef ZEND_ENGINE_2
3079 + if (src->filename) {
3080 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3081 + goto cleanup;
3082 + }
3083 + }
3084 +#endif
3085 +
3086 + return dst;
3087 +
3088 +
3089 +cleanup:
3090 + if(dst->name) deallocate(dst->name);
3091 +#ifdef ZEND_ENGINE_2
3092 + if(dst->doc_comment) deallocate(dst->doc_comment);
3093 + if(dst->filename) deallocate(dst->filename);
3094 +#else
3095 + if(dst->refcount) deallocate(dst->refcount);
3096 +#endif
3097 +
3098 + if(dst->builtin_functions) deallocate(dst->builtin_functions);
3099 + if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
3100 + if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3101 +
3102 +#ifdef ZEND_ENGINE_2
3103 + if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
3104 + if(dst->default_static_members.arBuckets)
3105 + {
3106 + my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3107 + }
3108 + if(dst->static_members && dst->static_members != &(dst->default_static_members))
3109 + {
3110 + my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3111 + deallocate(dst->static_members);
3112 + }
3113 + if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3114 +#endif
3115 + if(local_dst_alloc) deallocate(dst);
3116 +
3117 + return NULL;
3118 +}
3119 +/* }}} */
3120 +
3121 +/* {{{ my_copy_hashtable */
3122 +static HashTable* my_copy_hashtable_ex(HashTable* dst,
3123 + HashTable* src,
3124 + ht_copy_fun_t copy_fn,
3125 + ht_free_fun_t free_fn,
3126 + int holds_ptrs,
3127 + apc_malloc_t allocate,
3128 + apc_free_t deallocate,
3129 + ht_check_copy_fun_t check_fn,
3130 + ...)
3131 +{
3132 + Bucket* curr = NULL;
3133 + Bucket* prev = NULL;
3134 + Bucket* newp = NULL;
3135 + int first = 1;
3136 + int local_dst_alloc = 0;
3137 + int index = 0;
3138 +
3139 + assert(src != NULL);
3140 +
3141 + if (!dst) {
3142 + CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
3143 + local_dst_alloc = 1;
3144 + }
3145 +
3146 + memcpy(dst, src, sizeof(src[0]));
3147 +
3148 + /* allocate buckets for the new hashtable */
3149 + if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
3150 + if(local_dst_alloc) deallocate(dst);
3151 + return NULL;
3152 + }
3153 +
3154 + memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
3155 + dst->pInternalPointer = NULL;
3156 + dst->pListHead = NULL;
3157 +
3158 + for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
3159 + int n = curr->h % dst->nTableSize;
3160 +
3161 + if(check_fn) {
3162 + va_list args;
3163 + va_start(args, check_fn);
3164 +
3165 + /* Call the check_fn to see if the current bucket
3166 + * needs to be copied out
3167 + */
3168 + if(!check_fn(curr, args)) {
3169 + dst->nNumOfElements--;
3170 + continue;
3171 + }
3172 +
3173 + va_end(args);
3174 + }
3175 +
3176 + /* create a copy of the bucket 'curr' */
3177 + if(!(newp =
3178 + (Bucket*) apc_xmemcpy(curr,
3179 + sizeof(Bucket) + curr->nKeyLength - 1,
3180 + allocate))) {
3181 + goto cleanup;
3182 + }
3183 +
3184 + /* insert 'newp' into the linked list at its hashed index */
3185 + if (dst->arBuckets[n]) {
3186 + newp->pNext = dst->arBuckets[n];
3187 + newp->pLast = NULL;
3188 + newp->pNext->pLast = newp;
3189 + }
3190 + else {
3191 + newp->pNext = newp->pLast = NULL;
3192 + }
3193 +
3194 + dst->arBuckets[n] = newp;
3195 +
3196 + /* copy the bucket data using our 'copy_fn' callback function */
3197 + if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
3198 + goto cleanup;
3199 + }
3200 +
3201 + if (holds_ptrs) {
3202 + memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
3203 + }
3204 + else {
3205 + newp->pDataPtr = NULL;
3206 + }
3207 +
3208 + /* insert 'newp' into the table-thread linked list */
3209 + newp->pListLast = prev;
3210 + newp->pListNext = NULL;
3211 +
3212 + if (prev) {
3213 + prev->pListNext = newp;
3214 + }
3215 +
3216 + if (first) {
3217 + dst->pListHead = newp;
3218 + first = 0;
3219 + }
3220 +
3221 + prev = newp;
3222 + }
3223 +
3224 + dst->pListTail = newp;
3225 +
3226 + return dst;
3227 +
3228 + cleanup:
3229 + for(index = 0; index < dst->nTableSize; index++)
3230 + {
3231 + curr = dst->arBuckets[index];
3232 + while(curr != NULL)
3233 + {
3234 + Bucket * tmp = curr;
3235 + if(curr->pData && free_fn)
3236 + {
3237 + free_fn(curr->pData, deallocate);
3238 + }
3239 + curr = curr->pNext;
3240 + deallocate(tmp);
3241 + }
3242 + }
3243 + deallocate(dst->arBuckets);
3244 + if(local_dst_alloc) deallocate(dst);
3245 + else dst->arBuckets = NULL;
3246 +
3247 + return NULL;
3248 +}
3249 +/* }}} */
3250 +
3251 +/* {{{ my_copy_static_variables */
3252 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
3253 +{
3254 + if (src->static_variables == NULL) {
3255 + return NULL;
3256 + }
3257 +
3258 + return my_copy_hashtable(NULL,
3259 + src->static_variables,
3260 + (ht_copy_fun_t) my_copy_zval_ptr,
3261 + (ht_free_fun_t) my_free_zval_ptr,
3262 + 1,
3263 + allocate, deallocate);
3264 +}
3265 +/* }}} */
3266 +
3267 +/* {{{ apc_copy_zval */
3268 +zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
3269 +{
3270 + int local_dst_alloc = 0;
3271 + assert(src != NULL);
3272 +
3273 + if (!dst) {
3274 + CHECK(dst = (zval*) allocate(sizeof(zval)));
3275 + local_dst_alloc = 1;
3276 + }
3277 +
3278 + dst = my_copy_zval(dst, src, allocate, deallocate);
3279 + if(!dst) {
3280 + if(local_dst_alloc) deallocate(dst);
3281 + return NULL;
3282 + }
3283 + return dst;
3284 +}
3285 +/* }}} */
3286 +
3287 +#ifdef ZEND_ENGINE_2
3288 +/* {{{ apc_fixup_op_array_jumps */
3289 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
3290 +{
3291 + int i;
3292 +
3293 + for (i=0; i < dst->last; ++i) {
3294 + zend_op *zo = &(dst->opcodes[i]);
3295 + /*convert opline number to jump address*/
3296 + switch (zo->opcode) {
3297 + case ZEND_JMP:
3298 + /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
3299 + zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
3300 + break;
3301 + case ZEND_JMPZ:
3302 + case ZEND_JMPNZ:
3303 + case ZEND_JMPZ_EX:
3304 + case ZEND_JMPNZ_EX:
3305 + zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
3306 + break;
3307 + default:
3308 + break;
3309 + }
3310 + }
3311 +}
3312 +/* }}} */
3313 +#endif
3314 +
3315 +/* {{{ apc_copy_op_array */
3316 +zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3317 +{
3318 + int i;
3319 + int local_dst_alloc = 0;
3320 + apc_fileinfo_t fileinfo;
3321 + char canon_path[MAXPATHLEN];
3322 + char *fullpath = NULL;
3323 +#ifdef ZEND_ENGINE_2
3324 + apc_opflags_t * flags = NULL;
3325 +#endif
3326 +
3327 + assert(src != NULL);
3328 +
3329 + if (!dst) {
3330 + CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
3331 + local_dst_alloc = 1;
3332 + }
3333 +
3334 + if(APCG(apc_optimize_function)) {
3335 + APCG(apc_optimize_function)(src TSRMLS_CC);
3336 + }
3337 +
3338 + /* start with a bitwise copy of the array */
3339 + memcpy(dst, src, sizeof(src[0]));
3340 +
3341 + dst->function_name = NULL;
3342 + dst->filename = NULL;
3343 + dst->refcount = NULL;
3344 + dst->opcodes = NULL;
3345 + dst->brk_cont_array = NULL;
3346 + dst->static_variables = NULL;
3347 +#ifdef ZEND_ENGINE_2
3348 + dst->try_catch_array = NULL;
3349 + dst->arg_info = NULL;
3350 + dst->doc_comment = NULL;
3351 +#else
3352 + dst->arg_types = NULL;
3353 +#endif
3354 +#ifdef ZEND_ENGINE_2_1
3355 + dst->vars = NULL;
3356 +#endif
3357 +
3358 + /* copy the arg types array (if set) */
3359 +#ifdef ZEND_ENGINE_2
3360 + if (src->arg_info) {
3361 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
3362 + src->arg_info,
3363 + src->num_args,
3364 + allocate,
3365 + deallocate))) {
3366 + goto cleanup;
3367 + }
3368 + }
3369 +#else
3370 + if (src->arg_types) {
3371 + if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
3372 + sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
3373 + allocate))) {
3374 + goto cleanup;
3375 + }
3376 + }
3377 +#endif
3378 +
3379 + if (src->function_name) {
3380 + if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
3381 + goto cleanup;
3382 + }
3383 + }
3384 + if (src->filename) {
3385 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3386 + goto cleanup;
3387 + }
3388 + }
3389 +
3390 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
3391 + sizeof(src->refcount[0]),
3392 + allocate))) {
3393 + goto cleanup;
3394 + }
3395 +
3396 + /* deep-copy the opcodes */
3397 + if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
3398 + goto cleanup;
3399 + }
3400 +
3401 +#ifdef ZEND_ENGINE_2
3402 + if(APCG(reserved_offset) != -1) {
3403 + /* Insanity alert: the void* pointer is cast into an apc_opflags_t
3404 + * struct. apc_zend_init() checks to ensure that it fits in a void* */
3405 + flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
3406 + memset(flags, 0, sizeof(apc_opflags_t));
3407 + /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
3408 + }
3409 +#endif
3410 +
3411 + for (i = 0; i < src->last; i++) {
3412 +#ifdef ZEND_ENGINE_2
3413 + zend_op *zo = &(src->opcodes[i]);
3414 + /* a lot of files are merely constant arrays with no jumps */
3415 + switch (zo->opcode) {
3416 + case ZEND_JMP:
3417 + case ZEND_JMPZ:
3418 + case ZEND_JMPNZ:
3419 + case ZEND_JMPZ_EX:
3420 + case ZEND_JMPNZ_EX:
3421 + if(flags != NULL) {
3422 + flags->has_jumps = 1;
3423 + }
3424 + break;
3425 +#ifdef ZEND_ENGINE_2
3426 + /* auto_globals_jit was not in php-4.3.* */
3427 + case ZEND_FETCH_R:
3428 + case ZEND_FETCH_W:
3429 + case ZEND_FETCH_IS:
3430 + case ZEND_FETCH_FUNC_ARG:
3431 + if(PG(auto_globals_jit) && flags != NULL)
3432 + {
3433 + /* The fetch is only required if auto_globals_jit=1 */
3434 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
3435 + zo->op1.op_type == IS_CONST &&
3436 + zo->op1.u.constant.type == IS_STRING) {
3437 + znode * varname = &zo->op1;
3438 + if (varname->u.constant.value.str.val[0] == '_') {
3439 +#define SET_IF_AUTOGLOBAL(member) \
3440 + if(!strcmp(varname->u.constant.value.str.val, #member)) \
3441 + flags->member = 1 /* no ';' here */
3442 + SET_IF_AUTOGLOBAL(_GET);
3443 + else SET_IF_AUTOGLOBAL(_POST);
3444 + else SET_IF_AUTOGLOBAL(_COOKIE);
3445 + else SET_IF_AUTOGLOBAL(_SERVER);
3446 + else SET_IF_AUTOGLOBAL(_ENV);
3447 + else SET_IF_AUTOGLOBAL(_FILES);
3448 + else SET_IF_AUTOGLOBAL(_REQUEST);
3449 + else if(zend_is_auto_global(
3450 + varname->u.constant.value.str.val,
3451 + varname->u.constant.value.str.len
3452 + TSRMLS_CC))
3453 + {
3454 + flags->unknown_global = 1;
3455 + }
3456 + }
3457 + }
3458 + }
3459 + break;
3460 +#endif
3461 + case ZEND_RECV_INIT:
3462 + if(zo->op2.op_type == IS_CONST &&
3463 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
3464 + if(flags != NULL) {
3465 + flags->deep_copy = 1;
3466 + }
3467 + }
3468 + break;
3469 + default:
3470 + if((zo->op1.op_type == IS_CONST &&
3471 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
3472 + (zo->op2.op_type == IS_CONST &&
3473 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
3474 + if(flags != NULL) {
3475 + flags->deep_copy = 1;
3476 + }
3477 + }
3478 + break;
3479 + }
3480 +#endif
3481 + if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
3482 + int ii;
3483 + for(ii = i-1; ii>=0; ii--) {
3484 + my_destroy_zend_op(dst->opcodes+ii, deallocate);
3485 + }
3486 + goto cleanup;
3487 + }
3488 +#ifdef ZEND_ENGINE_2
3489 +/* This code breaks apc's rule#1 - cache what you compile */
3490 + if(APCG(fpstat)==0) {
3491 + if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
3492 + (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
3493 + /* constant includes */
3494 + if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) {
3495 + if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
3496 + if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
3497 + /* everything has to go through a realpath() */
3498 + zend_op *dzo = &(dst->opcodes[i]);
3499 + deallocate(dzo->op1.u.constant.value.str.val);
3500 + dzo->op1.u.constant.value.str.len = strlen(fullpath);
3501 + dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
3502 + }
3503 + }
3504 + }
3505 + }
3506 + }
3507 +#endif
3508 + }
3509 +
3510 +#ifdef ZEND_ENGINE_2
3511 + if(flags == NULL || flags->has_jumps) {
3512 + apc_fixup_op_array_jumps(dst,src);
3513 + }
3514 +#endif
3515 +
3516 + /* copy the break-continue array */
3517 + if (src->brk_cont_array) {
3518 + if(!(dst->brk_cont_array =
3519 + apc_xmemcpy(src->brk_cont_array,
3520 + sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
3521 + allocate))) {
3522 + goto cleanup_opcodes;
3523 + }
3524 + }
3525 +
3526 + /* copy the table of static variables */
3527 + if (src->static_variables) {
3528 + if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
3529 + goto cleanup_opcodes;
3530 + }
3531 + }
3532 +
3533 +#ifdef ZEND_ENGINE_2
3534 + if (src->try_catch_array) {
3535 + if(!(dst->try_catch_array =
3536 + apc_xmemcpy(src->try_catch_array,
3537 + sizeof(src->try_catch_array[0]) * src->last_try_catch,
3538 + allocate))) {
3539 + goto cleanup_opcodes;
3540 + }
3541 + }
3542 +#endif
3543 +
3544 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
3545 + if (src->vars) {
3546 + if(!(dst->vars = apc_xmemcpy(src->vars,
3547 + sizeof(src->vars[0]) * src->last_var,
3548 + allocate))) {
3549 + goto cleanup_opcodes;
3550 + }
3551 +
3552 + for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
3553 +
3554 + for(i = 0; i < src->last_var; i++) {
3555 + if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
3556 + src->vars[i].name_len + 1,
3557 + allocate))) {
3558 + dst->last_var = i;
3559 + goto cleanup_opcodes;
3560 + }
3561 + }
3562 + }
3563 +#endif
3564 +
3565 +#ifdef ZEND_ENGINE_2
3566 + if (src->doc_comment) {
3567 + if (!(dst->doc_comment
3568 + = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3569 + goto cleanup_opcodes;
3570 + }
3571 + }
3572 +#endif
3573 +
3574 + return dst;
3575 +
3576 +cleanup_opcodes:
3577 + if(dst->opcodes) {
3578 + for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
3579 + }
3580 +cleanup:
3581 + if(dst->function_name) deallocate(dst->function_name);
3582 + if(dst->refcount) deallocate(dst->refcount);
3583 + if(dst->filename) deallocate(dst->filename);
3584 +#ifdef ZEND_ENGINE_2
3585 + if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
3586 + if(dst->try_catch_array) deallocate(dst->try_catch_array);
3587 + if(dst->doc_comment) deallocate(dst->doc_comment);
3588 +#else
3589 + if(dst->arg_types) deallocate(dst->arg_types);
3590 +#endif
3591 + if(dst->opcodes) deallocate(dst->opcodes);
3592 + if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
3593 + if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
3594 +#ifdef ZEND_ENGINE_2_1
3595 + if (dst->vars) {
3596 + for(i=0; i < dst->last_var; i++) {
3597 + if(dst->vars[i].name) deallocate(dst->vars[i].name);
3598 + }
3599 + deallocate(dst->vars);
3600 + }
3601 +#endif
3602 + if(local_dst_alloc) deallocate(dst);
3603 + return NULL;
3604 +}
3605 +/* }}} */
3606 +
3607 +/* {{{ apc_copy_new_functions */
3608 +apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3609 +{
3610 + apc_function_t* array;
3611 + int new_count; /* number of new functions in table */
3612 + int i;
3613 +
3614 + new_count = zend_hash_num_elements(CG(function_table)) - old_count;
3615 + assert(new_count >= 0);
3616 +
3617 + CHECK(array =
3618 + (apc_function_t*)
3619 + allocate(sizeof(apc_function_t) * (new_count+1)));
3620 +
3621 + if (new_count == 0) {
3622 + array[0].function = NULL;
3623 + return array;
3624 + }
3625 +
3626 + /* Skip the first `old_count` functions in the table */
3627 + zend_hash_internal_pointer_reset(CG(function_table));
3628 + for (i = 0; i < old_count; i++) {
3629 + zend_hash_move_forward(CG(function_table));
3630 + }
3631 +
3632 + /* Add the next `new_count` functions to our array */
3633 + for (i = 0; i < new_count; i++) {
3634 + char* key;
3635 + uint key_size;
3636 + zend_function* fun;
3637 +
3638 + zend_hash_get_current_key_ex(CG(function_table),
3639 + &key,
3640 + &key_size,
3641 + NULL,
3642 + 0,
3643 + NULL);
3644 +
3645 + zend_hash_get_current_data(CG(function_table), (void**) &fun);
3646 +
3647 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3648 + int ii;
3649 + for(ii=i-1; ii>=0; ii--) {
3650 + deallocate(array[ii].name);
3651 + my_free_function(array[ii].function, deallocate);
3652 + }
3653 + deallocate(array);
3654 + return NULL;
3655 + }
3656 + array[i].name_len = (int) key_size-1;
3657 + if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
3658 + int ii;
3659 + deallocate(array[i].name);
3660 + for(ii=i-1; ii>=0; ii--) {
3661 + deallocate(array[ii].name);
3662 + my_free_function(array[ii].function, deallocate);
3663 + }
3664 + deallocate(array);
3665 + return NULL;
3666 + }
3667 + zend_hash_move_forward(CG(function_table));
3668 + }
3669 +
3670 + array[i].function = NULL;
3671 + return array;
3672 +}
3673 +/* }}} */
3674 +
3675 +/* {{{ apc_copy_new_classes */
3676 +apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3677 +{
3678 + apc_class_t* array;
3679 + int new_count; /* number of new classes in table */
3680 + int i;
3681 +
3682 + new_count = zend_hash_num_elements(CG(class_table)) - old_count;
3683 + assert(new_count >= 0);
3684 +
3685 + CHECK(array =
3686 + (apc_class_t*)
3687 + allocate(sizeof(apc_class_t)*(new_count+1)));
3688 +
3689 + if (new_count == 0) {
3690 + array[0].class_entry = NULL;
3691 + return array;
3692 + }
3693 +
3694 + /* Skip the first `old_count` classes in the table */
3695 + zend_hash_internal_pointer_reset(CG(class_table));
3696 + for (i = 0; i < old_count; i++) {
3697 + zend_hash_move_forward(CG(class_table));
3698 + }
3699 +
3700 + /* Add the next `new_count` classes to our array */
3701 + for (i = 0; i < new_count; i++) {
3702 + char* key;
3703 + uint key_size;
3704 + zend_class_entry* elem = NULL;
3705 +
3706 + array[i].class_entry = NULL;
3707 +
3708 + zend_hash_get_current_key_ex(CG(class_table),
3709 + &key,
3710 + &key_size,
3711 + NULL,
3712 + 0,
3713 + NULL);
3714 +
3715 + zend_hash_get_current_data(CG(class_table), (void**) &elem);
3716 +
3717 +
3718 +#ifdef ZEND_ENGINE_2
3719 + elem = *((zend_class_entry**)elem);
3720 +#endif
3721 +
3722 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3723 + int ii;
3724 +
3725 + for(ii=i-1; ii>=0; ii--) {
3726 + deallocate(array[ii].name);
3727 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3728 + deallocate(array[ii].class_entry);
3729 + }
3730 + deallocate(array);
3731 + return NULL;
3732 + }
3733 + array[i].name_len = (int) key_size-1;
3734 + if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
3735 + int ii;
3736 +
3737 + deallocate(array[i].name);
3738 + for(ii=i-1; ii>=0; ii--) {
3739 + deallocate(array[ii].name);
3740 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3741 + deallocate(array[ii].class_entry);
3742 + }
3743 + deallocate(array);
3744 + return NULL;
3745 + }
3746 +
3747 + /*
3748 + * If the class has a pointer to its parent class, save the parent
3749 + * name so that we can enable compile-time inheritance when we reload
3750 + * the child class; otherwise, set the parent name to null and scan
3751 + * the op_array to determine if this class inherits from some base
3752 + * class at execution-time.
3753 + */
3754 +
3755 + if (elem->parent) {
3756 + if(!(array[i].parent_name =
3757 + apc_xstrdup(elem->parent->name, allocate))) {
3758 + int ii;
3759 +
3760 + for(ii=i; ii>=0; ii--) {
3761 + deallocate(array[ii].name);
3762 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3763 + deallocate(array[ii].class_entry);
3764 + if(ii==i) continue;
3765 + if(array[ii].parent_name) deallocate(array[ii].parent_name);
3766 + }
3767 + deallocate(array);
3768 + return NULL;
3769 + }
3770 + array[i].is_derived = 1;
3771 + }
3772 + else {
3773 + array[i].parent_name = NULL;
3774 + array[i].is_derived = is_derived_class(op_array, key, key_size);
3775 + }
3776 +
3777 + zend_hash_move_forward(CG(class_table));
3778 + }
3779 +
3780 + array[i].class_entry = NULL;
3781 + return array;
3782 +}
3783 +/* }}} */
3784 +
3785 +/* {{{ my_destroy_zval_ptr */
3786 +static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
3787 +{
3788 + assert(src != NULL);
3789 + if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
3790 + deallocate(src[0]);
3791 + }
3792 +}
3793 +/* }}} */
3794 +
3795 +/* {{{ my_destroy_zval */
3796 +static int my_destroy_zval(zval* src, apc_free_t deallocate)
3797 +{
3798 + zval **tmp;
3799 + TSRMLS_FETCH();
3800 +
3801 + switch (src->type & ~IS_CONSTANT_INDEX) {
3802 + case IS_RESOURCE:
3803 + case IS_BOOL:
3804 + case IS_LONG:
3805 + case IS_DOUBLE:
3806 + case IS_NULL:
3807 + break;
3808 +
3809 + case IS_CONSTANT:
3810 + case IS_STRING:
3811 +#ifndef ZEND_ENGINE_2
3812 + case FLAG_IS_BC:
3813 +#endif
3814 + deallocate(src->value.str.val);
3815 + break;
3816 +
3817 + case IS_ARRAY:
3818 +
3819 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
3820 + if(APCG(copied_zvals)) {
3821 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3822 + (*tmp)->refcount--;
3823 + return FAILURE;
3824 + }
3825 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
3826 + }
3827 + /* fall through */
3828 +
3829 + case IS_CONSTANT_ARRAY:
3830 + my_free_hashtable(src->value.ht,
3831 + (ht_free_fun_t) my_free_zval_ptr,
3832 + deallocate);
3833 + break;
3834 +
3835 + case IS_OBJECT:
3836 +#ifndef ZEND_ENGINE_2
3837 + my_destroy_class_entry(src->value.obj.ce, deallocate);
3838 + deallocate(src->value.obj.ce);
3839 + my_free_hashtable(src->value.obj.properties,
3840 + (ht_free_fun_t) my_free_zval_ptr,
3841 + deallocate);
3842 +#endif
3843 + break;
3844 +
3845 + default:
3846 + assert(0);
3847 + }
3848 +
3849 + return SUCCESS;
3850 +}
3851 +/* }}} */
3852 +
3853 +/* {{{ my_destroy_znode */
3854 +static void my_destroy_znode(znode* src, apc_free_t deallocate)
3855 +{
3856 + if (src->op_type == IS_CONST) {
3857 + my_destroy_zval(&src->u.constant, deallocate);
3858 + }
3859 +}
3860 +/* }}} */
3861 +
3862 +/* {{{ my_destroy_zend_op */
3863 +static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
3864 +{
3865 + my_destroy_znode(&src->result, deallocate);
3866 + my_destroy_znode(&src->op1, deallocate);
3867 + my_destroy_znode(&src->op2, deallocate);
3868 +}
3869 +/* }}} */
3870 +
3871 +/* {{{ my_destroy_function */
3872 +static void my_destroy_function(zend_function* src, apc_free_t deallocate)
3873 +{
3874 + assert(src != NULL);
3875 +
3876 + switch (src->type) {
3877 + case ZEND_INTERNAL_FUNCTION:
3878 + case ZEND_OVERLOADED_FUNCTION:
3879 + break;
3880 +
3881 + case ZEND_USER_FUNCTION:
3882 + case ZEND_EVAL_CODE:
3883 + my_destroy_op_array(&src->op_array, deallocate);
3884 + break;
3885 +
3886 + default:
3887 + assert(0);
3888 + }
3889 +}
3890 +/* }}} */
3891 +
3892 +/* {{{ my_destroy_function_entry */
3893 +static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
3894 +{
3895 + assert(src != NULL);
3896 +
3897 + deallocate(src->fname);
3898 +#ifdef ZEND_ENGINE_2
3899 + if (src->arg_info) {
3900 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
3901 + }
3902 +#else
3903 + if (src->func_arg_types) {
3904 + deallocate(src->func_arg_types);
3905 + }
3906 +#endif
3907 +}
3908 +/* }}} */
3909 +
3910 +#ifdef ZEND_ENGINE_2
3911 +/* {{{ my_destroy_property_info*/
3912 +static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
3913 +{
3914 + assert(src != NULL);
3915 +
3916 + deallocate(src->name);
3917 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
3918 + if(src->doc_comment) deallocate(src->doc_comment);
3919 +#endif
3920 +}
3921 +/* }}} */
3922 +
3923 +/* {{{ my_destroy_arg_info_array */
3924 +static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
3925 +{
3926 + int i = 0;
3927 +
3928 + assert(src != NULL);
3929 +
3930 + for(i=0; i < num_args; i++) {
3931 + my_destroy_arg_info(&src[i], deallocate);
3932 + }
3933 +}
3934 +/* }}} */
3935 +
3936 +/* {{{ my_destroy_arg_info */
3937 +static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
3938 +{
3939 + assert(src != NULL);
3940 +
3941 + deallocate(src->name);
3942 + deallocate(src->class_name);
3943 +}
3944 +/* }}} */
3945 +#endif
3946 +
3947 +/* {{{ my_destroy_class_entry */
3948 +static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
3949 +{
3950 + uint i;
3951 +
3952 + assert(src != NULL);
3953 +
3954 + deallocate(src->name);
3955 +#ifndef ZEND_ENGINE_2
3956 + deallocate(src->refcount);
3957 +#else
3958 + if(src->doc_comment) deallocate(src->doc_comment);
3959 + if(src->filename) deallocate(src->filename);
3960 +#endif
3961 +
3962 + my_destroy_hashtable(&src->function_table,
3963 + (ht_free_fun_t) my_free_function,
3964 + deallocate);
3965 +
3966 + my_destroy_hashtable(&src->default_properties,
3967 + (ht_free_fun_t) my_free_zval_ptr,
3968 + deallocate);
3969 +
3970 +#ifdef ZEND_ENGINE_2
3971 + my_destroy_hashtable(&src->properties_info,
3972 + (ht_free_fun_t) my_free_property_info,
3973 + deallocate);
3974 + if(src->static_members)
3975 + {
3976 + my_destroy_hashtable(src->static_members,
3977 + (ht_free_fun_t) my_free_zval_ptr,
3978 + deallocate);
3979 + if(src->static_members != &(src->default_static_members))
3980 + {
3981 + deallocate(src->static_members);
3982 + }
3983 + }
3984 +
3985 + my_destroy_hashtable(&src->constants_table,
3986 + (ht_free_fun_t) my_free_zval_ptr,
3987 + deallocate);
3988 +#endif
3989 +
3990 + if (src->builtin_functions) {
3991 + for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
3992 + my_destroy_function_entry(&src->builtin_functions[i], deallocate);
3993 + }
3994 + deallocate(src->builtin_functions);
3995 + }
3996 +}
3997 +/* }}} */
3998 +
3999 +/* {{{ my_destroy_hashtable */
4000 +static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4001 +{
4002 + int i;
4003 +
4004 + assert(src != NULL);
4005 +
4006 + for (i = 0; i < src->nTableSize; i++) {
4007 + Bucket* p = src->arBuckets[i];
4008 + while (p != NULL) {
4009 + Bucket* q = p;
4010 + p = p->pNext;
4011 + free_fn(q->pData, deallocate);
4012 + deallocate(q);
4013 + }
4014 + }
4015 +
4016 + deallocate(src->arBuckets);
4017 +}
4018 +/* }}} */
4019 +
4020 +/* {{{ my_destroy_op_array */
4021 +static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
4022 +{
4023 + int i;
4024 +
4025 + assert(src != NULL);
4026 +
4027 +#ifdef ZEND_ENGINE_2
4028 + if (src->arg_info) {
4029 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
4030 + }
4031 +#else
4032 + if (src->arg_types) {
4033 + deallocate(src->arg_types);
4034 + }
4035 +#endif
4036 +
4037 + deallocate(src->function_name);
4038 + deallocate(src->filename);
4039 + deallocate(src->refcount);
4040 +
4041 + for (i = 0; i < src->last; i++) {
4042 + my_destroy_zend_op(src->opcodes + i, deallocate);
4043 + }
4044 + deallocate(src->opcodes);
4045 +
4046 + if (src->brk_cont_array) {
4047 + deallocate(src->brk_cont_array);
4048 + }
4049 +
4050 + if (src->static_variables) {
4051 + my_free_hashtable(src->static_variables,
4052 + (ht_free_fun_t) my_free_zval_ptr,
4053 + deallocate);
4054 + }
4055 +
4056 +#ifdef ZEND_ENGINE_2_1
4057 + if (src->vars) {
4058 + for(i=0; i < src->last_var; i++) {
4059 + if(src->vars[i].name) deallocate(src->vars[i].name);
4060 + }
4061 + deallocate(src->vars);
4062 + }
4063 +#endif
4064 +#ifdef ZEND_ENGINE_2
4065 + if(src->try_catch_array) {
4066 + deallocate(src->try_catch_array);
4067 + }
4068 + if (src->doc_comment) {
4069 + deallocate(src->doc_comment);
4070 + }
4071 +#endif
4072 +}
4073 +/* }}} */
4074 +
4075 +/* {{{ my_free_zval_ptr */
4076 +static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
4077 +{
4078 + my_destroy_zval_ptr(src, deallocate);
4079 + deallocate(src);
4080 +}
4081 +/* }}} */
4082 +
4083 +#ifdef ZEND_ENGINE_2
4084 +/* {{{ my_free_property_info */
4085 +static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
4086 +{
4087 + my_destroy_property_info(src, deallocate);
4088 + deallocate(src);
4089 +}
4090 +/* }}} */
4091 +
4092 +/* {{{ my_free_arg_info_array */
4093 +static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
4094 +{
4095 + my_destroy_arg_info_array(src, num_args, deallocate);
4096 + deallocate(src);
4097 +}
4098 +/* }}} */
4099 +
4100 +/* {{{ my_free_arg_info */
4101 +static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
4102 +{
4103 + my_destroy_arg_info(src, deallocate);
4104 + deallocate(src);
4105 +}
4106 +/* }}} */
4107 +#endif
4108 +
4109 +/* {{{ my_free_function */
4110 +static void my_free_function(zend_function* src, apc_free_t deallocate)
4111 +{
4112 + my_destroy_function(src, deallocate);
4113 + deallocate(src);
4114 +}
4115 +/* }}} */
4116 +
4117 +/* {{{ my_free_hashtable */
4118 +static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4119 +{
4120 + my_destroy_hashtable(src, free_fn, deallocate);
4121 + deallocate(src);
4122 +}
4123 +/* }}} */
4124 +
4125 +/* {{{ apc_free_op_array */
4126 +void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
4127 +{
4128 + if (src != NULL) {
4129 + my_destroy_op_array(src, deallocate);
4130 + deallocate(src);
4131 + }
4132 +}
4133 +/* }}} */
4134 +
4135 +/* {{{ apc_free_functions */
4136 +void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
4137 +{
4138 + int i;
4139 +
4140 + if (src != NULL) {
4141 + for (i = 0; src[i].function != NULL; i++) {
4142 + deallocate(src[i].name);
4143 + my_destroy_function(src[i].function, deallocate);
4144 + deallocate(src[i].function);
4145 + }
4146 + deallocate(src);
4147 + }
4148 +}
4149 +/* }}} */
4150 +
4151 +/* {{{ apc_free_classes */
4152 +void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
4153 +{
4154 + int i;
4155 +
4156 + if (src != NULL) {
4157 + for (i = 0; src[i].class_entry != NULL; i++) {
4158 + deallocate(src[i].name);
4159 + deallocate(src[i].parent_name);
4160 + my_destroy_class_entry(src[i].class_entry, deallocate);
4161 + deallocate(src[i].class_entry);
4162 + }
4163 + deallocate(src);
4164 + }
4165 +}
4166 +/* }}} */
4167 +
4168 +/* {{{ apc_free_zval */
4169 +void apc_free_zval(zval* src, apc_free_t deallocate)
4170 +{
4171 + if (src != NULL) {
4172 + if(my_destroy_zval(src, deallocate) == SUCCESS) {
4173 + deallocate(src);
4174 + }
4175 + }
4176 +}
4177 +/* }}} */
4178 +
4179 +
4180 +/* Used only by my_prepare_op_array_for_execution */
4181 +#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
4182 + /* The fetch is only required if auto_globals_jit=1 */ \
4183 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
4184 + zo->op1.op_type == IS_CONST && \
4185 + zo->op1.u.constant.type == IS_STRING && \
4186 + zo->op1.u.constant.value.str.val[0] == '_') { \
4187 + \
4188 + znode* varname = &zo->op1; \
4189 + (void)zend_is_auto_global(varname->u.constant.value.str.val, \
4190 + varname->u.constant.value.str.len \
4191 + TSRMLS_CC); \
4192 + } \
4193 +
4194 +/* {{{ my_prepare_op_array_for_execution */
4195 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4196 +{
4197 + /* combine my_fetch_global_vars and my_copy_data_exceptions.
4198 + * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4199 + * - If the opcode stream contain mutable data, ensure a copy.
4200 + * - Fixup array jumps in the same loop.
4201 + */
4202 + int i=src->last;
4203 + zend_op *zo;
4204 + zend_op *dzo;
4205 +#ifdef ZEND_ENGINE_2
4206 + apc_opflags_t * flags = APCG(reserved_offset) != -1 ?
4207 + (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
4208 + int needcopy = flags ? flags->deep_copy : 1;
4209 + /* auto_globals_jit was not in php4 */
4210 + int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
4211 +
4212 +#define FETCH_AUTOGLOBAL(member) do { \
4213 + if(flags && flags->member == 1) { \
4214 + zend_is_auto_global(#member,\
4215 + (sizeof(#member) - 1)\
4216 + TSRMLS_CC);\
4217 + } \
4218 +}while(0);
4219 +
4220 + FETCH_AUTOGLOBAL(_GET);
4221 + FETCH_AUTOGLOBAL(_POST);
4222 + FETCH_AUTOGLOBAL(_COOKIE);
4223 + FETCH_AUTOGLOBAL(_SERVER);
4224 + FETCH_AUTOGLOBAL(_ENV);
4225 + FETCH_AUTOGLOBAL(_FILES);
4226 + FETCH_AUTOGLOBAL(_REQUEST);
4227 +
4228 +#else
4229 + int needcopy = 0;
4230 + int do_prepare_fetch_global = 0;
4231 + int j = 0;
4232 +
4233 + for(j = 0; j < src->last; j++) {
4234 + zo = &src->opcodes[j];
4235 +
4236 + if( ((zo->op1.op_type == IS_CONST &&
4237 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4238 + ((zo->op2.op_type == IS_CONST &&
4239 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4240 + needcopy = 1;
4241 + }
4242 + }
4243 +#endif
4244 +
4245 + if(needcopy) {
4246 +
4247 + dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
4248 + sizeof(zend_op) * src->last,
4249 + apc_php_malloc);
4250 + zo = src->opcodes;
4251 + dzo = dst->opcodes;
4252 + while(i > 0) {
4253 +
4254 + if( ((zo->op1.op_type == IS_CONST &&
4255 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4256 + ((zo->op2.op_type == IS_CONST &&
4257 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4258 +
4259 + if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
4260 + assert(0); /* emalloc failed or a bad constant array */
4261 + }
4262 + }
4263 +
4264 +#ifdef ZEND_ENGINE_2
4265 + switch(zo->opcode) {
4266 + case ZEND_JMP:
4267 + dzo->op1.u.jmp_addr = dst->opcodes +
4268 + (zo->op1.u.jmp_addr - src->opcodes);
4269 + break;
4270 + case ZEND_JMPZ:
4271 + case ZEND_JMPNZ:
4272 + case ZEND_JMPZ_EX:
4273 + case ZEND_JMPNZ_EX:
4274 + dzo->op2.u.jmp_addr = dst->opcodes +
4275 + (zo->op2.u.jmp_addr - src->opcodes);
4276 + break;
4277 + case ZEND_FETCH_R:
4278 + case ZEND_FETCH_W:
4279 + case ZEND_FETCH_IS:
4280 + case ZEND_FETCH_FUNC_ARG:
4281 + if(do_prepare_fetch_global)
4282 + {
4283 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4284 + }
4285 + break;
4286 + default:
4287 + break;
4288 + }
4289 +#endif
4290 + i--;
4291 + zo++;
4292 + dzo++;
4293 + }
4294 +#ifdef ZEND_ENGINE_2
4295 + } else { /* !needcopy */
4296 + /* The fetch is only required if auto_globals_jit=1 */
4297 + if(do_prepare_fetch_global)
4298 + {
4299 + zo = src->opcodes;
4300 + while(i > 0) {
4301 +
4302 + if(zo->opcode == ZEND_FETCH_R ||
4303 + zo->opcode == ZEND_FETCH_W ||
4304 + zo->opcode == ZEND_FETCH_IS ||
4305 + zo->opcode == ZEND_FETCH_FUNC_ARG
4306 + ) {
4307 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4308 + }
4309 +
4310 + i--;
4311 + zo++;
4312 + }
4313 + }
4314 +#endif
4315 + }
4316 + return 1;
4317 +}
4318 +/* }}} */
4319 +
4320 +/* {{{ apc_copy_op_array_for_execution */
4321 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4322 +{
4323 + if(dst == NULL) {
4324 + dst = (zend_op_array*) emalloc(sizeof(src[0]));
4325 + }
4326 + memcpy(dst, src, sizeof(src[0]));
4327 + dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
4328 +
4329 + dst->refcount = apc_xmemcpy(src->refcount,
4330 + sizeof(src->refcount[0]),
4331 + apc_php_malloc);
4332 +
4333 + my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
4334 +
4335 + return dst;
4336 +}
4337 +/* }}} */
4338 +
4339 +/* {{{ apc_copy_function_for_execution */
4340 +zend_function* apc_copy_function_for_execution(zend_function* src)
4341 +{
4342 + zend_function* dst;
4343 + TSRMLS_FETCH();
4344 +
4345 + dst = (zend_function*) emalloc(sizeof(src[0]));
4346 + memcpy(dst, src, sizeof(src[0]));
4347 + apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
4348 + return dst;
4349 +}
4350 +/* }}} */
4351 +
4352 +/* {{{ apc_copy_function_for_execution_ex */
4353 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
4354 +{
4355 + if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
4356 + return apc_copy_function_for_execution(src);
4357 +}
4358 +/* }}} */
4359 +
4360 +/* {{{ apc_copy_class_entry_for_execution */
4361 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
4362 +{
4363 + zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
4364 + memcpy(dst, src, sizeof(src[0]));
4365 +
4366 +#ifdef ZEND_ENGINE_2
4367 + if(src->num_interfaces)
4368 + {
4369 + /* These are slots to be populated later by ADD_INTERFACE insns */
4370 + dst->interfaces = apc_php_malloc(
4371 + sizeof(zend_class_entry*) * src->num_interfaces);
4372 + memset(dst->interfaces, 0,
4373 + sizeof(zend_class_entry*) * src->num_interfaces);
4374 + }
4375 + else
4376 + {
4377 + /* assert(dst->interfaces == NULL); */
4378 + }
4379 +#endif
4380 +
4381 +#ifndef ZEND_ENGINE_2
4382 + dst->refcount = apc_xmemcpy(src->refcount,
4383 + sizeof(src->refcount[0]),
4384 + apc_php_malloc);
4385 +#endif
4386 +
4387 + /* Deep-copy the class properties, because they will be modified */
4388 +
4389 + my_copy_hashtable(&dst->default_properties,
4390 + &src->default_properties,
4391 + (ht_copy_fun_t) my_copy_zval_ptr,
4392 + (ht_free_fun_t) my_free_zval_ptr,
4393 + 1,
4394 + apc_php_malloc, apc_php_free);
4395 +
4396 + /* For derived classes, we must also copy the function hashtable (although
4397 + * we can merely bitwise copy the functions it contains) */
4398 +
4399 + my_copy_hashtable(&dst->function_table,
4400 + &src->function_table,
4401 + (ht_copy_fun_t) apc_copy_function_for_execution_ex,
4402 + NULL,
4403 + 0,
4404 + apc_php_malloc, apc_php_free);
4405 +#ifdef ZEND_ENGINE_2
4406 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
4407 +
4408 + /* zend_do_inheritance merges properties_info.
4409 + * Need only shallow copying as it doesn't hold the pointers.
4410 + */
4411 + my_copy_hashtable(&dst->properties_info,
4412 + &src->properties_info,
4413 + (ht_copy_fun_t) my_copy_property_info_for_execution,
4414 + NULL,
4415 + 0,
4416 + apc_php_malloc, apc_php_free);
4417 +
4418 +#ifdef ZEND_ENGINE_2_2
4419 + /* php5.2 introduced a scope attribute for property info */
4420 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4421 +#endif
4422 +
4423 + /* if inheritance results in a hash_del, it might result in
4424 + * a pefree() of the pointers here. Deep copying required.
4425 + */
4426 +
4427 + my_copy_hashtable(&dst->constants_table,
4428 + &src->constants_table,
4429 + (ht_copy_fun_t) my_copy_zval_ptr,
4430 + NULL,
4431 + 1,
4432 + apc_php_malloc, apc_php_free);
4433 +
4434 + my_copy_hashtable(&dst->default_static_members,
4435 + &src->default_static_members,
4436 + (ht_copy_fun_t) my_copy_zval_ptr,
4437 + (ht_free_fun_t) my_free_zval_ptr,
4438 + 1,
4439 + apc_php_malloc, apc_php_free);
4440 +
4441 + if(src->static_members != &(src->default_static_members))
4442 + {
4443 + dst->static_members = my_copy_hashtable(NULL,
4444 + src->static_members,
4445 + (ht_copy_fun_t) my_copy_zval_ptr,
4446 + (ht_free_fun_t) my_free_zval_ptr,
4447 + 1,
4448 + apc_php_malloc, apc_php_free);
4449 + }
4450 + else
4451 + {
4452 + dst->static_members = &(dst->default_static_members);
4453 + }
4454 +
4455 +#endif
4456 +
4457 + return dst;
4458 +}
4459 +/* }}} */
4460 +
4461 +/* {{{ apc_free_class_entry_after_execution */
4462 +void apc_free_class_entry_after_execution(zend_class_entry* src)
4463 +{
4464 +#ifdef ZEND_ENGINE_2
4465 + if(src->num_interfaces > 0 && src->interfaces) {
4466 + apc_php_free(src->interfaces);
4467 + src->interfaces = NULL;
4468 + src->num_interfaces = 0;
4469 + }
4470 + /* my_destroy_hashtable() does not play nice with refcounts */
4471 +
4472 + zend_hash_clean(&src->default_static_members);
4473 + if(src->static_members != &(src->default_static_members))
4474 + {
4475 + zend_hash_destroy(src->static_members);
4476 + apc_php_free(src->static_members);
4477 + src->static_members = NULL;
4478 + }
4479 + else
4480 + {
4481 + src->static_members = NULL;
4482 + }
4483 + zend_hash_clean(&src->default_properties);
4484 + zend_hash_clean(&src->constants_table);
4485 +#endif
4486 +
4487 + /* TODO: more cleanup */
4488 +}
4489 +/* }}} */
4490 +
4491 +#ifdef ZEND_ENGINE_2
4492 +
4493 +/* {{{ my_fixup_function */
4494 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4495 +{
4496 + zend_function* zf = p->pData;
4497 +
4498 + #define SET_IF_SAME_NAME(member) \
4499 + do { \
4500 + if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
4501 + dst->member = zf; \
4502 + } \
4503 + } \
4504 + while(0)
4505 +
4506 + if(zf->common.scope == src)
4507 + {
4508 +
4509 + /* Fixing up the default functions for objects here since
4510 + * we need to compare with the newly allocated functions
4511 + *
4512 + * caveat: a sub-class method can have the same name as the
4513 + * parent's constructor and create problems.
4514 + */
4515 +
4516 + if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
4517 + else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
4518 + else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
4519 + else
4520 + {
4521 + SET_IF_SAME_NAME(__get);
4522 + SET_IF_SAME_NAME(__set);
4523 + SET_IF_SAME_NAME(__unset);
4524 + SET_IF_SAME_NAME(__isset);
4525 + SET_IF_SAME_NAME(__call);
4526 +#ifdef ZEND_ENGINE_2_2
4527 + SET_IF_SAME_NAME(__tostring);
4528 +#endif
4529 + }
4530 + zf->common.scope = dst;
4531 + }
4532 + else
4533 + {
4534 + /* no other function should reach here */
4535 + assert(0);
4536 + }
4537 +
4538 + #undef SET_IF_SAME_NAME
4539 +}
4540 +/* }}} */
4541 +
4542 +#ifdef ZEND_ENGINE_2_2
4543 +/* {{{ my_fixup_property_info */
4544 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4545 +{
4546 + zend_property_info* property_info = (zend_property_info*)p->pData;
4547 +
4548 + if(property_info->ce == src)
4549 + {
4550 + property_info->ce = dst;
4551 + }
4552 + else
4553 + {
4554 + assert(0); /* should never happen */
4555 + }
4556 +}
4557 +/* }}} */
4558 +#endif
4559 +
4560 +/* {{{ my_fixup_hashtable */
4561 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
4562 +{
4563 + Bucket *p;
4564 +
4565 + uint i;
4566 +
4567 + for (i = 0; i < ht->nTableSize; i++) {
4568 + if(!ht->arBuckets) break;
4569 + p = ht->arBuckets[i];
4570 + while (p != NULL) {
4571 + fixup(p, src, dst);
4572 + p = p->pNext;
4573 + }
4574 + }
4575 +}
4576 +/* }}} */
4577 +
4578 +#endif
4579 +
4580 +/* {{{ my_check_copy_function */
4581 +static int my_check_copy_function(Bucket* p, va_list args)
4582 +{
4583 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4584 + zend_function* zf = (zend_function*)p->pData;
4585 +#ifndef ZEND_ENGINE_2
4586 + zend_class_entry* parent = src->parent;
4587 + zend_function* parent_fn = NULL;
4588 +#endif
4589 +
4590 +#ifdef ZEND_ENGINE_2
4591 + return (zf->common.scope == src);
4592 +#else
4593 + if (parent &&
4594 + zend_hash_quick_find(&parent->function_table, p->arKey,
4595 + p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
4596 +
4597 + if((parent_fn && zf) &&
4598 + (parent_fn->op_array.refcount == zf->op_array.refcount))
4599 + {
4600 + return 0;
4601 + }
4602 + }
4603 + return 1;
4604 +#endif
4605 +}
4606 +/* }}} */
4607 +
4608 +/* {{{ my_check_copy_default_property */
4609 +static int my_check_copy_default_property(Bucket* p, va_list args)
4610 +{
4611 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4612 + zend_class_entry* parent = src->parent;
4613 + zval ** child_prop = (zval**)p->pData;
4614 + zval ** parent_prop = NULL;
4615 +
4616 + if (parent &&
4617 + zend_hash_quick_find(&parent->default_properties, p->arKey,
4618 + p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
4619 +
4620 + if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
4621 + {
4622 + return 0;
4623 + }
4624 + }
4625 +
4626 + /* possibly not in the parent */
4627 + return 1;
4628 +}
4629 +/* }}} */
4630 +
4631 +#ifdef ZEND_ENGINE_2
4632 +
4633 +/* {{{ my_check_copy_property_info */
4634 +static int my_check_copy_property_info(Bucket* p, va_list args)
4635 +{
4636 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4637 + zend_class_entry* parent = src->parent;
4638 + zend_property_info* child_info = (zend_property_info*)p->pData;
4639 + zend_property_info* parent_info = NULL;
4640 +
4641 +#ifdef ZEND_ENGINE_2_2
4642 + /* so much easier */
4643 + return (child_info->ce == src);
4644 +#endif
4645 +
4646 + if (parent &&
4647 + zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
4648 + p->h, (void **) &parent_info)==SUCCESS) {
4649 + if(parent_info->flags & ZEND_ACC_PRIVATE)
4650 + {
4651 + return 1;
4652 + }
4653 + if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
4654 + (child_info->flags & ZEND_ACC_PPP_MASK))
4655 + {
4656 + /* TODO: figure out whether ACC_CHANGED is more appropriate
4657 + * here */
4658 + return 1;
4659 + }
4660 + return 0;
4661 + }
4662 +
4663 + /* property doesn't exist in parent, copy into cached child */
4664 + return 1;
4665 +}
4666 +/* }}} */
4667 +
4668 +/* {{{ my_check_copy_static_member */
4669 +static int my_check_copy_static_member(Bucket* p, va_list args)
4670 +{
4671 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4672 + HashTable * ht = va_arg(args, HashTable*);
4673 + zend_class_entry* parent = src->parent;
4674 + HashTable * parent_ht = NULL;
4675 + char * member_name;
4676 + char * class_name = NULL;
4677 +
4678 + zend_property_info *parent_info = NULL;
4679 + zend_property_info *child_info = NULL;
4680 + zval ** parent_prop = NULL;
4681 + zval ** child_prop = (zval**)(p->pData);
4682 +
4683 + if(!parent) {
4684 + return 1;
4685 + }
4686 +
4687 + /* these do not need free'ing */
4688 +#ifdef ZEND_ENGINE_2_2
4689 + zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
4690 +#else
4691 + zend_unmangle_property_name(p->arKey, &class_name, &member_name);
4692 +#endif
4693 +
4694 + /* please refer do_inherit_property_access_check in zend_compile.c
4695 + * to understand why we lookup in properties_info.
4696 + */
4697 + if((zend_hash_find(&parent->properties_info, member_name,
4698 + strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
4699 + &&
4700 + (zend_hash_find(&src->properties_info, member_name,
4701 + strlen(member_name)+1, (void**)&child_info) == SUCCESS))
4702 + {
4703 + if(child_info->flags & ZEND_ACC_STATIC &&
4704 + (parent_info->flags & ZEND_ACC_PROTECTED &&
4705 + child_info->flags & ZEND_ACC_PUBLIC))
4706 + {
4707 + /* Do not copy into static_members. zend_do_inheritance
4708 + * will automatically insert a NULL value.
4709 + * TODO: decrement refcount or fixup when copying out for exec ?
4710 + */
4711 + return 0;
4712 + }
4713 + if(ht == &(src->default_static_members))
4714 + {
4715 + parent_ht = &parent->default_static_members;
4716 + }
4717 + else
4718 + {
4719 + parent_ht = parent->static_members;
4720 + }
4721 +
4722 + if(zend_hash_quick_find(parent_ht, p->arKey,
4723 + p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
4724 + {
4725 + /* they point to the same zval */
4726 + if(*parent_prop == *child_prop)
4727 + {
4728 + return 0;
4729 + }
4730 + }
4731 + }
4732 +
4733 + return 1;
4734 +}
4735 +/* }}} */
4736 +#endif
4737 +
4738 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
4739 + * register a optimizer callback function, returns the previous callback
4740 + */
4741 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
4742 + apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
4743 + APCG(apc_optimize_function) = optimizer;
4744 + return old_optimizer;
4745 +}
4746 +
4747 +/*
4748 + * Local variables:
4749 + * tab-width: 4
4750 + * c-basic-offset: 4
4751 + * End:
4752 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4753 + * vim<600: expandtab sw=4 ts=4 sts=4
4754 + */
4755 diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.h php-5.2.5/ext/apc/apc_compile.h
4756 --- php-5.2.5-orig/ext/apc/apc_compile.h 1969-12-31 18:00:00.000000000 -0600
4757 +++ php-5.2.5/ext/apc/apc_compile.h 2007-12-26 16:51:32.000000000 -0600
4758 @@ -0,0 +1,134 @@
4759 +/*
4760 + +----------------------------------------------------------------------+
4761 + | APC |
4762 + +----------------------------------------------------------------------+
4763 + | Copyright (c) 2006 The PHP Group |
4764 + +----------------------------------------------------------------------+
4765 + | This source file is subject to version 3.01 of the PHP license, |
4766 + | that is bundled with this package in the file LICENSE, and is |
4767 + | available through the world-wide-web at the following url: |
4768 + | http://www.php.net/license/3_01.txt |
4769 + | If you did not receive a copy of the PHP license and are unable to |
4770 + | obtain it through the world-wide-web, please send a note to |
4771 + | license@php.net so we can mail you a copy immediately. |
4772 + +----------------------------------------------------------------------+
4773 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4774 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4775 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4776 + +----------------------------------------------------------------------+
4777 +
4778 + This software was contributed to PHP by Community Connect Inc. in 2002
4779 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4780 + Future revisions and derivatives of this source code must acknowledge
4781 + Community Connect Inc. as the original contributor of this module by
4782 + leaving this note intact in the source code.
4783 +
4784 + All other licensing and usage conditions are those of the PHP Group.
4785 +
4786 + */
4787 +
4788 +/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
4789 +
4790 +#ifndef APC_COMPILE_H
4791 +#define APC_COMPILE_H
4792 +
4793 +/*
4794 + * This module encapsulates most of the complexity involved in deep-copying
4795 + * the Zend compiler data structures. The routines are allocator-agnostic, so
4796 + * the same function can be used for copying to and from shared memory.
4797 + */
4798 +
4799 +#include "apc.h"
4800 +#include "apc_php.h"
4801 +
4802 +/* {{{ struct definition: apc_function_t */
4803 +typedef struct apc_function_t apc_function_t;
4804 +struct apc_function_t {
4805 + char* name; /* the function name */
4806 + int name_len; /* length of name */
4807 + zend_function* function; /* the zend function data structure */
4808 +};
4809 +/* }}} */
4810 +
4811 +/* {{{ struct definition: apc_class_t */
4812 +typedef struct apc_class_t apc_class_t;
4813 +struct apc_class_t {
4814 + char* name; /* the class name */
4815 + int name_len; /* length of name */
4816 + int is_derived; /* true if this is a derived class */
4817 + char* parent_name; /* the parent class name */
4818 + zend_class_entry* class_entry; /* the zend class data structure */
4819 +};
4820 +/* }}} */
4821 +
4822 +/* {{{ struct definition: apc_opflags_t */
4823 +typedef struct apc_opflags_t apc_opflags_t;
4824 +struct apc_opflags_t {
4825 + unsigned int has_jumps : 1; /* has jump offsets */
4826 + unsigned int deep_copy : 1; /* needs deep copy */
4827 +
4828 + /* autoglobal bits */
4829 + unsigned int _POST : 1;
4830 + unsigned int _GET : 1;
4831 + unsigned int _COOKIE : 1;
4832 + unsigned int _SERVER : 1;
4833 + unsigned int _ENV : 1;
4834 + unsigned int _FILES : 1;
4835 + unsigned int _REQUEST : 1;
4836 + unsigned int unknown_global : 1;
4837 +};
4838 +/* }}} */
4839 +
4840 +/*
4841 + * These are the top-level copy functions.
4842 + */
4843 +
4844 +extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4845 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
4846 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4847 +extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4848 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
4849 +
4850 +/*
4851 + * Deallocation functions corresponding to the copy functions above.
4852 + */
4853 +
4854 +extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
4855 +extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
4856 +extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
4857 +extern void apc_free_zval(zval* src, apc_free_t deallocate);
4858 +
4859 +/*
4860 + * These "copy-for-execution" functions must be called after retrieving an
4861 + * object from the shared cache. They do the minimal amount of work necessary
4862 + * to allow multiple processes to concurrently execute the same VM data
4863 + * structures.
4864 + */
4865 +
4866 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
4867 +extern zend_function* apc_copy_function_for_execution(zend_function* src);
4868 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
4869 +
4870 +/*
4871 + * The "free-after-execution" function performs a cursory clean up of the class data
4872 + * This is required to minimize memory leak warnings and to ensure correct destructor
4873 + * ordering of some variables.
4874 + */
4875 +extern void apc_free_class_entry_after_execution(zend_class_entry* src);
4876 +
4877 +/*
4878 + * Optimization callback definition and registration function.
4879 + */
4880 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
4881 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
4882 +
4883 +#endif
4884 +
4885 +/*
4886 + * Local variables:
4887 + * tab-width: 4
4888 + * c-basic-offset: 4
4889 + * End:
4890 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4891 + * vim<600: expandtab sw=4 ts=4 sts=4
4892 + */
4893 diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.c php-5.2.5/ext/apc/apc_debug.c
4894 --- php-5.2.5-orig/ext/apc/apc_debug.c 1969-12-31 18:00:00.000000000 -0600
4895 +++ php-5.2.5/ext/apc/apc_debug.c 2007-12-26 16:51:32.000000000 -0600
4896 @@ -0,0 +1,57 @@
4897 +/*
4898 + +----------------------------------------------------------------------+
4899 + | APC |
4900 + +----------------------------------------------------------------------+
4901 + | Copyright (c) 2006 The PHP Group |
4902 + +----------------------------------------------------------------------+
4903 + | This source file is subject to version 3.01 of the PHP license, |
4904 + | that is bundled with this package in the file LICENSE, and is |
4905 + | available through the world-wide-web at the following url: |
4906 + | http://www.php.net/license/3_01.txt |
4907 + | If you did not receive a copy of the PHP license and are unable to |
4908 + | obtain it through the world-wide-web, please send a note to |
4909 + | license@php.net so we can mail you a copy immediately. |
4910 + +----------------------------------------------------------------------+
4911 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4912 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4913 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4914 + +----------------------------------------------------------------------+
4915 +
4916 + This software was contributed to PHP by Community Connect Inc. in 2002
4917 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4918 + Future revisions and derivatives of this source code must acknowledge
4919 + Community Connect Inc. as the original contributor of this module by
4920 + leaving this note intact in the source code.
4921 +
4922 + All other licensing and usage conditions are those of the PHP Group.
4923 +*/
4924 +
4925 +/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
4926 +#include "apc.h"
4927 +#include <stdio.h>
4928 +#include "zend_compile.h"
4929 +
4930 +#ifdef __DEBUG_APC__
4931 +
4932 +#include <dlfcn.h>
4933 +
4934 +/* keep track of vld_dump_oparray() signature */
4935 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
4936 +
4937 +#endif
4938 +
4939 +void dump(zend_op_array *op_array TSRMLS_DC)
4940 +{
4941 +#ifdef __DEBUG_APC__
4942 + vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
4943 +
4944 + if(dump_op_array)
4945 + {
4946 + dump_op_array(op_array TSRMLS_CC);
4947 + }
4948 + else
4949 + {
4950 + apc_wprint("vld is not installed or something even worse.");
4951 + }
4952 +#endif
4953 +}
4954 diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.h php-5.2.5/ext/apc/apc_debug.h
4955 --- php-5.2.5-orig/ext/apc/apc_debug.h 1969-12-31 18:00:00.000000000 -0600
4956 +++ php-5.2.5/ext/apc/apc_debug.h 2007-12-26 16:51:32.000000000 -0600
4957 @@ -0,0 +1 @@
4958 +void dump(zend_op_array * TSRMLS_DC);
4959 diff -ubrN php-5.2.5-orig/ext/apc/apc.dsp php-5.2.5/ext/apc/apc.dsp
4960 --- php-5.2.5-orig/ext/apc/apc.dsp 1969-12-31 18:00:00.000000000 -0600
4961 +++ php-5.2.5/ext/apc/apc.dsp 2007-12-26 16:51:32.000000000 -0600
4962 @@ -0,0 +1,207 @@
4963 +# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
4964 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
4965 +# ** DO NOT EDIT **
4966 +
4967 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
4968 +
4969 +CFG=apc - Win32 Debug_TS
4970 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
4971 +!MESSAGE use the Export Makefile command and run
4972 +!MESSAGE
4973 +!MESSAGE NMAKE /f "apc.mak".
4974 +!MESSAGE
4975 +!MESSAGE You can specify a configuration when running NMAKE
4976 +!MESSAGE by defining the macro CFG on the command line. For example:
4977 +!MESSAGE
4978 +!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
4979 +!MESSAGE
4980 +!MESSAGE Possible choices for configuration are:
4981 +!MESSAGE
4982 +!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
4983 +!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
4984 +!MESSAGE
4985 +
4986 +# Begin Project
4987 +# PROP AllowPerConfigDependencies 0
4988 +# PROP Scc_ProjName ""
4989 +# PROP Scc_LocalPath ""
4990 +CPP=cl.exe
4991 +MTL=midl.exe
4992 +RSC=rc.exe
4993 +
4994 +!IF "$(CFG)" == "apc - Win32 Debug_TS"
4995 +
4996 +# PROP BASE Use_MFC 0
4997 +# PROP BASE Use_Debug_Libraries 1
4998 +# PROP BASE Output_Dir "Debug_TS"
4999 +# PROP BASE Intermediate_Dir "Debug_TS"
5000 +# PROP BASE Target_Dir ""
5001 +# PROP Use_MFC 0
5002 +# PROP Use_Debug_Libraries 1
5003 +# PROP Output_Dir "Debug_TS"
5004 +# PROP Intermediate_Dir "Debug_TS"
5005 +# PROP Ignore_Export_Lib 0
5006 +# PROP Target_Dir ""
5007 +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
5008 +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=1 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
5009 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
5010 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
5011 +# ADD BASE RSC /l 0x409 /d "_DEBUG"
5012 +# ADD RSC /l 0x409 /d "_DEBUG"
5013 +BSC32=bscmake.exe
5014 +# ADD BASE BSC32 /nologo
5015 +# ADD BSC32 /nologo
5016 +LINK32=link.exe
5017 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
5018 +# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug_TS/php_apc.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS"
5019 +
5020 +!ELSEIF "$(CFG)" == "apc - Win32 Release_TS"
5021 +
5022 +# PROP BASE Use_MFC 0
5023 +# PROP BASE Use_Debug_Libraries 0
5024 +# PROP BASE Output_Dir "Release_TS"
5025 +# PROP BASE Intermediate_Dir "Release_TS"
5026 +# PROP BASE Target_Dir ""
5027 +# PROP Use_MFC 0
5028 +# PROP Use_Debug_Libraries 0
5029 +# PROP Output_Dir "Release_TS"
5030 +# PROP Intermediate_Dir "Release_TS"
5031 +# PROP Ignore_Export_Lib 0
5032 +# PROP Target_Dir ""
5033 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5034 +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=0 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5035 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5036 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5037 +# ADD BASE RSC /l 0x409 /d "NDEBUG"
5038 +# ADD RSC /l 0x409 /d "NDEBUG"
5039 +BSC32=bscmake.exe
5040 +# ADD BASE BSC32 /nologo
5041 +# ADD BSC32 /nologo
5042 +LINK32=link.exe
5043 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
5044 +# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Release_TS/php_apc.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
5045 +
5046 +!ENDIF
5047 +
5048 +# Begin Target
5049 +
5050 +# Name "apc - Win32 Debug_TS"
5051 +# Name "apc - Win32 Release_TS"
5052 +# Begin Group "Source Files"
5053 +
5054 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
5055 +# Begin Source File
5056 +
5057 +SOURCE=.\apc.c
5058 +# End Source File
5059 +# Begin Source File
5060 +
5061 +SOURCE=.\apc_cache.c
5062 +# End Source File
5063 +# Begin Source File
5064 +
5065 +SOURCE=.\apc_compile.c
5066 +# End Source File
5067 +# Begin Source File
5068 +
5069 +SOURCE=.\apc_debug.c
5070 +# End Source File
5071 +# Begin Source File
5072 +
5073 +SOURCE=.\apc_fcntl_win32.c
5074 +# End Source File
5075 +# Begin Source File
5076 +
5077 +SOURCE=.\apc_main.c
5078 +# End Source File
5079 +# Begin Source File
5080 +
5081 +SOURCE=.\apc_rfc1867.c
5082 +# End Source File
5083 +# Begin Source File
5084 +
5085 +SOURCE=.\apc_shm.c
5086 +# End Source File
5087 +# Begin Source File
5088 +
5089 +SOURCE=.\apc_sma.c
5090 +# End Source File
5091 +# Begin Source File
5092 +
5093 +SOURCE=.\apc_stack.c
5094 +# End Source File
5095 +# Begin Source File
5096 +
5097 +SOURCE=.\apc_zend.c
5098 +# End Source File
5099 +# Begin Source File
5100 +
5101 +SOURCE=.\php_apc.c
5102 +# End Source File
5103 +# End Group
5104 +# Begin Group "Header Files"
5105 +
5106 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
5107 +# Begin Source File
5108 +
5109 +SOURCE=.\apc.h
5110 +# End Source File
5111 +# Begin Source File
5112 +
5113 +SOURCE=.\apc_cache.h
5114 +# End Source File
5115 +# Begin Source File
5116 +
5117 +SOURCE=.\apc_compile.h
5118 +# End Source File
5119 +# Begin Source File
5120 +
5121 +SOURCE=.\apc_debug.h
5122 +# End Source File
5123 +# Begin Source File
5124 +
5125 +SOURCE=.\apc_fcntl.h
5126 +# End Source File
5127 +# Begin Source File
5128 +
5129 +SOURCE=.\apc_globals.h
5130 +# End Source File
5131 +# Begin Source File
5132 +
5133 +SOURCE=.\apc_lock.h
5134 +# End Source File
5135 +# Begin Source File
5136 +
5137 +SOURCE=.\apc_main.h
5138 +# End Source File
5139 +# Begin Source File
5140 +
5141 +SOURCE=.\apc_php.h
5142 +# End Source File
5143 +# Begin Source File
5144 +
5145 +SOURCE=.\apc_shm.h
5146 +# End Source File
5147 +# Begin Source File
5148 +
5149 +SOURCE=.\apc_sma.h
5150 +# End Source File
5151 +# Begin Source File
5152 +
5153 +SOURCE=.\apc_stack.h
5154 +# End Source File
5155 +# Begin Source File
5156 +
5157 +SOURCE=.\apc_zend.h
5158 +# End Source File
5159 +# Begin Source File
5160 +
5161 +SOURCE=.\php_apc.h
5162 +# End Source File
5163 +# End Group
5164 +# Begin Group "Resource Files"
5165 +
5166 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
5167 +# End Group
5168 +# End Target
5169 +# End Project
5170 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.c php-5.2.5/ext/apc/apc_fcntl.c
5171 --- php-5.2.5-orig/ext/apc/apc_fcntl.c 1969-12-31 18:00:00.000000000 -0600
5172 +++ php-5.2.5/ext/apc/apc_fcntl.c 2007-12-26 16:51:32.000000000 -0600
5173 @@ -0,0 +1,118 @@
5174 +/*
5175 + +----------------------------------------------------------------------+
5176 + | APC |
5177 + +----------------------------------------------------------------------+
5178 + | Copyright (c) 2006 The PHP Group |
5179 + +----------------------------------------------------------------------+
5180 + | This source file is subject to version 3.01 of the PHP license, |
5181 + | that is bundled with this package in the file LICENSE, and is |
5182 + | available through the world-wide-web at the following url: |
5183 + | http://www.php.net/license/3_01.txt |
5184 + | If you did not receive a copy of the PHP license and are unable to |
5185 + | obtain it through the world-wide-web, please send a note to |
5186 + | license@php.net so we can mail you a copy immediately. |
5187 + +----------------------------------------------------------------------+
5188 + | Authors: George Schlossnagle <george@omniti.com> |
5189 + | Rasmus Lerdorf <rasmus@php.net> |
5190 + +----------------------------------------------------------------------+
5191 +
5192 + This software was contributed to PHP by Community Connect Inc. in 2002
5193 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5194 + Future revisions and derivatives of this source code must acknowledge
5195 + Community Connect Inc. as the original contributor of this module by
5196 + leaving this note intact in the source code.
5197 +
5198 + All other licensing and usage conditions are those of the PHP Group.
5199 +
5200 + */
5201 +
5202 +/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
5203 +
5204 +#include "apc_fcntl.h"
5205 +#include "apc.h"
5206 +#include <unistd.h>
5207 +#include <fcntl.h>
5208 +
5209 +int apc_fcntl_create(const char* pathname)
5210 +{
5211 + int fd;
5212 + if(pathname == NULL) {
5213 + char lock_path[] = "/tmp/.apc.XXXXXX";
5214 + mktemp(lock_path);
5215 + fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5216 + if(fd > 0 ) {
5217 + unlink(lock_path);
5218 + return fd;
5219 + } else {
5220 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
5221 + return -1;
5222 + }
5223 + }
5224 + fd = open(pathname, O_RDWR|O_CREAT, 0666);
5225 + if(fd > 0 ) {
5226 + unlink(pathname);
5227 + return fd;
5228 + }
5229 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
5230 + return -1;
5231 +}
5232 +
5233 +void apc_fcntl_destroy(int fd)
5234 +{
5235 + close(fd);
5236 +}
5237 +
5238 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5239 +{
5240 + int ret;
5241 + struct flock lock;
5242 +
5243 + lock.l_type = type;
5244 + lock.l_start = offset;
5245 + lock.l_whence = whence;
5246 + lock.l_len = len;
5247 + lock.l_pid = 0;
5248 +
5249 + do { ret = fcntl(fd, cmd, &lock) ; }
5250 + while(ret < 0 && errno == EINTR);
5251 + return(ret);
5252 +}
5253 +
5254 +void apc_fcntl_lock(int fd)
5255 +{
5256 + if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5257 + apc_eprint("apc_fcntl_lock failed:");
5258 + }
5259 +}
5260 +
5261 +void apc_fcntl_rdlock(int fd)
5262 +{
5263 + if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
5264 + apc_eprint("apc_fcntl_rdlock failed:");
5265 + }
5266 +}
5267 +
5268 +zend_bool apc_fcntl_nonblocking_lock(int fd)
5269 +{
5270 + if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5271 + if(errno==EACCES||errno==EAGAIN) return 0;
5272 + else apc_eprint("apc_fcntl_lock failed:");
5273 + }
5274 + return 1;
5275 +}
5276 +
5277 +void apc_fcntl_unlock(int fd)
5278 +{
5279 + if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
5280 + apc_eprint("apc_fcntl_unlock failed:");
5281 + }
5282 +}
5283 +
5284 +/*
5285 + * Local variables:
5286 + * tab-width: 4
5287 + * c-basic-offset: 4
5288 + * End:
5289 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5290 + * vim<600: expandtab sw=4 ts=4 sts=4
5291 + */
5292 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.h php-5.2.5/ext/apc/apc_fcntl.h
5293 --- php-5.2.5-orig/ext/apc/apc_fcntl.h 1969-12-31 18:00:00.000000000 -0600
5294 +++ php-5.2.5/ext/apc/apc_fcntl.h 2007-12-26 16:51:32.000000000 -0600
5295 @@ -0,0 +1,50 @@
5296 +/*
5297 + +----------------------------------------------------------------------+
5298 + | APC |
5299 + +----------------------------------------------------------------------+
5300 + | Copyright (c) 2006 The PHP Group |
5301 + +----------------------------------------------------------------------+
5302 + | This source file is subject to version 3.01 of the PHP license, |
5303 + | that is bundled with this package in the file LICENSE, and is |
5304 + | available through the world-wide-web at the following url: |
5305 + | http://www.php.net/license/3_01.txt. |
5306 + | If you did not receive a copy of the PHP license and are unable to |
5307 + | obtain it through the world-wide-web, please send a note to |
5308 + | license@php.net so we can mail you a copy immediately. |
5309 + +----------------------------------------------------------------------+
5310 + | Authors: George Schlossnagle <george@omniti.com> |
5311 + | Rasmus Lerdorf <rasmus@php.net> |
5312 + +----------------------------------------------------------------------+
5313 +
5314 + This software was contributed to PHP by Community Connect Inc. in 2002
5315 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5316 + Future revisions and derivatives of this source code must acknowledge
5317 + Community Connect Inc. as the original contributor of this module by
5318 + leaving this note intact in the source code.
5319 +
5320 + All other licensing and usage conditions are those of the PHP Group.
5321 +
5322 + */
5323 +
5324 +/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
5325 +
5326 +#ifndef APC_FCNTL_H
5327 +#define APC_FCNTL_H
5328 +
5329 +
5330 +extern int apc_fcntl_create(const char* pathname);
5331 +extern void apc_fcntl_destroy(int fd);
5332 +extern void apc_fcntl_lock(int fd);
5333 +extern void apc_fcntl_rdlock(int fd);
5334 +extern void apc_fcntl_unlock(int fd);
5335 +extern unsigned char apc_fcntl_nonblocking_lock(int fd);
5336 +#endif
5337 +
5338 +/*
5339 + * Local variables:
5340 + * tab-width: 4
5341 + * c-basic-offset: 4
5342 + * End:
5343 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5344 + * vim<600: expandtab sw=4 ts=4 sts=4
5345 + */
5346 diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl_win32.c php-5.2.5/ext/apc/apc_fcntl_win32.c
5347 --- php-5.2.5-orig/ext/apc/apc_fcntl_win32.c 1969-12-31 18:00:00.000000000 -0600
5348 +++ php-5.2.5/ext/apc/apc_fcntl_win32.c 2007-12-26 16:51:32.000000000 -0600
5349 @@ -0,0 +1,117 @@
5350 +/*
5351 + +----------------------------------------------------------------------+
5352 + | APC |
5353 + +----------------------------------------------------------------------+
5354 + | Copyright (c) 2006 The PHP Group |
5355 + +----------------------------------------------------------------------+
5356 + | This source file is subject to version 3.01 of the PHP license, |
5357 + | that is bundled with this package in the file LICENSE, and is |
5358 + | available through the world-wide-web at the following url: |
5359 + | http://www.php.net/license/3_01.txt |
5360 + | If you did not receive a copy of the PHP license and are unable to |
5361 + | obtain it through the world-wide-web, please send a note to |
5362 + | license@php.net so we can mail you a copy immediately. |
5363 + +----------------------------------------------------------------------+
5364 + | Authors: George Schlossnagle <george@omniti.com> |
5365 + | Edin Kadribasic <edink@php.net> |
5366 + +----------------------------------------------------------------------+
5367 +
5368 + This software was contributed to PHP by Community Connect Inc. in 2002
5369 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5370 + Future revisions and derivatives of this source code must acknowledge
5371 + Community Connect Inc. as the original contributor of this module by
5372 + leaving this note intact in the source code.
5373 +
5374 + All other licensing and usage conditions are those of the PHP Group.
5375 +
5376 + */
5377 +
5378 +/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
5379 +
5380 +#include "apc_fcntl.h"
5381 +#include "apc.h"
5382 +#include <php.h>
5383 +#include <win32/flock.h>
5384 +#include <io.h>
5385 +#include <fcntl.h>
5386 +#include <sys/types.h>
5387 +#include <sys/stat.h>
5388 +
5389 +int apc_fcntl_create(const char* pathname)
5390 +{
5391 + char *lock_file = emalloc(MAXPATHLEN);
5392 + HANDLE fd;
5393 + DWORD tmplen;
5394 + static int i=0;
5395 +
5396 + tmplen = GetTempPath(MAXPATHLEN, lock_file);
5397 + if (!tmplen) {
5398 + efree(lock_file);
5399 + return -1;
5400 + }
5401 +
5402 + snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
5403 +
5404 + fd = CreateFile(lock_file,
5405 + GENERIC_READ | GENERIC_WRITE,
5406 + FILE_SHARE_READ | FILE_SHARE_WRITE,
5407 + NULL,
5408 + OPEN_ALWAYS,
5409 + FILE_ATTRIBUTE_NORMAL,
5410 + NULL);
5411 +
5412 +
5413 + if (fd == INVALID_HANDLE_VALUE) {
5414 + apc_eprint("apc_fcntl_create: could not open %s", lock_file);
5415 + efree(lock_file);
5416 + return -1;
5417 + }
5418 +
5419 + efree(lock_file);
5420 + return (int)fd;
5421 +}
5422 +
5423 +void apc_fcntl_destroy(int fd)
5424 +{
5425 + CloseHandle((HANDLE)fd);
5426 +}
5427 +
5428 +void apc_fcntl_lock(int fd)
5429 +{
5430 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5431 +
5432 + if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
5433 + apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
5434 + }
5435 +}
5436 +
5437 +void apc_fcntl_rdlock(int fd)
5438 +{
5439 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5440 +
5441 + if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
5442 + apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
5443 + }
5444 +}
5445 +
5446 +void apc_fcntl_unlock(int fd)
5447 +{
5448 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5449 +
5450 + if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
5451 + DWORD error_code = GetLastError();
5452 + /* Ignore already unlocked error */
5453 + if (error_code != ERROR_NOT_LOCKED) {
5454 + apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
5455 + }
5456 + }
5457 +}
5458 +
5459 +/*
5460 + * Local variables:
5461 + * tab-width: 4
5462 + * c-basic-offset: 4
5463 + * End:
5464 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5465 + * vim<600: expandtab sw=4 ts=4 sts=4
5466 + */
5467 diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
5468 --- php-5.2.5-orig/ext/apc/apc_futex.c 1969-12-31 18:00:00.000000000 -0600
5469 +++ php-5.2.5/ext/apc/apc_futex.c 2007-12-26 16:51:32.000000000 -0600
5470 @@ -0,0 +1,116 @@
5471 +/*
5472 + +----------------------------------------------------------------------+
5473 + | APC |
5474 + +----------------------------------------------------------------------+
5475 + | Copyright (c) 2006 The PHP Group |
5476 + +----------------------------------------------------------------------+
5477 + | This source file is subject to version 3.01 of the PHP license, |
5478 + | that is bundled with this package in the file LICENSE, and is |
5479 + | available through the world-wide-web at the following url: |
5480 + | http://www.php.net/license/3_01.txt |
5481 + | If you did not receive a copy of the PHP license and are unable to |
5482 + | obtain it through the world-wide-web, please send a note to |
5483 + | license@php.net so we can mail you a copy immediately. |
5484 + +----------------------------------------------------------------------+
5485 + | Authors: Brian Shire <shire@php.net> |
5486 + +----------------------------------------------------------------------+
5487 +
5488 + */
5489 +
5490 +/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5491 +
5492 +/***************************************************************************
5493 +* Futex (Fast Userspace Mutex) support for APC
5494 +*
5495 +* Futex support provides user space locking with system calls only
5496 +* for the contended cases. Some required reading for this functionality is:
5497 +*
5498 +* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux'
5499 +* by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
5500 +* http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
5501 +*
5502 +* 'Futexes are Tricky' by Ulrich Drepper
5503 +* http://people.redhat.com/drepper/futex.pdf
5504 +*
5505 +*
5506 +* This implementation is optimized and designed for the i386 and x86_64
5507 +* architectures. Other architectures may require additional design
5508 +* to efficiently and safely implement this functionality.
5509 +*
5510 +* Lock values are:
5511 +* 0 = Unlocked
5512 +* 1 = Locked without any waiting processes
5513 +* 2 = Locked with an unknown number of waiting processes
5514 +*
5515 +***************************************************************************/
5516 +
5517 +#include "apc.h"
5518 +#include "apc_futex.h"
5519 +
5520 +#ifdef APC_FUTEX_LOCKS
5521 +
5522 +
5523 +inline int apc_futex_create()
5524 +{
5525 + return 0;
5526 +}
5527 +
5528 +inline void apc_futex_destroy(volatile int* lock)
5529 +{
5530 + return;
5531 +}
5532 +
5533 +void apc_futex_lock(volatile int* lock)
5534 +{
5535 + int c;
5536 +
5537 + /* Attempt to obtain a lock if not currently locked. If the previous
5538 + * value was not 0 then we did not obtain the lock, and must wait.
5539 + * If the previous value was 1 (has no waiting processes) then we
5540 + * set the lock to 2 before blocking on the futex wait operation.
5541 + * This implementation suffers from the possible difficulty of
5542 + * efficently implementing the atomic xchg operation on some
5543 + * architectures, and could also cause unecessary wake operations by
5544 + * setting the lock to 2 when there are no additional waiters.
5545 + */
5546 + if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
5547 + if(c != 2) {
5548 + c = apc_xchg(lock, 2);
5549 + }
5550 + while(c != 0) {
5551 + apc_futex_wait(lock, 2);
5552 + c = apc_xchg(lock, 2);
5553 + }
5554 + }
5555 +
5556 +}
5557 +
5558 +/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
5559 +inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
5560 +{
5561 + return apc_cmpxchg(lock, 0, 1) == 0;
5562 +}
5563 +
5564 +
5565 +inline void apc_futex_unlock(volatile int* lock)
5566 +{
5567 + /* set the lock to 0, if it's previous values was not 1 (no waiters)
5568 + * then perform a wake operation on one process letting it know the lock
5569 + * is available. This is an optimization to save wake calls if there
5570 + * are no waiting processes for the lock
5571 + */
5572 + if(apc_xchg(lock,0) != 1) {
5573 + apc_futex_wake(lock, 1);
5574 + }
5575 +}
5576 +
5577 +#endif
5578 +
5579 +/*
5580 + * Local variables:
5581 + * tab-width: 4
5582 + * c-basic-offset: 4
5583 + * End:
5584 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5585 + * vim<600: expandtab sw=4 ts=4 sts=4
5586 + */
5587 diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.h php-5.2.5/ext/apc/apc_futex.h
5588 --- php-5.2.5-orig/ext/apc/apc_futex.h 1969-12-31 18:00:00.000000000 -0600
5589 +++ php-5.2.5/ext/apc/apc_futex.h 2007-12-26 16:51:32.000000000 -0600
5590 @@ -0,0 +1,55 @@
5591 +/*
5592 + +----------------------------------------------------------------------+
5593 + | APC |
5594 + +----------------------------------------------------------------------+
5595 + | Copyright (c) 2006 The PHP Group |
5596 + +----------------------------------------------------------------------+
5597 + | This source file is subject to version 3.01 of the PHP license, |
5598 + | that is bundled with this package in the file LICENSE, and is |
5599 + | available through the world-wide-web at the following url: |
5600 + | http://www.php.net/license/3_01.txt |
5601 + | If you did not receive a copy of the PHP license and are unable to |
5602 + | obtain it through the world-wide-web, please send a note to |
5603 + | license@php.net so we can mail you a copy immediately. |
5604 + +----------------------------------------------------------------------+
5605 + | Authors: Brian Shire <shire@php.net> |
5606 + +----------------------------------------------------------------------+
5607 +
5608 + */
5609 +
5610 +/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5611 +
5612 +#ifndef APC_FUTEX_H
5613 +#define APC_FUTEX_H
5614 +
5615 +#include "apc.h"
5616 +
5617 +#ifdef APC_FUTEX_LOCKS
5618 +
5619 +#include <asm/types.h>
5620 +#include <unistd.h>
5621 +#include <linux/futex.h>
5622 +
5623 +#include "arch/atomic.h"
5624 +
5625 +#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
5626 +#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
5627 +#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
5628 +
5629 +int apc_futex_create();
5630 +void apc_futex_destroy(volatile int* lock);
5631 +void apc_futex_lock(volatile int* lock);
5632 +void apc_futex_unlock(volatile int* lock);
5633 +
5634 +#endif
5635 +
5636 +#endif
5637 +
5638 +/*
5639 + * Local variables:
5640 + * tab-width: 4
5641 + * c-basic-offset: 4
5642 + * End:
5643 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5644 + * vim<600: expandtab sw=4 ts=4 sts=4
5645 + */
5646 diff -ubrN php-5.2.5-orig/ext/apc/apc_globals.h php-5.2.5/ext/apc/apc_globals.h
5647 --- php-5.2.5-orig/ext/apc/apc_globals.h 1969-12-31 18:00:00.000000000 -0600
5648 +++ php-5.2.5/ext/apc/apc_globals.h 2007-12-26 16:51:32.000000000 -0600
5649 @@ -0,0 +1,119 @@
5650 +/*
5651 + +----------------------------------------------------------------------+
5652 + | APC |
5653 + +----------------------------------------------------------------------+
5654 + | Copyright (c) 2006 The PHP Group |
5655 + +----------------------------------------------------------------------+
5656 + | This source file is subject to version 3.01 of the PHP license, |
5657 + | that is bundled with this package in the file LICENSE, and is |
5658 + | available through the world-wide-web at the following url: |
5659 + | http://www.php.net/license/3_01.txt. |
5660 + | If you did not receive a copy of the PHP license and are unable to |
5661 + | obtain it through the world-wide-web, please send a note to |
5662 + | license@php.net so we can mail you a copy immediately. |
5663 + +----------------------------------------------------------------------+
5664 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5665 + | George Schlossnagle <george@omniti.com> |
5666 + | Rasmus Lerdorf <rasmus@php.net> |
5667 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5668 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5669 + +----------------------------------------------------------------------+
5670 +
5671 + This software was contributed to PHP by Community Connect Inc. in 2002
5672 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5673 + Future revisions and derivatives of this source code must acknowledge
5674 + Community Connect Inc. as the original contributor of this module by
5675 + leaving this note intact in the source code.
5676 +
5677 + All other licensing and usage conditions are those of the PHP Group.
5678 +
5679 + */
5680 +
5681 +/* $Id: apc_globals.h,v 3.70 2007/12/26 22:46:33 rasmus Exp $ */
5682 +
5683 +#ifndef APC_GLOBALS_H
5684 +#define APC_GLOBALS_H
5685 +
5686 +#define APC_VERSION "3.0.16"
5687 +
5688 +#include "apc_cache.h"
5689 +#include "apc_stack.h"
5690 +#include "apc_php.h"
5691 +
5692 +ZEND_BEGIN_MODULE_GLOBALS(apc)
5693 + /* configuration parameters */
5694 + zend_bool enabled; /* if true, apc is enabled (defaults to true) */
5695 + long shm_segments; /* number of shared memory segments to use */
5696 + long shm_size; /* size of each shared memory segment (in MB) */
5697 + long num_files_hint; /* parameter to apc_cache_create */
5698 + long user_entries_hint;
5699 + long gc_ttl; /* parameter to apc_cache_create */
5700 + long ttl; /* parameter to apc_cache_create */
5701 + long user_ttl;
5702 +#if APC_MMAP
5703 + char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */
5704 +#endif
5705 + char** filters; /* array of regex filters that prevent caching */
5706 +
5707 + /* module variables */
5708 + zend_bool initialized; /* true if module was initialized */
5709 + apc_stack_t* cache_stack; /* the stack of cached executable code */
5710 + zend_bool cache_by_default; /* true if files should be cached unless filtered out */
5711 + /* false if files should only be cached if filtered in */
5712 + long slam_defense; /* Probability of a process not caching an uncached file */
5713 + size_t* mem_size_ptr; /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
5714 + long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
5715 + zend_bool enable_cli; /* Flag to override turning APC off for CLI */
5716 + long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */
5717 + long slam_rand; /* A place to store the slam rand value for the request */
5718 + zend_bool fpstat; /* true if fullpath includes should be stat'ed */
5719 + zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */
5720 + zend_bool write_lock; /* true for a global write lock */
5721 + zend_bool report_autofilter; /* true for auto-filter warnings */
5722 + zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
5723 + apc_optimize_function_t apc_optimize_function; /* optimizer function callback */
5724 +#ifdef MULTIPART_EVENT_FORMDATA
5725 + zend_bool rfc1867; /* Flag to enable rfc1867 handler */
5726 + char* rfc1867_prefix; /* Key prefix */
5727 + char* rfc1867_name; /* Name of hidden field to activate upload progress/key suffix */
5728 + double rfc1867_freq; /* Update frequency as percentage or bytes */
5729 +#endif
5730 + HashTable *copied_zvals; /* my_copy recursion detection list */
5731 +#ifdef ZEND_ENGINE_2
5732 + int reserved_offset; /* offset for apc info in op_array->reserved[] */
5733 +#endif
5734 + zend_bool localcache; /* enable local cache */
5735 + long localcache_size; /* size of fast cache */
5736 + apc_local_cache_t* lcache; /* unlocked local cache */
5737 + zend_bool force_file_update; /* force files to be updated during apc_compile_file */
5738 + char canon_path[MAXPATHLEN]; /* canonical path for key data */
5739 +#if APC_FILEHITS
5740 + zval *filehits; /* Files that came from the cache for this request */
5741 +#endif
5742 + zend_bool coredump_unmap; /* Trap signals that coredump and unmap shared memory */
5743 +ZEND_END_MODULE_GLOBALS(apc)
5744 +
5745 +/* (the following declaration is defined in php_apc.c) */
5746 +ZEND_EXTERN_MODULE_GLOBALS(apc)
5747 +
5748 +#ifdef ZTS
5749 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
5750 +#else
5751 +# define APCG(v) (apc_globals.v)
5752 +#endif
5753 +
5754 +/* True globals */
5755 +extern apc_cache_t* apc_cache; /* the global compiler cache */
5756 +extern apc_cache_t* apc_user_cache; /* the global user content cache */
5757 +extern void* apc_compiled_filters; /* compiled filters */
5758 +
5759 +#endif
5760 +
5761 +/*
5762 + * Local variables:
5763 + * tab-width: 4
5764 + * c-basic-offset: 4
5765 + * End:
5766 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5767 + * vim<600: expandtab sw=4 ts=4 sts=4
5768 + */
5769 diff -ubrN php-5.2.5-orig/ext/apc/apc.h php-5.2.5/ext/apc/apc.h
5770 --- php-5.2.5-orig/ext/apc/apc.h 1969-12-31 18:00:00.000000000 -0600
5771 +++ php-5.2.5/ext/apc/apc.h 2007-12-26 16:51:32.000000000 -0600
5772 @@ -0,0 +1,126 @@
5773 +/*
5774 + +----------------------------------------------------------------------+
5775 + | APC |
5776 + +----------------------------------------------------------------------+
5777 + | Copyright (c) 2006 The PHP Group |
5778 + +----------------------------------------------------------------------+
5779 + | This source file is subject to version 3.01 of the PHP license, |
5780 + | that is bundled with this package in the file LICENSE, and is |
5781 + | available through the world-wide-web at the following url: |
5782 + | http://www.php.net/license/3_01.txt |
5783 + | If you did not receive a copy of the PHP license and are unable to |
5784 + | obtain it through the world-wide-web, please send a note to |
5785 + | license@php.net so we can mail you a copy immediately. |
5786 + +----------------------------------------------------------------------+
5787 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5788 + | George Schlossnagle <george@omniti.com> |
5789 + | Rasmus Lerdorf <rasmus@php.net> |
5790 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5791 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5792 + +----------------------------------------------------------------------+
5793 +
5794 + This software was contributed to PHP by Community Connect Inc. in 2002
5795 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5796 + Future revisions and derivatives of this source code must acknowledge
5797 + Community Connect Inc. as the original contributor of this module by
5798 + leaving this note intact in the source code.
5799 +
5800 + All other licensing and usage conditions are those of the PHP Group.
5801 +
5802 + */
5803 +
5804 +/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
5805 +
5806 +#ifndef APC_H
5807 +#define APC_H
5808 +
5809 +/*
5810 + * This module defines utilities and helper functions used elsewhere in APC.
5811 + */
5812 +
5813 +/* Commonly needed C library headers. */
5814 +#include <assert.h>
5815 +#include <errno.h>
5816 +#include <stdarg.h>
5817 +#include <stdio.h>
5818 +#include <stdlib.h>
5819 +#include <string.h>
5820 +#include <time.h>
5821 +
5822 +/* UNIX headers (needed for struct stat) */
5823 +#include <sys/types.h>
5824 +#include <sys/stat.h>
5825 +#ifndef PHP_WIN32
5826 +#include <unistd.h>
5827 +#endif
5828 +
5829 +#ifdef HAVE_CONFIG_H
5830 +#include <config.h>
5831 +#endif
5832 +
5833 +#include "php.h"
5834 +
5835 +/* log levels constants (see apc_log) */
5836 +enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
5837 +
5838 +/* typedefs for extensible memory allocators */
5839 +typedef void* (*apc_malloc_t)(size_t);
5840 +typedef void (*apc_free_t) (void*);
5841 +
5842 +/* wrappers for memory allocation routines */
5843 +extern void* apc_emalloc(size_t n);
5844 +extern void* apc_erealloc(void* p, size_t n);
5845 +extern void apc_efree(void* p);
5846 +extern char* apc_estrdup(const char* s);
5847 +extern void* apc_xstrdup(const char* s, apc_malloc_t f);
5848 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
5849 +
5850 +/* console display functions */
5851 +extern void apc_log(int level, const char* fmt, ...);
5852 +extern void apc_eprint(const char* fmt, ...);
5853 +extern void apc_wprint(const char* fmt, ...);
5854 +extern void apc_dprint(const char* fmt, ...);
5855 +extern void apc_nprint(const char* fmt, ...);
5856 +
5857 +/* string and text manipulation */
5858 +extern char* apc_append(const char* s, const char* t);
5859 +extern char* apc_substr(const char* s, int start, int length);
5860 +extern char** apc_tokenize(const char* s, char delim);
5861 +
5862 +/* filesystem functions */
5863 +
5864 +typedef struct apc_fileinfo_t
5865 +{
5866 + char fullpath[MAXPATHLEN+1];
5867 + struct stat st_buf;
5868 +} apc_fileinfo_t;
5869 +
5870 +#ifndef PHP_WIN32
5871 +#define apc_stat(f, b) stat(f, b)
5872 +#else
5873 +#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
5874 +extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
5875 +#endif
5876 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
5877 +
5878 +/* regular expression wrapper functions */
5879 +extern void* apc_regex_compile_array(char* patterns[]);
5880 +extern void apc_regex_destroy_array(void* p);
5881 +extern int apc_regex_match_array(void* p, const char* input);
5882 +
5883 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
5884 +extern unsigned int apc_crc32(const char* buf, int len);
5885 +
5886 +#define APC_NEGATIVE_MATCH 1
5887 +#define APC_POSITIVE_MATCH 2
5888 +
5889 +#endif
5890 +
5891 +/*
5892 + * Local variables:
5893 + * tab-width: 4
5894 + * c-basic-offset: 4
5895 + * End:
5896 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5897 + * vim<600: expandtab sw=4 ts=4 sts=4
5898 + */
5899 diff -ubrN php-5.2.5-orig/ext/apc/apc_lock.h php-5.2.5/ext/apc/apc_lock.h
5900 --- php-5.2.5-orig/ext/apc/apc_lock.h 1969-12-31 18:00:00.000000000 -0600
5901 +++ php-5.2.5/ext/apc/apc_lock.h 2007-12-26 16:51:32.000000000 -0600
5902 @@ -0,0 +1,105 @@
5903 +/*
5904 + +----------------------------------------------------------------------+
5905 + | APC |
5906 + +----------------------------------------------------------------------+
5907 + | Copyright (c) 2006 The PHP Group |
5908 + +----------------------------------------------------------------------+
5909 + | This source file is subject to version 3.01 of the PHP license, |
5910 + | that is bundled with this package in the file LICENSE, and is |
5911 + | available through the world-wide-web at the following url: |
5912 + | http://www.php.net/license/3_01.txt |
5913 + | If you did not receive a copy of the PHP license and are unable to |
5914 + | obtain it through the world-wide-web, please send a note to |
5915 + | license@php.net so we can mail you a copy immediately. |
5916 + +----------------------------------------------------------------------+
5917 + | Authors: George Schlossnagle <george@omniti.com> |
5918 + | Rasmus Lerdorf <rasmus@php.net> |
5919 + +----------------------------------------------------------------------+
5920 +
5921 + This software was contributed to PHP by Community Connect Inc. in 2002
5922 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5923 + Future revisions and derivatives of this source code must acknowledge
5924 + Community Connect Inc. as the original contributor of this module by
5925 + leaving this note intact in the source code.
5926 +
5927 + All other licensing and usage conditions are those of the PHP Group.
5928 +
5929 + */
5930 +
5931 +/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
5932 +
5933 +#ifndef APC_LOCK
5934 +#define APC_LOCK
5935 +
5936 +#include "apc_sem.h"
5937 +#include "apc_fcntl.h"
5938 +#include "apc_pthreadmutex.h"
5939 +#include "apc_futex.h"
5940 +#include "apc_spin.h"
5941 +#ifdef HAVE_CONFIG_H
5942 +#include <config.h>
5943 +#endif
5944 +
5945 +#ifdef TSRM_LOCKS
5946 +#define RDLOCK_AVAILABLE 0
5947 +#define NONBLOCKING_LOCK_AVAILABLE 0
5948 +/* quick & dirty: use TSRM mutex locks for now */
5949 +#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
5950 +#define apc_lck_destroy(a) tsrm_mutex_free((MUTEX_T)a)
5951 +#define apc_lck_lock(a) tsrm_mutex_lock((MUTEX_T)a)
5952 +#define apc_lck_rdlock(a) tsrm_mutex_lock((MUTEX_T)a)
5953 +#define apc_lck_unlock(a) tsrm_mutex_unlock((MUTEX_T)a)
5954 +#elif defined(APC_SEM_LOCKS)
5955 +#define RDLOCK_AVAILABLE 0
5956 +#define NONBLOCKING_LOCK_AVAILABLE 0
5957 +#define apc_lck_t int
5958 +#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
5959 +#define apc_lck_destroy(a) apc_sem_destroy(a)
5960 +#define apc_lck_lock(a) apc_sem_lock(a)
5961 +#define apc_lck_rdlock(a) apc_sem_lock(a)
5962 +#define apc_lck_unlock(a) apc_sem_unlock(a)
5963 +#elif defined(APC_PTHREADMUTEX_LOCKS)
5964 +#define RDLOCK_AVAILABLE 0
5965 +#define NONBLOCKING_LOCK_AVAILABLE 1
5966 +#define apc_lck_t pthread_mutex_t
5967 +#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
5968 +#define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a)
5969 +#define apc_lck_lock(a) apc_pthreadmutex_lock(&a)
5970 +#define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a)
5971 +#define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a)
5972 +#define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a)
5973 +#elif defined(APC_FUTEX_LOCKS)
5974 +#define NONBLOCKING_LOCK_AVAILABLE 1
5975 +#define apc_lck_t int
5976 +#define apc_lck_create(a,b,c,d) d=apc_futex_create()
5977 +#define apc_lck_destroy(a) apc_futex_destroy(&a)
5978 +#define apc_lck_lock(a) apc_futex_lock(&a)
5979 +#define apc_lck_nb_lock(a) apc_futex_nonblocking_lock(&a)
5980 +#define apc_lck_rdlock(a) apc_futex_lock(&a)
5981 +#define apc_lck_unlock(a) apc_futex_unlock(&a)
5982 +#elif defined(APC_SPIN_LOCKS)
5983 +#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
5984 +#define apc_lck_t slock_t
5985 +#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
5986 +#define apc_lck_destroy(a) apc_slock_destroy(&a)
5987 +#define apc_lck_lock(a) apc_slock_lock(&a)
5988 +#define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a)
5989 +#define apc_lck_rdlock(a) apc_slock_lock(&a)
5990 +#define apc_lck_unlock(a) apc_slock_unlock(&a)
5991 +#else
5992 +#define RDLOCK_AVAILABLE 1
5993 +#ifdef PHP_WIN32
5994 +#define NONBLOCKING_LOCK_AVAILABLE 0
5995 +#else
5996 +#define NONBLOCKING_LOCK_AVAILABLE 1
5997 +#endif
5998 +#define apc_lck_t int
5999 +#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
6000 +#define apc_lck_destroy(a) apc_fcntl_destroy(a)
6001 +#define apc_lck_lock(a) apc_fcntl_lock(a)
6002 +#define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a)
6003 +#define apc_lck_rdlock(a) apc_fcntl_rdlock(a)
6004 +#define apc_lck_unlock(a) apc_fcntl_unlock(a)
6005 +#endif
6006 +
6007 +#endif
6008 diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
6009 --- php-5.2.5-orig/ext/apc/apc_main.c 1969-12-31 18:00:00.000000000 -0600
6010 +++ php-5.2.5/ext/apc/apc_main.c 2007-12-26 16:51:32.000000000 -0600
6011 @@ -0,0 +1,701 @@
6012 +/*
6013 + +----------------------------------------------------------------------+
6014 + | APC |
6015 + +----------------------------------------------------------------------+
6016 + | Copyright (c) 2006 The PHP Group |
6017 + +----------------------------------------------------------------------+
6018 + | This source file is subject to version 3.01 of the PHP license, |
6019 + | that is bundled with this package in the file LICENSE, and is |
6020 + | available through the world-wide-web at the following url: |
6021 + | http://www.php.net/license/3_01.txt |
6022 + | If you did not receive a copy of the PHP license and are unable to |
6023 + | obtain it through the world-wide-web, please send a note to |
6024 + | license@php.net so we can mail you a copy immediately. |
6025 + +----------------------------------------------------------------------+
6026 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6027 + | Rasmus Lerdorf <rasmus@php.net> |
6028 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6029 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6030 + +----------------------------------------------------------------------+
6031 +
6032 + This software was contributed to PHP by Community Connect Inc. in 2002
6033 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6034 + Future revisions and derivatives of this source code must acknowledge
6035 + Community Connect Inc. as the original contributor of this module by
6036 + leaving this note intact in the source code.
6037 +
6038 + All other licensing and usage conditions are those of the PHP Group.
6039 +
6040 + */
6041 +
6042 +/* $Id: apc_main.c,v 3.103 2007/11/14 19:46:46 shire Exp $ */
6043 +
6044 +#include "apc_php.h"
6045 +#include "apc_main.h"
6046 +#include "apc.h"
6047 +#include "apc_lock.h"
6048 +#include "apc_cache.h"
6049 +#include "apc_compile.h"
6050 +#include "apc_globals.h"
6051 +#include "apc_sma.h"
6052 +#include "apc_stack.h"
6053 +#include "apc_zend.h"
6054 +#include "SAPI.h"
6055 +#if PHP_API_VERSION <= 20020918
6056 +#if HAVE_APACHE
6057 +#ifdef APC_PHP4_STAT
6058 +#undef XtOffsetOf
6059 +#include "httpd.h"
6060 +#endif
6061 +#endif
6062 +#endif
6063 +
6064 +/* {{{ module variables */
6065 +
6066 +/* pointer to the original Zend engine compile_file function */
6067 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
6068 +static zend_compile_t *old_compile_file;
6069 +
6070 +/* }}} */
6071 +
6072 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
6073 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
6074 +{
6075 + zend_compile_t *retval = old_compile_file;
6076 +
6077 + if (ptr != NULL) old_compile_file = ptr;
6078 + return retval;
6079 +}
6080 +/* }}} */
6081 +
6082 +/* {{{ install_function */
6083 +static int install_function(apc_function_t fn TSRMLS_DC)
6084 +{
6085 + int status =
6086 + zend_hash_add(EG(function_table),
6087 + fn.name,
6088 + fn.name_len+1,
6089 + apc_copy_function_for_execution(fn.function),
6090 + sizeof(fn.function[0]),
6091 + NULL);
6092 +
6093 + if (status == FAILURE) {
6094 + /* apc_eprint("Cannot redeclare %s()", fn.name); */
6095 + }
6096 +
6097 + return status;
6098 +}
6099 +/* }}} */
6100 +
6101 +/* {{{ install_class */
6102 +static int install_class(apc_class_t cl TSRMLS_DC)
6103 +{
6104 + zend_class_entry* class_entry = cl.class_entry;
6105 + zend_class_entry* parent = NULL;
6106 + int status;
6107 +#ifdef ZEND_ENGINE_2
6108 + zend_class_entry** allocated_ce = NULL;
6109 +#endif
6110 +
6111 +
6112 + /* Special case for mangled names. Mangled names are unique to a file.
6113 + * There is no way two classes with the same mangled name will occur,
6114 + * unless a file is included twice. And if in case, a file is included
6115 + * twice, all mangled name conflicts can be ignored and the class redeclaration
6116 + * error may be deferred till runtime of the corresponding DECLARE_CLASS
6117 + * calls.
6118 + */
6119 +
6120 + if(cl.name_len != 0 && cl.name[0] == '\0') {
6121 + if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
6122 + return SUCCESS;
6123 + }
6124 + }
6125 +
6126 +#ifdef ZEND_ENGINE_2
6127 + /*
6128 + * XXX: We need to free this somewhere...
6129 + */
6130 + allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
6131 +
6132 + if(!allocated_ce) {
6133 + return FAILURE;
6134 + }
6135 +
6136 + *allocated_ce =
6137 +#endif
6138 + class_entry =
6139 + apc_copy_class_entry_for_execution(cl.class_entry,
6140 + cl.is_derived);
6141 +
6142 +
6143 + /* restore parent class pointer for compile-time inheritance */
6144 + if (cl.parent_name != NULL) {
6145 +#ifdef ZEND_ENGINE_2
6146 + zend_class_entry** parent_ptr = NULL;
6147 + /*
6148 + * zend_lookup_class has to be due to presence of __autoload,
6149 + * just looking up the EG(class_table) is not enough in php5!
6150 + * Even more dangerously, thanks to __autoload and people using
6151 + * class names as filepaths for inclusion, this has to be case
6152 + * sensitive. zend_lookup_class automatically does a case_fold
6153 + * internally, but passes the case preserved version to __autoload.
6154 + * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
6155 + * zend_lookup_class does it internally anyway!
6156 + */
6157 + status = zend_lookup_class(cl.parent_name,
6158 + strlen(cl.parent_name),
6159 + &parent_ptr TSRMLS_CC);
6160 +#else
6161 + status = zend_hash_find(EG(class_table),
6162 + cl.parent_name,
6163 + strlen(cl.parent_name)+1,
6164 + (void**) &parent);
6165 +#endif
6166 + if (status == FAILURE) {
6167 + if(APCG(report_autofilter)) {
6168 + apc_wprint("Dynamic inheritance detected for class %s", cl.name);
6169 + }
6170 + class_entry->parent = NULL;
6171 + return status;
6172 + }
6173 + else {
6174 +#ifdef ZEND_ENGINE_2
6175 + parent = *parent_ptr;
6176 +#endif
6177 + class_entry->parent = parent;
6178 +#ifdef ZEND_ENGINE_2
6179 + zend_do_inheritance(class_entry, parent TSRMLS_CC);
6180 +#else
6181 + zend_do_inheritance(class_entry, parent);
6182 +#endif
6183 + }
6184 +
6185 +
6186 + }
6187 +
6188 +#ifdef ZEND_ENGINE_2
6189 + status = zend_hash_add(EG(class_table),
6190 + cl.name,
6191 + cl.name_len+1,
6192 + allocated_ce,
6193 + sizeof(zend_class_entry*),
6194 + NULL);
6195 +#else
6196 + status = zend_hash_add(EG(class_table),
6197 + cl.name,
6198 + cl.name_len+1,
6199 + class_entry,
6200 + sizeof(zend_class_entry),
6201 + NULL);
6202 +#endif
6203 +
6204 + if (status == FAILURE) {
6205 + apc_eprint("Cannot redeclare class %s", cl.name);
6206 + }
6207 + return status;
6208 +}
6209 +/* }}} */
6210 +
6211 +/* {{{ uninstall_class */
6212 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
6213 +{
6214 + int status;
6215 +
6216 +#ifdef ZEND_ENGINE_2
6217 + status = zend_hash_del(EG(class_table),
6218 + cl.name,
6219 + cl.name_len+1);
6220 +#else
6221 + status = zend_hash_del(EG(class_table),
6222 + cl.name,
6223 + cl.name_len+1);
6224 +#endif
6225 + if (status == FAILURE) {
6226 + apc_eprint("Cannot delete class %s", cl.name);
6227 + }
6228 + return status;
6229 +}
6230 +/* }}} */
6231 +
6232 +/* {{{ compare_file_handles */
6233 +static int compare_file_handles(void* a, void* b)
6234 +{
6235 + zend_file_handle* fh1 = (zend_file_handle*)a;
6236 + zend_file_handle* fh2 = (zend_file_handle*)b;
6237 + return (fh1->type == fh2->type &&
6238 + fh1->filename == fh2->filename &&
6239 + fh1->opened_path == fh2->opened_path);
6240 +}
6241 +/* }}} */
6242 +
6243 +/* {{{ cached_compile */
6244 +static zend_op_array* cached_compile(zend_file_handle* h,
6245 + int type TSRMLS_DC)
6246 +{
6247 + apc_cache_entry_t* cache_entry;
6248 + int i, ii;
6249 +
6250 + cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
6251 + assert(cache_entry != NULL);
6252 +
6253 + if (cache_entry->data.file.classes) {
6254 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6255 + if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
6256 + goto default_compile;
6257 + }
6258 + }
6259 + }
6260 +
6261 + if (cache_entry->data.file.functions) {
6262 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6263 + install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
6264 + }
6265 + }
6266 +
6267 +
6268 + return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
6269 +
6270 +default_compile:
6271 +
6272 + if(APCG(report_autofilter)) {
6273 + apc_wprint("Autofiltering %s", h->opened_path);
6274 + }
6275 +
6276 + if(cache_entry->data.file.classes) {
6277 + for(ii = 0; ii < i ; ii++) {
6278 + uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
6279 + }
6280 + }
6281 +
6282 + apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
6283 +
6284 + apc_cache_release(apc_cache, cache_entry);
6285 +
6286 + /* cannot free up cache data yet, it maybe in use */
6287 +
6288 + zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
6289 +
6290 + h->type = ZEND_HANDLE_FILENAME;
6291 +
6292 + return NULL;
6293 +}
6294 +/* }}} */
6295 +
6296 +/* {{{ my_compile_file
6297 + Overrides zend_compile_file */
6298 +static zend_op_array* my_compile_file(zend_file_handle* h,
6299 + int type TSRMLS_DC)
6300 +{
6301 + apc_cache_key_t key;
6302 + apc_cache_entry_t* cache_entry;
6303 + zend_op_array* op_array;
6304 + int num_functions, num_classes, ret;
6305 + zend_op_array* alloc_op_array;
6306 + apc_function_t* alloc_functions;
6307 + apc_class_t* alloc_classes;
6308 + time_t t;
6309 + char *path;
6310 + size_t mem_size;
6311 +
6312 + if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
6313 + return old_compile_file(h, type TSRMLS_CC);
6314 + }
6315 +
6316 + /* check our regular expression filters */
6317 + if (APCG(filters) && apc_compiled_filters) {
6318 + int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
6319 + if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
6320 + return old_compile_file(h, type TSRMLS_CC);
6321 + }
6322 + } else if(!APCG(cache_by_default)) {
6323 + return old_compile_file(h, type TSRMLS_CC);
6324 + }
6325 +
6326 +#if PHP_API_VERSION < 20041225
6327 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
6328 + t = ((request_rec *)SG(server_context))->request_time;
6329 +#else
6330 + t = time(0);
6331 +#endif
6332 +#else
6333 + t = sapi_get_request_time(TSRMLS_C);
6334 +#endif
6335 +
6336 +#ifdef __DEBUG_APC__
6337 + fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6338 +#endif
6339 +
6340 + /* try to create a cache key; if we fail, give up on caching */
6341 + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
6342 + return old_compile_file(h, type TSRMLS_CC);
6343 + }
6344 +
6345 +
6346 + if(!APCG(force_file_update)) {
6347 + if(APCG(localcache)) {
6348 + /* search for the file in the local cache */
6349 + cache_entry = apc_local_cache_find(APCG(lcache), key, t);
6350 + } else {
6351 + /* search for the file in the cache */
6352 + cache_entry = apc_cache_find(apc_cache, key, t);
6353 + }
6354 + } else {
6355 + cache_entry = NULL;
6356 + }
6357 +
6358 + if (cache_entry != NULL) {
6359 + int dummy = 1;
6360 + if (h->opened_path == NULL) {
6361 + h->opened_path = estrdup(cache_entry->data.file.filename);
6362 + }
6363 + zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
6364 + zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
6365 + apc_stack_push(APCG(cache_stack), cache_entry);
6366 + op_array = cached_compile(h, type TSRMLS_CC);
6367 + if(op_array) {
6368 +#ifdef APC_FILEHITS
6369 + /* If the file comes from the cache, add it to the global request file list */
6370 + add_next_index_string(APCG(filehits), h->filename, 1);
6371 +#endif
6372 + return op_array;
6373 + }
6374 + if(APCG(report_autofilter)) {
6375 + apc_wprint("Recompiling %s", h->opened_path);
6376 + }
6377 + /* TODO: check what happens with EG(included_files) */
6378 + }
6379 +
6380 + if(apc_cache_busy(apc_cache) && APCG(localcache)) {
6381 + /* possibly local cache returned NULL because cache is busy */
6382 + return old_compile_file(h, type TSRMLS_CC);
6383 + }
6384 +
6385 + /* remember how many functions and classes existed before compilation */
6386 + num_functions = zend_hash_num_elements(CG(function_table));
6387 + num_classes = zend_hash_num_elements(CG(class_table));
6388 +
6389 + /* compile the file using the default compile function */
6390 + op_array = old_compile_file(h, type TSRMLS_CC);
6391 + if (op_array == NULL) {
6392 + return NULL;
6393 + }
6394 + /*
6395 + * Basically this will cause a file only to be cached on a percentage
6396 + * of the attempts. This is to avoid cache slams when starting up a
6397 + * very busy server or when modifying files on a very busy live server.
6398 + * There is no point having many processes all trying to cache the same
6399 + * file at the same time. By introducing a chance of being cached
6400 + * we theoretically cut the cache slam problem by the given percentage.
6401 + * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
6402 + * to cache an uncached file will be ignored.
6403 + */
6404 + if(APCG(slam_defense)) {
6405 + if(APCG(slam_rand)==-1) {
6406 + APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
6407 + }
6408 + if(APCG(slam_rand) < APCG(slam_defense)) {
6409 + return op_array;
6410 + }
6411 + }
6412 +
6413 + /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
6414 + if(key.type == APC_CACHE_KEY_FPFILE) {
6415 + apc_fileinfo_t fileinfo;
6416 + struct stat *tmp_buf = NULL;
6417 + if(!strcmp(SG(request_info).path_translated, h->filename)) {
6418 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
6419 + }
6420 + if(tmp_buf) {
6421 + fileinfo.st_buf = *tmp_buf;
6422 + } else {
6423 + if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
6424 +#ifdef __DEBUG_APC__
6425 + fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
6426 +#endif
6427 + return op_array;
6428 + }
6429 + }
6430 + key.mtime = fileinfo.st_buf.st_mtime;
6431 + }
6432 +
6433 + HANDLE_BLOCK_INTERRUPTIONS();
6434 +
6435 +#if NONBLOCKING_LOCK_AVAILABLE
6436 + if(APCG(write_lock)) {
6437 + if(!apc_cache_write_lock(apc_cache)) {
6438 + HANDLE_UNBLOCK_INTERRUPTIONS();
6439 + return op_array;
6440 + }
6441 + }
6442 +#endif
6443 +
6444 + mem_size = 0;
6445 + APCG(mem_size_ptr) = &mem_size;
6446 + if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6447 + apc_cache_expunge(apc_cache,t);
6448 + apc_cache_expunge(apc_user_cache,t);
6449 + APCG(mem_size_ptr) = NULL;
6450 +#if NONBLOCKING_LOCK_AVAILABLE
6451 + if(APCG(write_lock)) {
6452 + apc_cache_write_unlock(apc_cache);
6453 + }
6454 +#endif
6455 + HANDLE_UNBLOCK_INTERRUPTIONS();
6456 + return op_array;
6457 + }
6458 +
6459 + if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6460 + apc_free_op_array(alloc_op_array, apc_sma_free);
6461 + apc_cache_expunge(apc_cache,t);
6462 + apc_cache_expunge(apc_user_cache,t);
6463 + APCG(mem_size_ptr) = NULL;
6464 +#if NONBLOCKING_LOCK_AVAILABLE
6465 + if(APCG(write_lock)) {
6466 + apc_cache_write_unlock(apc_cache);
6467 + }
6468 +#endif
6469 + HANDLE_UNBLOCK_INTERRUPTIONS();
6470 + return op_array;
6471 + }
6472 + if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6473 + apc_free_op_array(alloc_op_array, apc_sma_free);
6474 + apc_free_functions(alloc_functions, apc_sma_free);
6475 + apc_cache_expunge(apc_cache,t);
6476 + apc_cache_expunge(apc_user_cache,t);
6477 + APCG(mem_size_ptr) = NULL;
6478 +#if NONBLOCKING_LOCK_AVAILABLE
6479 + if(APCG(write_lock)) {
6480 + apc_cache_write_unlock(apc_cache);
6481 + }
6482 +#endif
6483 + HANDLE_UNBLOCK_INTERRUPTIONS();
6484 + return op_array;
6485 + }
6486 +
6487 + path = h->opened_path;
6488 + if(!path) path=h->filename;
6489 +
6490 +#ifdef __DEBUG_APC__
6491 + fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6492 +#endif
6493 +
6494 + if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
6495 + apc_free_op_array(alloc_op_array, apc_sma_free);
6496 + apc_free_functions(alloc_functions, apc_sma_free);
6497 + apc_free_classes(alloc_classes, apc_sma_free);
6498 + apc_cache_expunge(apc_cache,t);
6499 + apc_cache_expunge(apc_user_cache,t);
6500 + APCG(mem_size_ptr) = NULL;
6501 +#if NONBLOCKING_LOCK_AVAILABLE
6502 + if(APCG(write_lock)) {
6503 + apc_cache_write_unlock(apc_cache);
6504 + }
6505 +#endif
6506 + HANDLE_UNBLOCK_INTERRUPTIONS();
6507 + return op_array;
6508 + }
6509 + APCG(mem_size_ptr) = NULL;
6510 + cache_entry->mem_size = mem_size;
6511 +
6512 + if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
6513 + apc_cache_free_entry(cache_entry);
6514 + if(ret==-1) {
6515 + apc_cache_expunge(apc_cache,t);
6516 + apc_cache_expunge(apc_user_cache,t);
6517 + }
6518 + }
6519 +
6520 +#if NONBLOCKING_LOCK_AVAILABLE
6521 + if(APCG(write_lock)) {
6522 + apc_cache_write_unlock(apc_cache);
6523 + }
6524 +#endif
6525 + HANDLE_UNBLOCK_INTERRUPTIONS();
6526 +
6527 + return op_array;
6528 +}
6529 +/* }}} */
6530 +
6531 +/* {{{ module init and shutdown */
6532 +
6533 +int apc_module_init(int module_number TSRMLS_DC)
6534 +{
6535 + /* apc initialization */
6536 +#if APC_MMAP
6537 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
6538 +#else
6539 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
6540 +#endif
6541 + apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
6542 + apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
6543 +
6544 + apc_compiled_filters = apc_regex_compile_array(APCG(filters));
6545 +
6546 + /* override compilation */
6547 + old_compile_file = zend_compile_file;
6548 + zend_compile_file = my_compile_file;
6549 + REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
6550 +
6551 + APCG(initialized) = 1;
6552 + return 0;
6553 +}
6554 +
6555 +int apc_module_shutdown(TSRMLS_D)
6556 +{
6557 + if (!APCG(initialized))
6558 + return 0;
6559 +
6560 + /* restore compilation */
6561 + zend_compile_file = old_compile_file;
6562 +
6563 + /*
6564 + * In case we got interrupted by a SIGTERM or something else during execution
6565 + * we may have cache entries left on the stack that we need to check to make
6566 + * sure that any functions or classes these may have added to the global function
6567 + * and class tables are removed before we blow away the memory that hold them.
6568 + *
6569 + * This is merely to remove memory leak warnings - as the process is terminated
6570 + * immediately after shutdown. The following while loop can be removed without
6571 + * affecting anything else.
6572 + */
6573 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6574 + int i;
6575 + apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6576 + if (cache_entry->data.file.functions) {
6577 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6578 + zend_hash_del(EG(function_table),
6579 + cache_entry->data.file.functions[i].name,
6580 + cache_entry->data.file.functions[i].name_len+1);
6581 + }
6582 + }
6583 + if (cache_entry->data.file.classes) {
6584 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6585 + zend_hash_del(EG(class_table),
6586 + cache_entry->data.file.classes[i].name,
6587 + cache_entry->data.file.classes[i].name_len+1);
6588 + }
6589 + }
6590 + apc_cache_release(apc_cache, cache_entry);
6591 + }
6592 +
6593 + apc_cache_destroy(apc_cache);
6594 + apc_cache_destroy(apc_user_cache);
6595 + apc_sma_cleanup();
6596 +
6597 + APCG(initialized) = 0;
6598 + return 0;
6599 +}
6600 +
6601 +/* }}} */
6602 +
6603 +/* {{{ process init and shutdown */
6604 +int apc_process_init(int module_number TSRMLS_DC)
6605 +{
6606 + int minttl = (APCG(gc_ttl) > APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
6607 + int size = APCG(localcache_size);
6608 + if(APCG(initialized) && APCG(localcache)) {
6609 + /* TTL is 2 mins by default */
6610 + APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120);
6611 + }
6612 + return 0;
6613 +}
6614 +
6615 +int apc_process_shutdown(TSRMLS_D)
6616 +{
6617 + if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
6618 + apc_local_cache_destroy(APCG(lcache));
6619 + APCG(lcache) = NULL;
6620 + }
6621 + return 0;
6622 +}
6623 +/* }}} */
6624 +
6625 +/* {{{ request init and shutdown */
6626 +
6627 +int apc_request_init(TSRMLS_D)
6628 +{
6629 + apc_stack_clear(APCG(cache_stack));
6630 + APCG(slam_rand) = -1;
6631 + APCG(copied_zvals) = NULL;
6632 +
6633 +#ifdef APC_FILEHITS
6634 + ALLOC_INIT_ZVAL(APCG(filehits));
6635 + array_init(APCG(filehits));
6636 +#endif
6637 +
6638 + return 0;
6639 +}
6640 +
6641 +int apc_request_shutdown(TSRMLS_D)
6642 +{
6643 + apc_deactivate(TSRMLS_C);
6644 +
6645 +#ifdef APC_FILEHITS
6646 + zval_ptr_dtor(&APCG(filehits));
6647 +#endif
6648 +
6649 + return 0;
6650 +}
6651 +
6652 +/* }}} */
6653 +
6654 +/* {{{ apc_deactivate */
6655 +void apc_deactivate(TSRMLS_D)
6656 +{
6657 + /* The execution stack was unwound, which prevented us from decrementing
6658 + * the reference counts on active cache entries in `my_execute`.
6659 + */
6660 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6661 + int i;
6662 + zend_class_entry* zce = NULL;
6663 + void ** centry = (void*)(&zce);
6664 +#ifdef ZEND_ENGINE_2
6665 + zend_class_entry** pzce = NULL;
6666 +#endif
6667 +
6668 + apc_cache_entry_t* cache_entry =
6669 + (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6670 +
6671 + if (cache_entry->data.file.classes) {
6672 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6673 +#ifdef ZEND_ENGINE_2
6674 + centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
6675 +#endif
6676 + if(zend_hash_find(EG(class_table),
6677 + cache_entry->data.file.classes[i].name,
6678 + cache_entry->data.file.classes[i].name_len+1,
6679 + (void**)centry) == FAILURE)
6680 + {
6681 + /* double inclusion of conditional classes ends up failing
6682 + * this lookup the second time around.
6683 + */
6684 + continue;
6685 + }
6686 +
6687 +#ifdef ZEND_ENGINE_2
6688 + zce = *pzce;
6689 +#endif
6690 + zend_hash_del(EG(class_table),
6691 + cache_entry->data.file.classes[i].name,
6692 + cache_entry->data.file.classes[i].name_len+1);
6693 +
6694 + apc_free_class_entry_after_execution(zce);
6695 + }
6696 + }
6697 + apc_cache_release(apc_cache, cache_entry);
6698 + }
6699 + if(APCG(localcache)) {
6700 + apc_local_cache_cleanup(APCG(lcache));
6701 + }
6702 +}
6703 +/* }}} */
6704 +
6705 +/*
6706 + * Local variables:
6707 + * tab-width: 4
6708 + * c-basic-offset: 4
6709 + * End:
6710 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6711 + * vim<600: expandtab sw=4 ts=4 sts=4
6712 + */
6713 diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
6714 --- php-5.2.5-orig/ext/apc/apc_main.h 1969-12-31 18:00:00.000000000 -0600
6715 +++ php-5.2.5/ext/apc/apc_main.h 2007-12-26 16:51:32.000000000 -0600
6716 @@ -0,0 +1,67 @@
6717 +/*
6718 + +----------------------------------------------------------------------+
6719 + | APC |
6720 + +----------------------------------------------------------------------+
6721 + | Copyright (c) 2006 The PHP Group |
6722 + +----------------------------------------------------------------------+
6723 + | This source file is subject to version 3.01 of the PHP license, |
6724 + | that is bundled with this package in the file LICENSE, and is |
6725 + | available through the world-wide-web at the following url: |
6726 + | http://www.php.net/license/3_01.txt |
6727 + | If you did not receive a copy of the PHP license and are unable to |
6728 + | obtain it through the world-wide-web, please send a note to |
6729 + | license@php.net so we can mail you a copy immediately. |
6730 + +----------------------------------------------------------------------+
6731 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6732 + | George Schlossnagle <george@omniti.com> |
6733 + | Rasmus Lerdorf <rasmus@php.net> |
6734 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6735 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6736 + +----------------------------------------------------------------------+
6737 +
6738 + This software was contributed to PHP by Community Connect Inc. in 2002
6739 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6740 + Future revisions and derivatives of this source code must acknowledge
6741 + Community Connect Inc. as the original contributor of this module by
6742 + leaving this note intact in the source code.
6743 +
6744 + All other licensing and usage conditions are those of the PHP Group.
6745 +
6746 + */
6747 +
6748 +/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
6749 +
6750 +#ifndef APC_MAIN_H
6751 +#define APC_MAIN_H
6752 +
6753 +/*
6754 + * This module provides the primary interface between PHP and APC.
6755 + */
6756 +
6757 +extern int apc_module_init(int module_number TSRMLS_DC);
6758 +extern int apc_module_shutdown(TSRMLS_D);
6759 +extern int apc_process_init(int module_number TSRMLS_DC);
6760 +extern int apc_process_shutdown(TSRMLS_D);
6761 +extern int apc_request_init(TSRMLS_D);
6762 +extern int apc_request_shutdown(TSRMLS_D);
6763 +
6764 +/*
6765 + * apc_deactivate is called by the PHP interpreter when an "exception" is
6766 + * raised (e.g., a call to the exit function) that unwinds the execution
6767 + * stack.
6768 + */
6769 +extern void apc_deactivate();
6770 +
6771 +
6772 +extern const char* apc_version();
6773 +
6774 +#endif
6775 +
6776 +/*
6777 + * Local variables:
6778 + * tab-width: 4
6779 + * c-basic-offset: 4
6780 + * End:
6781 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6782 + * vim<600: expandtab sw=4 ts=4 sts=4
6783 + */
6784 diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
6785 --- php-5.2.5-orig/ext/apc/apc_mmap.c 1969-12-31 18:00:00.000000000 -0600
6786 +++ php-5.2.5/ext/apc/apc_mmap.c 2007-12-26 16:51:32.000000000 -0600
6787 @@ -0,0 +1,139 @@
6788 +/*
6789 + +----------------------------------------------------------------------+
6790 + | APC |
6791 + +----------------------------------------------------------------------+
6792 + | Copyright (c) 2006 The PHP Group |
6793 + +----------------------------------------------------------------------+
6794 + | This source file is subject to version 3.01 of the PHP license, |
6795 + | that is bundled with this package in the file LICENSE, and is |
6796 + | available through the world-wide-web at the following url: |
6797 + | http://www.php.net/license/3_01.txt |
6798 + | If you did not receive a copy of the PHP license and are unable to |
6799 + | obtain it through the world-wide-web, please send a note to |
6800 + | license@php.net so we can mail you a copy immediately. |
6801 + +----------------------------------------------------------------------+
6802 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
6803 + +----------------------------------------------------------------------+
6804 +
6805 + This software was contributed to PHP by Community Connect Inc. in 2002
6806 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6807 + Future revisions and derivatives of this source code must acknowledge
6808 + Community Connect Inc. as the original contributor of this module by
6809 + leaving this note intact in the source code.
6810 +
6811 + All other licensing and usage conditions are those of the PHP Group.
6812 +
6813 + */
6814 +
6815 +/* $Id: apc_mmap.c,v 3.7 2007/12/20 23:00:51 shire Exp $ */
6816 +
6817 +#include "apc.h"
6818 +
6819 +#if APC_MMAP
6820 +
6821 +#include <fcntl.h>
6822 +#include <sys/types.h>
6823 +#include <sys/mman.h>
6824 +
6825 +/*
6826 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
6827 + * tells whatever update daemons might be running to not flush dirty
6828 + * vm pages to disk unless absolutely necessary. My guess is that
6829 + * most systems that don't have this probably default to only synching
6830 + * to disk when absolutely necessary.
6831 + */
6832 +#ifndef MAP_NOSYNC
6833 +#define MAP_NOSYNC 0
6834 +#endif
6835 +
6836 +void *apc_mmap(char *file_mask, size_t size)
6837 +{
6838 + void* shmaddr; /* the shared memory address */
6839 +
6840 + /* If no filename was provided, do an anonymous mmap */
6841 + if(!file_mask || (file_mask && !strlen(file_mask))) {
6842 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
6843 + } else {
6844 + int fd;
6845 +
6846 + /*
6847 + * If the filemask contains .shm we try to do a POSIX-compliant shared memory
6848 + * backed mmap which should avoid synchs on some platforms. At least on
6849 + * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
6850 + * a file in a mounted shmfs. For this to work on Linux you need to make sure
6851 + * you actually have shmfs mounted. Also on Linux, make sure the file_mask you
6852 + * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX
6853 + * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
6854 + * path you want here.
6855 + */
6856 + if(strstr(file_mask,".shm")) {
6857 + mktemp(file_mask);
6858 + fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
6859 + if(fd == -1) {
6860 + apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
6861 + return (void *)-1;
6862 + }
6863 + if (ftruncate(fd, size) < 0) {
6864 + close(fd);
6865 + shm_unlink(file_mask);
6866 + apc_eprint("apc_mmap: ftruncate failed:");
6867 + return (void *)-1;
6868 + }
6869 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6870 + shm_unlink(file_mask);
6871 + close(fd);
6872 + }
6873 + /*
6874 + * Support anonymous mmap through the /dev/zero interface as well
6875 + */
6876 + else if(!strcmp(file_mask,"/dev/zero")) {
6877 + fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
6878 + if(fd == -1) {
6879 + apc_eprint("apc_mmap: open on /dev/zero failed:");
6880 + return (void *)-1;
6881 + }
6882 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6883 + close(fd);
6884 + }
6885 + /*
6886 + * Otherwise we do a normal filesystem mmap
6887 + */
6888 + else {
6889 + fd = mkstemp(file_mask);
6890 + if(fd == -1) {
6891 + apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
6892 + return (void *)-1;
6893 + }
6894 + if (ftruncate(fd, size) < 0) {
6895 + close(fd);
6896 + unlink(file_mask);
6897 + apc_eprint("apc_mmap: ftruncate failed:");
6898 + }
6899 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
6900 + close(fd);
6901 + unlink(file_mask);
6902 + }
6903 + }
6904 + if((int)shmaddr == -1) {
6905 + apc_eprint("apc_mmap: mmap failed:");
6906 + }
6907 + return shmaddr;
6908 +}
6909 +
6910 +void apc_unmap(void* shmaddr, size_t size)
6911 +{
6912 + if (munmap(shmaddr, size) < 0) {
6913 + apc_wprint("apc_unmap: munmap failed:");
6914 + }
6915 +}
6916 +
6917 +#endif
6918 +
6919 +/*
6920 + * Local variables:
6921 + * tab-width: 4
6922 + * c-basic-offset: 4
6923 + * End:
6924 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6925 + * vim<600: expandtab sw=4 ts=4 sts=4
6926 + */
6927 diff -ubrN php-5.2.5-orig/ext/apc/apc.php php-5.2.5/ext/apc/apc.php
6928 --- php-5.2.5-orig/ext/apc/apc.php 1969-12-31 18:00:00.000000000 -0600
6929 +++ php-5.2.5/ext/apc/apc.php 2007-12-26 16:51:32.000000000 -0600
6930 @@ -0,0 +1,1326 @@
6931 +<?php
6932 +/*
6933 + +----------------------------------------------------------------------+
6934 + | APC |
6935 + +----------------------------------------------------------------------+
6936 + | Copyright (c) 2006 The PHP Group |
6937 + +----------------------------------------------------------------------+
6938 + | This source file is subject to version 3.01 of the PHP license, |
6939 + | that is bundled with this package in the file LICENSE, and is |
6940 + | available through the world-wide-web at the following url: |
6941 + | http://www.php.net/license/3_01.txt |
6942 + | If you did not receive a copy of the PHP license and are unable to |
6943 + | obtain it through the world-wide-web, please send a note to |
6944 + | license@php.net so we can mail you a copy immediately. |
6945 + +----------------------------------------------------------------------+
6946 + | Authors: Ralf Becker <beckerr@php.net> |
6947 + | Rasmus Lerdorf <rasmus@php.net> |
6948 + | Ilia Alshanetsky <ilia@prohost.org> |
6949 + +----------------------------------------------------------------------+
6950 +
6951 + All other licensing and usage conditions are those of the PHP Group.
6952 +
6953 + */
6954 +
6955 +$VERSION='$Id: apc.php,v 3.68 2007/07/22 00:25:48 gopalv Exp $';
6956 +
6957 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
6958 +if (file_exists("apc.conf.php")) include("apc.conf.php");
6959 +////////////////////////////////////////////////////////
6960 +
6961 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
6962 +
6963 +defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if
6964 + // no other authentication is available
6965 + // If set to 0:
6966 + // There will be no further authentication. You
6967 + // will have to handle this by yourself!
6968 + // If set to 1:
6969 + // You need to change ADMIN_PASSWORD to make
6970 + // this work!
6971 +defaults('ADMIN_USERNAME','apc'); // Admin Username
6972 +defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!!
6973 +
6974 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let
6975 +// users generate a md5 or crypt password in a easy way to fill it in above
6976 +
6977 +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German
6978 +defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
6979 +
6980 +defaults('GRAPH_SIZE',200); // Image size
6981 +
6982 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
6983 +
6984 +
6985 +// "define if not defined"
6986 +function defaults($d,$v) {
6987 + if (!defined($d)) define($d,$v); // or just @define(...)
6988 +}
6989 +
6990 +// rewrite $PHP_SELF to block XSS attacks
6991 +//
6992 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES) : '';
6993 +$time = time();
6994 +$host = getenv('HOSTNAME');
6995 +if($host) { $host = '('.$host.')'; }
6996 +
6997 +// operation constants
6998 +define('OB_HOST_STATS',1);
6999 +define('OB_SYS_CACHE',2);
7000 +define('OB_USER_CACHE',3);
7001 +define('OB_SYS_CACHE_DIR',4);
7002 +define('OB_VERSION_CHECK',9);
7003 +
7004 +// check validity of input variables
7005 +$vardom=array(
7006 + 'OB' => '/^\d+$/', // operational mode switch
7007 + 'CC' => '/^[01]$/', // clear cache requested
7008 + 'DU' => '/^.*$/', // Delete User Key
7009 + 'SH' => '/^[a-z0-9]+$/', // shared object description
7010 +
7011 + 'IMG' => '/^[123]$/', // image to generate
7012 + 'LO' => '/^1$/', // login requested
7013 +
7014 + 'COUNT' => '/^\d+$/', // number of line displayed in list
7015 + 'SCOPE' => '/^[AD]$/', // list view scope
7016 + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key
7017 + 'SORT2' => '/^[DA]$/', // second sort key
7018 + 'AGGR' => '/^\d+$/', // aggregation by dir level
7019 + 'SEARCH' => '~^[a-zA-Z0-1/_.-]*$~' // aggregation by dir level
7020 +);
7021 +
7022 +// default cache mode
7023 +$cache_mode='opcode';
7024 +
7025 +// cache scope
7026 +$scope_list=array(
7027 + 'A' => 'cache_list',
7028 + 'D' => 'deleted_list'
7029 +);
7030 +
7031 +// handle POST and GET requests
7032 +if (empty($_REQUEST)) {
7033 + if (!empty($_GET) && !empty($_POST)) {
7034 + $_REQUEST = array_merge($_GET, $_POST);
7035 + } else if (!empty($_GET)) {
7036 + $_REQUEST = $_GET;
7037 + } else if (!empty($_POST)) {
7038 + $_REQUEST = $_POST;
7039 + } else {
7040 + $_REQUEST = array();
7041 + }
7042 +}
7043 +
7044 +// check parameter syntax
7045 +foreach($vardom as $var => $dom) {
7046 + if (!isset($_REQUEST[$var])) {
7047 + $MYREQUEST[$var]=NULL;
7048 + } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
7049 + $MYREQUEST[$var]=$_REQUEST[$var];
7050 + } else {
7051 + $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
7052 + }
7053 +}
7054 +
7055 +// check parameter sematics
7056 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
7057 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
7058 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
7059 +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS;
7060 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
7061 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
7062 +
7063 +$MY_SELF=
7064 + "$PHP_SELF".
7065 + "?SCOPE=".$MYREQUEST['SCOPE'].
7066 + "&SORT1=".$MYREQUEST['SORT1'].
7067 + "&SORT2=".$MYREQUEST['SORT2'].
7068 + "&COUNT=".$MYREQUEST['COUNT'];
7069 +$MY_SELF_WO_SORT=
7070 + "$PHP_SELF".
7071 + "?SCOPE=".$MYREQUEST['SCOPE'].
7072 + "&COUNT=".$MYREQUEST['COUNT'];
7073 +
7074 +// authentication needed?
7075 +//
7076 +if (!USE_AUTHENTICATION) {
7077 + $AUTHENTICATED=1;
7078 +} else {
7079 + $AUTHENTICATED=0;
7080 + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
7081 +
7082 + if (!isset($_SERVER['PHP_AUTH_USER']) ||
7083 + !isset($_SERVER['PHP_AUTH_PW']) ||
7084 + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
7085 + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
7086 + Header("WWW-Authenticate: Basic realm=\"APC Login\"");
7087 + Header("HTTP/1.0 401 Unauthorized");
7088 +
7089 + echo <<<EOB
7090 + <html><body>
7091 + <h1>Rejected!</h1>
7092 + <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
7093 + <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
7094 + </body></html>
7095 +EOB;
7096 + exit;
7097 +
7098 + } else {
7099 + $AUTHENTICATED=1;
7100 + }
7101 + }
7102 +}
7103 +
7104 +// select cache mode
7105 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
7106 + $cache_mode='user';
7107 +}
7108 +// clear cache
7109 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
7110 + apc_clear_cache($cache_mode);
7111 +}
7112 +
7113 +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
7114 + apc_delete($MYREQUEST['DU']);
7115 +}
7116 +
7117 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
7118 + echo "No cache info available. APC does not appear to be running.";
7119 + exit;
7120 +}
7121 +
7122 +$cache_user = apc_cache_info('user', 1);
7123 +$mem=apc_sma_info();
7124 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear
7125 +
7126 +// don't cache this page
7127 +//
7128 +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
7129 +header("Cache-Control: post-check=0, pre-check=0", false);
7130 +header("Pragma: no-cache"); // HTTP/1.0
7131 +
7132 +function duration($ts) {
7133 + global $time;
7134 + $years = (int)((($time - $ts)/(7*86400))/52.177457);
7135 + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
7136 + $weeks = (int)(($rem)/(7*86400));
7137 + $days = (int)(($rem)/86400) - $weeks*7;
7138 + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
7139 + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
7140 + $str = '';
7141 + if($years==1) $str .= "$years year, ";
7142 + if($years>1) $str .= "$years years, ";
7143 + if($weeks==1) $str .= "$weeks week, ";
7144 + if($weeks>1) $str .= "$weeks weeks, ";
7145 + if($days==1) $str .= "$days day,";
7146 + if($days>1) $str .= "$days days,";
7147 + if($hours == 1) $str .= " $hours hour and";
7148 + if($hours>1) $str .= " $hours hours and";
7149 + if($mins == 1) $str .= " 1 minute";
7150 + else $str .= " $mins minutes";
7151 + return $str;
7152 +}
7153 +
7154 +// create graphics
7155 +//
7156 +function graphics_avail() {
7157 + return extension_loaded('gd');
7158 +}
7159 +if (isset($MYREQUEST['IMG']))
7160 +{
7161 + if (!graphics_avail()) {
7162 + exit(0);
7163 + }
7164 +
7165 + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
7166 + $r=$diameter/2;
7167 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7168 +
7169 +
7170 + if (function_exists("imagefilledarc")) {
7171 + // exists only if GD 2.0.1 is avaliable
7172 + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
7173 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
7174 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
7175 + } else {
7176 + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
7177 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7178 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7179 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7180 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7181 + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
7182 + }
7183 + if ($text) {
7184 + if ($placeindex>0) {
7185 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7186 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7187 +
7188 + } else {
7189 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7190 + }
7191 + }
7192 + }
7193 +
7194 + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
7195 + $r=$diameter/2;
7196 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7197 +
7198 + if ($placeindex>0) {
7199 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7200 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7201 +
7202 + } else {
7203 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7204 + }
7205 + }
7206 +
7207 + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
7208 + global $col_black;
7209 + $x1=$x+$w-1;
7210 + $y1=$y+$h-1;
7211 +
7212 + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
7213 + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
7214 + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
7215 + imagerectangle($im, $x, $y1, $x1, $y, $color1);
7216 + if ($text) {
7217 + if ($placeindex>0) {
7218 +
7219 + if ($placeindex<16)
7220 + {
7221 + $px=5;
7222 + $py=$placeindex*12+6;
7223 + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
7224 + imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
7225 + imagestring($im,2,$px,$py-6,$text,$color1);
7226 +
7227 + } else {
7228 + if ($placeindex<31) {
7229 + $px=$x+40*2;
7230 + $py=($placeindex-15)*12+6;
7231 + } else {
7232 + $px=$x+40*2+100*intval(($placeindex-15)/15);
7233 + $py=($placeindex%15)*12+6;
7234 + }
7235 + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
7236 + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
7237 + imagestring($im,2,$px+2,$py-6,$text,$color1);
7238 + }
7239 + } else {
7240 + imagestring($im,4,$x+5,$y1-16,$text,$color1);
7241 + }
7242 + }
7243 + }
7244 +
7245 +
7246 + $size = GRAPH_SIZE; // image size
7247 + if ($MYREQUEST['IMG']==3)
7248 + $image = imagecreate(2*$size+150, $size+10);
7249 + else
7250 + $image = imagecreate($size+50, $size+10);
7251 +
7252 + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
7253 + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
7254 + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
7255 + $col_black = imagecolorallocate($image, 0, 0, 0);
7256 + imagecolortransparent($image,$col_white);
7257 +
7258 + switch ($MYREQUEST['IMG']) {
7259 +
7260 + case 1:
7261 + $s=$mem['num_seg']*$mem['seg_size'];
7262 + $a=$mem['avail_mem'];
7263 + $x=$y=$size/2;
7264 + $fuzz = 0.000001;
7265 +
7266 + // This block of code creates the pie chart. It is a lot more complex than you
7267 + // would expect because we try to visualize any memory fragmentation as well.
7268 + $angle_from = 0;
7269 + $string_placement=array();
7270 + for($i=0; $i<$mem['num_seg']; $i++) {
7271 + $ptr = 0;
7272 + $free = $mem['block_lists'][$i];
7273 + foreach($free as $block) {
7274 + if($block['offset']!=$ptr) { // Used block
7275 + $angle_to = $angle_from+($block['offset']-$ptr)/$s;
7276 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7277 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7278 + if (($angle_to-$angle_from)>0.05) {
7279 + array_push($string_placement, array($angle_from,$angle_to));
7280 + }
7281 + $angle_from = $angle_to;
7282 + }
7283 + $angle_to = $angle_from+($block['size'])/$s;
7284 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7285 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
7286 + if (($angle_to-$angle_from)>0.05) {
7287 + array_push($string_placement, array($angle_from,$angle_to));
7288 + }
7289 + $angle_from = $angle_to;
7290 + $ptr = $block['offset']+$block['size'];
7291 + }
7292 + if ($ptr < $mem['seg_size']) { // memory at the end
7293 + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
7294 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7295 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7296 + if (($angle_to-$angle_from)>0.05) {
7297 + array_push($string_placement, array($angle_from,$angle_to));
7298 + }
7299 + }
7300 + }
7301 + foreach ($string_placement as $angle) {
7302 + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
7303 + }
7304 + break;
7305 +
7306 + case 2:
7307 + $s=$cache['num_hits']+$cache['num_misses'];
7308 + $a=$cache['num_hits'];
7309 +
7310 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7311 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7312 + break;
7313 +
7314 + case 3:
7315 + $s=$mem['num_seg']*$mem['seg_size'];
7316 + $a=$mem['avail_mem'];
7317 + $x=130;
7318 + $y=1;
7319 + $j=1;
7320 +
7321 + // This block of code creates the bar chart. It is a lot more complex than you
7322 + // would expect because we try to visualize any memory fragmentation as well.
7323 + for($i=0; $i<$mem['num_seg']; $i++) {
7324 + $ptr = 0;
7325 + $free = $mem['block_lists'][$i];
7326 + foreach($free as $block) {
7327 + if($block['offset']!=$ptr) { // Used block
7328 + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
7329 + if ($h>0) {
7330 + $j++;
7331 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
7332 + else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
7333 + }
7334 + $y+=$h;
7335 + }
7336 + $h=(GRAPH_SIZE-5)*($block['size'])/$s;
7337 + if ($h>0) {
7338 + $j++;
7339 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
7340 + else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
7341 + }
7342 + $y+=$h;
7343 + $ptr = $block['offset']+$block['size'];
7344 + }
7345 + if ($ptr < $mem['seg_size']) { // memory at the end
7346 + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
7347 + if ($h > 0) {
7348 + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
7349 + }
7350 + }
7351 + }
7352 + break;
7353 + case 4:
7354 + $s=$cache['num_hits']+$cache['num_misses'];
7355 + $a=$cache['num_hits'];
7356 +
7357 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7358 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7359 + break;
7360 +
7361 + }
7362 + header("Content-type: image/png");
7363 + imagepng($image);
7364 + exit;
7365 +}
7366 +
7367 +// pretty printer for byte values
7368 +//
7369 +function bsize($s) {
7370 + foreach (array('','K','M','G') as $i => $k) {
7371 + if ($s < 1024) break;
7372 + $s/=1024;
7373 + }
7374 + return sprintf("%5.1f %sBytes",$s,$k);
7375 +}
7376 +
7377 +// sortable table header in "scripts for this host" view
7378 +function sortheader($key,$name,$extra='') {
7379 + global $MYREQUEST, $MY_SELF_WO_SORT;
7380 +
7381 + if ($MYREQUEST['SORT1']==$key) {
7382 + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
7383 + }
7384 + return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
7385 +
7386 +}
7387 +
7388 +// create menu entry
7389 +function menu_entry($ob,$title) {
7390 + global $MYREQUEST,$MY_SELF;
7391 + if ($MYREQUEST['OB']!=$ob) {
7392 + return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7393 + } else if (empty($MYREQUEST['SH'])) {
7394 + return "<li><span class=active>$title</span></li>";
7395 + } else {
7396 + return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7397 + }
7398 +}
7399 +
7400 +function put_login_link($s="Login")
7401 +{
7402 + global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
7403 + // needs ADMIN_PASSWORD to be changed!
7404 + //
7405 + if (!USE_AUTHENTICATION) {
7406 + return;
7407 + } else if (ADMIN_PASSWORD=='password')
7408 + {
7409 + print <<<EOB
7410 + <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
7411 +EOB;
7412 + } else if ($AUTHENTICATED) {
7413 + print <<<EOB
7414 + '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
7415 +EOB;
7416 + } else{
7417 + print <<<EOB
7418 + <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
7419 +EOB;
7420 + }
7421 +}
7422 +
7423 +
7424 +?>
7425 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7426 +<html>
7427 +<head><title>APC INFO <?php echo $host ?></title>
7428 +<style><!--
7429 +body { background:white; font-size:100.01%; margin:0; padding:0; }
7430 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
7431 +* html body {font-size:0.8em}
7432 +* html p {font-size:0.8em}
7433 +* html td {font-size:0.8em}
7434 +* html th {font-size:0.8em}
7435 +* html input {font-size:0.8em}
7436 +* html submit {font-size:0.8em}
7437 +td { vertical-align:top }
7438 +a { color:black; font-weight:none; text-decoration:none; }
7439 +a:hover { text-decoration:underline; }
7440 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
7441 +
7442 +
7443 +div.head div.login {
7444 + position:absolute;
7445 + right: 1em;
7446 + top: 1.2em;
7447 + color:white;
7448 + width:6em;
7449 + }
7450 +div.head div.login a {
7451 + position:absolute;
7452 + right: 0em;
7453 + background:rgb(119,123,180);
7454 + border:solid rgb(102,102,153) 2px;
7455 + color:white;
7456 + font-weight:bold;
7457 + padding:0.1em 0.5em 0.1em 0.5em;
7458 + text-decoration:none;
7459 + }
7460 +div.head div.login a:hover {
7461 + background:rgb(193,193,244);
7462 + }
7463 +
7464 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
7465 +* html h1.apc { margin-bottom:-7px; }
7466 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
7467 +h1.apc div.logo span.logo {
7468 + background:rgb(119,123,180);
7469 + color:black;
7470 + border-right: solid black 1px;
7471 + border-bottom: solid black 1px;
7472 + font-style:italic;
7473 + font-size:1em;
7474 + padding-left:1.2em;
7475 + padding-right:1.2em;
7476 + text-align:right;
7477 + }
7478 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
7479 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
7480 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
7481 +hr.apc {
7482 + background:white;
7483 + border-bottom:solid rgb(102,102,153) 1px;
7484 + border-style:none;
7485 + border-top:solid rgb(102,102,153) 10px;
7486 + height:12px;
7487 + margin:0;
7488 + margin-top:1px;
7489 + padding:0;
7490 +}
7491 +
7492 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
7493 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
7494 +ol.menu a {
7495 + background:rgb(153,153,204);
7496 + border:solid rgb(102,102,153) 2px;
7497 + color:white;
7498 + font-weight:bold;
7499 + margin-right:0em;
7500 + padding:0.1em 0.5em 0.1em 0.5em;
7501 + text-decoration:none;
7502 + margin-left: 5px;
7503 + }
7504 +ol.menu a.child_active {
7505 + background:rgb(153,153,204);
7506 + border:solid rgb(102,102,153) 2px;
7507 + color:white;
7508 + font-weight:bold;
7509 + margin-right:0em;
7510 + padding:0.1em 0.5em 0.1em 0.5em;
7511 + text-decoration:none;
7512 + border-left: solid black 5px;
7513 + margin-left: 0px;
7514 + }
7515 +ol.menu span.active {
7516 + background:rgb(153,153,204);
7517 + border:solid rgb(102,102,153) 2px;
7518 + color:black;
7519 + font-weight:bold;
7520 + margin-right:0em;
7521 + padding:0.1em 0.5em 0.1em 0.5em;
7522 + text-decoration:none;
7523 + border-left: solid black 5px;
7524 + }
7525 +ol.menu span.inactive {
7526 + background:rgb(193,193,244);
7527 + border:solid rgb(182,182,233) 2px;
7528 + color:white;
7529 + font-weight:bold;
7530 + margin-right:0em;
7531 + padding:0.1em 0.5em 0.1em 0.5em;
7532 + text-decoration:none;
7533 + margin-left: 5px;
7534 + }
7535 +ol.menu a:hover {
7536 + background:rgb(193,193,244);
7537 + text-decoration:none;
7538 + }
7539 +
7540 +
7541 +div.info {
7542 + background:rgb(204,204,204);
7543 + border:solid rgb(204,204,204) 1px;
7544 + margin-bottom:1em;
7545 + }
7546 +div.info h2 {
7547 + background:rgb(204,204,204);
7548 + color:black;
7549 + font-size:1em;
7550 + margin:0;
7551 + padding:0.1em 1em 0.1em 1em;
7552 + }
7553 +div.info table {
7554 + border:solid rgb(204,204,204) 1px;
7555 + border-spacing:0;
7556 + width:100%;
7557 + }
7558 +div.info table th {
7559 + background:rgb(204,204,204);
7560 + color:white;
7561 + margin:0;
7562 + padding:0.1em 1em 0.1em 1em;
7563 + }
7564 +div.info table th a.sortable { color:black; }
7565 +div.info table tr.tr-0 { background:rgb(238,238,238); }
7566 +div.info table tr.tr-1 { background:rgb(221,221,221); }
7567 +div.info table td { padding:0.3em 1em 0.3em 1em; }
7568 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
7569 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
7570 +div.info table td h3 {
7571 + color:black;
7572 + font-size:1.1em;
7573 + margin-left:-0.3em;
7574 + }
7575 +
7576 +div.graph { margin-bottom:1em }
7577 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
7578 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
7579 +div.graph table td.td-0 { background:rgb(238,238,238); }
7580 +div.graph table td.td-1 { background:rgb(221,221,221); }
7581 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
7582 +
7583 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
7584 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
7585 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
7586 +
7587 +div.sorting { margin:1.5em 0em 1.5em 2em }
7588 +.center { text-align:center }
7589 +.aright { position:absolute;right:1em }
7590 +.right { text-align:right }
7591 +.ok { color:rgb(0,200,0); font-weight:bold}
7592 +.failed { color:rgb(200,0,0); font-weight:bold}
7593 +
7594 +span.box {
7595 + border: black solid 1px;
7596 + border-right:solid black 2px;
7597 + border-bottom:solid black 2px;
7598 + padding:0 0.5em 0 0.5em;
7599 + margin-right:1em;
7600 +}
7601 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
7602 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
7603 +
7604 +div.authneeded {
7605 + background:rgb(238,238,238);
7606 + border:solid rgb(204,204,204) 1px;
7607 + color:rgb(200,0,0);
7608 + font-size:1.2em;
7609 + font-weight:bold;
7610 + padding:2em;
7611 + text-align:center;
7612 + }
7613 +
7614 +input {
7615 + background:rgb(153,153,204);
7616 + border:solid rgb(102,102,153) 2px;
7617 + color:white;
7618 + font-weight:bold;
7619 + margin-right:1em;
7620 + padding:0.1em 0.5em 0.1em 0.5em;
7621 + }
7622 +//-->
7623 +</style>
7624 +</head>
7625 +<body>
7626 +<div class="head">
7627 + <h1 class="apc">
7628 + <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
7629 + <div class="nameinfo">Opcode Cache</div>
7630 + </h1>
7631 + <div class="login">
7632 + <?php put_login_link(); ?>
7633 + </div>
7634 + <hr class="apc">
7635 +</div>
7636 +<?php
7637 +
7638 +
7639 +// Display main Menu
7640 +echo <<<EOB
7641 + <ol class=menu>
7642 + <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
7643 +EOB;
7644 +echo
7645 + menu_entry(1,'View Host Stats'),
7646 + menu_entry(2,'System Cache Entries');
7647 +if ($AUTHENTICATED) {
7648 + echo menu_entry(4,'Per-Directory Entries');
7649 +}
7650 +echo
7651 + menu_entry(3,'User Cache Entries'),
7652 + menu_entry(9,'Version Check');
7653 +
7654 +if ($AUTHENTICATED) {
7655 + echo <<<EOB
7656 + <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
7657 +EOB;
7658 +}
7659 +echo <<<EOB
7660 + </ol>
7661 +EOB;
7662 +
7663 +
7664 +// CONTENT
7665 +echo <<<EOB
7666 + <div class=content>
7667 +EOB;
7668 +
7669 +// MAIN SWITCH STATEMENT
7670 +
7671 +switch ($MYREQUEST['OB']) {
7672 +
7673 +
7674 +
7675 +
7676 +
7677 +// -----------------------------------------------
7678 +// Host Stats
7679 +// -----------------------------------------------
7680 +case OB_HOST_STATS:
7681 + $mem_size = $mem['num_seg']*$mem['seg_size'];
7682 + $mem_avail= $mem['avail_mem'];
7683 + $mem_used = $mem_size-$mem_avail;
7684 + $seg_size = bsize($mem['seg_size']);
7685 + $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
7686 + $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
7687 + $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
7688 + $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
7689 + $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
7690 + $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
7691 + $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
7692 + $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
7693 + $apcversion = phpversion('apc');
7694 + $phpversion = phpversion();
7695 + $number_files = $cache['num_entries'];
7696 + $size_files = bsize($cache['mem_size']);
7697 + $number_vars = $cache_user['num_entries'];
7698 + $size_vars = bsize($cache_user['mem_size']);
7699 + $i=0;
7700 + echo <<< EOB
7701 + <div class="info div1"><h2>General Cache Information</h2>
7702 + <table cellspacing=0><tbody>
7703 + <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
7704 + <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
7705 +EOB;
7706 +
7707 + if(!empty($_SERVER['SERVER_NAME']))
7708 + echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
7709 + if(!empty($_SERVER['SERVER_SOFTWARE']))
7710 + echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
7711 +
7712 + echo <<<EOB
7713 + <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
7714 + <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
7715 + </td></tr>
7716 +EOB;
7717 + echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
7718 + echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
7719 + echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
7720 + echo <<<EOB
7721 + </tbody></table>
7722 + </div>
7723 +
7724 + <div class="info div1"><h2>File Cache Information</h2>
7725 + <table cellspacing=0><tbody>
7726 + <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
7727 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
7728 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
7729 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
7730 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
7731 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
7732 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
7733 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
7734 + </tbody></table>
7735 + </div>
7736 +
7737 + <div class="info div1"><h2>User Cache Information</h2>
7738 + <table cellspacing=0><tbody>
7739 + <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
7740 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
7741 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
7742 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
7743 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
7744 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
7745 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
7746 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
7747 +
7748 + </tbody></table>
7749 + </div>
7750 +
7751 + <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
7752 +EOB;
7753 +
7754 + $j = 0;
7755 + foreach (ini_get_all('apc') as $k => $v) {
7756 + echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
7757 + $j = 1 - $j;
7758 + }
7759 +
7760 + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
7761 + $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
7762 + else
7763 + $mem_note = "Memory Usage";
7764 +
7765 + echo <<< EOB
7766 + </tbody></table>
7767 + </div>
7768 +
7769 + <div class="graph div3"><h2>Host Status Diagrams</h2>
7770 + <table cellspacing=0><tbody>
7771 +EOB;
7772 + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
7773 + echo <<<EOB
7774 + <tr>
7775 + <td class=td-0>$mem_note</td>
7776 + <td class=td-1>Hits &amp; Misses</td>
7777 + </tr>
7778 +EOB;
7779 +
7780 + echo
7781 + graphics_avail() ?
7782 + '<tr>'.
7783 + "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
7784 + "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
7785 + : "",
7786 + '<tr>',
7787 + '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
7788 + '<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
7789 + '</tr>',
7790 + '<tr>',
7791 + '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
7792 + '<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
7793 + echo <<< EOB
7794 + </tr>
7795 + </tbody></table>
7796 +
7797 + <br/>
7798 + <h2>Detailed Memory Usage and Fragmentation</h2>
7799 + <table cellspacing=0><tbody>
7800 + <tr>
7801 + <td class=td-0 colspan=2><br/>
7802 +EOB;
7803 +
7804 + // Fragementation: (freeseg - 1) / total_seg
7805 + $nseg = $freeseg = $fragsize = $freetotal = 0;
7806 + for($i=0; $i<$mem['num_seg']; $i++) {
7807 + $ptr = 0;
7808 + foreach($mem['block_lists'][$i] as $block) {
7809 + if ($block['offset'] != $ptr) {
7810 + ++$nseg;
7811 + }
7812 + $ptr = $block['offset'] + $block['size'];
7813 + /* Only consider blocks <5M for the fragmentation % */
7814 + if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
7815 + $freetotal+=$block['size'];
7816 + }
7817 + $freeseg += count($mem['block_lists'][$i]);
7818 + }
7819 +
7820 + if ($freeseg > 1) {
7821 + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
7822 + } else {
7823 + $frag = "0%";
7824 + }
7825 +
7826 + if (graphics_avail()) {
7827 + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
7828 + echo <<<EOB
7829 + <img alt="" $size src="$PHP_SELF?IMG=3&$time">
7830 +EOB;
7831 + }
7832 + echo <<<EOB
7833 + </br>Fragmentation: $frag
7834 + </td>
7835 + </tr>
7836 +EOB;
7837 + if(isset($mem['adist'])) {
7838 + foreach($mem['adist'] as $i=>$v) {
7839 + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
7840 + if($i==0) $range = "1";
7841 + else $range = "$cur - $nxt";
7842 + echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
7843 + }
7844 + }
7845 + echo <<<EOB
7846 + </tbody></table>
7847 + </div>
7848 +EOB;
7849 +
7850 + break;
7851 +
7852 +
7853 +// -----------------------------------------------
7854 +// User Cache Entries
7855 +// -----------------------------------------------
7856 +case OB_USER_CACHE:
7857 + if (!$AUTHENTICATED) {
7858 + echo '<div class="authneeded">You need to login to see the user values here!<br/>&nbsp;<br/>';
7859 + put_login_link("Login now!");
7860 + echo '</div>';
7861 + break;
7862 + }
7863 + $fieldname='info';
7864 + $fieldheading='User Entry Label';
7865 + $fieldkey='info';
7866 +
7867 +// -----------------------------------------------
7868 +// System Cache Entries
7869 +// -----------------------------------------------
7870 +case OB_SYS_CACHE:
7871 + if (!isset($fieldname))
7872 + {
7873 + $fieldname='filename';
7874 + $fieldheading='Script Filename';
7875 + if(ini_get("apc.stat")) $fieldkey='inode';
7876 + else $fieldkey='filename';
7877 + }
7878 + if (!empty($MYREQUEST['SH']))
7879 + {
7880 + echo <<< EOB
7881 + <div class="info"><table cellspacing=0><tbody>
7882 + <tr><th>Attribute</th><th>Value</th></tr>
7883 +EOB;
7884 +
7885 + $m=0;
7886 + foreach($scope_list as $j => $list) {
7887 + foreach($cache[$list] as $i => $entry) {
7888 + if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
7889 + foreach($entry as $k => $value) {
7890 + if (!$AUTHENTICATED) {
7891 + // hide all path entries if not logged in
7892 + $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
7893 + }
7894 +
7895 + if ($k == "num_hits") {
7896 + $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
7897 + }
7898 + if ($k == 'deletion_time') {
7899 + if(!$entry['deletion_time']) $value = "None";
7900 + }
7901 + echo
7902 + "<tr class=tr-$m>",
7903 + "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
7904 + "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
7905 + "</tr>";
7906 + $m=1-$m;
7907 + }
7908 + if($fieldkey=='info') {
7909 + echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
7910 + $output = var_export(apc_fetch($entry[$fieldkey]),true);
7911 + echo htmlspecialchars($output);
7912 + echo "</pre></td></tr>\n";
7913 + }
7914 + break;
7915 + }
7916 + }
7917 +
7918 + echo <<<EOB
7919 + </tbody></table>
7920 + </div>
7921 +EOB;
7922 + break;
7923 + }
7924 +
7925 + $cols=6;
7926 + echo <<<EOB
7927 + <div class=sorting><form>Scope:
7928 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
7929 + <select name=SCOPE>
7930 +EOB;
7931 + echo
7932 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
7933 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
7934 + "</select>",
7935 + ", Sorting:<select name=SORT1>",
7936 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
7937 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
7938 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
7939 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
7940 + "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
7941 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
7942 + "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
7943 + if($fieldname=='info') echo
7944 + "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
7945 + echo
7946 + '</select>',
7947 + '<select name=SORT2>',
7948 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
7949 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
7950 + '</select>',
7951 + '<select name=COUNT onChange="form.submit()">',
7952 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
7953 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
7954 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
7955 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
7956 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
7957 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
7958 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
7959 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
7960 + '</select>',
7961 + '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
7962 + '&nbsp;<input type=submit value="GO!">',
7963 + '</form></div>',
7964 +
7965 + '<div class="info"><table cellspacing=0><tbody>',
7966 + '<tr>',
7967 + '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>',
7968 + '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>',
7969 + '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>',
7970 + '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
7971 + '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
7972 + '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>';
7973 +
7974 + if($fieldname=='info') {
7975 + $cols+=2;
7976 + echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
7977 + }
7978 + echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
7979 +
7980 + // builds list with alpha numeric sortable keys
7981 + //
7982 + $list = array();
7983 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
7984 + switch($MYREQUEST['SORT1']) {
7985 + case 'A': $k=sprintf('%015d-',$entry['access_time']); break;
7986 + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break;
7987 + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break;
7988 + case 'M': $k=sprintf('%015d-',$entry['mtime']); break;
7989 + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
7990 + case 'T': $k=sprintf('%015d-',$entry['ttl']); break;
7991 + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
7992 + case 'S': $k=''; break;
7993 + }
7994 + if (!$AUTHENTICATED) {
7995 + // hide all path entries if not logged in
7996 + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
7997 + } else {
7998 + $list[$k.$entry[$fieldname]]=$entry;
7999 + }
8000 + }
8001 +
8002 + if ($list) {
8003 +
8004 + // sort list
8005 + //
8006 + switch ($MYREQUEST['SORT2']) {
8007 + case "A": krsort($list); break;
8008 + case "D": ksort($list); break;
8009 + }
8010 +
8011 + // output list
8012 + $i=0;
8013 + foreach($list as $k => $entry) {
8014 + if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {
8015 + echo
8016 + '<tr class=tr-',$i%2,'>',
8017 + "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
8018 + '<td class="td-n center">',$entry['num_hits'],'</td>',
8019 + '<td class="td-n right">',$entry['mem_size'],'</td>',
8020 + '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
8021 + '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
8022 + '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
8023 +
8024 + if($fieldname=='info') {
8025 + if($entry['ttl'])
8026 + echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
8027 + else
8028 + echo '<td class="td-n center">None</td>';
8029 + }
8030 + if ($entry['deletion_time']) {
8031 +
8032 + echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
8033 + } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
8034 +
8035 + echo '<td class="td-last center">';
8036 + echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
8037 + echo '</td>';
8038 + } else {
8039 + echo '<td class="td-last center"> &nbsp; </td>';
8040 + }
8041 + echo '</tr>';
8042 + $i++;
8043 + if ($i == $MYREQUEST['COUNT'])
8044 + break;
8045 + }
8046 + }
8047 +
8048 + } else {
8049 + echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
8050 + }
8051 + echo <<< EOB
8052 + </tbody></table>
8053 +EOB;
8054 +
8055 + if ($list && $i < count($list)) {
8056 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8057 + }
8058 +
8059 + echo <<< EOB
8060 + </div>
8061 +EOB;
8062 + break;
8063 +
8064 +
8065 +// -----------------------------------------------
8066 +// Per-Directory System Cache Entries
8067 +// -----------------------------------------------
8068 +case OB_SYS_CACHE_DIR:
8069 + if (!$AUTHENTICATED) {
8070 + break;
8071 + }
8072 +
8073 + echo <<<EOB
8074 + <div class=sorting><form>Scope:
8075 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
8076 + <select name=SCOPE>
8077 +EOB;
8078 + echo
8079 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
8080 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
8081 + "</select>",
8082 + ", Sorting:<select name=SORT1>",
8083 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
8084 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
8085 + "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
8086 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
8087 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
8088 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
8089 + '</select>',
8090 + '<select name=SORT2>',
8091 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
8092 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
8093 + '</select>',
8094 + '<select name=COUNT onChange="form.submit()">',
8095 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
8096 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
8097 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
8098 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
8099 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
8100 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
8101 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
8102 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
8103 + '</select>',
8104 + ", Group By Dir Level:<select name=AGGR>",
8105 + "<option value='' selected>None</option>";
8106 + for ($i = 1; $i < 10; $i++)
8107 + echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
8108 + echo '</select>',
8109 + '&nbsp;<input type=submit value="GO!">',
8110 + '</form></div>',
8111 +
8112 + '<div class="info"><table cellspacing=0><tbody>',
8113 + '<tr>',
8114 + '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
8115 + '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
8116 + '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8117 + '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>',
8118 + '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8119 + '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>',
8120 + '</tr>';
8121 +
8122 + // builds list with alpha numeric sortable keys
8123 + //
8124 + $tmp = $list = array();
8125 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
8126 + $n = dirname($entry['filename']);
8127 + if ($MYREQUEST['AGGR'] > 0) {
8128 + $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
8129 + }
8130 + if (!isset($tmp[$n])) {
8131 + $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
8132 + }
8133 + $tmp[$n]['hits'] += $entry['num_hits'];
8134 + $tmp[$n]['size'] += $entry['mem_size'];
8135 + ++$tmp[$n]['ents'];
8136 + }
8137 +
8138 + foreach ($tmp as $k => $v) {
8139 + switch($MYREQUEST['SORT1']) {
8140 + case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
8141 + case 'T': $kn=sprintf('%015d-',$v['ents']); break;
8142 + case 'H': $kn=sprintf('%015d-',$v['hits']); break;
8143 + case 'Z': $kn=sprintf('%015d-',$v['size']); break;
8144 + case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
8145 + case 'S': $kn = $k; break;
8146 + }
8147 + $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
8148 + }
8149 +
8150 + if ($list) {
8151 +
8152 + // sort list
8153 + //
8154 + switch ($MYREQUEST['SORT2']) {
8155 + case "A": krsort($list); break;
8156 + case "D": ksort($list); break;
8157 + }
8158 +
8159 + // output list
8160 + $i = 0;
8161 + foreach($list as $entry) {
8162 + echo
8163 + '<tr class=tr-',$i%2,'>',
8164 + "<td class=td-0>",$entry[0],'</a></td>',
8165 + '<td class="td-n center">',$entry[1],'</td>',
8166 + '<td class="td-n center">',$entry[2],'</td>',
8167 + '<td class="td-n center">',$entry[3],'</td>',
8168 + '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
8169 + '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
8170 + '</tr>';
8171 +
8172 + if (++$i == $MYREQUEST['COUNT']) break;
8173 + }
8174 +
8175 + } else {
8176 + echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
8177 + }
8178 + echo <<< EOB
8179 + </tbody></table>
8180 +EOB;
8181 +
8182 + if ($list && $i < count($list)) {
8183 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8184 + }
8185 +
8186 + echo <<< EOB
8187 + </div>
8188 +EOB;
8189 + break;
8190 +
8191 +// -----------------------------------------------
8192 +// Version check
8193 +// -----------------------------------------------
8194 +case OB_VERSION_CHECK:
8195 + echo <<<EOB
8196 + <div class="info"><h2>APC Version Information</h2>
8197 + <table cellspacing=0><tbody>
8198 + <tr>
8199 + <th></th>
8200 + </tr>
8201 +EOB;
8202 +
8203 + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
8204 + if (!$rss) {
8205 + echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
8206 + } else {
8207 + $apcversion = phpversion('apc');
8208 +
8209 + preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
8210 + echo '<tr class="tr-0 center"><td>';
8211 + if (version_compare($apcversion, $match[1], '>=')) {
8212 + echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
8213 + $i = 3;
8214 + } else {
8215 + echo '<div class="failed">You are running an older version of APC ('.$apcversion.'),
8216 + newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
8217 + http://pecl.php.net/package/APC/'.$match[1].'</a>
8218 + </div>';
8219 + $i = -1;
8220 + }
8221 + echo '</td></tr>';
8222 + echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
8223 +
8224 + preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
8225 + next($match[2]); next($match[2]);
8226 +
8227 + while (list(,$v) = each($match[2])) {
8228 + list(,$ver) = explode(' ', $v, 2);
8229 + if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
8230 + break;
8231 + } else if (!$i--) {
8232 + break;
8233 + }
8234 + echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
8235 + echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
8236 + next($match[2]);
8237 + }
8238 + echo '</td></tr>';
8239 + }
8240 + echo <<< EOB
8241 + </tbody></table>
8242 + </div>
8243 +EOB;
8244 + break;
8245 +
8246 +}
8247 +
8248 +echo <<< EOB
8249 + </div>
8250 +EOB;
8251 +
8252 +?>
8253 +
8254 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
8255 +</body>
8256 +</html>
8257 diff -ubrN php-5.2.5-orig/ext/apc/apc_php.h php-5.2.5/ext/apc/apc_php.h
8258 --- php-5.2.5-orig/ext/apc/apc_php.h 1969-12-31 18:00:00.000000000 -0600
8259 +++ php-5.2.5/ext/apc/apc_php.h 2007-12-26 16:51:32.000000000 -0600
8260 @@ -0,0 +1,71 @@
8261 +/*
8262 + +----------------------------------------------------------------------+
8263 + | APC |
8264 + +----------------------------------------------------------------------+
8265 + | Copyright (c) 2006 The PHP Group |
8266 + +----------------------------------------------------------------------+
8267 + | This source file is subject to version 3.01 of the PHP license, |
8268 + | that is bundled with this package in the file LICENSE, and is |
8269 + | available through the world-wide-web at the following url: |
8270 + | http://www.php.net/license/3_01.txt |
8271 + | If you did not receive a copy of the PHP license and are unable to |
8272 + | obtain it through the world-wide-web, please send a note to |
8273 + | license@php.net so we can mail you a copy immediately. |
8274 + +----------------------------------------------------------------------+
8275 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8276 + | George Schlossnagle <george@omniti.com> |
8277 + | Rasmus Lerdorf <rasmus@php.net> |
8278 + | Arun C. Murthy <arunc@yahoo-inc.com> |
8279 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
8280 + +----------------------------------------------------------------------+
8281 +
8282 + This software was contributed to PHP by Community Connect Inc. in 2002
8283 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8284 + Future revisions and derivatives of this source code must acknowledge
8285 + Community Connect Inc. as the original contributor of this module by
8286 + leaving this note intact in the source code.
8287 +
8288 + All other licensing and usage conditions are those of the PHP Group.
8289 +
8290 + */
8291 +
8292 +/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
8293 +
8294 +#ifndef APC_PHP_H
8295 +#define APC_PHP_H
8296 +
8297 +/*
8298 + * The purpose of this header file is to include all PHP and Zend headers that
8299 + * are typically needed elsewhere in APC. This makes it easy to insure that
8300 + * all required headers are available.
8301 + */
8302 +
8303 +#include "php.h"
8304 +#include "zend.h"
8305 +#include "zend_API.h"
8306 +#include "zend_compile.h"
8307 +#include "zend_hash.h"
8308 +#include "zend_extensions.h"
8309 +
8310 +#if ZEND_MODULE_API_NO > 20050922
8311 +#define ZEND_ENGINE_2_2
8312 +#endif
8313 +#if ZEND_MODULE_API_NO > 20050921
8314 +#define ZEND_ENGINE_2_1
8315 +#endif
8316 +#ifdef ZEND_ENGINE_2_1
8317 +#include "zend_vm.h"
8318 +#endif
8319 +
8320 +#include "rfc1867.h"
8321 +
8322 +#endif
8323 +
8324 +/*
8325 + * Local variables:
8326 + * tab-width: 4
8327 + * c-basic-offset: 4
8328 + * End:
8329 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8330 + * vim<600: expandtab sw=4 ts=4 sts=4
8331 + */
8332 diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthreadmutex.c
8333 --- php-5.2.5-orig/ext/apc/apc_pthreadmutex.c 1969-12-31 18:00:00.000000000 -0600
8334 +++ php-5.2.5/ext/apc/apc_pthreadmutex.c 2007-12-26 16:51:32.000000000 -0600
8335 @@ -0,0 +1,111 @@
8336 +/*
8337 + +----------------------------------------------------------------------+
8338 + | APC |
8339 + +----------------------------------------------------------------------+
8340 + | Copyright (c) 2006 The PHP Group |
8341 + +----------------------------------------------------------------------+
8342 + | This source file is subject to version 3.01 of the PHP license, |
8343 + | that is bundled with this package in the file LICENSE, and is |
8344 + | available through the world-wide-web at the following url: |
8345 + | http://www.php.net/license/3_01.txt |
8346 + | If you did not receive a copy of the PHP license and are unable to |
8347 + | obtain it through the world-wide-web, please send a note to |
8348 + | license@php.net so we can mail you a copy immediately. |
8349 + +----------------------------------------------------------------------+
8350 + | Authors: Brian Shire <shire@php.net> |
8351 + +----------------------------------------------------------------------+
8352 +
8353 + */
8354 +
8355 +/* $Id: apc_pthreadmutex.c,v 3.3 2007/12/21 01:36:51 shire Exp $ */
8356 +
8357 +#include "apc_pthreadmutex.h"
8358 +
8359 +#ifdef APC_PTHREADMUTEX_LOCKS
8360 +
8361 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock)
8362 +{
8363 + int result;
8364 + pthread_mutexattr_t* attr;
8365 + attr = malloc(sizeof(pthread_mutexattr_t));
8366 +
8367 + result = pthread_mutexattr_init(attr);
8368 + if(result == ENOMEM) {
8369 + apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
8370 + } else if(result == EINVAL) {
8371 + apc_eprint("pthread mutex error: attr does not point to writeable memory.");
8372 + } else if(result == EFAULT) {
8373 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8374 + }
8375 +
8376 +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
8377 + result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
8378 + if (result == EINVAL) {
8379 + apc_eprint("pthread_mutexattr_settype: unable to set adaptive mutexes");
8380 + }
8381 +#endif
8382 +
8383 + /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
8384 + result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
8385 + if(result == EINVAL) {
8386 + apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
8387 + } else if(result == EFAULT) {
8388 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8389 + } else if(result == ENOTSUP) {
8390 + apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
8391 + }
8392 +
8393 + if(pthread_mutex_init(lock, attr)) {
8394 + apc_eprint("unable to initialize pthread lock");
8395 + }
8396 + return lock;
8397 +}
8398 +
8399 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
8400 +{
8401 + return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
8402 +}
8403 +
8404 +void apc_pthreadmutex_lock(pthread_mutex_t *lock)
8405 +{
8406 + int result;
8407 + result = pthread_mutex_lock(lock);
8408 + if(result == EINVAL) {
8409 + apc_eprint("unable to obtain pthread lock (EINVAL)");
8410 + } else if(result == EDEADLK) {
8411 + apc_eprint("unable to obtain pthread lock (EDEADLK)");
8412 + }
8413 +}
8414 +
8415 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
8416 +{
8417 + if(pthread_mutex_unlock(lock)) {
8418 + apc_eprint("unable to unlock pthread lock");
8419 + }
8420 +}
8421 +
8422 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
8423 +{
8424 + int rval;
8425 + rval = pthread_mutex_trylock(lock);
8426 + if(rval == EBUSY) { /* Lock is already held */
8427 + return 0;
8428 + } else if(rval == 0) { /* Obtained lock */
8429 + return 1;
8430 + } else { /* Other error */
8431 + apc_eprint("unable to obtain pthread trylock");
8432 + return 0;
8433 + }
8434 +}
8435 +
8436 +
8437 +#endif
8438 +
8439 +/*
8440 + * Local variables:
8441 + * tab-width: 4
8442 + * c-basic-offset: 4
8443 + * End:
8444 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8445 + * vim<600: expandtab sw=4 ts=4 sts=4
8446 + */
8447 diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthreadmutex.h
8448 --- php-5.2.5-orig/ext/apc/apc_pthreadmutex.h 1969-12-31 18:00:00.000000000 -0600
8449 +++ php-5.2.5/ext/apc/apc_pthreadmutex.h 2007-12-26 16:51:32.000000000 -0600
8450 @@ -0,0 +1,48 @@
8451 +/*
8452 + +----------------------------------------------------------------------+
8453 + | APC |
8454 + +----------------------------------------------------------------------+
8455 + | Copyright (c) 2006 The PHP Group |
8456 + +----------------------------------------------------------------------+
8457 + | This source file is subject to version 3.01 of the PHP license, |
8458 + | that is bundled with this package in the file LICENSE, and is |
8459 + | available through the world-wide-web at the following url: |
8460 + | http://www.php.net/license/3_01.txt |
8461 + | If you did not receive a copy of the PHP license and are unable to |
8462 + | obtain it through the world-wide-web, please send a note to |
8463 + | license@php.net so we can mail you a copy immediately. |
8464 + +----------------------------------------------------------------------+
8465 + | Authors: Brian Shire <shire@php.net> |
8466 + +----------------------------------------------------------------------+
8467 +
8468 + */
8469 +
8470 +/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
8471 +
8472 +#ifndef APC_PTHREADMUTEX_H
8473 +#define APC_PTHREADMUTEX_H
8474 +
8475 +#include "apc.h"
8476 +
8477 +#ifdef APC_PTHREADMUTEX_LOCKS
8478 +
8479 +#include <pthread.h>
8480 +
8481 +pthread_mutex_t *apc_pthreadmutex_create();
8482 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
8483 +void apc_pthreadmutex_lock(pthread_mutex_t *lock);
8484 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
8485 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
8486 +
8487 +#endif
8488 +
8489 +#endif
8490 +
8491 +/*
8492 + * Local variables:
8493 + * tab-width: 4
8494 + * c-basic-offset: 4
8495 + * End:
8496 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8497 + * vim<600: expandtab sw=4 ts=4 sts=4
8498 + */
8499 diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
8500 --- php-5.2.5-orig/ext/apc/apc_rfc1867.c 1969-12-31 18:00:00.000000000 -0600
8501 +++ php-5.2.5/ext/apc/apc_rfc1867.c 2007-12-26 16:51:32.000000000 -0600
8502 @@ -0,0 +1,195 @@
8503 +/*
8504 + +----------------------------------------------------------------------+
8505 + | APC |
8506 + +----------------------------------------------------------------------+
8507 + | Copyright (c) 2006 The PHP Group |
8508 + +----------------------------------------------------------------------+
8509 + | This source file is subject to version 3.01 of the PHP license, |
8510 + | that is bundled with this package in the file LICENSE, and is |
8511 + | available through the world-wide-web at the following url: |
8512 + | http://www.php.net/license/3_01.txt |
8513 + | If you did not receive a copy of the PHP license and are unable to |
8514 + | obtain it through the world-wide-web, please send a note to |
8515 + | license@php.net so we can mail you a copy immediately. |
8516 + +----------------------------------------------------------------------+
8517 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
8518 + +----------------------------------------------------------------------+
8519 +
8520 + This software was contributed to PHP by Community Connect Inc. in 2002
8521 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8522 + Future revisions and derivatives of this source code must acknowledge
8523 + Community Connect Inc. as the original contributor of this module by
8524 + leaving this note intact in the source code.
8525 +
8526 + All other licensing and usage conditions are those of the PHP Group.
8527 +
8528 + */
8529 +
8530 +/* $Id: apc_rfc1867.c,v 3.12 2007/10/18 20:37:20 rasmus Exp $*/
8531 +
8532 +#include "apc.h"
8533 +#include "apc_globals.h"
8534 +#include "rfc1867.h"
8535 +
8536 +#ifdef PHP_WIN32
8537 +#include "win32/time.h"
8538 +#endif
8539 +
8540 +#ifdef MULTIPART_EVENT_FORMDATA
8541 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8542 +
8543 +static double my_time() {
8544 + struct timeval a;
8545 + double t;
8546 + gettimeofday(&a, NULL);
8547 + t = a.tv_sec + (a.tv_usec/1000000.00);
8548 + return t;
8549 +}
8550 +
8551 +void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
8552 + static char tracking_key[64];
8553 + static int key_length = 0;
8554 + static size_t content_length = 0;
8555 + static char filename[128];
8556 + static char name[64];
8557 + static char *temp_filename=NULL;
8558 + static int cancel_upload = 0;
8559 + static double start_time;
8560 + static size_t bytes_processed = 0;
8561 + static size_t prev_bytes_processed = 0;
8562 + static int update_freq = 0;
8563 + static double rate;
8564 + zval *track = NULL;
8565 +
8566 + switch (event) {
8567 + case MULTIPART_EVENT_START:
8568 + {
8569 + multipart_event_start *data = (multipart_event_start *) event_data;
8570 + content_length = data->content_length;
8571 + *tracking_key = '\0';
8572 + *name = '\0';
8573 + cancel_upload = 0;
8574 + temp_filename = NULL;
8575 + *filename= '\0';
8576 + key_length = 0;
8577 + start_time = my_time();
8578 + bytes_processed = 0;
8579 + rate = 0;
8580 + update_freq = APCG(rfc1867_freq);
8581 + if(update_freq < 0) { // frequency is a percentage, not bytes
8582 + update_freq = content_length * APCG(rfc1867_freq) / 100;
8583 + }
8584 + }
8585 + break;
8586 +
8587 + case MULTIPART_EVENT_FORMDATA:
8588 + {
8589 + int prefix_len = strlen(APCG(rfc1867_prefix));
8590 + multipart_event_formdata *data = (multipart_event_formdata *) event_data;
8591 + if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) && data->value && data->length && data->length < sizeof(tracking_key) - prefix_len) {
8592 + strlcat(tracking_key, APCG(rfc1867_prefix), 63);
8593 + strlcat(tracking_key, *data->value, 63);
8594 + key_length = data->length + prefix_len;
8595 + bytes_processed = data->post_bytes_processed;
8596 + }
8597 + }
8598 + break;
8599 +
8600 + case MULTIPART_EVENT_FILE_START:
8601 + if(*tracking_key) {
8602 + multipart_event_file_start *data = (multipart_event_file_start *) event_data;
8603 +
8604 + bytes_processed = data->post_bytes_processed;
8605 + strncpy(filename,*data->filename,127);
8606 + temp_filename = NULL;
8607 + strncpy(name,data->name,63);
8608 + ALLOC_INIT_ZVAL(track);
8609 + array_init(track);
8610 + add_assoc_long(track, "total", content_length);
8611 + add_assoc_long(track, "current", bytes_processed);
8612 + add_assoc_string(track, "filename", filename, 1);
8613 + add_assoc_string(track, "name", name, 1);
8614 + add_assoc_long(track, "done", 0);
8615 + add_assoc_double(track, "start_time", start_time);
8616 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8617 + zval_ptr_dtor(&track);
8618 + }
8619 + break;
8620 +
8621 + case MULTIPART_EVENT_FILE_DATA:
8622 + if(*tracking_key) {
8623 + multipart_event_file_data *data = (multipart_event_file_data *) event_data;
8624 + bytes_processed = data->post_bytes_processed;
8625 + ALLOC_INIT_ZVAL(track);
8626 + array_init(track);
8627 + add_assoc_long(track, "total", content_length);
8628 + add_assoc_long(track, "current", bytes_processed);
8629 + add_assoc_string(track, "filename", filename, 1);
8630 + add_assoc_string(track, "name", name, 1);
8631 + add_assoc_long(track, "done", 0);
8632 + add_assoc_double(track, "start_time", start_time);
8633 + if(bytes_processed - prev_bytes_processed > update_freq) {
8634 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8635 + prev_bytes_processed = bytes_processed;
8636 + }
8637 + zval_ptr_dtor(&track);
8638 + }
8639 + break;
8640 +
8641 + case MULTIPART_EVENT_FILE_END:
8642 + if(*tracking_key) {
8643 + multipart_event_file_end *data = (multipart_event_file_end *) event_data;
8644 + bytes_processed = data->post_bytes_processed;
8645 + cancel_upload = data->cancel_upload;
8646 + temp_filename = data->temp_filename;
8647 + ALLOC_INIT_ZVAL(track);
8648 + array_init(track);
8649 + add_assoc_long(track, "total", content_length);
8650 + add_assoc_long(track, "current", bytes_processed);
8651 + add_assoc_string(track, "filename", filename, 1);
8652 + add_assoc_string(track, "name", name, 1);
8653 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8654 + add_assoc_long(track, "cancel_upload", cancel_upload);
8655 + add_assoc_long(track, "done", 0);
8656 + add_assoc_double(track, "start_time", start_time);
8657 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8658 + zval_ptr_dtor(&track);
8659 + }
8660 + break;
8661 +
8662 + case MULTIPART_EVENT_END:
8663 + if(*tracking_key) {
8664 + double now = my_time();
8665 + multipart_event_end *data = (multipart_event_end *) event_data;
8666 + bytes_processed = data->post_bytes_processed;
8667 + if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
8668 + else rate = 8.0*bytes_processed; /* Too quick */
8669 + ALLOC_INIT_ZVAL(track);
8670 + array_init(track);
8671 + add_assoc_long(track, "total", content_length);
8672 + add_assoc_long(track, "current", bytes_processed);
8673 + add_assoc_double(track, "rate", rate);
8674 + add_assoc_string(track, "filename", filename, 1);
8675 + add_assoc_string(track, "name", name, 1);
8676 + if(temp_filename) {
8677 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8678 + }
8679 + add_assoc_long(track, "cancel_upload", cancel_upload);
8680 + add_assoc_long(track, "done", 1);
8681 + add_assoc_double(track, "start_time", start_time);
8682 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8683 + zval_ptr_dtor(&track);
8684 + }
8685 + break;
8686 + }
8687 +}
8688 +
8689 +#endif
8690 +/*
8691 + * Local variables:
8692 + * tab-width: 4
8693 + * c-basic-offset: 4
8694 + * End:
8695 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8696 + * vim<600: expandtab sw=4 ts=4 sts=4
8697 + */
8698 diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.c php-5.2.5/ext/apc/apc_sem.c
8699 --- php-5.2.5-orig/ext/apc/apc_sem.c 1969-12-31 18:00:00.000000000 -0600
8700 +++ php-5.2.5/ext/apc/apc_sem.c 2007-12-26 16:51:32.000000000 -0600
8701 @@ -0,0 +1,177 @@
8702 +/*
8703 + +----------------------------------------------------------------------+
8704 + | APC |
8705 + +----------------------------------------------------------------------+
8706 + | Copyright (c) 2006 The PHP Group |
8707 + +----------------------------------------------------------------------+
8708 + | This source file is subject to version 3.01 of the PHP license, |
8709 + | that is bundled with this package in the file LICENSE, and is |
8710 + | available through the world-wide-web at the following url: |
8711 + | http://www.php.net/license/3_01.txt |
8712 + | If you did not receive a copy of the PHP license and are unable to |
8713 + | obtain it through the world-wide-web, please send a note to |
8714 + | license@php.net so we can mail you a copy immediately. |
8715 + +----------------------------------------------------------------------+
8716 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8717 + +----------------------------------------------------------------------+
8718 +
8719 + This software was contributed to PHP by Community Connect Inc. in 2002
8720 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8721 + Future revisions and derivatives of this source code must acknowledge
8722 + Community Connect Inc. as the original contributor of this module by
8723 + leaving this note intact in the source code.
8724 +
8725 + All other licensing and usage conditions are those of the PHP Group.
8726 +
8727 + */
8728 +
8729 +/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
8730 +
8731 +#include "apc_sem.h"
8732 +#include "apc.h"
8733 +#include "php.h"
8734 +#include <sys/types.h>
8735 +#include <sys/ipc.h>
8736 +#include <sys/sem.h>
8737 +#include <sys/stat.h>
8738 +#include <unistd.h>
8739 +
8740 +#if HAVE_SEMUN
8741 +/* we have semun, no need to define */
8742 +#else
8743 +#undef HAVE_SEMUN
8744 +union semun {
8745 + int val; /* value for SETVAL */
8746 + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
8747 + unsigned short *array; /* array for GETALL, SETALL */
8748 + /* Linux specific part: */
8749 + struct seminfo *__buf; /* buffer for IPC_INFO */
8750 +};
8751 +#define HAVE_SEMUN 1
8752 +#endif
8753 +
8754 +#ifndef SEM_R
8755 +# define SEM_R 0444
8756 +#endif
8757 +#ifndef SEM_A
8758 +# define SEM_A 0222
8759 +#endif
8760 +
8761 +/* always use SEM_UNDO, otherwise we risk deadlock */
8762 +#define USE_SEM_UNDO
8763 +
8764 +#ifdef USE_SEM_UNDO
8765 +# define UNDO SEM_UNDO
8766 +#else
8767 +# define UNDO 0
8768 +#endif
8769 +
8770 +int apc_sem_create(const char* pathname, int proj, int initval)
8771 +{
8772 + int semid;
8773 + int perms;
8774 + union semun arg;
8775 + key_t key;
8776 +
8777 + perms = 0777;
8778 +
8779 + key = IPC_PRIVATE;
8780 + if (pathname != NULL) {
8781 + if ((key = ftok(pathname, proj)) < 0) {
8782 + apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
8783 + }
8784 + }
8785 +
8786 + if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
8787 + /* sempahore created for the first time, initialize now */
8788 + arg.val = initval;
8789 + if (semctl(semid, 0, SETVAL, arg) < 0) {
8790 + apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
8791 + }
8792 + }
8793 + else if (errno == EEXIST) {
8794 + /* sempahore already exists, don't initialize */
8795 + if ((semid = semget(key, 1, perms)) < 0) {
8796 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8797 + }
8798 + /* insert <sleazy way to avoid race condition> here */
8799 + }
8800 + else {
8801 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8802 + }
8803 +
8804 + return semid;
8805 +}
8806 +
8807 +void apc_sem_destroy(int semid)
8808 +{
8809 + /* we expect this call to fail often, so we do not check */
8810 + union semun arg;
8811 + semctl(semid, 0, IPC_RMID, arg);
8812 +}
8813 +
8814 +void apc_sem_lock(int semid)
8815 +{
8816 + struct sembuf op;
8817 +
8818 + op.sem_num = 0;
8819 + op.sem_op = -1;
8820 + op.sem_flg = UNDO;
8821 +
8822 + if (semop(semid, &op, 1) < 0) {
8823 + if (errno != EINTR) {
8824 + apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
8825 + }
8826 + }
8827 +}
8828 +
8829 +void apc_sem_unlock(int semid)
8830 +{
8831 + struct sembuf op;
8832 +
8833 + op.sem_num = 0;
8834 + op.sem_op = 1;
8835 + op.sem_flg = UNDO;
8836 +
8837 + if (semop(semid, &op, 1) < 0) {
8838 + if (errno != EINTR) {
8839 + apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
8840 + }
8841 + }
8842 +}
8843 +
8844 +void apc_sem_wait_for_zero(int semid)
8845 +{
8846 + struct sembuf op;
8847 +
8848 + op.sem_num = 0;
8849 + op.sem_op = 0;
8850 + op.sem_flg = UNDO;
8851 +
8852 + if (semop(semid, &op, 1) < 0) {
8853 + if (errno != EINTR) {
8854 + apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
8855 + }
8856 + }
8857 +}
8858 +
8859 +int apc_sem_get_value(int semid)
8860 +{
8861 + union semun arg;
8862 + unsigned short val[1];
8863 +
8864 + arg.array = val;
8865 + if (semctl(semid, 0, GETALL, arg) < 0) {
8866 + apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
8867 + }
8868 + return val[0];
8869 +}
8870 +
8871 +/*
8872 + * Local variables:
8873 + * tab-width: 4
8874 + * c-basic-offset: 4
8875 + * End:
8876 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8877 + * vim<600: expandtab sw=4 ts=4 sts=4
8878 + */
8879 diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.h php-5.2.5/ext/apc/apc_sem.h
8880 --- php-5.2.5-orig/ext/apc/apc_sem.h 1969-12-31 18:00:00.000000000 -0600
8881 +++ php-5.2.5/ext/apc/apc_sem.h 2007-12-26 16:51:32.000000000 -0600
8882 @@ -0,0 +1,51 @@
8883 +/*
8884 + +----------------------------------------------------------------------+
8885 + | APC |
8886 + +----------------------------------------------------------------------+
8887 + | Copyright (c) 2006 The PHP Group |
8888 + +----------------------------------------------------------------------+
8889 + | This source file is subject to version 3.01 of the PHP license, |
8890 + | that is bundled with this package in the file LICENSE, and is |
8891 + | available through the world-wide-web at the following url: |
8892 + | http://www.php.net/license/3_01.txt |
8893 + | If you did not receive a copy of the PHP license and are unable to |
8894 + | obtain it through the world-wide-web, please send a note to |
8895 + | license@php.net so we can mail you a copy immediately. |
8896 + +----------------------------------------------------------------------+
8897 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8898 + +----------------------------------------------------------------------+
8899 +
8900 + This software was contributed to PHP by Community Connect Inc. in 2002
8901 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8902 + Future revisions and derivatives of this source code must acknowledge
8903 + Community Connect Inc. as the original contributor of this module by
8904 + leaving this note intact in the source code.
8905 +
8906 + All other licensing and usage conditions are those of the PHP Group.
8907 +
8908 + */
8909 +
8910 +/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8911 +
8912 +#ifndef APC_SEM_H
8913 +#define APC_SEM_H
8914 +
8915 +/* Wrapper functions for SysV sempahores */
8916 +
8917 +extern int apc_sem_create(const char* pathname, int proj, int initval);
8918 +extern void apc_sem_destroy(int semid);
8919 +extern void apc_sem_lock(int semid);
8920 +extern void apc_sem_unlock(int semid);
8921 +extern void apc_sem_wait_for_zero(int semid);
8922 +extern int apc_sem_get_value(int semid);
8923 +
8924 +#endif
8925 +
8926 +/*
8927 + * Local variables:
8928 + * tab-width: 4
8929 + * c-basic-offset: 4
8930 + * End:
8931 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8932 + * vim<600: expandtab sw=4 ts=4 sts=4
8933 + */
8934 diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.c php-5.2.5/ext/apc/apc_shm.c
8935 --- php-5.2.5-orig/ext/apc/apc_shm.c 1969-12-31 18:00:00.000000000 -0600
8936 +++ php-5.2.5/ext/apc/apc_shm.c 2007-12-26 16:51:32.000000000 -0600
8937 @@ -0,0 +1,110 @@
8938 +/*
8939 + +----------------------------------------------------------------------+
8940 + | APC |
8941 + +----------------------------------------------------------------------+
8942 + | Copyright (c) 2006 The PHP Group |
8943 + +----------------------------------------------------------------------+
8944 + | This source file is subject to version 3.01 of the PHP license, |
8945 + | that is bundled with this package in the file LICENSE, and is |
8946 + | available through the world-wide-web at the following url: |
8947 + | http://www.php.net/license/3_01.txt |
8948 + | If you did not receive a copy of the PHP license and are unable to |
8949 + | obtain it through the world-wide-web, please send a note to |
8950 + | license@php.net so we can mail you a copy immediately. |
8951 + +----------------------------------------------------------------------+
8952 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8953 + | Rasmus Lerdorf <rasmus@php.net> |
8954 + +----------------------------------------------------------------------+
8955 +
8956 + This software was contributed to PHP by Community Connect Inc. in 2002
8957 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8958 + Future revisions and derivatives of this source code must acknowledge
8959 + Community Connect Inc. as the original contributor of this module by
8960 + leaving this note intact in the source code.
8961 +
8962 + All other licensing and usage conditions are those of the PHP Group.
8963 +
8964 + */
8965 +
8966 +/* $Id: apc_shm.c,v 3.11 2007/05/09 22:15:33 shire Exp $ */
8967 +
8968 +#include "apc_shm.h"
8969 +#include "apc.h"
8970 +#ifdef PHP_WIN32
8971 +/* shm functions are available in TSRM */
8972 +#include <tsrm/tsrm_win32.h>
8973 +#define key_t long
8974 +#else
8975 +#include <sys/ipc.h>
8976 +#include <sys/shm.h>
8977 +#include <sys/stat.h>
8978 +#endif
8979 +
8980 +#ifndef SHM_R
8981 +# define SHM_R 0444 /* read permission */
8982 +#endif
8983 +#ifndef SHM_A
8984 +# define SHM_A 0222 /* write permission */
8985 +#endif
8986 +
8987 +int apc_shm_create(const char* pathname, int proj, size_t size)
8988 +{
8989 + int shmid; /* shared memory id */
8990 + int oflag; /* permissions on shm */
8991 + key_t key; /* shm key returned by ftok */
8992 +
8993 + key = IPC_PRIVATE;
8994 +#ifndef PHP_WIN32
8995 + /* no ftok yet for win32 */
8996 + if (pathname != NULL) {
8997 + if ((key = ftok(pathname, proj)) < 0) {
8998 + apc_eprint("apc_shm_create: ftok failed:");
8999 + }
9000 + }
9001 +#endif
9002 +
9003 + oflag = IPC_CREAT | SHM_R | SHM_A;
9004 + if ((shmid = shmget(key, size, oflag)) < 0) {
9005 + apc_eprint("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment.", key, size, oflag, strerror(errno));
9006 + }
9007 +
9008 + return shmid;
9009 +}
9010 +
9011 +void apc_shm_destroy(int shmid)
9012 +{
9013 + /* we expect this call to fail often, so we do not check */
9014 + shmctl(shmid, IPC_RMID, 0);
9015 +}
9016 +
9017 +void* apc_shm_attach(int shmid)
9018 +{
9019 + void* shmaddr; /* the shared memory address */
9020 +
9021 + if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
9022 + apc_eprint("apc_shm_attach: shmat failed:");
9023 + }
9024 +
9025 + /*
9026 + * We set the shmid for removal immediately after attaching to it. The
9027 + * segment won't disappear until all processes have detached from it.
9028 + */
9029 + apc_shm_destroy(shmid);
9030 + return shmaddr;
9031 +}
9032 +
9033 +void apc_shm_detach(void* shmaddr)
9034 +{
9035 + if (shmdt(shmaddr) < 0) {
9036 + apc_eprint("apc_shm_detach: shmdt failed:");
9037 + }
9038 +}
9039 +
9040 +/*
9041 + * Local variables:
9042 + * tab-width: 4
9043 + * c-basic-offset: 4
9044 + * End:
9045 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9046 + * vim<600: expandtab sw=4 ts=4 sts=4
9047 + */
9048 diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.h php-5.2.5/ext/apc/apc_shm.h
9049 --- php-5.2.5-orig/ext/apc/apc_shm.h 1969-12-31 18:00:00.000000000 -0600
9050 +++ php-5.2.5/ext/apc/apc_shm.h 2007-12-26 16:51:32.000000000 -0600
9051 @@ -0,0 +1,54 @@
9052 +/*
9053 + +----------------------------------------------------------------------+
9054 + | APC |
9055 + +----------------------------------------------------------------------+
9056 + | Copyright (c) 2006 The PHP Group |
9057 + +----------------------------------------------------------------------+
9058 + | This source file is subject to version 3.01 of the PHP license, |
9059 + | that is bundled with this package in the file LICENSE, and is |
9060 + | available through the world-wide-web at the following url: |
9061 + | http://www.php.net/license/3_01.txt |
9062 + | If you did not receive a copy of the PHP license and are unable to |
9063 + | obtain it through the world-wide-web, please send a note to |
9064 + | license@php.net so we can mail you a copy immediately. |
9065 + +----------------------------------------------------------------------+
9066 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9067 + +----------------------------------------------------------------------+
9068 +
9069 + This software was contributed to PHP by Community Connect Inc. in 2002
9070 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9071 + Future revisions and derivatives of this source code must acknowledge
9072 + Community Connect Inc. as the original contributor of this module by
9073 + leaving this note intact in the source code.
9074 +
9075 + All other licensing and usage conditions are those of the PHP Group.
9076 +
9077 + */
9078 +
9079 +/* $Id: apc_shm.h,v 3.8 2007/05/23 01:23:21 auroraeosrose Exp $ */
9080 +
9081 +#ifndef APC_SHM_H
9082 +#define APC_SHM_H
9083 +
9084 +#include <sys/types.h>
9085 +#ifdef PHP_WIN32
9086 +#include <time.h>
9087 +#endif
9088 +
9089 +/* Wrapper functions for unix shared memory */
9090 +
9091 +extern int apc_shm_create(const char* name, int proj, size_t size);
9092 +extern void apc_shm_destroy(int shmid);
9093 +extern void* apc_shm_attach(int shmid);
9094 +extern void apc_shm_detach(void* shmaddr);
9095 +
9096 +#endif
9097 +
9098 +/*
9099 + * Local variables:
9100 + * tab-width: 4
9101 + * c-basic-offset: 4
9102 + * End:
9103 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9104 + * vim<600: expandtab sw=4 ts=4 sts=4
9105 + */
9106 diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.c php-5.2.5/ext/apc/apc_signal.c
9107 --- php-5.2.5-orig/ext/apc/apc_signal.c 1969-12-31 18:00:00.000000000 -0600
9108 +++ php-5.2.5/ext/apc/apc_signal.c 2007-12-26 16:51:32.000000000 -0600
9109 @@ -0,0 +1,178 @@
9110 +/*
9111 + +----------------------------------------------------------------------+
9112 + | APC |
9113 + +----------------------------------------------------------------------+
9114 + | Copyright (c) 2006 The PHP Group |
9115 + +----------------------------------------------------------------------+
9116 + | This source file is subject to version 3.01 of the PHP license, |
9117 + | that is bundled with this package in the file LICENSE, and is |
9118 + | available through the world-wide-web at the following url: |
9119 + | http://www.php.net/license/3_01.txt |
9120 + | If you did not receive a copy of the PHP license and are unable to |
9121 + | obtain it through the world-wide-web, please send a note to |
9122 + | license@php.net so we can mail you a copy immediately. |
9123 + +----------------------------------------------------------------------+
9124 + | Authors: Lucas Nealan <lucas@php.net> |
9125 + +----------------------------------------------------------------------+
9126 +
9127 + This software was contributed to PHP by Facebook Inc. in 2007.
9128 +
9129 + Future revisions and derivatives of this source code must acknowledge
9130 + Facebook Inc. as the original contributor of this module by leaving
9131 + this note intact in the source code.
9132 +
9133 + All other licensing and usage conditions are those of the PHP Group.
9134 + */
9135 +
9136 + /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */
9137 +
9138 + /* Allows apc to install signal handlers and maintain signalling
9139 + to already registered handlers. Registers all signals that
9140 + coredump by default and unmaps the shared memory segment
9141 + before the coredump. Note: PHP module init is called before
9142 + signals are set by Apache and thus apc_set_signals should
9143 + be called in request init (RINIT)
9144 + */
9145 +
9146 +#include <signal.h>
9147 +#include "apc_globals.h"
9148 +#include "apc_sma.h"
9149 +#include "apc_signal.h"
9150 +
9151 +static apc_signal_info_t apc_signal_info = {0};
9152 +
9153 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
9154 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
9155 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
9156 +
9157 +/* {{{ apc_core_unmap
9158 + * Coredump signal handler, unmaps shm and calls previously installed handlers
9159 + */
9160 +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context)
9161 +{
9162 + apc_sma_cleanup();
9163 + apc_rehandle_signal(signo, siginfo, context);
9164 +
9165 +#if !defined(WIN32) && !defined(NETWARE)
9166 + kill(getpid(), signo);
9167 +#else
9168 + raise(signo);
9169 +#endif
9170 +} /* }}} */
9171 +
9172 +/* {{{ apc_rehandle_signal
9173 + * Call the previously registered handler for a signal
9174 + */
9175 +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
9176 +{
9177 + int i;
9178 + apc_signal_entry_t p_sig = {0};
9179 +
9180 + for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) {
9181 + p_sig = *apc_signal_info.prev[i];
9182 + if (p_sig.signo == signo) {
9183 + if (p_sig.siginfo) {
9184 + (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
9185 + } else {
9186 + (*(void (*)(int))p_sig.handler)(signo);
9187 + }
9188 + }
9189 + }
9190 +
9191 +} /* }}} */
9192 +
9193 +/* {{{ apc_register_signal
9194 + * Set a handler for a previously installed signal and save so we can
9195 + * callback when handled
9196 + */
9197 +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
9198 +{
9199 +#if HAVE_SIGACTION
9200 + struct sigaction sa = {0};
9201 + apc_signal_entry_t p_sig = {0};
9202 +
9203 + if (sigaction(signo, NULL, &sa) == 0) {
9204 + if ((void*)sa.sa_handler == (void*)handler) {
9205 + return SUCCESS;
9206 + }
9207 +
9208 + if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
9209 + p_sig.signo = signo;
9210 + p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
9211 + p_sig.handler = (void *)sa.sa_handler;
9212 +
9213 + apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
9214 + apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
9215 + *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
9216 + } else {
9217 + /* inherit flags and mask if already set */
9218 + sigemptyset(&sa.sa_mask);
9219 + sa.sa_flags = 0;
9220 + sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
9221 +#if defined(SA_ONESHOT)
9222 + sa.sa_flags = SA_ONESHOT;
9223 +#elif defined(SA_RESETHAND)
9224 + sa.sa_flags = SA_RESETHAND;
9225 +#endif
9226 + }
9227 + sa.sa_handler = (void*)handler;
9228 +
9229 + if (sigaction(signo, &sa, NULL) < 0) {
9230 + apc_wprint("Error installing apc signal handler for %d", signo);
9231 + }
9232 +
9233 + return SUCCESS;
9234 + }
9235 +#endif
9236 + return FAILURE;
9237 +} /* }}} */
9238 +
9239 +/* {{{ apc_set_signals
9240 + * Install our signal handlers */
9241 +void apc_set_signals(TSRMLS_D)
9242 +{
9243 + if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
9244 + /* ISO C standard signals that coredump */
9245 + apc_register_signal(SIGSEGV, apc_core_unmap);
9246 + apc_register_signal(SIGABRT, apc_core_unmap);
9247 + apc_register_signal(SIGFPE, apc_core_unmap);
9248 + apc_register_signal(SIGILL, apc_core_unmap);
9249 + /* extended signals that coredump */
9250 +#ifdef SIGBUS
9251 + apc_register_signal(SIGBUS, apc_core_unmap);
9252 +#endif
9253 +#ifdef SIGABORT
9254 + apc_register_signal(SIGABORT, apc_core_unmap);
9255 +#endif
9256 +#ifdef SIGEMT
9257 + apc_register_signal(SIGEMT, apc_core_unmap);
9258 +#endif
9259 +#ifdef SIGIOT
9260 + apc_register_signal(SIGIOT, apc_core_unmap);
9261 +#endif
9262 +#ifdef SIGQUIT
9263 + apc_register_signal(SIGQUIT, apc_core_unmap);
9264 +#endif
9265 +#ifdef SIGSYS
9266 + apc_register_signal(SIGSYS, apc_core_unmap);
9267 +#endif
9268 +#ifdef SIGTRAP
9269 + apc_register_signal(SIGTRAP, apc_core_unmap);
9270 +#endif
9271 +#ifdef SIGXCPU
9272 + apc_register_signal(SIGXCPU, apc_core_unmap);
9273 +#endif
9274 +#ifdef SIGXFSZ
9275 + apc_register_signal(SIGXFSZ, apc_core_unmap);
9276 +#endif
9277 + }
9278 +} /* }}} */
9279 +
9280 +/*
9281 + * Local variables:
9282 + * tab-width: 4
9283 + * c-basic-offset: 4
9284 + * End:
9285 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9286 + * vim<600: expandtab sw=4 ts=4 sts=4
9287 + */
9288 diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.h php-5.2.5/ext/apc/apc_signal.h
9289 --- php-5.2.5-orig/ext/apc/apc_signal.h 1969-12-31 18:00:00.000000000 -0600
9290 +++ php-5.2.5/ext/apc/apc_signal.h 2007-12-26 16:51:32.000000000 -0600
9291 @@ -0,0 +1,50 @@
9292 +/*
9293 + +----------------------------------------------------------------------+
9294 + | APC |
9295 + +----------------------------------------------------------------------+
9296 + | Copyright (c) 2006 The PHP Group |
9297 + +----------------------------------------------------------------------+
9298 + | This source file is subject to version 3.01 of the PHP license, |
9299 + | that is bundled with this package in the file LICENSE, and is |
9300 + | available through the world-wide-web at the following url: |
9301 + | http://www.php.net/license/3_01.txt |
9302 + | If you did not receive a copy of the PHP license and are unable to |
9303 + | obtain it through the world-wide-web, please send a note to |
9304 + | license@php.net so we can mail you a copy immediately. |
9305 + +----------------------------------------------------------------------+
9306 + | Authors: Lucas Nealan <lucas@php.net> |
9307 + +----------------------------------------------------------------------+
9308 +
9309 + */
9310 +
9311 +/* $Id: apc_signal.h,v 1.1 2007/12/26 22:36:06 rasmus Exp $ */
9312 +
9313 +#ifndef APC_SIGNAL_H
9314 +#define APC_SIGNAL_H
9315 +
9316 +#include "apc.h"
9317 +#include "apc_php.h"
9318 +
9319 +typedef struct apc_signal_entry_t {
9320 + int signo; /* signal number */
9321 + int siginfo; /* siginfo style handler calling */
9322 + void* handler; /* signal handler */
9323 +} apc_signal_entry_t;
9324 +
9325 +typedef struct apc_signal_info_t {
9326 + int installed; /* How many signals we've installed handles for */
9327 + apc_signal_entry_t **prev; /* Previous signal handlers */
9328 +} apc_signal_info_t;
9329 +
9330 +void apc_set_signals(TSRMLS_D);
9331 +
9332 +#endif
9333 +
9334 +/*
9335 + * Local variables:
9336 + * tab-width: 4
9337 + * c-basic-offset: 4
9338 + * End:
9339 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9340 + * vim<600: expandtab sw=4 ts=4 sts=4
9341 + */
9342 diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.c php-5.2.5/ext/apc/apc_sma.c
9343 --- php-5.2.5-orig/ext/apc/apc_sma.c 1969-12-31 18:00:00.000000000 -0600
9344 +++ php-5.2.5/ext/apc/apc_sma.c 2007-12-26 16:51:32.000000000 -0600
9345 @@ -0,0 +1,628 @@
9346 +/*
9347 + +----------------------------------------------------------------------+
9348 + | APC |
9349 + +----------------------------------------------------------------------+
9350 + | Copyright (c) 2006 The PHP Group |
9351 + +----------------------------------------------------------------------+
9352 + | This source file is subject to version 3.01 of the PHP license, |
9353 + | that is bundled with this package in the file LICENSE, and is |
9354 + | available through the world-wide-web at the following url: |
9355 + | http://www.php.net/license/3_01.txt |
9356 + | If you did not receive a copy of the PHP license and are unable to |
9357 + | obtain it through the world-wide-web, please send a note to |
9358 + | license@php.net so we can mail you a copy immediately. |
9359 + +----------------------------------------------------------------------+
9360 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9361 + | Rasmus Lerdorf <rasmus@php.net> |
9362 + +----------------------------------------------------------------------+
9363 +
9364 + This software was contributed to PHP by Community Connect Inc. in 2002
9365 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9366 + Future revisions and derivatives of this source code must acknowledge
9367 + Community Connect Inc. as the original contributor of this module by
9368 + leaving this note intact in the source code.
9369 +
9370 + All other licensing and usage conditions are those of the PHP Group.
9371 +
9372 + */
9373 +
9374 +/* $Id: apc_sma.c,v 1.69 2007/12/26 21:35:39 gopalv Exp $ */
9375 +
9376 +#include "apc_sma.h"
9377 +#include "apc.h"
9378 +#include "apc_globals.h"
9379 +#include "apc_lock.h"
9380 +#include "apc_shm.h"
9381 +#include <limits.h>
9382 +#if APC_MMAP
9383 +void *apc_mmap(char *file_mask, size_t size);
9384 +void apc_unmap(void* shmaddr, size_t size);
9385 +#endif
9386 +
9387 +/* {{{ locking macros */
9388 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
9389 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
9390 +#define UNLOCK(c) { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
9391 +/* }}} */
9392 +
9393 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
9394 +
9395 +static int sma_initialized = 0; /* true if the sma has been initialized */
9396 +static unsigned int sma_numseg; /* number of shm segments to allow */
9397 +static size_t sma_segsize; /* size of each shm segment */
9398 +static size_t* sma_segments; /* array of shm segment ids */
9399 +static void** sma_shmaddrs; /* array of shm segment addresses */
9400 +static int sma_lastseg = 0; /* index of MRU segment */
9401 +
9402 +typedef struct header_t header_t;
9403 +struct header_t {
9404 + apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */
9405 + size_t segsize; /* size of entire segment */
9406 + size_t avail; /* bytes available (not necessarily contiguous) */
9407 + size_t nfoffset; /* start next fit search from this offset */
9408 +#if ALLOC_DISTRIBUTION
9409 + size_t adist[30];
9410 +#endif
9411 +};
9412 +
9413 +
9414 +/* do not enable for threaded http servers */
9415 +/* #define __APC_SMA_DEBUG__ 1 */
9416 +
9417 +#ifdef __APC_SMA_DEBUG__
9418 +/* global counter for identifying blocks
9419 + * Technically it is possible to do the same
9420 + * using offsets, but double allocations of the
9421 + * same offset can happen. */
9422 +static volatile size_t block_id = 0;
9423 +#endif
9424 +
9425 +#define APC_SMA_CANARIES 1
9426 +
9427 +typedef struct block_t block_t;
9428 +struct block_t {
9429 + size_t size; /* size of this block */
9430 + size_t next; /* offset in segment of next free block */
9431 +#ifdef APC_SMA_CANARIES
9432 + size_t canary; /* canary to check for memory overwrites */
9433 +#endif
9434 +#ifdef __APC_SMA_DEBUG__
9435 + size_t id; /* identifier for the memory block */
9436 +#endif
9437 +};
9438 +
9439 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
9440 + * module. Both assume the presence of a variable shmaddr that points to the
9441 + * beginning of the shared memory segment in question. */
9442 +
9443 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
9444 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
9445 +
9446 +/* Canary macros for setting, checking and resetting memory canaries */
9447 +#ifdef APC_SMA_CANARIES
9448 + #define SET_CANARY(v) (v)->canary = 0x42424242
9449 + #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
9450 + #define RESET_CANARY(v) (v)->canary = -42
9451 +#else
9452 + #define SET_CANARY(v)
9453 + #define CHECK_CANARY(v)
9454 + #define RESET_CANARY(v)
9455 +#endif
9456 +
9457 +
9458 +#ifdef max
9459 +#undef max
9460 +#endif
9461 +#define max(a, b) ((a) > (b) ? (a) : (b))
9462 +
9463 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
9464 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
9465 +#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
9466 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
9467 +/* }}} */
9468 +
9469 +/* {{{ sma_allocate: tries to allocate size bytes in a segment */
9470 +static int sma_allocate(void* shmaddr, size_t size)
9471 +{
9472 + header_t* header; /* header of shared memory segment */
9473 + block_t* prv; /* block prior to working block */
9474 + block_t* cur; /* working block in list */
9475 + block_t* prvnextfit; /* block before next fit */
9476 + size_t realsize; /* actual size of block needed, including header */
9477 + size_t last_offset; /* save the last search offset */
9478 + int wrapped=0;
9479 + const size_t block_size = ALIGNWORD(sizeof(struct block_t));
9480 +
9481 + realsize = ALIGNWORD(size + block_size);
9482 +
9483 + /*
9484 + * First, insure that the segment contains at least realsize free bytes,
9485 + * even if they are not contiguous.
9486 + */
9487 + header = (header_t*) shmaddr;
9488 + if (header->avail < realsize) {
9489 + return -1;
9490 + }
9491 +
9492 + prvnextfit = 0; /* initially null (no fit) */
9493 + last_offset = 0;
9494 +
9495 + /* If we have a next fit offset, start searching from there */
9496 + if(header->nfoffset) {
9497 + prv = BLOCKAT(header->nfoffset);
9498 + /* if prv is the last block, jump to the beginning */
9499 + if(prv->next == 0) {
9500 + prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9501 + wrapped = 1;
9502 + }
9503 + } else {
9504 + prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9505 + }
9506 +
9507 + CHECK_CANARY(prv);
9508 +
9509 + while (prv->next != header->nfoffset) {
9510 + cur = BLOCKAT(prv->next);
9511 +#ifdef __APC_SMA_DEBUG__
9512 + CHECK_CANARY(cur);
9513 +#endif
9514 + /* If it can fit realiszie bytes in cur block, stop searching */
9515 + if (cur->size >= realsize) {
9516 + prvnextfit = prv;
9517 + break;
9518 + }
9519 + last_offset = prv->next;
9520 + prv = cur;
9521 + if(wrapped && (prv->next >= header->nfoffset)) break;
9522 +
9523 + /* Check to see if we need to wrap around and search from the top */
9524 + if(header->nfoffset && prv->next == 0) {
9525 + prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9526 +#ifdef __APC_SMA_DEBUG__
9527 + CHECK_CANARY(prv);
9528 +#endif
9529 + last_offset = 0;
9530 + wrapped = 1;
9531 + }
9532 + }
9533 +
9534 + if (prvnextfit == 0) {
9535 + header->nfoffset = 0;
9536 + return -1;
9537 + }
9538 +
9539 + prv = prvnextfit;
9540 + cur = BLOCKAT(prv->next);
9541 +
9542 + CHECK_CANARY(prv);
9543 + CHECK_CANARY(cur);
9544 +
9545 + if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
9546 + /* cur is big enough for realsize, but too small to split - unlink it */
9547 + prv->next = cur->next;
9548 + }
9549 + else {
9550 + block_t* nxt; /* the new block (chopped part of cur) */
9551 + size_t nxtoffset; /* offset of the block currently after cur */
9552 + size_t oldsize; /* size of cur before split */
9553 +
9554 + /* nextfit is too big; split it into two smaller blocks */
9555 + nxtoffset = cur->next;
9556 + oldsize = cur->size;
9557 + prv->next += realsize; /* skip over newly allocated block */
9558 + cur->size = realsize; /* Set the size of this new block */
9559 + nxt = BLOCKAT(prv->next);
9560 + nxt->next = nxtoffset; /* Re-link the shortened block */
9561 + nxt->size = oldsize - realsize; /* and fix the size */
9562 + SET_CANARY(nxt);
9563 +#ifdef __APC_SMA_DEBUG__
9564 + nxt->id = -1;
9565 +#endif
9566 + }
9567 +
9568 + /* update the block header */
9569 + header->avail -= cur->size;
9570 +#if ALLOC_DISTRIBUTION
9571 + header->adist[(int)(log(size)/log(2))]++;
9572 +#endif
9573 +
9574 + header->nfoffset = last_offset;
9575 +
9576 + SET_CANARY(cur);
9577 +#ifdef __APC_SMA_DEBUG__
9578 + cur->id = ++block_id;
9579 + fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
9580 +#endif
9581 +
9582 + return OFFSET(cur) + block_size;
9583 +}
9584 +/* }}} */
9585 +
9586 +/* {{{ sma_deallocate: deallocates the block at the given offset */
9587 +static int sma_deallocate(void* shmaddr, int offset)
9588 +{
9589 + header_t* header; /* header of shared memory segment */
9590 + block_t* cur; /* the new block to insert */
9591 + block_t* prv; /* the block before cur */
9592 + block_t* nxt; /* the block after cur */
9593 + size_t size; /* size of deallocated block */
9594 +
9595 + offset -= ALIGNWORD(sizeof(struct block_t));
9596 + assert(offset >= 0);
9597 +
9598 + /* find position of new block in free list */
9599 + cur = BLOCKAT(offset);
9600 + prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9601 +
9602 + CHECK_CANARY(cur);
9603 +
9604 +#ifdef __APC_SMA_DEBUG__
9605 + CHECK_CANARY(prv);
9606 + fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
9607 +#endif
9608 + while (prv->next != 0 && prv->next < offset) {
9609 + prv = BLOCKAT(prv->next);
9610 +#ifdef __APC_SMA_DEBUG__
9611 + CHECK_CANARY(prv);
9612 +#endif
9613 + }
9614 +
9615 + CHECK_CANARY(prv);
9616 +
9617 + /* insert new block after prv */
9618 + cur->next = prv->next;
9619 + prv->next = offset;
9620 +
9621 +#ifdef __APC_SMA_DEBUG__
9622 + CHECK_CANARY(cur);
9623 + cur->id = -1;
9624 +#endif
9625 +
9626 + /* update the block header */
9627 + header = (header_t*) shmaddr;
9628 + header->avail += cur->size;
9629 + size = cur->size;
9630 +
9631 + if (((char *)prv) + prv->size == (char *) cur) {
9632 + /* cur and prv share an edge, combine them */
9633 + prv->size += cur->size;
9634 + prv->next = cur->next;
9635 + RESET_CANARY(cur);
9636 + cur = prv;
9637 + }
9638 +
9639 + nxt = BLOCKAT(cur->next);
9640 +
9641 + if (((char *)cur) + cur->size == (char *) nxt) {
9642 + /* cur and nxt shared an edge, combine them */
9643 + cur->size += nxt->size;
9644 + cur->next = nxt->next;
9645 +#ifdef __APC_SMA_DEBUG__
9646 + CHECK_CANARY(nxt);
9647 + nxt->id = -1; /* assert this or set it ? */
9648 +#endif
9649 + RESET_CANARY(nxt);
9650 + }
9651 + header->nfoffset = 0; /* Reset the next fit search marker */
9652 +
9653 + return size;
9654 +}
9655 +/* }}} */
9656 +
9657 +/* {{{ apc_sma_init */
9658 +
9659 +void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask)
9660 +{
9661 + int i;
9662 +
9663 + if (sma_initialized) {
9664 + return;
9665 + }
9666 + sma_initialized = 1;
9667 +
9668 +#if APC_MMAP
9669 + /*
9670 + * I don't think multiple anonymous mmaps makes any sense
9671 + * so force sma_numseg to 1 in this case
9672 + */
9673 + if(!mmap_file_mask ||
9674 + (mmap_file_mask && !strlen(mmap_file_mask)) ||
9675 + (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
9676 + sma_numseg = 1;
9677 + } else {
9678 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9679 + }
9680 +#else
9681 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9682 +#endif
9683 +
9684 + sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
9685 +
9686 + sma_segments = (size_t*) apc_emalloc(sma_numseg*sizeof(size_t));
9687 + sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
9688 +
9689 + for (i = 0; i < sma_numseg; i++) {
9690 + header_t* header;
9691 + block_t* block;
9692 + void* shmaddr;
9693 +
9694 +#if APC_MMAP
9695 + sma_segments[i] = sma_segsize;
9696 + sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
9697 + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
9698 +#else
9699 + sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
9700 + sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
9701 +#endif
9702 + shmaddr = sma_shmaddrs[i];
9703 +
9704 + header = (header_t*) shmaddr;
9705 + apc_lck_create(NULL, 0, 1, header->sma_lock);
9706 + header->segsize = sma_segsize;
9707 + header->avail = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
9708 + header->nfoffset = 0;
9709 +#if ALLOC_DISTRIBUTION
9710 + {
9711 + int j;
9712 + for(j=0; j<30; j++) header->adist[j] = 0;
9713 + }
9714 +#endif
9715 + block = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9716 + block->size = 0;
9717 + block->next = ALIGNWORD(sizeof(header_t)) + ALIGNWORD(sizeof(block_t));
9718 + SET_CANARY(block);
9719 +#ifdef __APC_SMA_DEBUG__
9720 + block->id = -1;
9721 +#endif
9722 + block = BLOCKAT(block->next);
9723 + block->size = header->avail;
9724 + block->next = 0;
9725 + SET_CANARY(block);
9726 +#ifdef __APC_SMA_DEBUG__
9727 + block->id = -1;
9728 +#endif
9729 + }
9730 +}
9731 +/* }}} */
9732 +
9733 +/* {{{ apc_sma_cleanup */
9734 +void apc_sma_cleanup()
9735 +{
9736 + int i;
9737 +
9738 + assert(sma_initialized);
9739 +
9740 + for (i = 0; i < sma_numseg; i++) {
9741 + apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
9742 +#if APC_MMAP
9743 + apc_unmap(sma_shmaddrs[i], sma_segments[i]);
9744 +#else
9745 + apc_shm_detach(sma_shmaddrs[i]);
9746 +#endif
9747 + }
9748 + sma_initialized = 0;
9749 + apc_efree(sma_segments);
9750 + apc_efree(sma_shmaddrs);
9751 +}
9752 +/* }}} */
9753 +
9754 +/* {{{ apc_sma_malloc */
9755 +void* apc_sma_malloc(size_t n)
9756 +{
9757 + int off;
9758 + int i;
9759 +
9760 + TSRMLS_FETCH();
9761 + assert(sma_initialized);
9762 + LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9763 +
9764 + off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
9765 + if (off != -1) {
9766 + void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
9767 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9768 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9769 + return p;
9770 + }
9771 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9772 +
9773 + for (i = 0; i < sma_numseg; i++) {
9774 + if (i == sma_lastseg) {
9775 + continue;
9776 + }
9777 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9778 + off = sma_allocate(sma_shmaddrs[i], n);
9779 + if (off != -1) {
9780 + void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
9781 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9782 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9783 + sma_lastseg = i;
9784 + return p;
9785 + }
9786 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9787 + }
9788 +
9789 + return NULL;
9790 +}
9791 +/* }}} */
9792 +
9793 +/* {{{ apc_sma_realloc */
9794 +void* apc_sma_realloc(void *p, size_t n)
9795 +{
9796 + apc_sma_free(p);
9797 + return apc_sma_malloc(n);
9798 +}
9799 +/* }}} */
9800 +
9801 +/* {{{ apc_sma_strdup */
9802 +char* apc_sma_strdup(const char* s)
9803 +{
9804 + void* q;
9805 + int len;
9806 +
9807 + if(!s) return NULL;
9808 +
9809 + len = strlen(s)+1;
9810 + q = apc_sma_malloc(len);
9811 + if(!q) return NULL;
9812 + memcpy(q, s, len);
9813 + return q;
9814 +}
9815 +/* }}} */
9816 +
9817 +/* {{{ apc_sma_free */
9818 +void apc_sma_free(void* p)
9819 +{
9820 + int i;
9821 + size_t offset;
9822 + size_t d_size;
9823 + TSRMLS_FETCH();
9824 +
9825 + if (p == NULL) {
9826 + return;
9827 + }
9828 +
9829 + assert(sma_initialized);
9830 +
9831 + for (i = 0; i < sma_numseg; i++) {
9832 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9833 + offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
9834 + if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
9835 + d_size = sma_deallocate(sma_shmaddrs[i], offset);
9836 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
9837 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9838 + return;
9839 + }
9840 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9841 + }
9842 +
9843 + apc_eprint("apc_sma_free: could not locate address %p", p);
9844 +}
9845 +/* }}} */
9846 +
9847 +/* {{{ apc_sma_info */
9848 +apc_sma_info_t* apc_sma_info(zend_bool limited)
9849 +{
9850 + apc_sma_info_t* info;
9851 + apc_sma_link_t** link;
9852 + int i;
9853 + char* shmaddr;
9854 + block_t* prv;
9855 +
9856 + if (!sma_initialized) {
9857 + return NULL;
9858 + }
9859 +
9860 + info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
9861 + info->num_seg = sma_numseg;
9862 + info->seg_size = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
9863 +
9864 + info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
9865 + for (i = 0; i < sma_numseg; i++) {
9866 + info->list[i] = NULL;
9867 + }
9868 +
9869 + if(limited) return info;
9870 +
9871 + /* For each segment */
9872 + for (i = 0; i < sma_numseg; i++) {
9873 + RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9874 + shmaddr = sma_shmaddrs[i];
9875 + prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9876 +
9877 + link = &info->list[i];
9878 +
9879 + /* For each block in this segment */
9880 + while (prv->next != 0) {
9881 + block_t* cur = BLOCKAT(prv->next);
9882 +#ifdef __APC_SMA_DEBUG__
9883 + CHECK_CANARY(cur);
9884 +#endif
9885 +
9886 + *link = apc_emalloc(sizeof(apc_sma_link_t));
9887 + (*link)->size = cur->size;
9888 + (*link)->offset = prv->next;
9889 + (*link)->next = NULL;
9890 + link = &(*link)->next;
9891 +
9892 + prv = cur;
9893 + }
9894 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9895 + }
9896 +
9897 + return info;
9898 +}
9899 +/* }}} */
9900 +
9901 +/* {{{ apc_sma_free_info */
9902 +void apc_sma_free_info(apc_sma_info_t* info)
9903 +{
9904 + int i;
9905 +
9906 + for (i = 0; i < info->num_seg; i++) {
9907 + apc_sma_link_t* p = info->list[i];
9908 + while (p) {
9909 + apc_sma_link_t* q = p;
9910 + p = p->next;
9911 + apc_efree(q);
9912 + }
9913 + }
9914 + apc_efree(info->list);
9915 + apc_efree(info);
9916 +}
9917 +/* }}} */
9918 +
9919 +/* {{{ apc_sma_get_avail_mem */
9920 +size_t apc_sma_get_avail_mem()
9921 +{
9922 + size_t avail_mem = 0;
9923 + int i;
9924 +
9925 + for (i = 0; i < sma_numseg; i++) {
9926 + header_t* header = (header_t*) sma_shmaddrs[i];
9927 + avail_mem += header->avail;
9928 + }
9929 + return avail_mem;
9930 +}
9931 +/* }}} */
9932 +
9933 +#if ALLOC_DISTRIBUTION
9934 +size_t *apc_sma_get_alloc_distribution(void) {
9935 + header_t* header = (header_t*) sma_shmaddrs[0];
9936 + return header->adist;
9937 +}
9938 +#endif
9939 +
9940 +#if 0
9941 +/* {{{ apc_sma_check_integrity */
9942 +void apc_sma_check_integrity()
9943 +{
9944 + int i;
9945 +
9946 + /* For each segment */
9947 + for (i = 0; i < sma_numseg; i++) {
9948 + char* shmaddr = sma_shmaddrs[i];
9949 + header_t* header = (header_t*) shmaddr;
9950 + block_t* prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
9951 + int avail = 0;
9952 +
9953 + /* For each block in this segment */
9954 + while (prv->next != 0) {
9955 + block_t* cur = BLOCKAT(prv->next);
9956 + avail += cur->size;
9957 + prv = cur;
9958 + }
9959 +
9960 + assert(avail == header->avail);
9961 + }
9962 +}
9963 +/* }}} */
9964 +#endif
9965 +
9966 +/*
9967 + * Local variables:
9968 + * tab-width: 4
9969 + * c-basic-offset: 4
9970 + * End:
9971 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9972 + * vim<600: expandtab sw=4 ts=4 sts=4
9973 + */
9974 diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.h php-5.2.5/ext/apc/apc_sma.h
9975 --- php-5.2.5-orig/ext/apc/apc_sma.h 1969-12-31 18:00:00.000000000 -0600
9976 +++ php-5.2.5/ext/apc/apc_sma.h 2007-12-26 16:51:32.000000000 -0600
9977 @@ -0,0 +1,82 @@
9978 +/*
9979 + +----------------------------------------------------------------------+
9980 + | APC |
9981 + +----------------------------------------------------------------------+
9982 + | Copyright (c) 2006 The PHP Group |
9983 + +----------------------------------------------------------------------+
9984 + | This source file is subject to version 3.01 of the PHP license, |
9985 + | that is bundled with this package in the file LICENSE, and is |
9986 + | available through the world-wide-web at the following url: |
9987 + | http://www.php.net/license/3_01.txt |
9988 + | If you did not receive a copy of the PHP license and are unable to |
9989 + | obtain it through the world-wide-web, please send a note to |
9990 + | license@php.net so we can mail you a copy immediately. |
9991 + +----------------------------------------------------------------------+
9992 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9993 + +----------------------------------------------------------------------+
9994 +
9995 + This software was contributed to PHP by Community Connect Inc. in 2002
9996 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9997 + Future revisions and derivatives of this source code must acknowledge
9998 + Community Connect Inc. as the original contributor of this module by
9999 + leaving this note intact in the source code.
10000 +
10001 + All other licensing and usage conditions are those of the PHP Group.
10002 +
10003 + */
10004 +
10005 +/* $Id: apc_sma.h,v 1.18 2007/05/11 01:46:31 shire Exp $ */
10006 +
10007 +#ifndef APC_SMA_H
10008 +#define APC_SMA_H
10009 +
10010 +#define ALLOC_DISTRIBUTION 0
10011 +
10012 +#include "apc.h"
10013 +
10014 +/* Simple shared memory allocator */
10015 +
10016 +extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask);
10017 +extern void apc_sma_cleanup();
10018 +extern void* apc_sma_malloc(size_t size);
10019 +extern void* apc_sma_realloc(void* p, size_t size);
10020 +extern char* apc_sma_strdup(const char *s);
10021 +extern void apc_sma_free(void* p);
10022 +#if ALLOC_DISTRIBUTION
10023 +extern size_t *apc_sma_get_alloc_distribution();
10024 +#endif
10025 +
10026 +/* {{{ struct definition: apc_sma_link_t */
10027 +typedef struct apc_sma_link_t apc_sma_link_t;
10028 +struct apc_sma_link_t {
10029 + long size; /* size of this free block */
10030 + long offset; /* offset in segment of this block */
10031 + apc_sma_link_t* next; /* link to next free block */
10032 +};
10033 +/* }}} */
10034 +
10035 +/* {{{ struct definition: apc_sma_info_t */
10036 +typedef struct apc_sma_info_t apc_sma_info_t;
10037 +struct apc_sma_info_t {
10038 + int num_seg; /* number of shared memory segments */
10039 + long seg_size; /* size of each shared memory segment */
10040 + apc_sma_link_t** list; /* there is one list per segment */
10041 +};
10042 +/* }}} */
10043 +
10044 +extern apc_sma_info_t* apc_sma_info(zend_bool limited);
10045 +extern void apc_sma_free_info(apc_sma_info_t* info);
10046 +
10047 +extern size_t apc_sma_get_avail_mem();
10048 +extern void apc_sma_check_integrity();
10049 +
10050 +#endif
10051 +
10052 +/*
10053 + * Local variables:
10054 + * tab-width: 4
10055 + * c-basic-offset: 4
10056 + * End:
10057 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10058 + * vim<600: expandtab sw=4 ts=4 sts=4
10059 + */
10060 diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
10061 --- php-5.2.5-orig/ext/apc/apc_spin.c 1969-12-31 18:00:00.000000000 -0600
10062 +++ php-5.2.5/ext/apc/apc_spin.c 2007-12-26 16:51:32.000000000 -0600
10063 @@ -0,0 +1,65 @@
10064 +/*
10065 + +----------------------------------------------------------------------+
10066 + | APC |
10067 + +----------------------------------------------------------------------+
10068 + | Copyright (c) 2007 The PHP Group |
10069 + +----------------------------------------------------------------------+
10070 + | This source file is subject to version 3.01 of the PHP license, |
10071 + | that is bundled with this package in the file LICENSE, and is |
10072 + | available through the world-wide-web at the following url: |
10073 + | http://www.php.net/license/3_01.txt |
10074 + | If you did not receive a copy of the PHP license and are unable to |
10075 + | obtain it through the world-wide-web, please send a note to |
10076 + | license@php.net so we can mail you a copy immediately. |
10077 + +----------------------------------------------------------------------+
10078 + | Authors: Brian Shire <shire@php.net> |
10079 + +----------------------------------------------------------------------+
10080 +
10081 + */
10082 +
10083 +/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
10084 +
10085 +#include "apc_spin.h"
10086 +
10087 +#ifdef APC_SPIN_LOCKS
10088 +
10089 +slock_t *apc_slock_create(slock_t *lock)
10090 +{
10091 + S_INIT_LOCK(lock);
10092 +}
10093 +
10094 +void apc_slock_destroy(slock_t *lock)
10095 +{
10096 + S_LOCK_FREE(lock);
10097 +}
10098 +
10099 +void apc_slock_lock(slock_t *lock)
10100 +{
10101 + S_LOCK(lock);
10102 +}
10103 +
10104 +void apc_slock_unlock(slock_t *lock)
10105 +{
10106 + S_UNLOCK(lock);
10107 +}
10108 +
10109 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
10110 +{
10111 + /* Technically we aren't supposed to call this directly, but the original
10112 + * code provides no method for absolute non-blocking locks, so we'll call into
10113 + * the TAS (test and set) functionality directly
10114 + */
10115 + return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */
10116 +}
10117 +
10118 +
10119 +#endif
10120 +
10121 +/*
10122 + * Local variables:
10123 + * tab-width: 4
10124 + * c-basic-offset: 4
10125 + * End:
10126 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10127 + * vim<600: expandtab sw=4 ts=4 sts=4
10128 + */
10129 diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
10130 --- php-5.2.5-orig/ext/apc/apc_spin.h 1969-12-31 18:00:00.000000000 -0600
10131 +++ php-5.2.5/ext/apc/apc_spin.h 2007-12-26 16:51:32.000000000 -0600
10132 @@ -0,0 +1,48 @@
10133 +/*
10134 + +----------------------------------------------------------------------+
10135 + | APC |
10136 + +----------------------------------------------------------------------+
10137 + | Copyright (c) 2007 The PHP Group |
10138 + +----------------------------------------------------------------------+
10139 + | This source file is subject to version 3.01 of the PHP license, |
10140 + | that is bundled with this package in the file LICENSE, and is |
10141 + | available through the world-wide-web at the following url: |
10142 + | http://www.php.net/license/3_01.txt |
10143 + | If you did not receive a copy of the PHP license and are unable to |
10144 + | obtain it through the world-wide-web, please send a note to |
10145 + | license@php.net so we can mail you a copy immediately. |
10146 + +----------------------------------------------------------------------+
10147 + | Authors: Brian Shire <shire@php.net> |
10148 + +----------------------------------------------------------------------+
10149 +
10150 + */
10151 +
10152 +/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
10153 +
10154 +#ifndef APC_SPIN_H
10155 +#define APC_SPIN_H
10156 +
10157 +#include "apc.h"
10158 +
10159 +#ifdef APC_SPIN_LOCKS
10160 +
10161 +#include "pgsql_s_lock.h"
10162 +
10163 +pthread_mutex_t *apc_spin_create();
10164 +void apc_spin_destroy(pthread_mutex_t *lock);
10165 +void apc_spin_lock(pthread_mutex_t *lock);
10166 +void apc_spin_unlock(pthread_mutex_t *lock);
10167 +zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
10168 +
10169 +#endif
10170 +
10171 +#endif
10172 +
10173 +/*
10174 + * Local variables:
10175 + * tab-width: 4
10176 + * c-basic-offset: 4
10177 + * End:
10178 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10179 + * vim<600: expandtab sw=4 ts=4 sts=4
10180 + */
10181 diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
10182 --- php-5.2.5-orig/ext/apc/apc_stack.c 1969-12-31 18:00:00.000000000 -0600
10183 +++ php-5.2.5/ext/apc/apc_stack.c 2007-12-26 16:51:32.000000000 -0600
10184 @@ -0,0 +1,105 @@
10185 +/*
10186 + +----------------------------------------------------------------------+
10187 + | APC |
10188 + +----------------------------------------------------------------------+
10189 + | Copyright (c) 2006 The PHP Group |
10190 + +----------------------------------------------------------------------+
10191 + | This source file is subject to version 3.01 of the PHP license, |
10192 + | that is bundled with this package in the file LICENSE, and is |
10193 + | available through the world-wide-web at the following url: |
10194 + | http://www.php.net/license/3_01.txt |
10195 + | If you did not receive a copy of the PHP license and are unable to |
10196 + | obtain it through the world-wide-web, please send a note to |
10197 + | license@php.net so we can mail you a copy immediately. |
10198 + +----------------------------------------------------------------------+
10199 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10200 + +----------------------------------------------------------------------+
10201 +
10202 + This software was contributed to PHP by Community Connect Inc. in 2002
10203 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10204 + Future revisions and derivatives of this source code must acknowledge
10205 + Community Connect Inc. as the original contributor of this module by
10206 + leaving this note intact in the source code.
10207 +
10208 + All other licensing and usage conditions are those of the PHP Group.
10209 +
10210 + */
10211 +
10212 +/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
10213 +
10214 +#include "apc_stack.h"
10215 +#include "apc.h"
10216 +
10217 +struct apc_stack_t {
10218 + void** data;
10219 + int capacity;
10220 + int size;
10221 +};
10222 +
10223 +apc_stack_t* apc_stack_create(int size_hint)
10224 +{
10225 + apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
10226 +
10227 + stack->capacity = (size_hint > 0) ? size_hint : 10;
10228 + stack->size = 0;
10229 + stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
10230 +
10231 + return stack;
10232 +}
10233 +
10234 +void apc_stack_destroy(apc_stack_t* stack)
10235 +{
10236 + if (stack != NULL) {
10237 + apc_efree(stack->data);
10238 + apc_efree(stack);
10239 + }
10240 +}
10241 +
10242 +void apc_stack_clear(apc_stack_t* stack)
10243 +{
10244 + assert(stack != NULL);
10245 + stack->size = 0;
10246 +}
10247 +
10248 +void apc_stack_push(apc_stack_t* stack, void* item)
10249 +{
10250 + assert(stack != NULL);
10251 + if (stack->size == stack->capacity) {
10252 + stack->capacity *= 2;
10253 + stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
10254 + }
10255 + stack->data[stack->size++] = item;
10256 +}
10257 +
10258 +void* apc_stack_pop(apc_stack_t* stack)
10259 +{
10260 + assert(stack != NULL && stack->size > 0);
10261 + return stack->data[--stack->size];
10262 +}
10263 +
10264 +void* apc_stack_top(apc_stack_t* stack)
10265 +{
10266 + assert(stack != NULL && stack->size > 0);
10267 + return stack->data[stack->size-1];
10268 +}
10269 +
10270 +void* apc_stack_get(apc_stack_t* stack, int n)
10271 +{
10272 + assert(stack != NULL && stack->size > n);
10273 + return stack->data[n];
10274 +}
10275 +
10276 +int apc_stack_size(apc_stack_t* stack)
10277 +{
10278 + assert(stack != NULL);
10279 + return stack->size;
10280 +}
10281 +
10282 +/*
10283 + * Local variables:
10284 + * tab-width: 4
10285 + * c-basic-offset: 4
10286 + * End:
10287 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10288 + * vim<600: expandtab sw=4 ts=4 sts=4
10289 + */
10290 diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.h php-5.2.5/ext/apc/apc_stack.h
10291 --- php-5.2.5-orig/ext/apc/apc_stack.h 1969-12-31 18:00:00.000000000 -0600
10292 +++ php-5.2.5/ext/apc/apc_stack.h 2007-12-26 16:51:32.000000000 -0600
10293 @@ -0,0 +1,58 @@
10294 +/*
10295 + +----------------------------------------------------------------------+
10296 + | APC |
10297 + +----------------------------------------------------------------------+
10298 + | Copyright (c) 2006 The PHP Group |
10299 + +----------------------------------------------------------------------+
10300 + | This source file is subject to version 3.01 of the PHP license, |
10301 + | that is bundled with this package in the file LICENSE, and is |
10302 + | available through the world-wide-web at the following url: |
10303 + | http://www.php.net/license/3_01.txt |
10304 + | If you did not receive a copy of the PHP license and are unable to |
10305 + | obtain it through the world-wide-web, please send a note to |
10306 + | license@php.net so we can mail you a copy immediately. |
10307 + +----------------------------------------------------------------------+
10308 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10309 + | George Schlossnagle <george@omniti.com> |
10310 + +----------------------------------------------------------------------+
10311 +
10312 + This software was contributed to PHP by Community Connect Inc. in 2002
10313 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10314 + Future revisions and derivatives of this source code must acknowledge
10315 + Community Connect Inc. as the original contributor of this module by
10316 + leaving this note intact in the source code.
10317 +
10318 + All other licensing and usage conditions are those of the PHP Group.
10319 +
10320 + */
10321 +
10322 +/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
10323 +
10324 +#ifndef APC_STACK_H
10325 +#define APC_STACK_H
10326 +
10327 +/* Basic stack datatype */
10328 +
10329 +#define T apc_stack_t*
10330 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
10331 +
10332 +extern T apc_stack_create(int size_hint);
10333 +extern void apc_stack_destroy(T stack);
10334 +extern void apc_stack_clear(T stack);
10335 +extern void apc_stack_push(T stack, void* item);
10336 +extern void* apc_stack_pop(T stack);
10337 +extern void* apc_stack_top(T stack);
10338 +extern void* apc_stack_get(T stack, int n);
10339 +extern int apc_stack_size(T stack);
10340 +
10341 +#undef T
10342 +#endif
10343 +
10344 +/*
10345 + * Local variables:
10346 + * tab-width: 4
10347 + * c-basic-offset: 4
10348 + * End:
10349 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10350 + * vim<600: expandtab sw=4 ts=4 sts=4
10351 + */
10352 diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.c php-5.2.5/ext/apc/apc_zend.c
10353 --- php-5.2.5-orig/ext/apc/apc_zend.c 1969-12-31 18:00:00.000000000 -0600
10354 +++ php-5.2.5/ext/apc/apc_zend.c 2007-12-26 16:51:32.000000000 -0600
10355 @@ -0,0 +1,277 @@
10356 +/*
10357 + +----------------------------------------------------------------------+
10358 + | APC |
10359 + +----------------------------------------------------------------------+
10360 + | Copyright (c) 2006 The PHP Group |
10361 + +----------------------------------------------------------------------+
10362 + | This source file is subject to version 3.01 of the PHP license, |
10363 + | that is bundled with this package in the file LICENSE, and is |
10364 + | available through the world-wide-web at the following url: |
10365 + | http://www.php.net/license/3_01.txt |
10366 + | If you did not receive a copy of the PHP license and are unable to |
10367 + | obtain it through the world-wide-web, please send a note to |
10368 + | license@php.net so we can mail you a copy immediately. |
10369 + +----------------------------------------------------------------------+
10370 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10371 + +----------------------------------------------------------------------+
10372 +
10373 + This software was contributed to PHP by Community Connect Inc. in 2002
10374 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10375 + Future revisions and derivatives of this source code must acknowledge
10376 + Community Connect Inc. as the original contributor of this module by
10377 + leaving this note intact in the source code.
10378 +
10379 + All other licensing and usage conditions are those of the PHP Group.
10380 +
10381 + */
10382 +
10383 +/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
10384 +
10385 +#include "apc_zend.h"
10386 +#include "apc_globals.h"
10387 +
10388 +void* apc_php_malloc(size_t n)
10389 +{
10390 + return emalloc(n);
10391 +}
10392 +
10393 +void apc_php_free(void* p)
10394 +{
10395 + efree(p);
10396 +}
10397 +
10398 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
10399 +# define ZEND_VM_KIND_CALL 1
10400 +#endif
10401 +
10402 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
10403 +# define ZEND_VM_KIND ZEND_VM_KIND_CALL
10404 +#endif
10405 +
10406 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
10407 +# define APC_OPCODE_OVERRIDE
10408 +#endif
10409 +
10410 +#ifdef APC_OPCODE_OVERRIDE
10411 +
10412 +#ifdef ZEND_ENGINE_2_1
10413 +/* Taken from Zend/zend_vm_execute.h */
10414 +#define _CONST_CODE 0
10415 +#define _TMP_CODE 1
10416 +#define _VAR_CODE 2
10417 +#define _UNUSED_CODE 3
10418 +#define _CV_CODE 4
10419 +static inline int _apc_opcode_handler_decode(zend_op *opline)
10420 +{
10421 + static const int apc_vm_decode[] = {
10422 + _UNUSED_CODE, /* 0 */
10423 + _CONST_CODE, /* 1 = IS_CONST */
10424 + _TMP_CODE, /* 2 = IS_TMP_VAR */
10425 + _UNUSED_CODE, /* 3 */
10426 + _VAR_CODE, /* 4 = IS_VAR */
10427 + _UNUSED_CODE, /* 5 */
10428 + _UNUSED_CODE, /* 6 */
10429 + _UNUSED_CODE, /* 7 */
10430 + _UNUSED_CODE, /* 8 = IS_UNUSED */
10431 + _UNUSED_CODE, /* 9 */
10432 + _UNUSED_CODE, /* 10 */
10433 + _UNUSED_CODE, /* 11 */
10434 + _UNUSED_CODE, /* 12 */
10435 + _UNUSED_CODE, /* 13 */
10436 + _UNUSED_CODE, /* 14 */
10437 + _UNUSED_CODE, /* 15 */
10438 + _CV_CODE /* 16 = IS_CV */
10439 + };
10440 + return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
10441 +}
10442 +
10443 +# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline;
10444 +# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline)
10445 +# if PHP_MAJOR_VERSION >= 6
10446 +# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1)
10447 +# else
10448 +# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1)
10449 +# endif
10450 +# define APC_REPLACE_OPCODE(opname) { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; }
10451 +
10452 +#else /* ZE2.0 */
10453 +# define APC_ZEND_ONLINE
10454 +# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode)
10455 +# define APC_OPCODE_HANDLER_COUNT 512
10456 +# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname;
10457 +#endif
10458 +
10459 +static opcode_handler_t *apc_original_opcode_handlers;
10460 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
10461 +
10462 +#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
10463 +
10464 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
10465 +{
10466 + *freeval = NULL;
10467 +
10468 + switch (node->op_type) {
10469 + case IS_CONST:
10470 + return &(node->u.constant);
10471 + case IS_VAR:
10472 + return APC_EX_T(node->u.var).var.ptr;
10473 + case IS_TMP_VAR:
10474 + return (*freeval = &APC_EX_T(node->u.var).tmp_var);
10475 +#ifdef ZEND_ENGINE_2_1
10476 + case IS_CV:
10477 + {
10478 + zval ***ret = &execute_data->CVs[node->u.var];
10479 +
10480 + if (!*ret) {
10481 + zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
10482 +
10483 + if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
10484 + apc_nprint("Undefined variable: %s", cv->name);
10485 + return &EG(uninitialized_zval);
10486 + }
10487 + }
10488 + return **ret;
10489 + }
10490 +#endif
10491 + case IS_UNUSED:
10492 + default:
10493 + return NULL;
10494 + }
10495 +}
10496 +
10497 +static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
10498 +{
10499 + APC_ZEND_OPLINE
10500 + zval *freeop1 = NULL;
10501 + zval *inc_filename = NULL, tmp_inc_filename;
10502 + char realpath[MAXPATHLEN];
10503 + php_stream_wrapper *wrapper;
10504 + char *path_for_open;
10505 + int ret = 0;
10506 + #ifdef ZEND_ENGINE_2
10507 + apc_opflags_t* flags = NULL;
10508 + #endif
10509 +
10510 + if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
10511 + Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
10512 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10513 + }
10514 +
10515 + inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
10516 + if (Z_TYPE_P(inc_filename) != IS_STRING) {
10517 + tmp_inc_filename = *inc_filename;
10518 + zval_copy_ctor(&tmp_inc_filename);
10519 + convert_to_string(&tmp_inc_filename);
10520 + inc_filename = &tmp_inc_filename;
10521 + }
10522 +
10523 + wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
10524 + if (wrapper != &php_plain_files_wrapper ||
10525 + !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
10526 + !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
10527 + /* Fallback to original handler */
10528 + if (inc_filename == &tmp_inc_filename) {
10529 + zval_dtor(&tmp_inc_filename);
10530 + }
10531 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10532 + }
10533 +
10534 + if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
10535 + if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
10536 + ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
10537 + ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
10538 + }
10539 + if (inc_filename == &tmp_inc_filename) {
10540 + zval_dtor(&tmp_inc_filename);
10541 + }
10542 + if (freeop1) {
10543 + zval_dtor(freeop1);
10544 + }
10545 + execute_data->opline++;
10546 + return 0;
10547 + }
10548 +
10549 + if (inc_filename == &tmp_inc_filename) {
10550 + zval_dtor(&tmp_inc_filename);
10551 + }
10552 +
10553 + if(APCG(reserved_offset) != -1) {
10554 + /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
10555 + flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
10556 + }
10557 +
10558 +#ifdef ZEND_ENGINE_2
10559 + if(flags && flags->deep_copy == 1) {
10560 + /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily
10561 + * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
10562 + */
10563 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
10564 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10565 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
10566 +#else
10567 + if(0) {
10568 + /* do nothing, have nothing, be nothing */
10569 +#endif
10570 + } else {
10571 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10572 + }
10573 +
10574 + return ret;
10575 +}
10576 +
10577 +void apc_zend_init(TSRMLS_D)
10578 +{
10579 + zend_extension dummy_ext;
10580 +#ifdef ZEND_ENGINE_2
10581 + APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext);
10582 + assert(APCG(reserved_offset) == dummy_ext.resource_number);
10583 + assert(APCG(reserved_offset) != -1);
10584 + assert(sizeof(apc_opflags_t) <= sizeof(void*));
10585 +#endif
10586 + if (!APCG(include_once)) {
10587 + /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
10588 + return;
10589 + }
10590 +
10591 + memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
10592 +
10593 + /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
10594 +#ifdef ZEND_ENGINE_2_1
10595 + apc_original_opcode_handlers = zend_opcode_handlers;
10596 + zend_opcode_handlers = apc_opcode_handlers;
10597 +#else
10598 + apc_original_opcode_handlers = apc_opcode_handlers;
10599 +#endif
10600 +
10601 + APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
10602 +}
10603 +
10604 +void apc_zend_shutdown(TSRMLS_D)
10605 +{
10606 + if (!APCG(include_once)) {
10607 + /* Nothing changed, nothing to restore */
10608 + return;
10609 + }
10610 +
10611 +#ifdef ZEND_ENGINE_2_1
10612 + zend_opcode_handlers = apc_original_opcode_handlers;
10613 +#else
10614 + memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
10615 +#endif
10616 +}
10617 +
10618 +#else /* Opcode Overrides unavailable */
10619 +
10620 +void apc_zend_init(TSRMLS_D) { }
10621 +void apc_zend_shutdown(TSRMLS_D) { }
10622 +
10623 +#endif /* APC_OPCODE_OVERRIDE */
10624 +
10625 +/*
10626 + * Local variables:
10627 + * tab-width: 4
10628 + * c-basic-offset: 4
10629 + * End:
10630 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10631 + * vim<600: expandtab sw=4 ts=4 sts=4
10632 + */
10633 diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
10634 --- php-5.2.5-orig/ext/apc/apc_zend.h 1969-12-31 18:00:00.000000000 -0600
10635 +++ php-5.2.5/ext/apc/apc_zend.h 2007-12-26 16:51:32.000000000 -0600
10636 @@ -0,0 +1,53 @@
10637 +/*
10638 + +----------------------------------------------------------------------+
10639 + | APC |
10640 + +----------------------------------------------------------------------+
10641 + | Copyright (c) 2006 The PHP Group |
10642 + +----------------------------------------------------------------------+
10643 + | This source file is subject to version 3.01 of the PHP license, |
10644 + | that is bundled with this package in the file LICENSE, and is |
10645 + | available through the world-wide-web at the following url: |
10646 + | http://www.php.net/license/3_01.txt |
10647 + | If you did not receive a copy of the PHP license and are unable to |
10648 + | obtain it through the world-wide-web, please send a note to |
10649 + | license@php.net so we can mail you a copy immediately. |
10650 + +----------------------------------------------------------------------+
10651 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10652 + +----------------------------------------------------------------------+
10653 +
10654 + This software was contributed to PHP by Community Connect Inc. in 2002
10655 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10656 + Future revisions and derivatives of this source code must acknowledge
10657 + Community Connect Inc. as the original contributor of this module by
10658 + leaving this note intact in the source code.
10659 +
10660 + All other licensing and usage conditions are those of the PHP Group.
10661 +
10662 + */
10663 +
10664 +/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
10665 +
10666 +#ifndef APC_ZEND_H
10667 +#define APC_ZEND_H
10668 +
10669 +/* Utilities for interfacing with the zend engine */
10670 +
10671 +#include "apc.h"
10672 +#include "apc_php.h"
10673 +
10674 +extern void* apc_php_malloc(size_t n);
10675 +extern void apc_php_free(void* p);
10676 +
10677 +extern void apc_zend_init(TSRMLS_D);
10678 +extern void apc_zend_shutdown(TSRMLS_D);
10679 +
10680 +#endif
10681 +
10682 +/*
10683 + * Local variables:
10684 + * tab-width: 4
10685 + * c-basic-offset: 4
10686 + * End:
10687 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10688 + * vim<600: expandtab sw=4 ts=4 sts=4
10689 + */
10690 diff -ubrN php-5.2.5-orig/ext/apc/arch/atomic.h php-5.2.5/ext/apc/arch/atomic.h
10691 --- php-5.2.5-orig/ext/apc/arch/atomic.h 1969-12-31 18:00:00.000000000 -0600
10692 +++ php-5.2.5/ext/apc/arch/atomic.h 2007-12-26 16:51:32.000000000 -0600
10693 @@ -0,0 +1,38 @@
10694 +/*
10695 + +----------------------------------------------------------------------+
10696 + | APC |
10697 + +----------------------------------------------------------------------+
10698 + | Copyright (c) 2006 The PHP Group |
10699 + +----------------------------------------------------------------------+
10700 + | This source file is subject to version 3.01 of the PHP license, |
10701 + | that is bundled with this package in the file LICENSE, and is |
10702 + | available through the world-wide-web at the following url: |
10703 + | http://www.php.net/license/3_01.txt |
10704 + | If you did not receive a copy of the PHP license and are unable to |
10705 + | obtain it through the world-wide-web, please send a note to |
10706 + | license@php.net so we can mail you a copy immediately. |
10707 + +----------------------------------------------------------------------+
10708 + | Authors: Brian Shire <shire@php.net> |
10709 + +----------------------------------------------------------------------+
10710 +
10711 + */
10712 +
10713 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10714 +
10715 +#ifndef APC_ARCH_ATOMIC_H
10716 +
10717 +#define APC_ARCH_ATOMIC_H
10718 +
10719 +#if defined __x86_64__
10720 +#include "x86_64/atomic.h"
10721 +
10722 +#elif defined __i386__
10723 +#include "i386/atomic.h"
10724 +
10725 +#else
10726 +#error "Unknown or Unsupported Architecture. If you would like futex suupport for your architecture, please file a request at http://pecl.php.net/bugs/report.php?package=APC"
10727 +
10728 +#endif
10729 +
10730 +
10731 +#endif
10732 diff -ubrN php-5.2.5-orig/ext/apc/arch/i386/atomic.h php-5.2.5/ext/apc/arch/i386/atomic.h
10733 --- php-5.2.5-orig/ext/apc/arch/i386/atomic.h 1969-12-31 18:00:00.000000000 -0600
10734 +++ php-5.2.5/ext/apc/arch/i386/atomic.h 2007-12-26 16:51:32.000000000 -0600
10735 @@ -0,0 +1,79 @@
10736 +/*
10737 + +----------------------------------------------------------------------+
10738 + | APC |
10739 + +----------------------------------------------------------------------+
10740 + | Copyright (c) 2006 The PHP Group |
10741 + +----------------------------------------------------------------------+
10742 + | This source file is subject to version 3.01 of the PHP license, |
10743 + | that is bundled with this package in the file LICENSE, and is |
10744 + | available through the world-wide-web at the following url: |
10745 + | http://www.php.net/license/3_01.txt |
10746 + | If you did not receive a copy of the PHP license and are unable to |
10747 + | obtain it through the world-wide-web, please send a note to |
10748 + | license@php.net so we can mail you a copy immediately. |
10749 + +----------------------------------------------------------------------+
10750 + | Authors: Brian Shire <shire@php.net> |
10751 + +----------------------------------------------------------------------+
10752 +
10753 + */
10754 +
10755 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10756 +
10757 +
10758 +#include <sys/syscall.h>
10759 +#include <sys/time.h>
10760 +#include <linux/futex.h>
10761 +
10762 +/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
10763 +static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
10764 +
10765 + long int ret;
10766 +
10767 + /* i386 system calls are performed with nt 80h operation.
10768 + * the argument order is a, b, c, d, S, D
10769 + */
10770 + asm volatile ("int $0x80"
10771 + : "=a" (ret)
10772 + : "0" (SYS_futex),
10773 + "b" (futex),
10774 + "c" (op),
10775 + "d" (val),
10776 + "S" (timeout)
10777 + : "memory"
10778 + );
10779 +
10780 + return ret;
10781 +
10782 +}
10783 +
10784 +
10785 +static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
10786 +
10787 + int prev;
10788 +
10789 + asm volatile ("LOCK cmpxchgl %1, %2"
10790 + : "=a" (prev)
10791 + : "r" (new),
10792 + "m" (*(ptr)),
10793 + "0"(old)
10794 + : "memory", "cc"
10795 + );
10796 +
10797 + return prev;
10798 +}
10799 +
10800 +static inline int apc_xchg(volatile int *ptr, int new) {
10801 +
10802 + int ret;
10803 +
10804 + asm volatile ("LOCK xchgl %[new], %[ptr]"
10805 + : "=a" (ret)
10806 + : [new] "0" (new),
10807 + [ptr] "m" (*(ptr))
10808 + : "memory"
10809 + );
10810 +
10811 + return ret;
10812 +
10813 +}
10814 +
10815 diff -ubrN php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h php-5.2.5/ext/apc/arch/x86_64/atomic.h
10816 --- php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h 1969-12-31 18:00:00.000000000 -0600
10817 +++ php-5.2.5/ext/apc/arch/x86_64/atomic.h 2007-12-26 16:51:32.000000000 -0600
10818 @@ -0,0 +1,80 @@
10819 +/*
10820 + +----------------------------------------------------------------------+
10821 + | APC |
10822 + +----------------------------------------------------------------------+
10823 + | Copyright (c) 2006 The PHP Group |
10824 + +----------------------------------------------------------------------+
10825 + | This source file is subject to version 3.01 of the PHP license, |
10826 + | that is bundled with this package in the file LICENSE, and is |
10827 + | available through the world-wide-web at the following url: |
10828 + | http://www.php.net/license/3_01.txt |
10829 + | If you did not receive a copy of the PHP license and are unable to |
10830 + | obtain it through the world-wide-web, please send a note to |
10831 + | license@php.net so we can mail you a copy immediately. |
10832 + +----------------------------------------------------------------------+
10833 + | Authors: Brian Shire <shire@php.net> |
10834 + +----------------------------------------------------------------------+
10835 +
10836 + */
10837 +
10838 +/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
10839 +
10840 +
10841 +#include <sys/syscall.h>
10842 +#include <sys/time.h>
10843 +#include <linux/futex.h>
10844 +
10845 +/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
10846 +static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
10847 +
10848 + long int ret;
10849 +
10850 + /* x86_64 system calls are performed with the faster SYSCALL operation.
10851 + * the argument order is D, S, d, c, b, a rather than
10852 + * a, b, c, d, S, D as on the i386 int 80h call.
10853 + */
10854 + asm volatile ("syscall"
10855 + : "=a" (ret)
10856 + : "0" (SYS_futex),
10857 + "D" (futex),
10858 + "S" (op),
10859 + "d" (val),
10860 + "c" (timeout)
10861 + : "r11", "rcx", "memory"
10862 + );
10863 +
10864 + return ret;
10865 +
10866 +}
10867 +
10868 +
10869 +static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
10870 +
10871 + int prev;
10872 +
10873 + asm volatile ("LOCK cmpxchgl %1, %2"
10874 + : "=a" (prev)
10875 + : "r" (new),
10876 + "m" (*(ptr)),
10877 + "0"(old)
10878 + : "memory", "cc"
10879 + );
10880 +
10881 + return prev;
10882 +}
10883 +
10884 +static inline int apc_xchg(volatile int *ptr, int new) {
10885 +
10886 + int ret;
10887 +
10888 + asm volatile ("LOCK xchgl %[new], %[ptr]"
10889 + : "=a" (ret)
10890 + : [new] "0" (new),
10891 + [ptr] "m" (*(ptr))
10892 + : "memory"
10893 + );
10894 +
10895 + return ret;
10896 +
10897 +}
10898 +
10899 diff -ubrN php-5.2.5-orig/ext/apc/CHANGELOG php-5.2.5/ext/apc/CHANGELOG
10900 --- php-5.2.5-orig/ext/apc/CHANGELOG 1969-12-31 18:00:00.000000000 -0600
10901 +++ php-5.2.5/ext/apc/CHANGELOG 2007-12-26 16:51:32.000000000 -0600
10902 @@ -0,0 +1,211 @@
10903 +3.0.16: 2007-12-26
10904 +- Fix for longstanding cache-full crash (Christian Seiler)
10905 + http://news.php.net/php.pecl.dev/4951 for the details
10906 +- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
10907 +- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
10908 +- Minor cleanups (Lucas Nealan)
10909 +- Added configure option to enable apc_cache_info('filehits') (Shire)
10910 +
10911 +3.0.15: 2007-10-18
10912 +- Eliminate a per-request time() syscall (Rasmus)
10913 +- Added rfc1867 prefix, name, and freq ini options (Shire)
10914 +- Allow deletion of individual user cache entries via apc.php (Sara)
10915 +- Fix overzealous cleanup during RSHUTDOWN (Gopal)
10916 +- Fix memory alignment and locking issues (Gopal)
10917 +- Make apc_compile insert/replace entries (Shire)
10918 +- Make mixed inheritance recompile & cache afresh (Gopal)
10919 +- Make nostat mode search include_path for canonicalization (Gopal)
10920 +- ZTS & other compile fixes (Gopal, Edin, Shire)
10921 +
10922 +3.0.14: 2007-03-21
10923 +- Build fix (Shire)
10924 +- Don't hook the upload hook if APC is disabled (Rasmus)
10925 +- Local shadow cache support (Gopal)
10926 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
10927 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
10928 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
10929 +- Allocator fixes to reduce fragmentation (Gopal)
10930 +
10931 +3.0.13: 2007-02-24
10932 +- File upload progress (Rasmus)
10933 +- Pthread mutex and spin locks (Shire)
10934 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
10935 +- apc.stat_ctime flag for ctime checks (Rasmus)
10936 +- Multiple key fetches with apc_fetch (Shire)
10937 +- Canary checks for shm memory deallocation (Gopal)
10938 +- Add hooks for external optimizer (Shire)
10939 +- Obsolete and remove apc optimizer (Gopal)
10940 +- APC info changes - cache insert rate, hit and miss rates (Shire)
10941 +- Fix apc_load_constants (Gopal)
10942 +- Rewrite dump opcode code to use vld (Gopal)
10943 +- Use apc_[ewn]print functions for error reporting (Shire)
10944 +- Auto global fixes and refactoring (Gopal, Shire)
10945 +- Fix memory leaks in object serialization (Ilia)
10946 +- Memory cleanup code for destructor order (Gopal)
10947 +- Win32 build fixes (Ilia, Wez)
10948 +- ZTS and Php 4 build fixes (Bjori)
10949 +- Add apc_add() function (Rasmus)
10950 +- Add optional limited flag to apc_sma_info() (Rasmus)
10951 +
10952 +3.0.12p2: 2006-09-05
10953 +- Package version up
10954 +
10955 +3.0,12p1: 2006-09-05
10956 +- PHP4 build fixes
10957 +
10958 +3.0.12: 2006-09-05
10959 +- PHP 5.2 compatibility (Gopal)
10960 +- TSRM fixes (Gopal)
10961 +- Add extra flags to op_array->reserved to improve op array
10962 + processing code (Gopal)
10963 +- Fix crashes in optimizer and cli mode (Ilia)
10964 +- Optimizer fixes for PHP5 (Ilia, Gopal)
10965 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
10966 +- Php 4 function table and properties fixes (Gopal)
10967 +- Fix memory leaks in apc_cache_info (Gopal)
10968 +
10969 +3.0.11: 2006-08-16
10970 +- Made --enable-apc-mmap the default compile option (for real this time)
10971 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
10972 + only fetch header information to make it useful when you have tens of
10973 + thousands of entries. (Brian Shire)
10974 +- 64-bit fixes (George)
10975 +- Don't mix Full Path and Inode keys (George)
10976 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
10977 + require_once() and include_once() statements. (Sara)
10978 +- Add a non-blocking write_lock for cache inserts. This is a better approach
10979 + to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
10980 +- A bit of work on the optimizer. (Sara)
10981 +- Various memory issues resolved. (Gopal)
10982 +
10983 +3.0.10: 2006-03-11
10984 +- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
10985 + includes will not be stat'ed for any changes. You will have to restart the server if you
10986 + change anything. This mode increases performance quite a bit, especially if you have a
10987 + lot of includes.
10988 +
10989 +- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
10990 + than it solves. I'll need to revisit locking and signal handling at some point soon.
10991 +
10992 +3.0.9: 2006-03-04
10993 +- Eliminate rand() call when slam_defense is not set (Rasmus)
10994 +- Fix for __isset problem (Gopal)
10995 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
10996 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
10997 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
10998 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
10999 +- Add automatic serialization of objects in apc_store() (Marcus)
11000 +- 64-bit .ini flag fix (Rasmus)
11001 +- Static members fix (Gopal)
11002 +- sma_cleanup() mem leak fix (Rasmus)
11003 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
11004 +- Fix autoglobals JIT bug (Gopal)
11005 +- Fix instance bug (Gopal)
11006 +- Add a lock cleanup safety net to request shutdown (Rasmus)
11007 +- Fix apc.slam_defense edge-case bug (Rasmus)
11008 +- User entry memory usage tracking support (Ilia)
11009 +- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
11010 +
11011 +3.0.8: 2005-08-24
11012 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
11013 +Cache corruption fix in cache-full cleanup code (Gopal)
11014 +
11015 +3.0.7: 2005-08-16
11016 +- Fix to apc.php to show final segment in frag chart. (Ilia)
11017 +- A couple of win32 fixes. (Frank)
11018 +- Add apc.enable_cli ini directive. (Rasmus)
11019 +- Add test cases. (Marcus)
11020 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
11021 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
11022 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
11023 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
11024 +
11025 +3.0.6: 2005-07-30
11026 +- Added apc.php to package.xml file.
11027 +- Track per-entry memory usage. (Val)
11028 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
11029 +- fcntl locking robustness fixes. (Rasmus)
11030 +- Shared read-locks where possible. (Rasmus)
11031 +- Added file_update_protection configuration parameter. (Rasmus)
11032 +- Windows ZTS fixes (Frank)
11033 +
11034 +3.0.5: 2005-07-27
11035 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
11036 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
11037 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
11038 +- Segfault in cache cleanup code (Ilia, Rasmus)
11039 +
11040 +3.0.4: 2005-07-18
11041 +- Add win32 support (Edin )
11042 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
11043 +- A couple of other minor fixes
11044 +
11045 +3.0.3: 2005-07-05
11046 +- Fix compile problem against PHP 5.0.x
11047 +
11048 +3.0.2: 2005-07-05
11049 +- Better shm error message
11050 +
11051 +3.0.1: 2005-07-05
11052 +- PHP4 build fix
11053 +
11054 +3.0: 2005-06-23
11055 +- PHP 5.1 support (Arun, Gopal, Rasmus)
11056 +- Major Inheritance bug fix (Arun, Gopal)
11057 +
11058 +2.0: 2003-02-10
11059 +- ground-up rewrite sharing none of the original source code (djc)
11060 +
11061 +1.0.10:
11062 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
11063 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
11064 + this parameter to your php.ini file to activate apc shm or mmap caching
11065 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
11066 + 2001-05-15]
11067 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
11068 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
11069 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
11070 +- fixed regex support [gws 2001-05-16]
11071 +- enhanced reader-writer lock support [rg 2001-05-07]
11072 +
11073 +1.0.9:
11074 +- fixed (?) memory alignment bug on 64 bit archiecures
11075 +- added many cache visibiliy functions
11076 +- added opional fcntl locks under shm version
11077 +- numerous bug fixes
11078 +
11079 +1.0.8:
11080 +- added ability to detect and decompile compiled files placed as 'source'
11081 + [gws,dw 2001-01-30]
11082 +- fixed apc_rstat bug [gws 2001-01-29]
11083 +- added hack to support included urls [gws 2001-01-30]
11084 +- fixed apc_cache_index [mb 2001-01-31]
11085 +- added multiple regex support [gs 2001-02-03]
11086 +- added apc_cache_info [mb,gs 2001-02-03]
11087 +
11088 +1.0.7:
11089 +- partially fixed for Solaris [gws 2001-01-29]
11090 +- fixed mtime support for relative includes [gws 2001-01-29]
11091 +- code cleanup [yg,ta,gws 2001-01-29]
11092 +
11093 +1.0.6:
11094 +- support for mtime in mmap [yg,gws 2001-01-27]
11095 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
11096 +
11097 +1.0.5:
11098 +- support for relative include paths [djc,gws 2001-01-19]
11099 +- class member array support fixed [djc 2001-01-18]
11100 +- added apc_cache_index [gws 2001-01-18]
11101 +
11102 +1.0.4:
11103 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
11104 +
11105 +1.0.3:
11106 +- fixed support for class inheritance [djc 2001-01-16]
11107 +
11108 +1.0.2:
11109 +- support for inherited classes [gws 2001-01-15]
11110 +- support for intialization of class variables and objects [gws 2001-01-13]
11111 +
11112 +1.0.1:
11113 +- added optional file modification time check [djc 2001-01-12]
11114 diff -ubrN php-5.2.5-orig/ext/apc/config.m4 php-5.2.5/ext/apc/config.m4
11115 --- php-5.2.5-orig/ext/apc/config.m4 1969-12-31 18:00:00.000000000 -0600
11116 +++ php-5.2.5/ext/apc/config.m4 2007-12-26 16:51:32.000000000 -0600
11117 @@ -0,0 +1,238 @@
11118 +dnl
11119 +dnl $Id: config.m4,v 3.30 2007/12/26 22:31:20 rasmus Exp $
11120 +dnl
11121 +
11122 +AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
11123 +AC_ARG_WITH(apxs,
11124 +[ --with-apxs[=FILE] Get compiler flags from apxs -q. Provide the
11125 + pathname to the Apache apxs tool; defaults to "apxs".],[
11126 + if test "$withval" != "no"; then
11127 + if test "$withval" = "yes"; then
11128 + APXS=apxs
11129 + $APXS -q CFLAGS >/dev/null 2>&1
11130 + if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
11131 + APXS=/usr/sbin/apxs
11132 + elif test -x /usr/bin/apxs2; then
11133 + APXS=/usr/bin/apxs2
11134 + elif test -x /usr/sbin/apxs2; then
11135 + APXS=/usr/sbin/apxs2
11136 + fi
11137 + else
11138 + PHP_EXPAND_PATH($withval, APXS)
11139 + fi
11140 +
11141 + $APXS -q CFLAGS >/dev/null 2>&1
11142 + if test "$?" != "0"; then
11143 + AC_MSG_RESULT()
11144 + AC_MSG_RESULT()
11145 + AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:])
11146 + AC_MSG_RESULT()
11147 + AC_MSG_RESULT([1. Perl is not installed;])
11148 + AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);])
11149 + AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs])
11150 + AC_MSG_RESULT([The output of $APXS follows])
11151 + $APXS -q CFLAGS
11152 + AC_MSG_ERROR([Aborting])
11153 + fi
11154 +
11155 + APC_CFLAGS=`$APXS -q CFLAGS`
11156 + AC_MSG_RESULT(yes)
11157 + else
11158 + AC_MSG_RESULT(no)
11159 + fi
11160 +],[
11161 + AC_MSG_RESULT(no)
11162 +])
11163 +
11164 +PHP_ARG_ENABLE(apc, whether to enable APC support,
11165 +[ --enable-apc Enable APC support])
11166 +
11167 +AC_MSG_CHECKING(Checking whether we should enable cache request file info)
11168 +AC_ARG_ENABLE(apc-filehits,
11169 +[ --enable-apc-filehits Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
11170 +[
11171 + PHP_APC_FILEHITS=$enableval
11172 + AC_MSG_RESULT($enableval)
11173 +],
11174 +[
11175 + PHP_APC_FILEHITS=no
11176 + AC_MSG_RESULT(no)
11177 +])
11178 +
11179 +
11180 +
11181 +AC_MSG_CHECKING(Checking whether we should use mmap)
11182 +AC_ARG_ENABLE(apc-mmap,
11183 +[ --disable-apc-mmap
11184 + Disable mmap support and use IPC shm instead],
11185 +[
11186 + PHP_APC_MMAP=$enableval
11187 + AC_MSG_RESULT($enableval)
11188 +], [
11189 + PHP_APC_MMAP=yes
11190 + AC_MSG_RESULT(yes)
11191 +])
11192 +
11193 +AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
11194 +AC_ARG_ENABLE(apc-sem,
11195 +[ --enable-apc-sem
11196 + Enable semaphore locks instead of fcntl],
11197 +[
11198 + PHP_APC_SEM=$enableval
11199 + AC_MSG_RESULT($enableval)
11200 +], [
11201 + PHP_APC_SEM=no
11202 + AC_MSG_RESULT(no)
11203 +])
11204 +
11205 +AC_MSG_CHECKING(Checking whether we should use futex locking)
11206 +AC_ARG_ENABLE(apc-futex,
11207 +[ --enable-apc-futex
11208 + Enable linux futex based locks EXPERIMENTAL ],
11209 +[
11210 + PHP_APC_FUTEX=$enableval
11211 + AC_MSG_RESULT($enableval)
11212 +],
11213 +[
11214 + PHP_APC_FUTEX=no
11215 + AC_MSG_RESULT(no)
11216 +])
11217 +
11218 +if test "$PHP_APC_FUTEX" != "no"; then
11219 + AC_CHECK_HEADER(linux/futex.h, , [ AC_MSG_ERROR([futex.h not found. Please verify you that are running a 2.5 or older linux kernel and that futex support is enabled.]); ] )
11220 +fi
11221 +
11222 +AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
11223 +AC_ARG_ENABLE(apc-pthreadmutex,
11224 +[ --disable-apc-pthreadmutex
11225 + Disable pthread mutex locking ],
11226 +[
11227 + PHP_APC_PTHREADMUTEX=no
11228 + AC_MSG_RESULT(no)
11229 +],
11230 +[
11231 + PHP_APC_PTHREADMUTEX=yes
11232 + AC_MSG_RESULT(yes)
11233 +])
11234 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
11235 + orig_LIBS="$LIBS"
11236 + LIBS="$LIBS -lpthread"
11237 + AC_TRY_RUN(
11238 + [
11239 + #include <sys/types.h>
11240 + #include <pthread.h>
11241 + main() {
11242 + pthread_mutex_t mutex;
11243 + pthread_mutexattr_t attr;
11244 +
11245 + if(pthread_mutexattr_init(&attr)) {
11246 + puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
11247 + return -1;
11248 + }
11249 + if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
11250 + puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
11251 + return -1;
11252 + }
11253 + if(pthread_mutex_init(&mutex, &attr)) {
11254 + puts("Unable to initialize the mutex (pthread_mutex_init).");
11255 + return -1;
11256 + }
11257 + if(pthread_mutexattr_destroy(&attr)) {
11258 + puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
11259 + return -1;
11260 + }
11261 + if(pthread_mutex_destroy(&mutex)) {
11262 + puts("Unable to destroy mutex (pthread_mutex_destroy).");
11263 + return -1;
11264 + }
11265 +
11266 + puts("pthread mutex's are supported!");
11267 + return 0;
11268 + }
11269 + ],
11270 + [ dnl -Success-
11271 + PHP_ADD_LIBRARY(pthread)
11272 + ],
11273 + [ dnl -Failure-
11274 + AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
11275 + PHP_APC_PTHREADMUTEX=no
11276 + ],
11277 + [
11278 + PHP_ADD_LIBRARY(pthread)
11279 + ]
11280 + )
11281 + LIBS="$orig_LIBS"
11282 +fi
11283 +
11284 +AC_MSG_CHECKING(Checking whether we should use spin locks)
11285 +AC_ARG_ENABLE(apc-spinlocks,
11286 +[ --enable-apc-spinlocks
11287 + Enable spin locks EXPERIMENTAL ],
11288 +[
11289 + PHP_APC_SPINLOCKS=$enableval
11290 + AC_MSG_RESULT($enableval)
11291 +],
11292 +[
11293 + PHP_APC_SPINLOCKS=no
11294 + AC_MSG_RESULT(no)
11295 +])
11296 +
11297 +if test "$PHP_APC" != "no"; then
11298 + test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
11299 + test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
11300 +
11301 + if test "$PHP_APC_SEM" != "no"; then
11302 + AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
11303 + elif test "$PHP_APC_FUTEX" != "no"; then
11304 + AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
11305 + elif test "$PHP_APC_SPINLOCKS" != "no"; then
11306 + AC_DEFINE(APC_SPIN_LOCKS, 1, [ ])
11307 + elif test "$PHP_APC_PTHREADMUTEX" != "no"; then
11308 + AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
11309 + fi
11310 +
11311 + AC_CHECK_FUNCS(sigaction)
11312 + AC_CACHE_CHECK(for union semun, php_cv_semun,
11313 + [
11314 + AC_TRY_COMPILE([
11315 +#include <sys/types.h>
11316 +#include <sys/ipc.h>
11317 +#include <sys/sem.h>
11318 + ], [union semun x;], [
11319 + php_cv_semun=yes
11320 + ],[
11321 + php_cv_semun=no
11322 + ])
11323 + ])
11324 + if test "$php_cv_semun" = "yes"; then
11325 + AC_DEFINE(HAVE_SEMUN, 1, [ ])
11326 + else
11327 + AC_DEFINE(HAVE_SEMUN, 0, [ ])
11328 + fi
11329 +
11330 + apc_sources="apc.c php_apc.c \
11331 + apc_cache.c \
11332 + apc_compile.c \
11333 + apc_debug.c \
11334 + apc_fcntl.c \
11335 + apc_main.c \
11336 + apc_mmap.c \
11337 + apc_sem.c \
11338 + apc_shm.c \
11339 + apc_futex.c \
11340 + apc_pthreadmutex.c \
11341 + apc_spin.c \
11342 + pgsql_s_lock.c \
11343 + apc_sma.c \
11344 + apc_stack.c \
11345 + apc_zend.c \
11346 + apc_rfc1867.c \
11347 + apc_signal.c "
11348 +
11349 + PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
11350 + PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
11351 + PHP_SUBST(APC_SHARED_LIBADD)
11352 + PHP_SUBST(APC_CFLAGS)
11353 + AC_DEFINE(HAVE_APC, 1, [ ])
11354 +fi
11355 +
11356 diff -ubrN php-5.2.5-orig/ext/apc/INSTALL php-5.2.5/ext/apc/INSTALL
11357 --- php-5.2.5-orig/ext/apc/INSTALL 1969-12-31 18:00:00.000000000 -0600
11358 +++ php-5.2.5/ext/apc/INSTALL 2007-12-26 16:51:32.000000000 -0600
11359 @@ -0,0 +1,422 @@
11360 +Installation Instructions for APC
11361 +---------------------------------
11362 +
11363 +This version of APC should work on PHP 4.3.0 - 4.4.x and
11364 +5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer
11365 +supported. Upgrade to PHP 5.1.x or 5.2.x and you will
11366 +notice all sorts of performance increases.
11367 +
11368 +CVS Instructions
11369 +----------------
11370 +Building from CVS can be done like this:
11371 +
11372 + cvs -d :pserver:cvsread@cvs.php.net:/repository login
11373 + Password: phpfi
11374 + cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
11375 + cd pecl/apc
11376 + phpize
11377 + ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
11378 + make
11379 + make install
11380 +
11381 +Suggested Configuration (in your php.ini file)
11382 +----------------------------------------------
11383 + extension=apc.so
11384 + apc.enabled=1
11385 + apc.shm_segments=1
11386 + apc.shm_size=128
11387 + apc.ttl=7200
11388 + apc.user_ttl=7200
11389 + apc.num_files_hint=1024
11390 + apc.mmap_file_mask=/tmp/apc.XXXXXX
11391 + apc.enable_cli=1
11392 +
11393 +These are fully described at the bottom of this file.
11394 +
11395 +PHP 4 Optimization
11396 +------------------
11397 +If you are trying to get every little bit of speed out of PHP4+APC, you need
11398 +to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
11399 +your CPPFLAGS. (if you don't have httpd.h, install the apache_dev package
11400 +for your OS) and do:
11401 + export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
11402 + setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
11403 +and then re-run your configure script.
11404 +
11405 +This optimization saves a stat syscall on the main script file. In PHP5 this
11406 +optimization is automatic and doesn't need any special build flags.
11407 +
11408 +The second thing you are going to want to do to save another syscall is to
11409 +compile using the --with-apxs configure switch. This should work for both
11410 +Apache1 and Apache2. Point it directly at your apxs2 script for Apache2.
11411 +eg. --with-apxs=/usr/local/bin/apxs2
11412 +
11413 ++---------------------+
11414 +| QUICK INSTALL (DSO) |
11415 ++---------------------+
11416 +
11417 +These instructions assume your PHP installation is located in /usr/local/php and you
11418 +want Apache optimizations (--with-apxs).
11419 +
11420 +$ gunzip -c apc_x.y.tar.gz | tar xf -
11421 +$ cd apc_x.y
11422 +$ /usr/local/php/bin/phpize
11423 +$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
11424 +$ make
11425 +$ make install
11426 +
11427 +You will probably need to run the final command (make install) as root.
11428 +
11429 +The above sequence of commands will install a .so file in your PHP
11430 +installation extension directory. The output of make install should display
11431 +that path to the screen.
11432 +
11433 +Next you must edit your php.ini file, which is normally located in
11434 +/usr/local/php/lib/php.ini, and add the following line:
11435 +
11436 + extension="apc.so"
11437 +
11438 +Replace "/path/to/php/extensions" with whatever path was displayed when you
11439 +ran make install above.
11440 +
11441 +Then restart your web server and consult the output of phpinfo(). If there is
11442 +an informational section for APC, the installation was successful.
11443 +
11444 ++------------------------+
11445 +| QUICK INSTALL (Static) |
11446 ++------------------------+
11447 +
11448 +APC will not successfully compile on all systems as a DSO. If you run into
11449 +problems using the DSO quick install, you can try to compile it statically
11450 +into PHP. (The DSO install is recommended, though.)
11451 +
11452 +These instructions assume the current directory is the root of the PHP source
11453 +tree, and that you have already configured PHP by running its bundled
11454 +configure script.
11455 +
11456 +$ cd ext
11457 +$ gunzip -c apc_x.y.tar.gz | tar xf -
11458 +$ cd ..
11459 +$ ./buildconf
11460 +$ ./config.nice
11461 +$ make
11462 +$ make install
11463 +
11464 +Once this is complete, simply restart your web server. You do not need to
11465 +modify your php.ini file to enable APC.
11466 +
11467 ++-----------------+
11468 +| VERBOSE INSTALL |
11469 ++-----------------+
11470 +
11471 +These instructions assume your PHP installation is located in /usr/local/php.
11472 +
11473 +1. Unpack your distribution file.
11474 +
11475 + You will have downloaded a file named something like apc_x.y.tar.gz.
11476 + Unzip this file with a command like
11477 +
11478 + gunzip apc_x.y.tar.gz
11479 +
11480 + Next you have to untar it with
11481 +
11482 + tar xvf apc_x.y.tar
11483 +
11484 + This will create an apc_x.y directory. cd into this new directory:
11485 +
11486 + cd apc_x.y
11487 +
11488 +2. Run phpize.
11489 +
11490 + phpize is a script that should have been installed with PHP, and is
11491 + normally located in /usr/local/php/bin assuming you installed PHP in
11492 + /usr/local/php. (If you do not have the phpize script, you must reinstall
11493 + PHP and be sure not to disable PEAR.)
11494 +
11495 + Run the phpize command:
11496 +
11497 + /usr/local/php/bin/phpize
11498 +
11499 + Its output should resemble this:
11500 +
11501 + autoheader: `config.h.in' is created
11502 + You should update your `aclocal.m4' by running aclocal.
11503 + Configuring for:
11504 + PHP Api Version: 20020918
11505 + Zend Module Api No: 20020429
11506 + Zend Extension Api No: 20021010
11507 +
11508 + phpize should create a configure script in the current directory. If you
11509 + get errors instead, you might be missing some required development tools,
11510 + such as autoconf or libtool. You can try downloading the latest versions
11511 + of those tools and running phpize again.
11512 +
11513 +3. Run the configure script.
11514 +
11515 + phpize creates a configure script. The only option you need to specify is
11516 + the location of your php-config script:
11517 +
11518 + ./configure --enable-apc
11519 +
11520 + php-config should be located in the same directory as phpize.
11521 +
11522 + If you prefer to use mmap instead of the default IPC shared memory support,
11523 + add --enable-apc-mmap to your configure line.
11524 +
11525 + If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
11526 + --enable-sem to your configure line. If you don't have a problem
11527 + with your server segaulting, or any other unnatural accumulation of
11528 + semaphores on your system, the semaphore based locking is slightly faster.
11529 +
11530 +4. Compile and install the files. Simply type: make install
11531 +
11532 + (You may need to be root in order to install)
11533 +
11534 + If you encounter errors from libtool or gcc during this step, please
11535 + contact the project maintainer (dcowgill@php.net).
11536 +
11537 +5. Edit your php.ini
11538 +
11539 + make install should have printed a line resembling the following:
11540 +
11541 + Installing shared extensions: /path/to/extension/
11542 +
11543 + Copy the path /path/to/extension/ and add the following line to your
11544 + php.ini file (normally located in /usr/local/php/lib/php.ini):
11545 +
11546 + extension="apc.so"
11547 +
11548 + If you don't have a php.ini file in that location, you can create it now.
11549 +
11550 +6. Restart the web server and test the installation.
11551 +
11552 + Restart your web server now (for apache, it's apachectl restart) and
11553 + create a small test PHP file in your document root. The file should
11554 + contain just the following line:
11555 +
11556 + <?php phpinfo() ?>
11557 +
11558 + Request that file in a web browser. If there is an entry for APC in the
11559 + list of installed modules, the installation was successful.
11560 +
11561 + If APC is not listed, consult your web server error log. If it contains an
11562 + error message saying that it can't load the APC extension, your system
11563 + might not be able to load shared libraries created with PHP's build
11564 + system. One alternative would be to compile APC statically into PHP. See
11565 + the Quick Install (Static) instructions above.
11566 +
11567 + You should consult your error log anyway to see if APC generated any
11568 + errors. On BSD-based platforms, it is typical for APC to be unable to
11569 + allocate the default-sized shared memory segment. See below for hints on
11570 + raising your system's shared memory limitations.
11571 +
11572 ++-----------------+
11573 +| CONFIGURING APC |
11574 ++-----------------+
11575 +
11576 +Although the default APC settings are fine for many installations, serious
11577 +users should consider tuning the following parameters:
11578 +
11579 + OPTION DESCRIPTION
11580 + ------------------ --------------------------------------------------
11581 + apc.enabled This can be set to 0 to disable APC. This is
11582 + primarily useful when APC is statically compiled
11583 + into PHP, since there is no other way to disable
11584 + it (when compiled as a DSO, the zend_extension
11585 + line can just be commented-out).
11586 + (Default: 1)
11587 +
11588 + apc.shm_segments The number of shared memory segments to allocate
11589 + for the compiler cache. If APC is running out of
11590 + shared memory but you have already set
11591 + apc.shm_size as high as your system allows, you
11592 + can try raising this value. Setting this to a
11593 + value other than 1 has no effect in mmap mode
11594 + since mmap'ed shm segments don't have size limits.
11595 + (Default: 1)
11596 +
11597 + apc.shm_size The size of each shared memory segment in MB.
11598 + By default, some systems (including most BSD
11599 + variants) have very low limits on the size of a
11600 + shared memory segment.
11601 + (Default: 30)
11602 +
11603 + apc.optimization This option has been deprecated.
11604 + (Default: 0)
11605 +
11606 + apc.num_files_hint A "hint" about the number of distinct source files
11607 + that will be included or requested on your web
11608 + server. Set to zero or omit if you're not sure;
11609 + this setting is mainly useful for sites that have
11610 + many thousands of source files.
11611 + (Default: 1000)
11612 +
11613 + apc.user_entries_hint Just like num_files_hint, a "hint" about the number
11614 + of distinct user cache variables to store.
11615 + Set to zero or omit if you're not sure;
11616 + (Default: 4096)
11617 +
11618 + apc.ttl The number of seconds a cache entry is allowed to
11619 + idle in a slot in case this cache entry slot is
11620 + needed by another entry. Leaving this at zero
11621 + means that your cache could potentially fill up
11622 + with stale entries while newer entries won't be
11623 + cached.
11624 + (Default: 0)
11625 +
11626 + apc.user_ttl The number of seconds a user cache entry is allowed
11627 + to idle in a slot in case this cache entry slot is
11628 + needed by another entry. Leaving this at zero
11629 + means that your cache could potentially fill up
11630 + with stale entries while newer entries won't be
11631 + cached.
11632 + (Default: 0)
11633 +
11634 +
11635 + apc.gc_ttl The number of seconds that a cache entry may
11636 + remain on the garbage-collection list. This value
11637 + provides a failsafe in the event that a server
11638 + process dies while executing a cached source file;
11639 + if that source file is modified, the memory
11640 + allocated for the old version will not be
11641 + reclaimed until this TTL reached. Set to zero to
11642 + disable this feature.
11643 + (Default: 3600)
11644 +
11645 + apc.cache_by_default On by default, but can be set to off and used in
11646 + conjunction with positive apc.filters so that files
11647 + are only cached if matched by a positive filter.
11648 + (Default: On)
11649 +
11650 + apc.filters A comma-separated list of POSIX extended regular
11651 + expressions. If any pattern matches the source
11652 + filename, the file will not be cached. Note that
11653 + the filename used for matching is the one passed
11654 + to include/require, not the absolute path. If the
11655 + first character of the expression is a + then the
11656 + expression will be additive in the sense that any
11657 + files matched by the expression will be cached, and
11658 + if the first character is a - then anything matched
11659 + will not be cached. The - case is the default, so
11660 + it can be left off.
11661 + (Default: "")
11662 +
11663 + apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap
11664 + this is the mktemp-style file_mask to pass to the
11665 + mmap module for determing whether your mmap'ed memory
11666 + region is going to be file-backed or shared memory
11667 + backed. For straight file-backed mmap, set it to
11668 + something like /tmp/apc.XXXXXX (exactly 6 X's).
11669 + To use POSIX-style shm_open/mmap put a ".shm"
11670 + somewhere in your mask. eg. "/apc.shm.XXXXXX"
11671 + You can also set it to "/dev/zero" to use your
11672 + kernel's /dev/zero interface to anonymous mmap'ed
11673 + memory. Leaving it undefined will force an
11674 + anonymous mmap.
11675 + (Default: "")
11676 +
11677 + apc.slam_defense ** DEPRECATED - Use apc.write_lock instead **
11678 + On very busy servers whenever you start the server or
11679 + modify files you can create a race of many processes
11680 + all trying to cache the same file at the same time.
11681 + This option sets the percentage of processes that will
11682 + skip trying to cache an uncached file. Or think of it
11683 + as the probability of a single process to skip caching.
11684 + For example, setting this to 75 would mean that there is
11685 + a 75% chance that the process will not cache an uncached
11686 + file. So the higher the setting the greater the defense
11687 + against cache slams. Setting this to 0 disables this
11688 + feature.
11689 + (Default: 0)
11690 +
11691 + apc.file_update_protection
11692 + When you modify a file on a live web server you really
11693 + should do so in an atomic manner. That is, write to a
11694 + temporary file and rename (mv) the file into its permanent
11695 + position when it is ready. Many text editors, cp, tar and
11696 + other such programs don't do this. This means that there
11697 + is a chance that a file is accessed (and cached) while it
11698 + is still being written to. This file_update_protection
11699 + setting puts a delay on caching brand new files. The
11700 + default is 2 seconds which means that if the modification
11701 + timestamp (mtime) on a file shows that it is less than 2
11702 + seconds old when it is accessed, it will not be cached.
11703 + The unfortunate person who accessed this half-written file
11704 + will still see weirdness, but at least it won't persist.
11705 + If you are certain you always atomically update your files
11706 + by using something like rsync which does this correctly, you
11707 + can turn this protection off by setting it to 0. If you
11708 + have a system that is flooded with io causing some update
11709 + procedure to take longer than 2 seconds, you may want to
11710 + increase this a bit.
11711 + (Default: 2)
11712 +
11713 + apc.enable_cli Mostly for testing and debugging. Setting this enables APC
11714 + for the CLI version of PHP. Normally you wouldn't want to
11715 + create, populate and tear down the APC cache on every CLI
11716 + request, but for various test scenarios it is handy to be
11717 + able to enable APC for the CLI version of APC easily.
11718 + (Default: 0)
11719 +
11720 + apc.max_file_size Prevents large files from being cached.
11721 + (Default: 1M)
11722 +
11723 + apc.stat Whether to stat the main script file and the fullpath
11724 + includes. If you turn this off you will need to restart
11725 + your server in order to update scripts.
11726 + (Default: 1)
11727 +
11728 + apc.write_lock On busy servers when you first start up the server, or when
11729 + many files are modified, you can end up with all your processes
11730 + trying to compile and cache the same files. With write_lock
11731 + enabled, only one process at a time will try to compile an
11732 + uncached script while the other processes will run uncached
11733 + instead of sitting around waiting on a lock.
11734 + (Default: 1)
11735 +
11736 + apc.report_autofilter Logs any scripts that were automatically excluded from being
11737 + cached due to early/late binding issues.
11738 + (Default: 0)
11739 +
11740 + apc.rfc1867 RFC1867 File Upload Progress hook handler is only available
11741 + if you compiled APC against PHP 5.2.0 or later. When enabled
11742 + any file uploads which includes a field called
11743 + APC_UPLOAD_PROGRESS before the file field in an upload form
11744 + will cause APC to automatically create an upload_<key>
11745 + user cache entry where <key> is the value of the
11746 + APC_UPLOAD_PROGRESS form entry.
11747 +
11748 + Note that the file upload tracking is not threadsafe at this
11749 + point, so new uploads that happen while a previous one is
11750 + still going will disable the tracking for the previous.
11751 + (Default: 0)
11752 +
11753 + apc.rfc1867_prefix Key prefix to use for the user cache entry generated by
11754 + rfc1867 upload progress functionality.
11755 + (Default: "upload_")
11756 +
11757 + apc.rfc1867_name Specify the hidden form entry name that activates APC upload
11758 + progress and specifies the user cache key suffix.
11759 + (Default: "APC_UPLOAD_PROGRESS")
11760 +
11761 + apc.rfc1867_freq The frequency that updates should be made to the user cache
11762 + entry for upload progress. This can take the form of a
11763 + percentage of the total file size or a size in bytes
11764 + optionally suffixed with 'k', 'm', or 'g' for kilobytes,
11765 + megabytes, or gigabytes respectively (case insensitive).
11766 + A setting of 0 updates as often as possible, which may cause
11767 + slower uploads.
11768 + (Default: 0)
11769 +
11770 + apc.localcache This enables a lock-free local process shadow-cache which
11771 + reduces lock contention when the cache is being written to.
11772 + (Default: 0)
11773 +
11774 + apc.localcache.size The size of the local process shadow-cache, should be set to
11775 + a sufficently large value, approximately half of num_files_hint.
11776 + (Default: 512)
11777 +
11778 + apc.include_once_override
11779 + Optimize include_once and require_once calls and avoid the
11780 + expensive system calls used.
11781 + (Default: 0)
11782 diff -ubrN php-5.2.5-orig/ext/apc/LICENSE php-5.2.5/ext/apc/LICENSE
11783 --- php-5.2.5-orig/ext/apc/LICENSE 1969-12-31 18:00:00.000000000 -0600
11784 +++ php-5.2.5/ext/apc/LICENSE 2007-12-26 16:51:32.000000000 -0600
11785 @@ -0,0 +1,68 @@
11786 +--------------------------------------------------------------------
11787 + The PHP License, version 3.01
11788 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
11789 +--------------------------------------------------------------------
11790 +
11791 +Redistribution and use in source and binary forms, with or without
11792 +modification, is permitted provided that the following conditions
11793 +are met:
11794 +
11795 + 1. Redistributions of source code must retain the above copyright
11796 + notice, this list of conditions and the following disclaimer.
11797 +
11798 + 2. Redistributions in binary form must reproduce the above copyright
11799 + notice, this list of conditions and the following disclaimer in
11800 + the documentation and/or other materials provided with the
11801 + distribution.
11802 +
11803 + 3. The name "PHP" must not be used to endorse or promote products
11804 + derived from this software without prior written permission. For
11805 + written permission, please contact group@php.net.
11806 +
11807 + 4. Products derived from this software may not be called "PHP", nor
11808 + may "PHP" appear in their name, without prior written permission
11809 + from group@php.net. You may indicate that your software works in
11810 + conjunction with PHP by saying "Foo for PHP" instead of calling
11811 + it "PHP Foo" or "phpfoo"
11812 +
11813 + 5. The PHP Group may publish revised and/or new versions of the
11814 + license from time to time. Each version will be given a
11815 + distinguishing version number.
11816 + Once covered code has been published under a particular version
11817 + of the license, you may always continue to use it under the terms
11818 + of that version. You may also choose to use such covered code
11819 + under the terms of any subsequent version of the license
11820 + published by the PHP Group. No one other than the PHP Group has
11821 + the right to modify the terms applicable to covered code created
11822 + under this License.
11823 +
11824 + 6. Redistributions of any form whatsoever must retain the following
11825 + acknowledgment:
11826 + "This product includes PHP software, freely available from
11827 + <http://www.php.net/software/>".
11828 +
11829 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
11830 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
11831 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11832 +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
11833 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
11834 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11835 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
11836 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11837 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
11838 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11839 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11840 +OF THE POSSIBILITY OF SUCH DAMAGE.
11841 +
11842 +--------------------------------------------------------------------
11843 +
11844 +This software consists of voluntary contributions made by many
11845 +individuals on behalf of the PHP Group.
11846 +
11847 +The PHP Group can be contacted via Email at group@php.net.
11848 +
11849 +For more information on the PHP Group and the PHP project,
11850 +please see <http://www.php.net>.
11851 +
11852 +PHP includes the Zend Engine, freely available at
11853 +<http://www.zend.com>.
11854 diff -ubrN php-5.2.5-orig/ext/apc/NOTICE php-5.2.5/ext/apc/NOTICE
11855 --- php-5.2.5-orig/ext/apc/NOTICE 1969-12-31 18:00:00.000000000 -0600
11856 +++ php-5.2.5/ext/apc/NOTICE 2007-12-26 16:51:32.000000000 -0600
11857 @@ -0,0 +1,43 @@
11858 +This is the NOTICE file that holds acknowledgements and stuff.
11859 +
11860 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
11861 +This extension is being released under the PHP License for complete compliance
11862 +with PHP and to encourage wide-spread use. It is our intention that this
11863 +project be kept open source and that all commercial spin-offs contribute their
11864 +modifications back into the public source-tree.
11865 +
11866 +Creators:
11867 + Daniel Cowgill
11868 + George Schlossnagle
11869 +
11870 +PHP5 support and major features by:
11871 + Arun C. Murthy
11872 + Gopal Vijayaraghavan
11873 + Rasmus Lerdorf
11874 +
11875 +This software was contributed to PHP by Community Connect Inc. in 2002
11876 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11877 +Future revisions and derivatives of this source code must acknowledge
11878 +Community Connect Inc. as the original contributor of this module by
11879 +leaving this note intact in the source code.
11880 +
11881 +All other licensing and usage conditions are those of the PHP Group.
11882 +
11883 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting
11884 +this project and providing a challenging and stimulating environment in
11885 +which exciting projects can happen.
11886 +
11887 +Contributors:
11888 + Mike Bretz bug fixes, GUI, and lots of work
11889 + Ricardo Galli changed read-write locks to prefer readers
11890 + Yann Grossel bug fixes
11891 + Thies Arntzen bug fixes
11892 + Sara Golemon optimizer work
11893 +
11894 +Special Thanks:
11895 + Florian Baumert help debugging phplib problems
11896 + Thomas Duffey help debugging inheritance issues
11897 + Vibol Hou help debugging phplib problems
11898 + Angel Li diffs for ANSI comment compliance
11899 + Christian Rishøj help debugging phplib problems
11900 + Sascha Schumann memory error bug fix
11901 diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
11902 --- php-5.2.5-orig/ext/apc/package.xml 1969-12-31 18:00:00.000000000 -0600
11903 +++ php-5.2.5/ext/apc/package.xml 2007-12-26 16:51:32.000000000 -0600
11904 @@ -0,0 +1,534 @@
11905 +<?xml version="1.0" encoding="UTF-8"?>
11906 +<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
11907 + <name>APC</name>
11908 + <channel>pecl.php.net</channel>
11909 + <summary>Alternative PHP Cache</summary>
11910 + <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
11911 + <lead>
11912 + <name>Daniel Cowgill</name>
11913 + <user>dcowgill</user>
11914 + <email>dan@mail.communityconnect.com</email>
11915 + <active>no</active>
11916 + </lead>
11917 + <lead>
11918 + <name>George Schlossnagle</name>
11919 + <user>gschlossnagle</user>
11920 + <email>george@omniti.com</email>
11921 + <active>no</active>
11922 + </lead>
11923 + <lead>
11924 + <name>Rasmus Lerdorf</name>
11925 + <user>rasmus</user>
11926 + <email>rasmus@php.net</email>
11927 + <active>yes</active>
11928 + </lead>
11929 + <lead>
11930 + <name>Gopal Vijayaraghavan</name>
11931 + <user>gopalv</user>
11932 + <email>gopalv@php.net</email>
11933 + <active>yes</active>
11934 + </lead>
11935 + <developer>
11936 + <name>Edin Kadribasic</name>
11937 + <user>edink</user>
11938 + <email>edink@emini.dk</email>
11939 + <active>yes</active>
11940 + </developer>
11941 + <developer>
11942 + <name>Ilia Alshanetsky</name>
11943 + <user>iliaa</user>
11944 + <email>ilia@prohost.org</email>
11945 + <active>yes</active>
11946 + </developer>
11947 + <developer>
11948 + <name>Marcus Börger</name>
11949 + <user>helly</user>
11950 + <email>helly@php.net</email>
11951 + <active>yes</active>
11952 + </developer>
11953 + <developer>
11954 + <name>Sara Golemon</name>
11955 + <user>pollita</user>
11956 + <email>pollita@php.net</email>
11957 + <active>yes</active>
11958 + </developer>
11959 + <developer>
11960 + <name>Brian Shire</name>
11961 + <user>shire</user>
11962 + <email>shire@php.net</email>
11963 + <active>yes</active>
11964 + </developer>
11965 + <date>2007-12-26</date>
11966 + <time>14:51:32</time>
11967 + <version>
11968 + <release>3.0.16</release>
11969 + <api>3.0.0</api>
11970 + </version>
11971 + <stability>
11972 + <release>stable</release>
11973 + <api>stable</api>
11974 + </stability>
11975 + <license uri="http://www.php.net/license">PHP License</license>
11976 + <notes>* Fix for longstanding cache-full crash (Christian Seiler)
11977 + http://news.php.net/php.pecl.dev/4951 for the details
11978 +* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
11979 +* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
11980 +* Minor cleanups (Lucas Nealan)
11981 +* Added configure option to enable apc_cache_info(&apos;filehits&apos;) (Shire)</notes>
11982 + <contents>
11983 + <dir name="/">
11984 + <file md5sum="841596cff3b9bd83e79d01ccb591ff55" name="tests/apc_001.phpt" role="test" />
11985 + <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
11986 + <file md5sum="411fdc85b170ec696298d38f93132d6b" name="tests/apc_003.phpt" role="test" />
11987 + <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
11988 + <file md5sum="2a2e8b29dba8df697dbd81b306ccbe73" name="arch/i386/atomic.h" role="src" />
11989 + <file md5sum="7f01c5cd3a1742c20d6d285f119596a6" name="arch/x86_64/atomic.h" role="src" />
11990 + <file md5sum="26748a0d6567c5611408eb69fb25c671" name="arch/atomic.h" role="src" />
11991 + <file md5sum="0714a0039d9ea63cfc26043a7d86f04c" name="CHANGELOG" role="doc" />
11992 + <file md5sum="3b6ad608e37fb34b24afb90084b4770b" name="INSTALL" role="doc" />
11993 + <file md5sum="694f49a7e1f276ba75a3dd2c5acd580d" name="LICENSE" role="doc" />
11994 + <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
11995 + <file md5sum="efa40416571fc54aa59912203c0391e6" name="TODO" role="doc" />
11996 + <file md5sum="b7dd14328e218d3ecc97d85fb83d7ba7" name="TECHNOTES.txt" role="doc" />
11997 + <file md5sum="c4384f370db6a6112d6c21268bc9a278" name="apc.c" role="src" />
11998 + <file md5sum="09a525ff9a3850e6de42eee2adf07463" name="apc.dsp" role="src" />
11999 + <file md5sum="109694ee417962096eb3e962d6bcce8a" name="apc.h" role="src" />
12000 + <file md5sum="ee19b49ef26dbd491b846a19f9bc9e6a" name="apc_cache.c" role="src" />
12001 + <file md5sum="e0a4f0c5a49a0beba10f2f831e1b63b6" name="apc_cache.h" role="src" />
12002 + <file md5sum="7576310688084dd737f7c7bc11c75e22" name="apc_compile.c" role="src" />
12003 + <file md5sum="a0eea1abcf4ec395ea9a195e98c2cc65" name="apc_compile.h" role="src" />
12004 + <file md5sum="64bbe1f8cf18261255ef5874039e76e9" name="apc_debug.c" role="src" />
12005 + <file md5sum="46d182a6122f3c29a1904f62af7cfb51" name="apc_debug.h" role="src" />
12006 + <file md5sum="3dbdb44d0fc2d45ae15719b4fc5746cd" name="apc_fcntl.c" role="src" />
12007 + <file md5sum="f4fc86769ce871d42ce0085fa7323d79" name="apc_fcntl.h" role="src" />
12008 + <file md5sum="9dffe726c9b6cfdd640e07782a0f409b" name="apc_futex.c" role="src" />
12009 + <file md5sum="ff999238a10bfb6b715e4e8f54ec8326" name="apc_futex.h" role="src" />
12010 + <file md5sum="33d241202d41095bc1b6fdafc1063cb9" name="apc_globals.h" role="src" />
12011 + <file md5sum="3e6f98c635b18902aab221f29d8b70ec" name="apc_lock.h" role="src" />
12012 + <file md5sum="0667187c715fea98569b51a491fb445b" name="apc_main.c" role="src" />
12013 + <file md5sum="2e8f99d31b4d088eb14859c6e137544a" name="apc_main.h" role="src" />
12014 + <file md5sum="e9e447ef3994b85d064c9a49f7ed0917" name="apc_mmap.c" role="src" />
12015 + <file md5sum="a22df1256e20fef8160bbf9529723b50" name="apc_php.h" role="src" />
12016 + <file md5sum="c285337c2e0b852de9f79ac5015a3fa7" name="apc_pthreadmutex.c" role="src" />
12017 + <file md5sum="e4e6943b0cfb31facd1148c2dbfc4c93" name="apc_pthreadmutex.h" role="src" />
12018 + <file md5sum="ea3822772adb45e0046faef855c32aba" name="apc_sem.c" role="src" />
12019 + <file md5sum="1a7fb689f8d5b01fad537b277c81d59f" name="apc_sem.h" role="src" />
12020 + <file md5sum="632e60d387e5555f4aa03a8948f52ea7" name="apc_shm.c" role="src" />
12021 + <file md5sum="6de8e94976f01b2f48ef97020a008774" name="apc_shm.h" role="src" />
12022 + <file md5sum="25d3e2a3d1c2f9afa8e103492ca7e89e" name="apc_sma.c" role="src" />
12023 + <file md5sum="fdc0aebc501f2e29389611fa61084da0" name="apc_sma.h" role="src" />
12024 + <file md5sum="ecd6cc1d56d99dbb7364d40c975fca5e" name="apc_spin.c" role="src" />
12025 + <file md5sum="c716852258453471a6927f95a617e30f" name="apc_spin.h" role="src" />
12026 + <file md5sum="17cceda297a61a9185bcafd7d897fad4" name="apc_stack.c" role="src" />
12027 + <file md5sum="db2f213a3e616313d7864222874197ea" name="apc_stack.h" role="src" />
12028 + <file md5sum="8cccb8ecfa2d5a893537b2c1a8b6b718" name="apc_zend.c" role="src" />
12029 + <file md5sum="2ee61624ec5d779d02746ba7254aed14" name="apc_zend.h" role="src" />
12030 + <file md5sum="113d74a5e70119a63fb86815bf50d03b" name="apc_signal.c" role="src" />
12031 + <file md5sum="af4c7d0595ce32346f7ee37707d7dada" name="apc_signal.h" role="src" />
12032 + <file md5sum="5cbb3cbe6477799e7e5fd816eda69937" name="config.m4" role="src" />
12033 + <file md5sum="b748744f64eb4fbe201cce84cc3d7e33" name="php_apc.c" role="src" />
12034 + <file md5sum="8c092033ef0cd8a5d207acb4f6ecec11" name="php_apc.h" role="src" />
12035 + <file md5sum="76fe025ee14897783cee848dc1a77fa6" name="pgsql_s_lock.c" role="src" />
12036 + <file md5sum="b67725b96ecf0e6851eccce632bab289" name="pgsql_s_lock.h" role="src" />
12037 + <file md5sum="298e1c6721b21635ef46094c6a175af5" name="apc_fcntl_win32.c" role="src" />
12038 + <file md5sum="072c127617c90a92331372a3b99494d3" name="apc_rfc1867.c" role="src" />
12039 + <file md5sum="41fb805e7a151dc6edfe78780b5102d0" name="apc.php" role="php" />
12040 + </dir>
12041 + </contents>
12042 + <dependencies>
12043 + <required>
12044 + <php>
12045 + <min>4.3.0</min>
12046 + <exclude>5.0.0</exclude>
12047 + <exclude>5.0.1</exclude>
12048 + <exclude>5.0.2</exclude>
12049 + <exclude>5.0.3</exclude>
12050 + <exclude>5.0.4</exclude>
12051 + <exclude>5.0.5</exclude>
12052 + </php>
12053 + <pearinstaller>
12054 + <min>1.4.0</min>
12055 + </pearinstaller>
12056 + </required>
12057 + </dependencies>
12058 + <providesextension>apc</providesextension>
12059 + <extsrcrelease>
12060 + <configureoption default="yes" name="with-apxs" prompt="Use apxs to set compile flags (if using APC with Apache)?" />
12061 + </extsrcrelease>
12062 + <changelog>
12063 + <release>
12064 + <stability>
12065 + <release>stable</release>
12066 + <api>stable</api>
12067 + </stability>
12068 + <version>
12069 + <release>2.0.0</release>
12070 + <api>2.0.0</api>
12071 + </version>
12072 + <date>2003-07-01</date>
12073 + <notes>Complete rework.</notes>
12074 + </release>
12075 + <release>
12076 + <stability>
12077 + <release>stable</release>
12078 + <api>stable</api>
12079 + </stability>
12080 + <version>
12081 + <release>2.0.1</release>
12082 + <api>2.0.0</api>
12083 + </version>
12084 + <date>2003-07-01</date>
12085 + <notes>Win32 support added.</notes>
12086 + </release>
12087 + <release>
12088 + <stability>
12089 + <release>stable</release>
12090 + <api>stable</api>
12091 + </stability>
12092 + <version>
12093 + <release>2.0.2</release>
12094 + <api>2.0.0</api>
12095 + </version>
12096 + <date>2004-03-12</date>
12097 + <notes>Fixed non-existant class bug.</notes>
12098 + </release>
12099 + <release>
12100 + <stability>
12101 + <release>stable</release>
12102 + <api>stable</api>
12103 + </stability>
12104 + <version>
12105 + <release>3.0.0</release>
12106 + <api>3.0.0</api>
12107 + </version>
12108 + <date>2005-07-05</date>
12109 + <notes>PHP-5.1 Support and numerous fixes</notes>
12110 + </release>
12111 + <release>
12112 + <stability>
12113 + <release>stable</release>
12114 + <api>stable</api>
12115 + </stability>
12116 + <version>
12117 + <release>3.0.1</release>
12118 + <api>3.0.0</api>
12119 + </version>
12120 + <date>2005-07-05</date>
12121 + <notes>PHP4 build fix</notes>
12122 + </release>
12123 + <release>
12124 + <stability>
12125 + <release>stable</release>
12126 + <api>stable</api>
12127 + </stability>
12128 + <version>
12129 + <release>3.0.2</release>
12130 + <api>3.0.0</api>
12131 + </version>
12132 + <date>2005-07-05</date>
12133 + <notes>Default to mmap and add a better error message for shmget failures</notes>
12134 + </release>
12135 + <release>
12136 + <stability>
12137 + <release>stable</release>
12138 + <api>stable</api>
12139 + </stability>
12140 + <version>
12141 + <release>3.0.3</release>
12142 + <api>3.0.0</api>
12143 + </version>
12144 + <date>2005-07-07</date>
12145 + <notes>Fix compile problem against PHP 5.0.x</notes>
12146 + </release>
12147 + <release>
12148 + <stability>
12149 + <release>stable</release>
12150 + <api>stable</api>
12151 + </stability>
12152 + <version>
12153 + <release>3.0.4</release>
12154 + <api>3.0.0</api>
12155 + </version>
12156 + <date>2005-07-18</date>
12157 + <notes>Add win32 support from Edin.
12158 +Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches
12159 +A couple of other minor fixes.</notes>
12160 + </release>
12161 + <release>
12162 + <stability>
12163 + <release>stable</release>
12164 + <api>stable</api>
12165 + </stability>
12166 + <version>
12167 + <release>3.0.5</release>
12168 + <api>3.0.0</api>
12169 + </version>
12170 + <date>2005-07-27</date>
12171 + <notes>Make it easier for sapis that only populate file_handle-&gt;filename to use APC. (Rasmus)
12172 +Support extensions such as bcompiler that need to hook into compile_file. (Val)
12173 +Ralf Becker&apos;s apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
12174 +Segfault in cache cleanup code (Ilia, Rasmus)</notes>
12175 + </release>
12176 + <release>
12177 + <stability>
12178 + <release>stable</release>
12179 + <api>stable</api>
12180 + </stability>
12181 + <version>
12182 + <release>3.0.6</release>
12183 + <api>3.0.0</api>
12184 + </version>
12185 + <date>2005-07-30</date>
12186 + <notes>Added apc.php to package.xml file.
12187 +Track per-entry memory usage. (Val)
12188 +Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
12189 +fcntl locking robustness fixes. (Rasmus)
12190 +Shared read-locks where possible. (Rasmus)
12191 +Added file_update_protection configuration parameter. (Rasmus)
12192 +Windows ZTS fixes (Frank)</notes>
12193 + </release>
12194 + <release>
12195 + <stability>
12196 + <release>stable</release>
12197 + <api>stable</api>
12198 + </stability>
12199 + <version>
12200 + <release>3.0.7</release>
12201 + <api>3.0.0</api>
12202 + </version>
12203 + <date>2005-08-16</date>
12204 + <notes>Fix to apc.php to show final segment in frag chart. (Ilia)
12205 +A couple of win32 fixes. (Frank)
12206 +Add apc.enable_cli ini directive. (Rasmus)
12207 +Add test cases. (Marcus)
12208 +Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
12209 +Simplify user cache handling by removing the user_cache_stack (Rasmus)
12210 +Fix apc_fetch() memory corruption (Andrei,Rasmus)
12211 +Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)</notes>
12212 + </release>
12213 + <release>
12214 + <stability>
12215 + <release>stable</release>
12216 + <api>stable</api>
12217 + </stability>
12218 + <version>
12219 + <release>3.0.8</release>
12220 + <api>3.0.0</api>
12221 + </version>
12222 + <date>2005-08-24</date>
12223 + <notes>Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
12224 +Cache corruption fix in cache-full cleanup code (Gopal)</notes>
12225 + </release>
12226 + <release>
12227 + <stability>
12228 + <release>stable</release>
12229 + <api>stable</api>
12230 + </stability>
12231 + <version>
12232 + <release>3.0.9</release>
12233 + <api>3.0.0</api>
12234 + </version>
12235 + <date>2006-03-04</date>
12236 + <notes>Eliminate rand() call when slam_defense is not set (Rasmus)
12237 +Fix for __isset problem (Gopal)
12238 +Rewrite allocator from a &quot;best fit&quot; to a &quot;next fit&quot; algorithm (Rasmus)
12239 +Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
12240 +Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
12241 +Add cache busy flag which is set when an expunge is underway (Rasmus)
12242 +Add automatic serialization of objects in apc_store() (Marcus)
12243 +64-bit .ini flag fix (Rasmus)
12244 +Static members fix (Gopal)
12245 +sma_cleanup() mem leak fix (Rasmus)
12246 +Fix for http://pecl.php.net/bugs/5311 (Rasmus)
12247 +Fix autoglobals JIT bug (Gopal)
12248 +Fix instance bug (Gopal)
12249 +Add a lock cleanup safety net to request shutdown (Rasmus)
12250 +Fix apc.slam_defense edge-case bug (Rasmus)
12251 +User entry memory usage tracking support (Ilia)
12252 +Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)</notes>
12253 + </release>
12254 + <release>
12255 + <stability>
12256 + <release>stable</release>
12257 + <api>stable</api>
12258 + </stability>
12259 + <version>
12260 + <release>3.0.10</release>
12261 + <api>3.0.0</api>
12262 + </version>
12263 + <date>2006-03-11</date>
12264 + <notes>* Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
12265 + includes will not be stat&apos;ed for any changes. You will have to restart the server if you
12266 + change anything. This mode increases performance quite a bit, especially if you have a
12267 + lot of includes.
12268 +
12269 +* Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
12270 + than it solves. I&apos;ll need to revisit locking and signal handling at some point soon.</notes>
12271 + </release>
12272 + <release>
12273 + <stability>
12274 + <release>stable</release>
12275 + <api>stable</api>
12276 + </stability>
12277 + <version>
12278 + <release>3.0.11</release>
12279 + <api>3.0.0</api>
12280 + </version>
12281 + <date>2006-08-16</date>
12282 + <notes>* Made --enable-apc-mmap the default compile option (for real this time)
12283 +
12284 +* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
12285 + only fetch header information to make it useful when you have tens of
12286 + thousands of entries. (Brian Shire)
12287 +
12288 +* 64-bit fixes (George)
12289 +
12290 +* Don&apos;t mix Full Path and Inode keys (George)
12291 +
12292 +* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
12293 + require_once() and include_once() statements. (Sara)
12294 +
12295 +* Add a non-blocking write_lock for cache inserts. This is a better approach
12296 + to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
12297 +
12298 +* A bit of work on the optimizer. (Sara)
12299 +
12300 +* Various memory issues resolved. (Gopal)</notes>
12301 + </release>
12302 + <release>
12303 + <stability>
12304 + <release>stable</release>
12305 + <api>stable</api>
12306 + </stability>
12307 + <version>
12308 + <release>3.0.12</release>
12309 + <api>3.0.0</api>
12310 + </version>
12311 + <date>2006-09-04</date>
12312 + <notes>* Fix stray debug message
12313 +
12314 +* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
12315 +
12316 +* Performance boost - Replace multiple loops over the opcode
12317 + array with a single loop for copying, jump fixups and auto
12318 + global pre-fetches. (Gopal)
12319 +
12320 +* Perform fetch_global checks only in php5 and only if
12321 + auto_globals_jit is enabled. (Gopal)
12322 +
12323 +* Fix bug #8579 - scrub php4 classes&apos; function_table and default
12324 + properties before inserting into cache. (Gopal)
12325 +
12326 +* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a
12327 + op1-&gt;type. The opcodes applicable are ZEND_FETCH_R and
12328 + ZEND_FETCH_W. (Gopal)
12329 +
12330 +* PHP 5.2 Compatibility (Gopal)
12331 +
12332 +* Make the include_once override optional - default off (Sara)
12333 +
12334 +* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
12335 +
12336 +* Ensure that the apc_globals-&gt;cache_stack is cleared before the
12337 + shm cache is destroyed. Fixes segfault for corner-case i.e request
12338 + shutdown (apc_deactivate) is not called before module shutdown
12339 + calls (php_apc_shutdown_globals) (Gopal)
12340 +
12341 +* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
12342 +
12343 +* Fix memory leak of apc_cache_info_t-&gt;deleted_list (Gopal)</notes>
12344 + </release>
12345 + <release>
12346 + <stability>
12347 + <release>stable</release>
12348 + <api>stable</api>
12349 + </stability>
12350 + <version>
12351 + <release>3.0.12p1</release>
12352 + <api>3.0.0</api>
12353 + </version>
12354 + <date>2006-09-05</date>
12355 + <notes>* The only change here is a trivial PHP 4 build fix.</notes>
12356 + </release>
12357 + <release>
12358 + <stability>
12359 + <release>stable</release>
12360 + <api>stable</api>
12361 + </stability>
12362 + <version>
12363 + <release>3.0.12p2</release>
12364 + <api>3.0.0</api>
12365 + </version>
12366 + <date>2006-09-05</date>
12367 + <notes>* Let&apos;s get the version number right. 3.0.12p2 now.</notes>
12368 + </release>
12369 + <release>
12370 + <stability>
12371 + <release>stable</release>
12372 + <api>stable</api>
12373 + </stability>
12374 + <version>
12375 + <release>3.0.13</release>
12376 + <api>3.0.0</api>
12377 + </version>
12378 + <date>2007-02-24</date>
12379 + <notes>* PHP 5.2 file upload progress tracking support (Rasmus)
12380 +* Pthread mutex and spin locks (Shire)
12381 +* Recursive zval support for apc_fetch/_store (Shire, Gopal)
12382 +* apc.stat_ctime flag for ctime checks (Rasmus)
12383 +* Multiple key fetches with apc_fetch (Shire)
12384 +* Canary checks for shm memory deallocation (Gopal)
12385 +* Add hooks for external optimizer (Shire)
12386 +* Obsolete and remove apc optimizer (Gopal)
12387 +* APC info changes - cache insert rate, hit and miss rates (Shire)
12388 +* Fix apc_load_constants (Gopal)
12389 +* Rewrite dump opcode code to use vld (Gopal)
12390 +* Use apc_[ewn]print functions for error reporting (Shire)
12391 +* Auto global fixes and refactoring (Gopal, Shire)
12392 +* Fix memory leaks in object serialization (Ilia)
12393 +* Memory cleanup code for destructor order (Gopal)
12394 +* Win32 build fixes (Ilia, Wez)
12395 +* ZTS and Php 4 build fixes (Bjori)
12396 +* Add apc_add() function (Rasmus)
12397 +* Add optional limited flag to apc_sma_info() (Rasmus)</notes>
12398 + </release>
12399 + <release>
12400 + <stability>
12401 + <release>stable</release>
12402 + <api>stable</api>
12403 + </stability>
12404 + <version>
12405 + <release>3.0.14</release>
12406 + <api>3.0.0</api>
12407 + </version>
12408 + <date>2007-04-02</date>
12409 + <notes>* Build fix (Shire)
12410 +* Don&apos;t hook the upload hook if APC is disabled (Rasmus)
12411 +* Local shadow cache support (Gopal)
12412 +* Avoid uneccessary loops over op_arrays for &quot;known&quot; auto-globals (Gopal)
12413 +* Fix apc_add() to overwrite timed out user entries (Rasmus)
12414 +* Fix double inclusion of files with conditional classes in php4 (Gopal)
12415 +* Allocator fixes to reduce fragmentation (Gopal)</notes>
12416 + </release>
12417 + <release>
12418 + <stability>
12419 + <release>stable</release>
12420 + <api>stable</api>
12421 + </stability>
12422 + <version>
12423 + <release>3.0.15</release>
12424 + <api>3.0.0</api>
12425 + </version>
12426 + <date>2007-10-18</date>
12427 + <notes>* Eliminate a per-request time() syscall (Rasmus)
12428 +* Added rfc1867 prefix, name, and freq ini options (Shire)
12429 +* Allow deletion of individual user cache entries via apc.php (Sara)
12430 +* Fix overzealous cleanup during RSHUTDOWN (Gopal)
12431 +* Fix memory alignment and locking issues (Gopal)
12432 +* Make apc_compile insert/replace entries (Shire)
12433 +* Make mixed inheritance recompile &amp; cache afresh (Gopal)
12434 +* Make nostat mode search include_path for canonicalization (Gopal)
12435 +* ZTS &amp; other compile fixes (Gopal, Edin, Shire)</notes>
12436 + </release>
12437 + </changelog>
12438 +</package>
12439 diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.c php-5.2.5/ext/apc/pgsql_s_lock.c
12440 --- php-5.2.5-orig/ext/apc/pgsql_s_lock.c 1969-12-31 18:00:00.000000000 -0600
12441 +++ php-5.2.5/ext/apc/pgsql_s_lock.c 2007-12-26 16:51:32.000000000 -0600
12442 @@ -0,0 +1,481 @@
12443 +/*
12444 + +----------------------------------------------------------------------+
12445 + | APC |
12446 + +----------------------------------------------------------------------+
12447 + | Copyright (c) 2007 The PHP Group |
12448 + +----------------------------------------------------------------------+
12449 + | This source file is subject to version 3.01 of the PHP license, |
12450 + | that is bundled with this package in the file LICENSE, and is |
12451 + | available through the world-wide-web at the following url: |
12452 + | http://www.php.net/license/3_01.txt |
12453 + | If you did not receive a copy of the PHP license and are unable to |
12454 + | obtain it through the world-wide-web, please send a note to |
12455 + | license@php.net so we can mail you a copy immediately. |
12456 + +----------------------------------------------------------------------+
12457 + | The following code was ported from the PostgreSQL project, please |
12458 + | see appropriate copyright notices that follow. |
12459 + | Initial conversion by Brian Shire <shire@php.net> |
12460 + +----------------------------------------------------------------------+
12461 +
12462 + */
12463 +
12464 +/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
12465 +
12466 +/*-------------------------------------------------------------------------
12467 + *
12468 + * s_lock.c
12469 + * Hardware-dependent implementation of spinlocks.
12470 + *
12471 + *
12472 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
12473 + * Portions Copyright (c) 1994, Regents of the University of California
12474 + *
12475 + *
12476 + * IDENTIFICATION
12477 + * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
12478 + *
12479 + *-------------------------------------------------------------------------
12480 + */
12481 +/* #include "postgres.h" -- Removed for APC */
12482 +
12483 +/* -- Added for APC -- */
12484 +#include "apc.h"
12485 +#ifdef APC_SPIN_LOCKS
12486 +
12487 +#ifdef S_LOCK_TEST
12488 +#include <stdio.h>
12489 +#endif
12490 +#ifndef WIN32
12491 +#include <sys/select.h>
12492 +#endif
12493 +/* ---- */
12494 +
12495 +#include <time.h>
12496 +#include <unistd.h>
12497 +
12498 +/* #include "storage/s_lock.h" -- Removed for APC */
12499 +#include "pgsql_s_lock.h"
12500 +
12501 +static int spins_per_delay = DEFAULT_SPINS_PER_DELAY;
12502 +
12503 +
12504 +/* -- APC specific additions ------------------------------*/
12505 +/* The following dependencies have been copied from
12506 + * other pgsql source files. The original locations
12507 + * have been noted.
12508 + */
12509 +
12510 +/* -- from include/c.h -- */
12511 +#ifndef TRUE
12512 +#define TRUE 1
12513 +#endif
12514 +
12515 +#ifndef FALSE
12516 +#define FALSE 0
12517 +#endif
12518 +
12519 +/* -- from include/pg_config_manual.h -- */
12520 +#define MAX_RANDOM_VALUE (0x7FFFFFFF)
12521 +
12522 +/*
12523 + * Max
12524 + * Return the maximum of two numbers.
12525 + */
12526 +#define Max(x, y) ((x) > (y) ? (x) : (y))
12527 +
12528 +/* -- from include/c.h -- */
12529 +/*
12530 + * Min
12531 + * Return the minimum of two numbers.
12532 + */
12533 +#define Min(x, y) ((x) < (y) ? (x) : (y))
12534 +
12535 +
12536 +/* -- from backend/port/win32/signal.c -- */
12537 +/*
12538 + * pg_usleep --- delay the specified number of microseconds.
12539 + *
12540 + * NOTE: although the delay is specified in microseconds, the effective
12541 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
12542 + * the requested delay to be rounded up to the next resolution boundary.
12543 + *
12544 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
12545 + */
12546 +void
12547 +pg_usleep(long microsec)
12548 +{
12549 + if (microsec > 0)
12550 + {
12551 +#ifndef WIN32
12552 + struct timeval delay;
12553 +
12554 + delay.tv_sec = microsec / 1000000L;
12555 + delay.tv_usec = microsec % 1000000L;
12556 + (void) select(0, NULL, NULL, NULL, &delay);
12557 +#else
12558 + SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
12559 +#endif
12560 + }
12561 +}
12562 +
12563 +/* -- End APC specific additions ------------------------------*/
12564 +
12565 +
12566 +/*
12567 + * s_lock_stuck() - complain about a stuck spinlock
12568 + */
12569 +static void
12570 +s_lock_stuck(volatile slock_t *lock, const char *file, int line)
12571 +{
12572 +#if defined(S_LOCK_TEST)
12573 + fprintf(stderr,
12574 + "\nStuck spinlock (%p) detected at %s:%d.\n",
12575 + lock, file, line);
12576 + exit(1);
12577 +#else
12578 + /* -- Removed for APC
12579 + elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
12580 + lock, file, line);
12581 + */
12582 + apc_eprint("Stuck spinlock (%p) detected", lock);
12583 +#endif
12584 +}
12585 +
12586 +
12587 +/*
12588 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
12589 + */
12590 +void
12591 +s_lock(volatile slock_t *lock, const char *file, int line)
12592 +{
12593 + /*
12594 + * We loop tightly for awhile, then delay using pg_usleep() and try again.
12595 + * Preferably, "awhile" should be a small multiple of the maximum time we
12596 + * expect a spinlock to be held. 100 iterations seems about right as an
12597 + * initial guess. However, on a uniprocessor the loop is a waste of
12598 + * cycles, while in a multi-CPU scenario it's usually better to spin a bit
12599 + * longer than to call the kernel, so we try to adapt the spin loop count
12600 + * depending on whether we seem to be in a uniprocessor or multiprocessor.
12601 + *
12602 + * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
12603 + * be wrong; there are platforms where that can result in a "stuck
12604 + * spinlock" failure. This has been seen particularly on Alphas; it seems
12605 + * that the first TAS after returning from kernel space will always fail
12606 + * on that hardware.
12607 + *
12608 + * Once we do decide to block, we use randomly increasing pg_usleep()
12609 + * delays. The first delay is 1 msec, then the delay randomly increases to
12610 + * about one second, after which we reset to 1 msec and start again. The
12611 + * idea here is that in the presence of heavy contention we need to
12612 + * increase the delay, else the spinlock holder may never get to run and
12613 + * release the lock. (Consider situation where spinlock holder has been
12614 + * nice'd down in priority by the scheduler --- it will not get scheduled
12615 + * until all would-be acquirers are sleeping, so if we always use a 1-msec
12616 + * sleep, there is a real possibility of starvation.) But we can't just
12617 + * clamp the delay to an upper bound, else it would take a long time to
12618 + * make a reasonable number of tries.
12619 + *
12620 + * We time out and declare error after NUM_DELAYS delays (thus, exactly
12621 + * that many tries). With the given settings, this will usually take 2 or
12622 + * so minutes. It seems better to fix the total number of tries (and thus
12623 + * the probability of unintended failure) than to fix the total time
12624 + * spent.
12625 + *
12626 + * The pg_usleep() delays are measured in milliseconds because 1 msec is a
12627 + * common resolution limit at the OS level for newer platforms. On older
12628 + * platforms the resolution limit is usually 10 msec, in which case the
12629 + * total delay before timeout will be a bit more.
12630 + */
12631 +#define MIN_SPINS_PER_DELAY 10
12632 +#define MAX_SPINS_PER_DELAY 1000
12633 +#define NUM_DELAYS 1000
12634 +#define MIN_DELAY_MSEC 1
12635 +#define MAX_DELAY_MSEC 1000
12636 +
12637 + int spins = 0;
12638 + int delays = 0;
12639 + int cur_delay = 0;
12640 +
12641 + while (TAS(lock))
12642 + {
12643 + /* CPU-specific delay each time through the loop */
12644 + SPIN_DELAY();
12645 +
12646 + /* Block the process every spins_per_delay tries */
12647 + if (++spins >= spins_per_delay)
12648 + {
12649 + if (++delays > NUM_DELAYS)
12650 + s_lock_stuck(lock, file, line);
12651 +
12652 + if (cur_delay == 0) /* first time to delay? */
12653 + cur_delay = MIN_DELAY_MSEC;
12654 +
12655 + pg_usleep(cur_delay * 1000L);
12656 +
12657 +#if defined(S_LOCK_TEST)
12658 + fprintf(stdout, "*");
12659 + fflush(stdout);
12660 +#endif
12661 +
12662 + /* increase delay by a random fraction between 1X and 2X */
12663 + cur_delay += (int) (cur_delay *
12664 + ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
12665 + /* wrap back to minimum delay when max is exceeded */
12666 + if (cur_delay > MAX_DELAY_MSEC)
12667 + cur_delay = MIN_DELAY_MSEC;
12668 +
12669 + spins = 0;
12670 + }
12671 + }
12672 +
12673 + /*
12674 + * If we were able to acquire the lock without delaying, it's a good
12675 + * indication we are in a multiprocessor. If we had to delay, it's a sign
12676 + * (but not a sure thing) that we are in a uniprocessor. Hence, we
12677 + * decrement spins_per_delay slowly when we had to delay, and increase it
12678 + * rapidly when we didn't. It's expected that spins_per_delay will
12679 + * converge to the minimum value on a uniprocessor and to the maximum
12680 + * value on a multiprocessor.
12681 + *
12682 + * Note: spins_per_delay is local within our current process. We want to
12683 + * average these observations across multiple backends, since it's
12684 + * relatively rare for this function to even get entered, and so a single
12685 + * backend might not live long enough to converge on a good value. That
12686 + * is handled by the two routines below.
12687 + */
12688 + if (cur_delay == 0)
12689 + {
12690 + /* we never had to delay */
12691 + if (spins_per_delay < MAX_SPINS_PER_DELAY)
12692 + spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
12693 + }
12694 + else
12695 + {
12696 + if (spins_per_delay > MIN_SPINS_PER_DELAY)
12697 + spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
12698 + }
12699 +}
12700 +
12701 +
12702 +#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
12703 +/*
12704 + * Set local copy of spins_per_delay during backend startup.
12705 + *
12706 + * NB: this has to be pretty fast as it is called while holding a spinlock
12707 + */
12708 +void
12709 +set_spins_per_delay(int shared_spins_per_delay)
12710 +{
12711 + spins_per_delay = shared_spins_per_delay;
12712 +}
12713 +
12714 +/*
12715 + * Update shared estimate of spins_per_delay during backend exit.
12716 + *
12717 + * NB: this has to be pretty fast as it is called while holding a spinlock
12718 + */
12719 +int
12720 +update_spins_per_delay(int shared_spins_per_delay)
12721 +{
12722 + /*
12723 + * We use an exponential moving average with a relatively slow adaption
12724 + * rate, so that noise in any one backend's result won't affect the shared
12725 + * value too much. As long as both inputs are within the allowed range,
12726 + * the result must be too, so we need not worry about clamping the result.
12727 + *
12728 + * We deliberately truncate rather than rounding; this is so that single
12729 + * adjustments inside a backend can affect the shared estimate (see the
12730 + * asymmetric adjustment rules above).
12731 + */
12732 + return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
12733 +}
12734 +#endif
12735 +
12736 +/*
12737 + * Various TAS implementations that cannot live in s_lock.h as no inline
12738 + * definition exists (yet).
12739 + * In the future, get rid of tas.[cso] and fold it into this file.
12740 + *
12741 + * If you change something here, you will likely need to modify s_lock.h too,
12742 + * because the definitions for these are split between this file and s_lock.h.
12743 + */
12744 +
12745 +
12746 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
12747 +
12748 +
12749 +#if defined(__GNUC__)
12750 +
12751 +/*
12752 + * All the gcc flavors that are not inlined
12753 + */
12754 +
12755 +
12756 +/*
12757 + * Note: all the if-tests here probably ought to be testing gcc version
12758 + * rather than platform, but I don't have adequate info to know what to
12759 + * write. Ideally we'd flush all this in favor of the inline version.
12760 + */
12761 +#if defined(__m68k__) && !defined(__linux__)
12762 +/* really means: extern int tas(slock_t* **lock); */
12763 +static void
12764 +tas_dummy()
12765 +{
12766 + __asm__ __volatile__(
12767 +#if defined(__NetBSD__) && defined(__ELF__)
12768 +/* no underscore for label and % for registers */
12769 + "\
12770 +.global tas \n\
12771 +tas: \n\
12772 + movel %sp@(0x4),%a0 \n\
12773 + tas %a0@ \n\
12774 + beq _success \n\
12775 + moveq #-128,%d0 \n\
12776 + rts \n\
12777 +_success: \n\
12778 + moveq #0,%d0 \n\
12779 + rts \n"
12780 +#else
12781 + "\
12782 +.global _tas \n\
12783 +_tas: \n\
12784 + movel sp@(0x4),a0 \n\
12785 + tas a0@ \n\
12786 + beq _success \n\
12787 + moveq #-128,d0 \n\
12788 + rts \n\
12789 +_success: \n\
12790 + moveq #0,d0 \n\
12791 + rts \n"
12792 +#endif /* __NetBSD__ && __ELF__ */
12793 + );
12794 +}
12795 +#endif /* __m68k__ && !__linux__ */
12796 +#else /* not __GNUC__ */
12797 +
12798 +/*
12799 + * All non gcc
12800 + */
12801 +
12802 +
12803 +#if defined(sun3)
12804 +static void
12805 +tas_dummy() /* really means: extern int tas(slock_t
12806 + * *lock); */
12807 +{
12808 + asm("LLA0:");
12809 + asm(" .data");
12810 + asm(" .text");
12811 + asm("|#PROC# 04");
12812 + asm(" .globl _tas");
12813 + asm("_tas:");
12814 + asm("|#PROLOGUE# 1");
12815 + asm(" movel sp@(0x4),a0");
12816 + asm(" tas a0@");
12817 + asm(" beq LLA1");
12818 + asm(" moveq #-128,d0");
12819 + asm(" rts");
12820 + asm("LLA1:");
12821 + asm(" moveq #0,d0");
12822 + asm(" rts");
12823 + asm(" .data");
12824 +}
12825 +#endif /* sun3 */
12826 +#endif /* not __GNUC__ */
12827 +#endif /* HAVE_SPINLOCKS */
12828 +
12829 +
12830 +
12831 +/*****************************************************************************/
12832 +#if defined(S_LOCK_TEST)
12833 +
12834 +/*
12835 + * test program for verifying a port's spinlock support.
12836 + */
12837 +
12838 +struct test_lock_struct
12839 +{
12840 + char pad1;
12841 + slock_t lock;
12842 + char pad2;
12843 +};
12844 +
12845 +volatile struct test_lock_struct test_lock;
12846 +
12847 +int
12848 +main()
12849 +{
12850 + srandom((unsigned int) time(NULL));
12851 +
12852 + test_lock.pad1 = test_lock.pad2 = 0x44;
12853 +
12854 + S_INIT_LOCK(&test_lock.lock);
12855 +
12856 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12857 + {
12858 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12859 + return 1;
12860 + }
12861 +
12862 + if (!S_LOCK_FREE(&test_lock.lock))
12863 + {
12864 + printf("S_LOCK_TEST: failed, lock not initialized\n");
12865 + return 1;
12866 + }
12867 +
12868 + S_LOCK(&test_lock.lock);
12869 +
12870 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12871 + {
12872 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12873 + return 1;
12874 + }
12875 +
12876 + if (S_LOCK_FREE(&test_lock.lock))
12877 + {
12878 + printf("S_LOCK_TEST: failed, lock not locked\n");
12879 + return 1;
12880 + }
12881 +
12882 + S_UNLOCK(&test_lock.lock);
12883 +
12884 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12885 + {
12886 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12887 + return 1;
12888 + }
12889 +
12890 + if (!S_LOCK_FREE(&test_lock.lock))
12891 + {
12892 + printf("S_LOCK_TEST: failed, lock not unlocked\n");
12893 + return 1;
12894 + }
12895 +
12896 + S_LOCK(&test_lock.lock);
12897 +
12898 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
12899 + {
12900 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
12901 + return 1;
12902 + }
12903 +
12904 + if (S_LOCK_FREE(&test_lock.lock))
12905 + {
12906 + printf("S_LOCK_TEST: failed, lock not re-locked\n");
12907 + return 1;
12908 + }
12909 +
12910 + printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
12911 + printf(" exit with a 'stuck spinlock' message\n");
12912 + printf(" if S_LOCK() and TAS() are working.\n");
12913 + fflush(stdout);
12914 +
12915 + s_lock(&test_lock.lock, __FILE__, __LINE__);
12916 +
12917 + printf("S_LOCK_TEST: failed, lock not locked\n");
12918 + return 1;
12919 +}
12920 +
12921 +#endif /* S_LOCK_TEST */
12922 +
12923 +#endif /* APC_SPIN_LOCKS */
12924 diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.h php-5.2.5/ext/apc/pgsql_s_lock.h
12925 --- php-5.2.5-orig/ext/apc/pgsql_s_lock.h 1969-12-31 18:00:00.000000000 -0600
12926 +++ php-5.2.5/ext/apc/pgsql_s_lock.h 2007-12-26 16:51:32.000000000 -0600
12927 @@ -0,0 +1,928 @@
12928 +/*
12929 + +----------------------------------------------------------------------+
12930 + | APC |
12931 + +----------------------------------------------------------------------+
12932 + | Copyright (c) 2007 The PHP Group |
12933 + +----------------------------------------------------------------------+
12934 + | This source file is subject to version 3.01 of the PHP license, |
12935 + | that is bundled with this package in the file LICENSE, and is |
12936 + | available through the world-wide-web at the following url: |
12937 + | http://www.php.net/license/3_01.txt |
12938 + | If you did not receive a copy of the PHP license and are unable to |
12939 + | obtain it through the world-wide-web, please send a note to |
12940 + | license@php.net so we can mail you a copy immediately. |
12941 + +----------------------------------------------------------------------+
12942 + | The following code was ported from the PostgreSQL project, please |
12943 + | see appropriate copyright notices that follow. |
12944 + | Initial conversion by Brian Shire <shire@php.net> |
12945 + +----------------------------------------------------------------------+
12946 +
12947 + */
12948 +
12949 +/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
12950 +
12951 +/*-------------------------------------------------------------------------
12952 + *
12953 + * s_lock.h
12954 + * Hardware-dependent implementation of spinlocks.
12955 + *
12956 + * NOTE: none of the macros in this file are intended to be called directly.
12957 + * Call them through the hardware-independent macros in spin.h.
12958 + *
12959 + * The following hardware-dependent macros must be provided for each
12960 + * supported platform:
12961 + *
12962 + * void S_INIT_LOCK(slock_t *lock)
12963 + * Initialize a spinlock (to the unlocked state).
12964 + *
12965 + * void S_LOCK(slock_t *lock)
12966 + * Acquire a spinlock, waiting if necessary.
12967 + * Time out and abort() if unable to acquire the lock in a
12968 + * "reasonable" amount of time --- typically ~ 1 minute.
12969 + *
12970 + * void S_UNLOCK(slock_t *lock)
12971 + * Unlock a previously acquired lock.
12972 + *
12973 + * bool S_LOCK_FREE(slock_t *lock)
12974 + * Tests if the lock is free. Returns TRUE if free, FALSE if locked.
12975 + * This does *not* change the state of the lock.
12976 + *
12977 + * void SPIN_DELAY(void)
12978 + * Delay operation to occur inside spinlock wait loop.
12979 + *
12980 + * Note to implementors: there are default implementations for all these
12981 + * macros at the bottom of the file. Check if your platform can use
12982 + * these or needs to override them.
12983 + *
12984 + * Usually, S_LOCK() is implemented in terms of an even lower-level macro
12985 + * TAS():
12986 + *
12987 + * int TAS(slock_t *lock)
12988 + * Atomic test-and-set instruction. Attempt to acquire the lock,
12989 + * but do *not* wait. Returns 0 if successful, nonzero if unable
12990 + * to acquire the lock.
12991 + *
12992 + * TAS() is NOT part of the API, and should never be called directly.
12993 + *
12994 + * CAUTION: on some platforms TAS() may sometimes report failure to acquire
12995 + * a lock even when the lock is not locked. For example, on Alpha TAS()
12996 + * will "fail" if interrupted. Therefore TAS() should always be invoked
12997 + * in a retry loop, even if you are certain the lock is free.
12998 + *
12999 + * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
13000 + * points, ie, loads and stores of other values must not be moved across
13001 + * a lock or unlock. In most cases it suffices to make the operation be
13002 + * done through a "volatile" pointer.
13003 + *
13004 + * On most supported platforms, TAS() uses a tas() function written
13005 + * in assembly language to execute a hardware atomic-test-and-set
13006 + * instruction. Equivalent OS-supplied mutex routines could be used too.
13007 + *
13008 + * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
13009 + * defined), then we fall back on an emulation that uses SysV semaphores
13010 + * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
13011 + * implementation, because of the cost of a kernel call per lock or unlock.
13012 + * An old report is that Postgres spends around 40% of its time in semop(2)
13013 + * when using the SysV semaphore code.
13014 + *
13015 + *
13016 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
13017 + * Portions Copyright (c) 1994, Regents of the University of California
13018 + *
13019 + * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
13020 + *
13021 + *-------------------------------------------------------------------------
13022 + */
13023 +#ifndef S_LOCK_H
13024 +#define S_LOCK_H
13025 +
13026 +/** APC namespace protection ************************************************/
13027 +/* hack to protect against any possible runtime namespace collisions...*/
13028 +#define pg_usleep apc_spin_pg_usleep
13029 +#define s_lock apc_spin_s_lock
13030 +#define spins_per_delay apc_spin_spins_per_delay
13031 +/****************************************************************************/
13032 +
13033 +
13034 +/* #include "storage/pg_sema.h" -- Removed for APC */
13035 +
13036 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
13037 +
13038 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
13039 +
13040 +
13041 +#if defined(__GNUC__) || defined(__ICC)
13042 +/*************************************************************************
13043 + * All the gcc inlines
13044 + * Gcc consistently defines the CPU as __cpu__.
13045 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
13046 + */
13047 +
13048 +/*----------
13049 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
13050 +
13051 + __asm__ __volatile__(
13052 + " instruction \n"
13053 + " instruction \n"
13054 + " instruction \n"
13055 +: "=r"(_res), "+m"(*lock) // return register, in/out lock value
13056 +: "r"(lock) // lock pointer, in input register
13057 +: "memory", "cc"); // show clobbered registers here
13058 +
13059 + * The output-operands list (after first colon) should always include
13060 + * "+m"(*lock), whether or not the asm code actually refers to this
13061 + * operand directly. This ensures that gcc believes the value in the
13062 + * lock variable is used and set by the asm code. Also, the clobbers
13063 + * list (after third colon) should always include "memory"; this prevents
13064 + * gcc from thinking it can cache the values of shared-memory fields
13065 + * across the asm code. Add "cc" if your asm code changes the condition
13066 + * code register, and also list any temp registers the code uses.
13067 + *----------
13068 + */
13069 +
13070 +
13071 +#ifdef __i386__ /* 32-bit i386 */
13072 +#define HAS_TEST_AND_SET
13073 +
13074 +typedef unsigned char slock_t;
13075 +
13076 +#define TAS(lock) tas(lock)
13077 +
13078 +static __inline__ int
13079 +tas(volatile slock_t *lock)
13080 +{
13081 + register slock_t _res = 1;
13082 +
13083 + /*
13084 + * Use a non-locking test before asserting the bus lock. Note that the
13085 + * extra test appears to be a small loss on some x86 platforms and a small
13086 + * win on others; it's by no means clear that we should keep it.
13087 + */
13088 + __asm__ __volatile__(
13089 + " cmpb $0,%1 \n"
13090 + " jne 1f \n"
13091 + " lock \n"
13092 + " xchgb %0,%1 \n"
13093 + "1: \n"
13094 +: "+q"(_res), "+m"(*lock)
13095 +:
13096 +: "memory", "cc");
13097 + return (int) _res;
13098 +}
13099 +
13100 +#define SPIN_DELAY() spin_delay()
13101 +
13102 +static __inline__ void
13103 +spin_delay(void)
13104 +{
13105 + /*
13106 + * This sequence is equivalent to the PAUSE instruction ("rep" is
13107 + * ignored by old IA32 processors if the following instruction is
13108 + * not a string operation); the IA-32 Architecture Software
13109 + * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
13110 + * PAUSE in the inner loop of a spin lock is necessary for good
13111 + * performance:
13112 + *
13113 + * The PAUSE instruction improves the performance of IA-32
13114 + * processors supporting Hyper-Threading Technology when
13115 + * executing spin-wait loops and other routines where one
13116 + * thread is accessing a shared lock or semaphore in a tight
13117 + * polling loop. When executing a spin-wait loop, the
13118 + * processor can suffer a severe performance penalty when
13119 + * exiting the loop because it detects a possible memory order
13120 + * violation and flushes the core processor's pipeline. The
13121 + * PAUSE instruction provides a hint to the processor that the
13122 + * code sequence is a spin-wait loop. The processor uses this
13123 + * hint to avoid the memory order violation and prevent the
13124 + * pipeline flush. In addition, the PAUSE instruction
13125 + * de-pipelines the spin-wait loop to prevent it from
13126 + * consuming execution resources excessively.
13127 + */
13128 + __asm__ __volatile__(
13129 + " rep; nop \n");
13130 +}
13131 +
13132 +#endif /* __i386__ */
13133 +
13134 +
13135 +#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
13136 +#define HAS_TEST_AND_SET
13137 +
13138 +typedef unsigned char slock_t;
13139 +
13140 +#define TAS(lock) tas(lock)
13141 +
13142 +static __inline__ int
13143 +tas(volatile slock_t *lock)
13144 +{
13145 + register slock_t _res = 1;
13146 +
13147 + /*
13148 + * On Opteron, using a non-locking test before the locking instruction
13149 + * is a huge loss. On EM64T, it appears to be a wash or small loss,
13150 + * so we needn't bother to try to distinguish the sub-architectures.
13151 + */
13152 + __asm__ __volatile__(
13153 + " lock \n"
13154 + " xchgb %0,%1 \n"
13155 +: "+q"(_res), "+m"(*lock)
13156 +:
13157 +: "memory", "cc");
13158 + return (int) _res;
13159 +}
13160 +
13161 +#define SPIN_DELAY() spin_delay()
13162 +
13163 +static __inline__ void
13164 +spin_delay(void)
13165 +{
13166 + /*
13167 + * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
13168 + * Opteron, but it may be of some use on EM64T, so we keep it.
13169 + */
13170 + __asm__ __volatile__(
13171 + " rep; nop \n");
13172 +}
13173 +
13174 +#endif /* __x86_64__ */
13175 +
13176 +
13177 +#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */
13178 +#define HAS_TEST_AND_SET
13179 +
13180 +typedef unsigned int slock_t;
13181 +
13182 +#define TAS(lock) tas(lock)
13183 +
13184 +#ifndef __INTEL_COMPILER
13185 +
13186 +static __inline__ int
13187 +tas(volatile slock_t *lock)
13188 +{
13189 + long int ret;
13190 +
13191 + __asm__ __volatile__(
13192 + " xchg4 %0=%1,%2 \n"
13193 +: "=r"(ret), "+m"(*lock)
13194 +: "r"(1)
13195 +: "memory");
13196 + return (int) ret;
13197 +}
13198 +
13199 +#else /* __INTEL_COMPILER */
13200 +
13201 +static __inline__ int
13202 +tas(volatile slock_t *lock)
13203 +{
13204 + int ret;
13205 +
13206 + ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
13207 +
13208 + return ret;
13209 +}
13210 +
13211 +#endif /* __INTEL_COMPILER */
13212 +#endif /* __ia64__ || __ia64 */
13213 +
13214 +
13215 +#if defined(__arm__) || defined(__arm)
13216 +#define HAS_TEST_AND_SET
13217 +
13218 +typedef unsigned char slock_t;
13219 +
13220 +#define TAS(lock) tas(lock)
13221 +
13222 +static __inline__ int
13223 +tas(volatile slock_t *lock)
13224 +{
13225 + register slock_t _res = 1;
13226 +
13227 + __asm__ __volatile__(
13228 + " swpb %0, %0, [%2] \n"
13229 +: "+r"(_res), "+m"(*lock)
13230 +: "r"(lock)
13231 +: "memory");
13232 + return (int) _res;
13233 +}
13234 +
13235 +#endif /* __arm__ */
13236 +
13237 +
13238 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
13239 +#if defined(__s390__) || defined(__s390x__)
13240 +#define HAS_TEST_AND_SET
13241 +
13242 +typedef unsigned int slock_t;
13243 +
13244 +#define TAS(lock) tas(lock)
13245 +
13246 +static __inline__ int
13247 +tas(volatile slock_t *lock)
13248 +{
13249 + int _res = 0;
13250 +
13251 + __asm__ __volatile__(
13252 + " cs %0,%3,0(%2) \n"
13253 +: "+d"(_res), "+m"(*lock)
13254 +: "a"(lock), "d"(1)
13255 +: "memory", "cc");
13256 + return _res;
13257 +}
13258 +
13259 +#endif /* __s390__ || __s390x__ */
13260 +
13261 +
13262 +#if defined(__sparc__) /* Sparc */
13263 +#define HAS_TEST_AND_SET
13264 +
13265 +typedef unsigned char slock_t;
13266 +
13267 +#define TAS(lock) tas(lock)
13268 +
13269 +static __inline__ int
13270 +tas(volatile slock_t *lock)
13271 +{
13272 + register slock_t _res;
13273 +
13274 + /*
13275 + * See comment in /pg/backend/port/tas/solaris_sparc.s for why this
13276 + * uses "ldstub", and that file uses "cas". gcc currently generates
13277 + * sparcv7-targeted binaries, so "cas" use isn't possible.
13278 + */
13279 + __asm__ __volatile__(
13280 + " ldstub [%2], %0 \n"
13281 +: "=r"(_res), "+m"(*lock)
13282 +: "r"(lock)
13283 +: "memory");
13284 + return (int) _res;
13285 +}
13286 +
13287 +#endif /* __sparc__ */
13288 +
13289 +
13290 +/* PowerPC */
13291 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
13292 +#define HAS_TEST_AND_SET
13293 +
13294 +#if defined(__ppc64__) || defined(__powerpc64__)
13295 +typedef unsigned long slock_t;
13296 +#else
13297 +typedef unsigned int slock_t;
13298 +#endif
13299 +
13300 +#define TAS(lock) tas(lock)
13301 +/*
13302 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
13303 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
13304 + */
13305 +static __inline__ int
13306 +tas(volatile slock_t *lock)
13307 +{
13308 + slock_t _t;
13309 + int _res;
13310 +
13311 + __asm__ __volatile__(
13312 +" lwarx %0,0,%3 \n"
13313 +" cmpwi %0,0 \n"
13314 +" bne 1f \n"
13315 +" addi %0,%0,1 \n"
13316 +" stwcx. %0,0,%3 \n"
13317 +" beq 2f \n"
13318 +"1: li %1,1 \n"
13319 +" b 3f \n"
13320 +"2: \n"
13321 +" isync \n"
13322 +" li %1,0 \n"
13323 +"3: \n"
13324 +
13325 +: "=&r"(_t), "=r"(_res), "+m"(*lock)
13326 +: "r"(lock)
13327 +: "memory", "cc");
13328 + return _res;
13329 +}
13330 +
13331 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
13332 +#define S_UNLOCK(lock) \
13333 +do \
13334 +{ \
13335 + __asm__ __volatile__ (" sync \n"); \
13336 + *((volatile slock_t *) (lock)) = 0; \
13337 +} while (0)
13338 +
13339 +#endif /* powerpc */
13340 +
13341 +
13342 +/* Linux Motorola 68k */
13343 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
13344 +#define HAS_TEST_AND_SET
13345 +
13346 +typedef unsigned char slock_t;
13347 +
13348 +#define TAS(lock) tas(lock)
13349 +
13350 +static __inline__ int
13351 +tas(volatile slock_t *lock)
13352 +{
13353 + register int rv;
13354 +
13355 + __asm__ __volatile__(
13356 + " clrl %0 \n"
13357 + " tas %1 \n"
13358 + " sne %0 \n"
13359 +: "=d"(rv), "+m"(*lock)
13360 +:
13361 +: "memory", "cc");
13362 + return rv;
13363 +}
13364 +
13365 +#endif /* (__mc68000__ || __m68k__) && __linux__ */
13366 +
13367 +
13368 +/*
13369 + * VAXen -- even multiprocessor ones
13370 + * (thanks to Tom Ivar Helbekkmo)
13371 + */
13372 +#if defined(__vax__)
13373 +#define HAS_TEST_AND_SET
13374 +
13375 +typedef unsigned char slock_t;
13376 +
13377 +#define TAS(lock) tas(lock)
13378 +
13379 +static __inline__ int
13380 +tas(volatile slock_t *lock)
13381 +{
13382 + register int _res;
13383 +
13384 + __asm__ __volatile__(
13385 + " movl $1, %0 \n"
13386 + " bbssi $0, (%2), 1f \n"
13387 + " clrl %0 \n"
13388 + "1: \n"
13389 +: "=&r"(_res), "+m"(*lock)
13390 +: "r"(lock)
13391 +: "memory");
13392 + return _res;
13393 +}
13394 +
13395 +#endif /* __vax__ */
13396 +
13397 +
13398 +#if defined(__ns32k__) /* National Semiconductor 32K */
13399 +#define HAS_TEST_AND_SET
13400 +
13401 +typedef unsigned char slock_t;
13402 +
13403 +#define TAS(lock) tas(lock)
13404 +
13405 +static __inline__ int
13406 +tas(volatile slock_t *lock)
13407 +{
13408 + register int _res;
13409 +
13410 + __asm__ __volatile__(
13411 + " sbitb 0, %1 \n"
13412 + " sfsd %0 \n"
13413 +: "=r"(_res), "+m"(*lock)
13414 +:
13415 +: "memory");
13416 + return _res;
13417 +}
13418 +
13419 +#endif /* __ns32k__ */
13420 +
13421 +
13422 +#if defined(__alpha) || defined(__alpha__) /* Alpha */
13423 +/*
13424 + * Correct multi-processor locking methods are explained in section 5.5.3
13425 + * of the Alpha AXP Architecture Handbook, which at this writing can be
13426 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
13427 + * For gcc we implement the handbook's code directly with inline assembler.
13428 + */
13429 +#define HAS_TEST_AND_SET
13430 +
13431 +typedef unsigned long slock_t;
13432 +
13433 +#define TAS(lock) tas(lock)
13434 +
13435 +static __inline__ int
13436 +tas(volatile slock_t *lock)
13437 +{
13438 + register slock_t _res;
13439 +
13440 + __asm__ __volatile__(
13441 + " ldq $0, %1 \n"
13442 + " bne $0, 2f \n"
13443 + " ldq_l %0, %1 \n"
13444 + " bne %0, 2f \n"
13445 + " mov 1, $0 \n"
13446 + " stq_c $0, %1 \n"
13447 + " beq $0, 2f \n"
13448 + " mb \n"
13449 + " br 3f \n"
13450 + "2: mov 1, %0 \n"
13451 + "3: \n"
13452 +: "=&r"(_res), "+m"(*lock)
13453 +:
13454 +: "memory", "0");
13455 + return (int) _res;
13456 +}
13457 +
13458 +#define S_UNLOCK(lock) \
13459 +do \
13460 +{\
13461 + __asm__ __volatile__ (" mb \n"); \
13462 + *((volatile slock_t *) (lock)) = 0; \
13463 +} while (0)
13464 +
13465 +#endif /* __alpha || __alpha__ */
13466 +
13467 +
13468 +#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
13469 +/* Note: on SGI we use the OS' mutex ABI, see below */
13470 +/* Note: R10000 processors require a separate SYNC */
13471 +#define HAS_TEST_AND_SET
13472 +
13473 +typedef unsigned int slock_t;
13474 +
13475 +#define TAS(lock) tas(lock)
13476 +
13477 +static __inline__ int
13478 +tas(volatile slock_t *lock)
13479 +{
13480 + register volatile slock_t *_l = lock;
13481 + register int _res;
13482 + register int _tmp;
13483 +
13484 + __asm__ __volatile__(
13485 + " .set push \n"
13486 + " .set mips2 \n"
13487 + " .set noreorder \n"
13488 + " .set nomacro \n"
13489 + " ll %0, %2 \n"
13490 + " or %1, %0, 1 \n"
13491 + " sc %1, %2 \n"
13492 + " xori %1, 1 \n"
13493 + " or %0, %0, %1 \n"
13494 + " sync \n"
13495 + " .set pop "
13496 +: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
13497 +:
13498 +: "memory");
13499 + return _res;
13500 +}
13501 +
13502 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
13503 +#define S_UNLOCK(lock) \
13504 +do \
13505 +{ \
13506 + __asm__ __volatile__( \
13507 + " .set push \n" \
13508 + " .set mips2 \n" \
13509 + " .set noreorder \n" \
13510 + " .set nomacro \n" \
13511 + " sync \n" \
13512 + " .set pop "); \
13513 + *((volatile slock_t *) (lock)) = 0; \
13514 +} while (0)
13515 +
13516 +#endif /* __mips__ && !__sgi */
13517 +
13518 +
13519 +/* These live in s_lock.c, but only for gcc */
13520 +
13521 +
13522 +#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
13523 +#define HAS_TEST_AND_SET
13524 +
13525 +typedef unsigned char slock_t;
13526 +#endif
13527 +
13528 +
13529 +#endif /* __GNUC__ */
13530 +
13531 +
13532 +
13533 +/*
13534 + * ---------------------------------------------------------------------
13535 + * Platforms that use non-gcc inline assembly:
13536 + * ---------------------------------------------------------------------
13537 + */
13538 +
13539 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
13540 +
13541 +
13542 +#if defined(USE_UNIVEL_CC) /* Unixware compiler */
13543 +#define HAS_TEST_AND_SET
13544 +
13545 +typedef unsigned char slock_t;
13546 +
13547 +#define TAS(lock) tas(lock)
13548 +
13549 +asm int
13550 +tas(volatile slock_t *s_lock)
13551 +{
13552 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
13553 +%mem s_lock
13554 + pushl %ebx
13555 + movl s_lock, %ebx
13556 + movl $255, %eax
13557 + lock
13558 + xchgb %al, (%ebx)
13559 + popl %ebx
13560 +}
13561 +
13562 +#endif /* defined(USE_UNIVEL_CC) */
13563 +
13564 +
13565 +#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */
13566 +/*
13567 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
13568 + * have some builtin functions that accomplish much the same results.
13569 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
13570 + * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only
13571 + * operate on an int (ie, longword), but that's OK as long as we define
13572 + * S_INIT_LOCK to zero out the whole quadword.
13573 + */
13574 +#define HAS_TEST_AND_SET
13575 +
13576 +typedef unsigned long slock_t;
13577 +
13578 +#include <alpha/builtins.h>
13579 +#define S_INIT_LOCK(lock) (*(lock) = 0)
13580 +#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
13581 +#define S_UNLOCK(lock) __UNLOCK_LONG(lock)
13582 +
13583 +#endif /* __alpha || __alpha__ */
13584 +
13585 +
13586 +#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
13587 +/*
13588 + * HP's PA-RISC
13589 + *
13590 + * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
13591 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
13592 + * struct. The active word in the struct is whichever has the aligned address;
13593 + * the other three words just sit at -1.
13594 + *
13595 + * When using gcc, we can inline the required assembly code.
13596 + */
13597 +#define HAS_TEST_AND_SET
13598 +
13599 +typedef struct
13600 +{
13601 + int sema[4];
13602 +} slock_t;
13603 +
13604 +#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
13605 +
13606 +#if defined(__GNUC__)
13607 +
13608 +static __inline__ int
13609 +tas(volatile slock_t *lock)
13610 +{
13611 + volatile int *lockword = TAS_ACTIVE_WORD(lock);
13612 + register int lockval;
13613 +
13614 + __asm__ __volatile__(
13615 + " ldcwx 0(0,%2),%0 \n"
13616 +: "=r"(lockval), "+m"(*lockword)
13617 +: "r"(lockword)
13618 +: "memory");
13619 + return (lockval == 0);
13620 +}
13621 +
13622 +#endif /* __GNUC__ */
13623 +
13624 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
13625 +
13626 +#define S_INIT_LOCK(lock) \
13627 + do { \
13628 + volatile slock_t *lock_ = (lock); \
13629 + lock_->sema[0] = -1; \
13630 + lock_->sema[1] = -1; \
13631 + lock_->sema[2] = -1; \
13632 + lock_->sema[3] = -1; \
13633 + } while (0)
13634 +
13635 +#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
13636 +
13637 +#endif /* __hppa || __hppa__ */
13638 +
13639 +
13640 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
13641 +
13642 +#define HAS_TEST_AND_SET
13643 +
13644 +typedef unsigned int slock_t;
13645 +
13646 +#include <ia64/sys/inline.h>
13647 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
13648 +
13649 +#endif /* HPUX on IA64, non gcc */
13650 +
13651 +
13652 +#if defined(__sgi) /* SGI compiler */
13653 +/*
13654 + * SGI IRIX 5
13655 + * slock_t is defined as a unsigned long. We use the standard SGI
13656 + * mutex API.
13657 + *
13658 + * The following comment is left for historical reasons, but is probably
13659 + * not a good idea since the mutex ABI is supported.
13660 + *
13661 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
13662 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
13663 + * for the R3000 chips out there.
13664 + */
13665 +#define HAS_TEST_AND_SET
13666 +
13667 +typedef unsigned long slock_t;
13668 +
13669 +#include "mutex.h"
13670 +#define TAS(lock) (test_and_set(lock,1))
13671 +#define S_UNLOCK(lock) (test_then_and(lock,0))
13672 +#define S_INIT_LOCK(lock) (test_then_and(lock,0))
13673 +#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
13674 +#endif /* __sgi */
13675 +
13676 +
13677 +#if defined(sinix) /* Sinix */
13678 +/*
13679 + * SINIX / Reliant UNIX
13680 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
13681 + * member. (Basically same as SGI)
13682 + */
13683 +#define HAS_TEST_AND_SET
13684 +
13685 +#include "abi_mutex.h"
13686 +typedef abilock_t slock_t;
13687 +
13688 +#define TAS(lock) (!acquire_lock(lock))
13689 +#define S_UNLOCK(lock) release_lock(lock)
13690 +#define S_INIT_LOCK(lock) init_lock(lock)
13691 +#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
13692 +#endif /* sinix */
13693 +
13694 +
13695 +#if defined(_AIX) /* AIX */
13696 +/*
13697 + * AIX (POWER)
13698 + */
13699 +#define HAS_TEST_AND_SET
13700 +
13701 +typedef unsigned int slock_t;
13702 +
13703 +#define TAS(lock) _check_lock(lock, 0, 1)
13704 +#define S_UNLOCK(lock) _clear_lock(lock, 0)
13705 +#endif /* _AIX */
13706 +
13707 +
13708 +#if defined (nextstep) /* Nextstep */
13709 +#define HAS_TEST_AND_SET
13710 +
13711 +typedef struct mutex slock_t;
13712 +
13713 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */
13714 +
13715 +#define S_LOCK(lock) mutex_lock(lock)
13716 +#define S_UNLOCK(lock) mutex_unlock(lock)
13717 +#define S_INIT_LOCK(lock) mutex_init(lock)
13718 +/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
13719 +#define S_LOCK_FREE(alock) ((alock)->lock == 0)
13720 +#endif /* nextstep */
13721 +
13722 +
13723 +/* These are in s_lock.c */
13724 +
13725 +
13726 +#if defined(sun3) /* Sun3 */
13727 +#define HAS_TEST_AND_SET
13728 +
13729 +typedef unsigned char slock_t;
13730 +#endif
13731 +
13732 +
13733 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
13734 +#define HAS_TEST_AND_SET
13735 +
13736 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
13737 +typedef unsigned int slock_t;
13738 +#else
13739 +typedef unsigned char slock_t;
13740 +#endif
13741 +
13742 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
13743 + slock_t cmp);
13744 +
13745 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
13746 +#endif
13747 +
13748 +
13749 +#ifdef WIN32_ONLY_COMPILER
13750 +typedef LONG slock_t;
13751 +
13752 +#define HAS_TEST_AND_SET
13753 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
13754 +
13755 +#define SPIN_DELAY() spin_delay()
13756 +
13757 +static __forceinline void
13758 +spin_delay(void)
13759 +{
13760 + /* See comment for gcc code. Same code, MASM syntax */
13761 + __asm rep nop;
13762 +}
13763 +
13764 +#endif
13765 +
13766 +
13767 +#endif /* !defined(HAS_TEST_AND_SET) */
13768 +
13769 +
13770 +/* Blow up if we didn't have any way to do spinlocks */
13771 +#ifndef HAS_TEST_AND_SET
13772 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
13773 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
13774 +/* #error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-bugs@postgresql.org. */
13775 +#endif
13776 +
13777 +
13778 +#else /* !HAVE_SPINLOCKS */
13779 +
13780 +
13781 +/*
13782 + * Fake spinlock implementation using semaphores --- slow and prone
13783 + * to fall foul of kernel limits on number of semaphores, so don't use this
13784 + * unless you must! The subroutines appear in spin.c.
13785 + */
13786 +
13787 +/* -- Removed for APC
13788 +typedef PGSemaphoreData slock_t;
13789 +
13790 +extern bool s_lock_free_sema(volatile slock_t *lock);
13791 +extern void s_unlock_sema(volatile slock_t *lock);
13792 +extern void s_init_lock_sema(volatile slock_t *lock);
13793 +extern int tas_sema(volatile slock_t *lock);
13794 +
13795 +#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
13796 +#define S_UNLOCK(lock) s_unlock_sema(lock)
13797 +#define S_INIT_LOCK(lock) s_init_lock_sema(lock)
13798 +#define TAS(lock) tas_sema(lock)
13799 +*/
13800 +
13801 +#endif /* HAVE_SPINLOCKS */
13802 +
13803 +
13804 +/*
13805 + * Default Definitions - override these above as needed.
13806 + */
13807 +
13808 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
13809 +
13810 +#if !defined(S_LOCK)
13811 +#define S_LOCK(lock) \
13812 + do { \
13813 + if (TAS(lock)) \
13814 + s_lock((lock), __FILE__, __LINE__); \
13815 + } while (0)
13816 +#endif /* S_LOCK */
13817 +
13818 +#if !defined(S_LOCK_FREE)
13819 +#define S_LOCK_FREE(lock) (*(lock) == 0)
13820 +#endif /* S_LOCK_FREE */
13821 +
13822 +#if !defined(S_UNLOCK)
13823 +#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
13824 +#endif /* S_UNLOCK */
13825 +
13826 +#if !defined(S_INIT_LOCK)
13827 +#define S_INIT_LOCK(lock) S_UNLOCK(lock)
13828 +#endif /* S_INIT_LOCK */
13829 +
13830 +#if !defined(SPIN_DELAY)
13831 +#define SPIN_DELAY() ((void) 0)
13832 +#endif /* SPIN_DELAY */
13833 +
13834 +#if !defined(TAS)
13835 +extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
13836 + * s_lock.c */
13837 +
13838 +#define TAS(lock) tas(lock)
13839 +#endif /* TAS */
13840 +
13841 +
13842 +/*
13843 + * Platform-independent out-of-line support routines
13844 + */
13845 +extern void s_lock(volatile slock_t *lock, const char *file, int line);
13846 +
13847 +/* Support for dynamic adjustment of spins_per_delay */
13848 +#define DEFAULT_SPINS_PER_DELAY 100
13849 +
13850 +#if 0 /* -- Removed from APC use -- */
13851 +extern void set_spins_per_delay(int shared_spins_per_delay);
13852 +extern int update_spins_per_delay(int shared_spins_per_delay);
13853 +#endif
13854 +
13855 +#endif /* S_LOCK_H */
13856 diff -ubrN php-5.2.5-orig/ext/apc/php_apc.c php-5.2.5/ext/apc/php_apc.c
13857 --- php-5.2.5-orig/ext/apc/php_apc.c 1969-12-31 18:00:00.000000000 -0600
13858 +++ php-5.2.5/ext/apc/php_apc.c 2007-12-26 16:51:32.000000000 -0600
13859 @@ -0,0 +1,991 @@
13860 +/*
13861 + +----------------------------------------------------------------------+
13862 + | APC |
13863 + +----------------------------------------------------------------------+
13864 + | Copyright (c) 2006 The PHP Group |
13865 + +----------------------------------------------------------------------+
13866 + | This source file is subject to version 3.01 of the PHP license, |
13867 + | that is bundled with this package in the file LICENSE, and is |
13868 + | available through the world-wide-web at the following url: |
13869 + | http://www.php.net/license/3_01.txt |
13870 + | If you did not receive a copy of the PHP license and are unable to |
13871 + | obtain it through the world-wide-web, please send a note to |
13872 + | license@php.net so we can mail you a copy immediately. |
13873 + +----------------------------------------------------------------------+
13874 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13875 + | Rasmus Lerdorf <rasmus@php.net> |
13876 + +----------------------------------------------------------------------+
13877 +
13878 + This software was contributed to PHP by Community Connect Inc. in 2002
13879 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13880 + Future revisions and derivatives of this source code must acknowledge
13881 + Community Connect Inc. as the original contributor of this module by
13882 + leaving this note intact in the source code.
13883 +
13884 + All other licensing and usage conditions are those of the PHP Group.
13885 +
13886 + */
13887 +
13888 +/* $Id: php_apc.c,v 3.154 2007/12/26 22:31:20 rasmus Exp $ */
13889 +
13890 +#include "apc_zend.h"
13891 +#include "apc_cache.h"
13892 +#include "apc_main.h"
13893 +#include "apc_sma.h"
13894 +#include "apc_lock.h"
13895 +#include "php_globals.h"
13896 +#include "php_ini.h"
13897 +#include "ext/standard/info.h"
13898 +#include "SAPI.h"
13899 +#include "rfc1867.h"
13900 +#include "php_apc.h"
13901 +#if PHP_API_VERSION <= 20020918
13902 +#if HAVE_APACHE
13903 +#ifdef APC_PHP4_STAT
13904 +#undef XtOffsetOf
13905 +#include "httpd.h"
13906 +#endif
13907 +#endif
13908 +#endif
13909 +
13910 +#if HAVE_SIGACTION
13911 +#include "apc_signal.h"
13912 +#endif
13913 +
13914 +/* {{{ PHP_FUNCTION declarations */
13915 +PHP_FUNCTION(apc_cache_info);
13916 +PHP_FUNCTION(apc_clear_cache);
13917 +PHP_FUNCTION(apc_sma_info);
13918 +PHP_FUNCTION(apc_store);
13919 +PHP_FUNCTION(apc_fetch);
13920 +PHP_FUNCTION(apc_delete);
13921 +PHP_FUNCTION(apc_compile_file);
13922 +PHP_FUNCTION(apc_define_constants);
13923 +PHP_FUNCTION(apc_load_constants);
13924 +PHP_FUNCTION(apc_add);
13925 +/* }}} */
13926 +
13927 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
13928 +ZEND_DECLARE_MODULE_GLOBALS(apc)
13929 +
13930 +/* True globals */
13931 +apc_cache_t* apc_cache = NULL;
13932 +apc_cache_t* apc_user_cache = NULL;
13933 +void* apc_compiled_filters = NULL;
13934 +
13935 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
13936 +{
13937 + apc_globals->filters = NULL;
13938 + apc_globals->initialized = 0;
13939 + apc_globals->cache_stack = apc_stack_create(0);
13940 + apc_globals->cache_by_default = 1;
13941 + apc_globals->slam_defense = 0;
13942 + apc_globals->mem_size_ptr = NULL;
13943 + apc_globals->fpstat = 1;
13944 + apc_globals->stat_ctime = 0;
13945 + apc_globals->write_lock = 1;
13946 + apc_globals->report_autofilter = 0;
13947 + apc_globals->apc_optimize_function = NULL;
13948 +#ifdef MULTIPART_EVENT_FORMDATA
13949 + apc_globals->rfc1867 = 0;
13950 +#endif
13951 + apc_globals->copied_zvals = NULL;
13952 +#ifdef ZEND_ENGINE_2
13953 + apc_globals->reserved_offset = -1;
13954 +#endif
13955 + apc_globals->localcache = 0;
13956 + apc_globals->localcache_size = 0;
13957 + apc_globals->lcache = NULL;
13958 + apc_globals->force_file_update = 0;
13959 + apc_globals->coredump_unmap = 0;
13960 +}
13961 +
13962 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
13963 +{
13964 + /* deallocate the ignore patterns */
13965 + if (apc_globals->filters != NULL) {
13966 + int i;
13967 + for (i=0; apc_globals->filters[i] != NULL; i++) {
13968 + apc_efree(apc_globals->filters[i]);
13969 + }
13970 + apc_efree(apc_globals->filters);
13971 + }
13972 +
13973 + /* the stack should be empty */
13974 + assert(apc_stack_size(apc_globals->cache_stack) == 0);
13975 +
13976 + /* apc cleanup */
13977 + apc_stack_destroy(apc_globals->cache_stack);
13978 +
13979 + /* the rest of the globals are cleaned up in apc_module_shutdown() */
13980 +}
13981 +
13982 +/* }}} */
13983 +
13984 +/* {{{ PHP_INI */
13985 +
13986 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
13987 +{
13988 + APCG(filters) = apc_tokenize(new_value, ',');
13989 + return SUCCESS;
13990 +}
13991 +/* }}} */
13992 +
13993 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
13994 +{
13995 +#if APC_MMAP
13996 + if(atoi(new_value)!=1) {
13997 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
13998 + }
13999 + APCG(shm_segments) = 1;
14000 +#else
14001 + APCG(shm_segments) = atoi(new_value);
14002 +#endif
14003 + return SUCCESS;
14004 +}
14005 +/* }}} */
14006 +
14007 +#ifdef MULTIPART_EVENT_FORMDATA
14008 +static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
14009 +{
14010 + int tmp;
14011 + tmp = zend_atoi(new_value, new_value_length);
14012 + if(tmp < 0) {
14013 + apc_eprint("rfc1867_freq must be greater than or equal to zero.");
14014 + return FAILURE;
14015 + }
14016 + if(new_value[new_value_length-1] == '%') {
14017 + if(tmp > 100) {
14018 + apc_eprint("rfc1867_freq cannot be over 100%%");
14019 + return FAILURE;
14020 + }
14021 + APCG(rfc1867_freq) = tmp / 100.0;
14022 + } else {
14023 + APCG(rfc1867_freq) = tmp;
14024 + }
14025 + return SUCCESS;
14026 +}
14027 +/* }}} */
14028 +#endif
14029 +
14030 +#ifdef ZEND_ENGINE_2
14031 +#define OnUpdateInt OnUpdateLong
14032 +#endif
14033 +
14034 +PHP_INI_BEGIN()
14035 +STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
14036 +STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
14037 +STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
14038 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
14039 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
14040 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
14041 +STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
14042 +STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
14043 +STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
14044 +#if APC_MMAP
14045 +STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
14046 +#endif
14047 +PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
14048 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
14049 +STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
14050 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
14051 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
14052 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
14053 +STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
14054 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
14055 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
14056 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
14057 +#ifdef MULTIPART_EVENT_FORMDATA
14058 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
14059 +STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
14060 +STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
14061 +STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
14062 +#endif
14063 +STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
14064 +STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size, zend_apc_globals, apc_globals)
14065 +STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
14066 +PHP_INI_END()
14067 +
14068 +/* }}} */
14069 +
14070 +/* {{{ PHP_MINFO_FUNCTION(apc) */
14071 +static PHP_MINFO_FUNCTION(apc)
14072 +{
14073 + php_info_print_table_start();
14074 + php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
14075 + php_info_print_table_row(2, "Version", APC_VERSION);
14076 +#if APC_MMAP
14077 + php_info_print_table_row(2, "MMAP Support", "Enabled");
14078 + php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
14079 +#else
14080 + php_info_print_table_row(2, "MMAP Support", "Disabled");
14081 +#endif
14082 +#if APC_SEM_LOCKS
14083 + php_info_print_table_row(2, "Locking type", "IPC Semaphore");
14084 +#elif APC_FUTEX_LOCKS
14085 + php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
14086 +#elif APC_PTHREADMUTEX_LOCKS
14087 + php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
14088 +#elif APC_SPIN_LOCKS
14089 + php_info_print_table_row(2, "Locking type", "spin Locks");
14090 +#else
14091 + php_info_print_table_row(2, "Locking type", "File Locks");
14092 +#endif
14093 + php_info_print_table_row(2, "Revision", "$Revision: 3.154 $");
14094 + php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
14095 + php_info_print_table_end();
14096 + DISPLAY_INI_ENTRIES();
14097 +}
14098 +/* }}} */
14099 +
14100 +#ifdef MULTIPART_EVENT_FORMDATA
14101 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
14102 +#endif
14103 +
14104 +/* {{{ PHP_MINIT_FUNCTION(apc) */
14105 +static PHP_MINIT_FUNCTION(apc)
14106 +{
14107 + ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
14108 +
14109 + REGISTER_INI_ENTRIES();
14110 +
14111 + /* Disable APC in cli mode unless overridden by apc.enable_cli */
14112 + if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
14113 + APCG(enabled) = 0;
14114 + }
14115 +
14116 + if (APCG(enabled)) {
14117 + if(APCG(initialized)) {
14118 + apc_process_init(module_number TSRMLS_CC);
14119 + } else {
14120 + apc_module_init(module_number TSRMLS_CC);
14121 + apc_zend_init(TSRMLS_C);
14122 + apc_process_init(module_number TSRMLS_CC);
14123 +#ifdef MULTIPART_EVENT_FORMDATA
14124 + /* File upload progress tracking */
14125 + if(APCG(rfc1867)) {
14126 + php_rfc1867_callback = apc_rfc1867_progress;
14127 + }
14128 +#endif
14129 + }
14130 + }
14131 +
14132 + return SUCCESS;
14133 +}
14134 +/* }}} */
14135 +
14136 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
14137 +static PHP_MSHUTDOWN_FUNCTION(apc)
14138 +{
14139 + if(APCG(enabled)) {
14140 + apc_process_shutdown(TSRMLS_C);
14141 + apc_zend_shutdown(TSRMLS_C);
14142 + apc_module_shutdown(TSRMLS_C);
14143 +#ifndef ZTS
14144 + php_apc_shutdown_globals(&apc_globals);
14145 +#endif
14146 + }
14147 +#ifdef ZTS
14148 + ts_free_id(apc_globals_id);
14149 +#endif
14150 + UNREGISTER_INI_ENTRIES();
14151 + return SUCCESS;
14152 +}
14153 +/* }}} */
14154 +
14155 +/* {{{ PHP_RINIT_FUNCTION(apc) */
14156 +static PHP_RINIT_FUNCTION(apc)
14157 +{
14158 + if(APCG(enabled)) {
14159 + apc_request_init(TSRMLS_C);
14160 +
14161 +#if HAVE_SIGACTION
14162 + apc_set_signals();
14163 +#endif
14164 + }
14165 + return SUCCESS;
14166 +}
14167 +/* }}} */
14168 +
14169 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
14170 +static PHP_RSHUTDOWN_FUNCTION(apc)
14171 +{
14172 + if(APCG(enabled)) {
14173 + apc_request_shutdown(TSRMLS_C);
14174 + }
14175 + return SUCCESS;
14176 +}
14177 +/* }}} */
14178 +
14179 +/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
14180 +PHP_FUNCTION(apc_cache_info)
14181 +{
14182 + apc_cache_info_t* info;
14183 + apc_cache_link_t* p;
14184 + zval* list;
14185 + char *cache_type;
14186 + int ct_len;
14187 + zend_bool limited=0;
14188 +
14189 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
14190 + return;
14191 + }
14192 +
14193 + if(ZEND_NUM_ARGS()) {
14194 + if(!strcasecmp(cache_type,"user")) {
14195 + info = apc_cache_info(apc_user_cache, limited);
14196 + } else if(!strcasecmp(cache_type,"filehits")) {
14197 +#ifdef APC_FILEHITS
14198 + RETVAL_ZVAL(APCG(filehits), 1, 0);
14199 + return;
14200 +#else
14201 + RETURN_FALSE;
14202 +#endif
14203 + } else {
14204 + info = apc_cache_info(apc_cache, limited);
14205 + }
14206 + } else info = apc_cache_info(apc_cache, limited);
14207 +
14208 + if(!info) {
14209 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
14210 + RETURN_FALSE;
14211 + }
14212 +
14213 + array_init(return_value);
14214 + add_assoc_long(return_value, "num_slots", info->num_slots);
14215 + add_assoc_long(return_value, "ttl", info->ttl);
14216 + add_assoc_long(return_value, "num_hits", info->num_hits);
14217 + add_assoc_long(return_value, "num_misses", info->num_misses);
14218 + add_assoc_long(return_value, "start_time", info->start_time);
14219 + add_assoc_long(return_value, "expunges", info->expunges);
14220 + add_assoc_long(return_value, "mem_size", info->mem_size);
14221 + add_assoc_long(return_value, "num_entries", info->num_entries);
14222 + add_assoc_long(return_value, "num_inserts", info->num_inserts);
14223 +#ifdef MULTIPART_EVENT_FORMDATA
14224 + add_assoc_long(return_value, "file_upload_progress", 1);
14225 +#else
14226 + add_assoc_long(return_value, "file_upload_progress", 0);
14227 +#endif
14228 +#if APC_MMAP
14229 + add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
14230 +#else
14231 + add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
14232 +#endif
14233 +#if APC_SEM_LOCKS
14234 + add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
14235 +#elif APC_FUTEX_LOCKS
14236 + add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
14237 +#elif APC_PTHREADMUTEX_LOCKS
14238 + add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
14239 +#elif APC_SPIN_LOCKS
14240 + add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
14241 +#else
14242 + add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
14243 +#endif
14244 + if(limited) {
14245 + apc_cache_free_info(info);
14246 + return;
14247 + }
14248 +
14249 + ALLOC_INIT_ZVAL(list);
14250 + array_init(list);
14251 +
14252 + for (p = info->list; p != NULL; p = p->next) {
14253 + zval* link;
14254 +
14255 + ALLOC_INIT_ZVAL(link);
14256 + array_init(link);
14257 +
14258 + if(p->type == APC_CACHE_ENTRY_FILE) {
14259 + add_assoc_string(link, "filename", p->data.file.filename, 1);
14260 + add_assoc_long(link, "device", p->data.file.device);
14261 + add_assoc_long(link, "inode", p->data.file.inode);
14262 + add_assoc_string(link, "type", "file", 1);
14263 + } else if(p->type == APC_CACHE_ENTRY_USER) {
14264 + add_assoc_string(link, "info", p->data.user.info, 1);
14265 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
14266 + add_assoc_string(link, "type", "user", 1);
14267 + }
14268 + add_assoc_long(link, "num_hits", p->num_hits);
14269 + add_assoc_long(link, "mtime", p->mtime);
14270 + add_assoc_long(link, "creation_time", p->creation_time);
14271 + add_assoc_long(link, "deletion_time", p->deletion_time);
14272 + add_assoc_long(link, "access_time", p->access_time);
14273 + add_assoc_long(link, "ref_count", p->ref_count);
14274 + add_assoc_long(link, "mem_size", p->mem_size);
14275 + add_next_index_zval(list, link);
14276 + }
14277 + add_assoc_zval(return_value, "cache_list", list);
14278 +
14279 + ALLOC_INIT_ZVAL(list);
14280 + array_init(list);
14281 +
14282 + for (p = info->deleted_list; p != NULL; p = p->next) {
14283 + zval* link;
14284 +
14285 + ALLOC_INIT_ZVAL(link);
14286 + array_init(link);
14287 +
14288 + if(p->type == APC_CACHE_ENTRY_FILE) {
14289 + add_assoc_string(link, "filename", p->data.file.filename, 1);
14290 + add_assoc_long(link, "device", p->data.file.device);
14291 + add_assoc_long(link, "inode", p->data.file.inode);
14292 + add_assoc_string(link, "type", "file", 1);
14293 + } else if(p->type == APC_CACHE_ENTRY_USER) {
14294 + add_assoc_string(link, "info", p->data.user.info, 1);
14295 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
14296 + add_assoc_string(link, "type", "user", 1);
14297 + }
14298 + add_assoc_long(link, "num_hits", p->num_hits);
14299 + add_assoc_long(link, "mtime", p->mtime);
14300 + add_assoc_long(link, "creation_time", p->creation_time);
14301 + add_assoc_long(link, "deletion_time", p->deletion_time);
14302 + add_assoc_long(link, "access_time", p->access_time);
14303 + add_assoc_long(link, "ref_count", p->ref_count);
14304 + add_assoc_long(link, "mem_size", p->mem_size);
14305 + add_next_index_zval(list, link);
14306 + }
14307 + add_assoc_zval(return_value, "deleted_list", list);
14308 +
14309 + apc_cache_free_info(info);
14310 +}
14311 +/* }}} */
14312 +
14313 +/* {{{ proto void apc_clear_cache() */
14314 +PHP_FUNCTION(apc_clear_cache)
14315 +{
14316 + char *cache_type;
14317 + int ct_len;
14318 +
14319 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
14320 + return;
14321 + }
14322 +
14323 + if(ZEND_NUM_ARGS()) {
14324 + if(!strcasecmp(cache_type,"user")) {
14325 + apc_cache_clear(apc_user_cache);
14326 + RETURN_TRUE;
14327 + }
14328 + }
14329 + apc_cache_clear(apc_cache);
14330 +}
14331 +/* }}} */
14332 +
14333 +/* {{{ proto array apc_sma_info([bool limited]) */
14334 +PHP_FUNCTION(apc_sma_info)
14335 +{
14336 + apc_sma_info_t* info;
14337 + zval* block_lists;
14338 + int i;
14339 + zend_bool limited = 0;
14340 +
14341 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
14342 + return;
14343 + }
14344 +
14345 + info = apc_sma_info(limited);
14346 +
14347 + if(!info) {
14348 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
14349 + RETURN_FALSE;
14350 + }
14351 +
14352 + array_init(return_value);
14353 + add_assoc_long(return_value, "num_seg", info->num_seg);
14354 + add_assoc_long(return_value, "seg_size", info->seg_size);
14355 + add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
14356 +
14357 + if(limited) {
14358 + apc_sma_free_info(info);
14359 + return;
14360 + }
14361 +
14362 +#if ALLOC_DISTRIBUTION
14363 + {
14364 + size_t *adist = apc_sma_get_alloc_distribution();
14365 + zval* list;
14366 + ALLOC_INIT_ZVAL(list);
14367 + array_init(list);
14368 + for(i=0; i<30; i++) {
14369 + add_next_index_long(list, adist[i]);
14370 + }
14371 + add_assoc_zval(return_value, "adist", list);
14372 + }
14373 +#endif
14374 + ALLOC_INIT_ZVAL(block_lists);
14375 + array_init(block_lists);
14376 +
14377 + for (i = 0; i < info->num_seg; i++) {
14378 + apc_sma_link_t* p;
14379 + zval* list;
14380 +
14381 + ALLOC_INIT_ZVAL(list);
14382 + array_init(list);
14383 +
14384 + for (p = info->list[i]; p != NULL; p = p->next) {
14385 + zval* link;
14386 +
14387 + ALLOC_INIT_ZVAL(link);
14388 + array_init(link);
14389 +
14390 + add_assoc_long(link, "size", p->size);
14391 + add_assoc_long(link, "offset", p->offset);
14392 + add_next_index_zval(list, link);
14393 + }
14394 + add_next_index_zval(block_lists, list);
14395 + }
14396 + add_assoc_zval(return_value, "block_lists", block_lists);
14397 + apc_sma_free_info(info);
14398 +}
14399 +/* }}} */
14400 +
14401 +/* {{{ _apc_store */
14402 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
14403 + apc_cache_entry_t *entry;
14404 + apc_cache_key_t key;
14405 + time_t t;
14406 + size_t mem_size = 0;
14407 +
14408 +#if PHP_API_VERSION < 20041225
14409 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14410 + t = ((request_rec *)SG(server_context))->request_time;
14411 +#else
14412 + t = time(0);
14413 +#endif
14414 +#else
14415 + t = sapi_get_request_time(TSRMLS_C);
14416 +#endif
14417 +
14418 + if(!APCG(enabled)) return 0;
14419 +
14420 + HANDLE_BLOCK_INTERRUPTIONS();
14421 +
14422 + APCG(mem_size_ptr) = &mem_size;
14423 + if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
14424 + APCG(mem_size_ptr) = NULL;
14425 + apc_cache_expunge(apc_cache,t);
14426 + apc_cache_expunge(apc_user_cache,t);
14427 + HANDLE_UNBLOCK_INTERRUPTIONS();
14428 + return 0;
14429 + }
14430 +
14431 + if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
14432 + APCG(mem_size_ptr) = NULL;
14433 + apc_cache_free_entry(entry);
14434 + apc_cache_expunge(apc_cache,t);
14435 + apc_cache_expunge(apc_user_cache,t);
14436 + HANDLE_UNBLOCK_INTERRUPTIONS();
14437 + return 0;
14438 + }
14439 +
14440 + if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
14441 + APCG(mem_size_ptr) = NULL;
14442 + apc_cache_free_entry(entry);
14443 + apc_cache_expunge(apc_cache,t);
14444 + apc_cache_expunge(apc_user_cache,t);
14445 + HANDLE_UNBLOCK_INTERRUPTIONS();
14446 + return 0;
14447 + }
14448 +
14449 + APCG(mem_size_ptr) = NULL;
14450 +
14451 + HANDLE_UNBLOCK_INTERRUPTIONS();
14452 +
14453 + return 1;
14454 +}
14455 +/* }}} */
14456 +
14457 +/* {{{ proto int apc_store(string key, zval var [, ttl ])
14458 + */
14459 +PHP_FUNCTION(apc_store) {
14460 + zval *val;
14461 + char *strkey;
14462 + int strkey_len;
14463 + long ttl = 0L;
14464 +
14465 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
14466 + return;
14467 + }
14468 +
14469 + if(!strkey_len) RETURN_FALSE;
14470 +
14471 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
14472 + RETURN_FALSE;
14473 +}
14474 +/* }}} */
14475 +
14476 +/* {{{ proto int apc_add(string key, zval var [, ttl ])
14477 + */
14478 +PHP_FUNCTION(apc_add) {
14479 + zval *val;
14480 + char *strkey;
14481 + int strkey_len;
14482 + long ttl = 0L;
14483 +
14484 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
14485 + return;
14486 + }
14487 +
14488 + if(!strkey_len) RETURN_FALSE;
14489 +
14490 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
14491 + RETURN_FALSE;
14492 +}
14493 +/* }}} */
14494 +
14495 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
14496 + return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
14497 +}
14498 +
14499 +/* {{{ RETURN_ZVAL for php4 */
14500 +#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
14501 +#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
14502 +#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
14503 +#define ZVAL_ZVAL(z, zv, copy, dtor) { \
14504 + int is_ref, refcount; \
14505 + is_ref = (z)->is_ref; \
14506 + refcount = (z)->refcount; \
14507 + *(z) = *(zv); \
14508 + if (copy) { \
14509 + zval_copy_ctor(z); \
14510 + } \
14511 + if (dtor) { \
14512 + if (!copy) { \
14513 + ZVAL_NULL(zv); \
14514 + } \
14515 + zval_ptr_dtor(&zv); \
14516 + } \
14517 + (z)->is_ref = is_ref; \
14518 + (z)->refcount = refcount; \
14519 + }
14520 +#endif
14521 +/* }}} */
14522 +
14523 +/* {{{ proto mixed apc_fetch(mixed key)
14524 + */
14525 +PHP_FUNCTION(apc_fetch) {
14526 + zval *key;
14527 + HashTable *hash;
14528 + HashPosition hpos;
14529 + zval **hentry;
14530 + zval *result;
14531 + zval *result_entry;
14532 + char *strkey;
14533 + int strkey_len;
14534 + apc_cache_entry_t* entry;
14535 + time_t t;
14536 +
14537 + if(!APCG(enabled)) RETURN_FALSE;
14538 +
14539 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
14540 + return;
14541 + }
14542 +
14543 +#if PHP_API_VERSION < 20041225
14544 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14545 + t = ((request_rec *)SG(server_context))->request_time;
14546 +#else
14547 + t = time(0);
14548 +#endif
14549 +#else
14550 + t = sapi_get_request_time(TSRMLS_C);
14551 +#endif
14552 +
14553 + if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
14554 + convert_to_string(key);
14555 + }
14556 +
14557 + if(Z_TYPE_P(key) == IS_STRING) {
14558 + strkey = Z_STRVAL_P(key);
14559 + strkey_len = Z_STRLEN_P(key);
14560 + if(!strkey_len) RETURN_FALSE;
14561 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
14562 + if(entry) {
14563 + /* deep-copy returned shm zval to emalloc'ed return_value */
14564 + apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
14565 + apc_cache_release(apc_user_cache, entry);
14566 + } else {
14567 + RETURN_FALSE;
14568 + }
14569 + } else if(Z_TYPE_P(key) == IS_ARRAY) {
14570 + hash = Z_ARRVAL_P(key);
14571 + MAKE_STD_ZVAL(result);
14572 + array_init(result);
14573 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
14574 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
14575 + if(Z_TYPE_PP(hentry) != IS_STRING) {
14576 + apc_wprint("apc_fetch() expects a string or array of strings.");
14577 + RETURN_FALSE;
14578 + }
14579 + entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
14580 + if(entry) {
14581 + /* deep-copy returned shm zval to emalloc'ed return_value */
14582 + MAKE_STD_ZVAL(result_entry);
14583 + apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
14584 + apc_cache_release(apc_user_cache, entry);
14585 + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
14586 + } /* don't set values we didn't find */
14587 + zend_hash_move_forward_ex(hash, &hpos);
14588 + }
14589 + RETURN_ZVAL(result, 0, 1);
14590 + } else {
14591 + apc_wprint("apc_fetch() expects a string or array of strings.");
14592 + RETURN_FALSE;
14593 + }
14594 +
14595 + return;
14596 +}
14597 +/* }}} */
14598 +
14599 +/* {{{ proto mixed apc_delete(string key)
14600 + */
14601 +PHP_FUNCTION(apc_delete) {
14602 + char *strkey;
14603 + int strkey_len;
14604 +
14605 + if(!APCG(enabled)) RETURN_FALSE;
14606 +
14607 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
14608 + return;
14609 + }
14610 +
14611 + if(!strkey_len) RETURN_FALSE;
14612 +
14613 + if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
14614 + RETURN_TRUE;
14615 + } else {
14616 + RETURN_FALSE;
14617 + }
14618 +}
14619 +/* }}} */
14620 +
14621 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
14622 + char *const_key;
14623 + unsigned int const_key_len;
14624 + zval **entry;
14625 + HashPosition pos;
14626 +
14627 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
14628 + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
14629 + zend_constant c;
14630 + int key_type;
14631 + ulong num_key;
14632 +
14633 + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
14634 + if(key_type != HASH_KEY_IS_STRING) {
14635 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14636 + continue;
14637 + }
14638 + switch(Z_TYPE_PP(entry)) {
14639 + case IS_LONG:
14640 + case IS_DOUBLE:
14641 + case IS_STRING:
14642 + case IS_BOOL:
14643 + case IS_RESOURCE:
14644 + case IS_NULL:
14645 + break;
14646 + default:
14647 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14648 + continue;
14649 + }
14650 + c.value = **entry;
14651 + zval_copy_ctor(&c.value);
14652 + c.flags = case_sensitive;
14653 + c.name = zend_strndup(const_key, const_key_len);
14654 + c.name_len = const_key_len;
14655 +#ifdef ZEND_ENGINE_2
14656 + c.module_number = PHP_USER_CONSTANT;
14657 +#endif
14658 + zend_register_constant(&c TSRMLS_CC);
14659 +
14660 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
14661 + }
14662 +}
14663 +
14664 +/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
14665 + */
14666 +PHP_FUNCTION(apc_define_constants) {
14667 + char *strkey;
14668 + int strkey_len;
14669 + zval *constants = NULL;
14670 + zend_bool case_sensitive = 1;
14671 + int argc = ZEND_NUM_ARGS();
14672 +
14673 + if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
14674 + return;
14675 + }
14676 +
14677 + if(!strkey_len) RETURN_FALSE;
14678 +
14679 + _apc_define_constants(constants, case_sensitive TSRMLS_CC);
14680 + if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
14681 + RETURN_FALSE;
14682 +} /* }}} */
14683 +
14684 +/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
14685 + */
14686 +PHP_FUNCTION(apc_load_constants) {
14687 + char *strkey;
14688 + int strkey_len;
14689 + apc_cache_entry_t* entry;
14690 + time_t t;
14691 + zend_bool case_sensitive = 1;
14692 +
14693 + if(!APCG(enabled)) RETURN_FALSE;
14694 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
14695 + return;
14696 + }
14697 +
14698 + if(!strkey_len) RETURN_FALSE;
14699 +
14700 +#if PHP_API_VERSION < 20041225
14701 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
14702 + t = ((request_rec *)SG(server_context))->request_time;
14703 +#else
14704 + t = time(0);
14705 +#endif
14706 +#else
14707 + t = sapi_get_request_time(TSRMLS_C);
14708 +#endif
14709 +
14710 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
14711 +
14712 + if(entry) {
14713 + _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
14714 + apc_cache_release(apc_user_cache, entry);
14715 + RETURN_TRUE;
14716 + } else {
14717 + RETURN_FALSE;
14718 + }
14719 +}
14720 +/* }}} */
14721 +
14722 +/* {{{ proto boolean apc_compile_file(string filename)
14723 + */
14724 +PHP_FUNCTION(apc_compile_file) {
14725 + char *filename;
14726 + int filename_len;
14727 + zend_file_handle file_handle;
14728 + zend_op_array *op_array;
14729 + long slam_defense = 0;
14730 + char** filters = NULL;
14731 + zend_bool cache_by_default = 1;
14732 + HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
14733 + HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
14734 +
14735 + if(!APCG(enabled)) RETURN_FALSE;
14736 +
14737 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
14738 + return;
14739 + }
14740 +
14741 + if(!filename) RETURN_FALSE;
14742 +
14743 + /* reset slam defense, filters, and cache_by_default */
14744 + slam_defense = APCG(slam_defense);
14745 + APCG(slam_defense) = 0;
14746 +
14747 + filters = APCG(filters);
14748 + APCG(filters) = NULL;
14749 +
14750 + cache_by_default = APCG(cache_by_default);
14751 + APCG(cache_by_default) = 1;
14752 +
14753 + /* Replace function/class tables to avoid namespace conflicts */
14754 + zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
14755 + cg_orig_function_table = CG(function_table);
14756 + CG(function_table) = &cg_function_table;
14757 + zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
14758 + cg_orig_class_table = CG(class_table);
14759 + CG(class_table) = &cg_class_table;
14760 + eg_orig_function_table = EG(function_table);
14761 + EG(function_table) = CG(function_table);
14762 + eg_orig_class_table = EG(class_table);
14763 + EG(class_table) = CG(class_table);
14764 + APCG(force_file_update) = 1;
14765 +
14766 + /* Compile the file, loading it into the cache */
14767 + file_handle.type = ZEND_HANDLE_FILENAME;
14768 + file_handle.filename = filename;
14769 + file_handle.free_filename = 0;
14770 + file_handle.opened_path = NULL;
14771 + zend_try {
14772 + op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
14773 + } zend_catch {
14774 + apc_wprint("Error compiling %s in apc_compile_file.", filename);
14775 + op_array = NULL;
14776 + } zend_end_try();
14777 +
14778 + /* Return class/function tables to previous states, destroy temp tables */
14779 + APCG(force_file_update) = 0;
14780 + CG(function_table) = cg_orig_function_table;
14781 + zend_hash_destroy(&cg_function_table);
14782 + CG(class_table) = cg_orig_class_table;
14783 + zend_hash_destroy(&cg_class_table);
14784 + EG(function_table) = eg_orig_function_table;
14785 + EG(class_table) = eg_orig_class_table;
14786 +
14787 + /* Restore global settings */
14788 + APCG(slam_defense) = slam_defense;
14789 + APCG(filters) = filters;
14790 + APCG(cache_by_default) = cache_by_default;
14791 +
14792 + if(op_array == NULL) { RETURN_FALSE; }
14793 +
14794 + /* Free up everything */
14795 + zend_destroy_file_handle(&file_handle TSRMLS_CC);
14796 +#ifdef ZEND_ENGINE_2
14797 + destroy_op_array(op_array TSRMLS_CC);
14798 +#else
14799 + destroy_op_array(op_array);
14800 +#endif
14801 + efree(op_array);
14802 +
14803 + RETURN_TRUE;
14804 +}
14805 +/* }}} */
14806 +
14807 +/* {{{ apc_functions[] */
14808 +function_entry apc_functions[] = {
14809 + PHP_FE(apc_cache_info, NULL)
14810 + PHP_FE(apc_clear_cache, NULL)
14811 + PHP_FE(apc_sma_info, NULL)
14812 + PHP_FE(apc_store, NULL)
14813 + PHP_FE(apc_fetch, NULL)
14814 + PHP_FE(apc_delete, NULL)
14815 + PHP_FE(apc_define_constants, NULL)
14816 + PHP_FE(apc_load_constants, NULL)
14817 + PHP_FE(apc_compile_file, NULL)
14818 + PHP_FE(apc_add, NULL)
14819 + {NULL, NULL, NULL}
14820 +};
14821 +/* }}} */
14822 +
14823 +/* {{{ module definition structure */
14824 +
14825 +zend_module_entry apc_module_entry = {
14826 + STANDARD_MODULE_HEADER,
14827 + "apc",
14828 + apc_functions,
14829 + PHP_MINIT(apc),
14830 + PHP_MSHUTDOWN(apc),
14831 + PHP_RINIT(apc),
14832 + PHP_RSHUTDOWN(apc),
14833 + PHP_MINFO(apc),
14834 + APC_VERSION,
14835 + STANDARD_MODULE_PROPERTIES
14836 +};
14837 +
14838 +#ifdef COMPILE_DL_APC
14839 +ZEND_GET_MODULE(apc)
14840 +#endif
14841 +/* }}} */
14842 +
14843 +/*
14844 + * Local variables:
14845 + * tab-width: 4
14846 + * c-basic-offset: 4
14847 + * End:
14848 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
14849 + * vim<600: expandtab sw=4 ts=4 sts=4
14850 + */
14851 diff -ubrN php-5.2.5-orig/ext/apc/php_apc.h php-5.2.5/ext/apc/php_apc.h
14852 --- php-5.2.5-orig/ext/apc/php_apc.h 1969-12-31 18:00:00.000000000 -0600
14853 +++ php-5.2.5/ext/apc/php_apc.h 2007-12-26 16:51:32.000000000 -0600
14854 @@ -0,0 +1,52 @@
14855 +/*
14856 + +----------------------------------------------------------------------+
14857 + | APC |
14858 + +----------------------------------------------------------------------+
14859 + | Copyright (c) 2006 The PHP Group |
14860 + +----------------------------------------------------------------------+
14861 + | This source file is subject to version 3.01 of the PHP license, |
14862 + | that is bundled with this package in the file LICENSE, and is |
14863 + | available through the world-wide-web at the following url: |
14864 + | http://www.php.net/license/3_01.txt |
14865 + | If you did not receive a copy of the PHP license and are unable to |
14866 + | obtain it through the world-wide-web, please send a note to |
14867 + | license@php.net so we can mail you a copy immediately. |
14868 + +----------------------------------------------------------------------+
14869 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
14870 + | George Schlossnagle <george@omniti.com> |
14871 + | Rasmus Lerdorf <rasmus@php.net> |
14872 + +----------------------------------------------------------------------+
14873 +
14874 + This software was contributed to PHP by Community Connect Inc. in 2002
14875 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
14876 + Future revisions and derivatives of this source code must acknowledge
14877 + Community Connect Inc. as the original contributor of this module by
14878 + leaving this note intact in the source code.
14879 +
14880 + All other licensing and usage conditions are those of the PHP Group.
14881 +
14882 + */
14883 +
14884 +/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
14885 +
14886 +#ifndef PHP_APC_H
14887 +#define PHP_APC_H
14888 +
14889 +#include "apc_php.h"
14890 +#include "apc_globals.h"
14891 +
14892 +extern zend_module_entry apc_module_entry;
14893 +#define apc_module_ptr &apc_module_entry
14894 +
14895 +#define phpext_apc_ptr apc_module_ptr
14896 +
14897 +#endif /* PHP_APC_H */
14898 +
14899 +/*
14900 + * Local variables:
14901 + * tab-width: 4
14902 + * c-basic-offset: 4
14903 + * End:
14904 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
14905 + * vim<600: expandtab sw=4 ts=4 sts=4
14906 + */
14907 diff -ubrN php-5.2.5-orig/ext/apc/TECHNOTES.txt php-5.2.5/ext/apc/TECHNOTES.txt
14908 --- php-5.2.5-orig/ext/apc/TECHNOTES.txt 1969-12-31 18:00:00.000000000 -0600
14909 +++ php-5.2.5/ext/apc/TECHNOTES.txt 2007-12-26 16:51:32.000000000 -0600
14910 @@ -0,0 +1,361 @@
14911 +APC Quick-Start Braindump
14912 +
14913 +This is a rapidly written braindump of how APC currently works in the
14914 +form of a quick-start guide to start hacking on APC.
14915 +
14916 +1. Install and use APC a bit so you know what it does from the end-user's
14917 + perspective.
14918 + user-space functions are all explained here:
14919 +
14920 +2. Grab the current APC code from CVS:
14921 +
14922 + cvs -d:pserver:cvsread@cvs.php.net:/repository login
14923 + Password: phpfi
14924 + cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
14925 +
14926 + apc/php_apc.c has most of the code for the user-visible stuff. It is
14927 + also a regular PHP extension in the sense that there are MINIT, MINFO,
14928 + MSHUTDOWN, RSHUTDOWN, etc. functions.
14929 +
14930 +3. Build it.
14931 +
14932 + cd pecl/apc
14933 + phpize
14934 + ./configure --enable-apc --enable-mmap
14935 + make
14936 + cp modules/apc.so /usr/local/lib/php
14937 + apachectl restart
14938 +
14939 +4. Debugging Hints
14940 +
14941 + apachectl stop
14942 + gdb /usr/bin/httpd
14943 + break ??
14944 + run -X
14945 +
14946 + Grab the .gdbinit from the PHP source tree and have a look at the macros.
14947 +
14948 +5. Look through apc/apc_sma.c
14949 + It is a pretty standard memory allocator.
14950 +
14951 + apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
14952 + caller just like malloc, realloc, strdup and free
14953 +
14954 + On server startup the MINIT hook in php_apc.c calls apc_module_init() in
14955 + apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into
14956 + apc_mmap.c to mmap the specified sized segment (I tend to just use a single
14957 + segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and
14958 + then unlinks that file right after the mmap to provide automatic shared memory
14959 + cleanup in case the process dies.
14960 +
14961 + Once the region has been initialized we stick a header_t at the beginning
14962 + of the region. It contains the total size in header->segsize and the number
14963 + of bytes available in header->avail.
14964 +
14965 + After the header comes a bit of a hack. A zero-sized block is inserted just
14966 + to make things easier later on. And then a huge block that is basically
14967 + the size of the entire segment minus the two (for the 0-sized block, and this one)
14968 + block headers.
14969 +
14970 + The code for this is:
14971 +
14972 + header = (header_t*) shmaddr;
14973 + header->segsize = sma_segsize;
14974 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
14975 + memset(&header->lock,0,sizeof(header->lock));
14976 + sma_lock = &header->lock;
14977 + block = BLOCKAT(sizeof(header_t));
14978 + block->size = 0;
14979 + block->next = sizeof(header_t) + sizeof(block_t);
14980 + block = BLOCKAT(block->next);
14981 + block->size = header->avail;
14982 + block->next = 0;
14983 +
14984 + So the shared memory looks like this:
14985 +
14986 + +--------+-------+---------------------------------+
14987 + | header | block | block |
14988 + +--------+-------+---------------------------------+
14989 +
14990 + sma_shmaddrs[0] gives you the address of header
14991 +
14992 + The blocks are just a simple offset-based linked list (so no pointers):
14993 +
14994 + typedef struct block_t block_t;
14995 + struct block_t {
14996 + size_t size; /* size of this block */
14997 + size_t next; /* offset in segment of next free block */
14998 + size_t canary; /* canary to check for memory overwrites */
14999 +#ifdef __APC_SMA_DEBUG__
15000 + int id; /* identifier for the memory block */
15001 +#endif
15002 + };
15003 +
15004 + The BLOCKAT macro turns an offset into an actual address for you:
15005 +
15006 + #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
15007 +
15008 + where shmaddr = sma_shaddrs[0]
15009 +
15010 + And the OFFSET macro goes the other way:
15011 +
15012 + #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
15013 +
15014 + Allocating a block with a call to apc_sma_allocate() walks through the
15015 + linked list of blocks until it finds one that is >= to the requested size.
15016 + The first call to apc_sma_allocate() will hit the second block. We then
15017 + chop up that block so it looks like this:
15018 +
15019 + +--------+-------+-------+-------------------------+
15020 + | header | block | block | block |
15021 + +--------+-------+-------+-------------------------+
15022 +
15023 + Then we unlink that block from the linked list so it won't show up
15024 + as an available block on the next allocate. So we actually have:
15025 +
15026 + +--------+-------+ +-------------------------+
15027 + | header | block |------>| block |
15028 + +--------+-------+ +-------------------------+
15029 +
15030 + And header->avail along with block->size of the remaining large
15031 + block are updated accordingly. The arrow there representing the
15032 + link which now points to a block with an offset further along in
15033 + the segment.
15034 +
15035 + When the block is freed using apc_sma_deallocate() the steps are
15036 + basically just reversed. The block is put back and then the deallocate
15037 + code looks at the block before and after to see if the block immediately
15038 + before and after are free and if so the blocks are combined. So you never
15039 + have 2 free blocks next to each other, apart from at the front with that
15040 + 0-sized dummy block. This mostly prevents fragmentation. I have been
15041 + toying with the idea of always allocating block at 2^n boundaries to make
15042 + it more likely that they will be re-used to cut down on fragmentation further.
15043 + That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
15044 +
15045 + Of course, anytime we fiddle with our shared memory segment we lock using
15046 + the locking macros, LOCK() and UNLOCK().
15047 +
15048 + That should mostly take care of the low-level shared memory handling.
15049 +
15050 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
15051 + cache logic.
15052 +
15053 + The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
15054 + and apc_cache.c for actual cache manipulation.
15055 +
15056 + After the shared memory segment is created and the caches are initialized,
15057 + apc_module_init() installs the my_compile_file() function overriding Zend's
15058 + version. I'll talk about my_compile_file() and the rest of apc_compile.c
15059 + in the next section. For now I will stick with apc_main.c and apc_cache.c
15060 + and talk about the actual caches. A cache consists of a block of shared
15061 + memory returned by apc_sma_allocate() via apc_sma_malloc(). You will
15062 + notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper
15063 + around PHP's own emalloc() function which allocates per-process memory from
15064 + PHP's pool-based memory allocator. Don't confuse apc_emalloc() and
15065 + apc_sma_malloc() as the first is per-process and the second is shared memory.
15066 +
15067 + The cache is stored in/described by this struct allocated locally using
15068 + emalloc():
15069 +
15070 + struct apc_cache_t {
15071 + void* shmaddr; /* process (local) address of shared cache */
15072 + header_t* header; /* cache header (stored in SHM) */
15073 + slot_t** slots; /* array of cache slots (stored in SHM) */
15074 + int num_slots; /* number of slots in cache */
15075 + int gc_ttl; /* maximum time on GC list for a slot */
15076 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
15077 + };
15078 +
15079 + Whenever you see functions that take a 'cache' argument, this is what they
15080 + take. And apc_cache_create() returns a pointer to this populated struct.
15081 +
15082 + At the beginning of the cache we have a header. Remember, we are down a level now
15083 + from the sma stuff. The sma stuff is the low-level shared-memory allocator which
15084 + has its own header which is completely separate and invisible to apc_cache.c.
15085 + As far as apc_cache.c is concerned the block of memory it is working with could
15086 + have come from a call to malloc().
15087 +
15088 + The header looks like this:
15089 +
15090 + typedef struct header_t header_t;
15091 + struct header_t {
15092 + int num_hits; /* total successful hits in cache */
15093 + int num_misses; /* total unsuccessful hits in cache */
15094 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
15095 + };
15096 +
15097 + Since this is at the start of the shared memory segment, these values are accessible
15098 + across all the yapache processes and hence access to them has to be locked.
15099 +
15100 + After the header we have an array of slots. The number of slots is user-defined
15101 + through the apc.num_slots ini hint. Each slot is described by:
15102 +
15103 + typedef struct slot_t slot_t;
15104 + struct slot_t {
15105 + apc_cache_key_t key; /* slot key */
15106 + apc_cache_entry_t* value; /* slot value */
15107 + slot_t* next; /* next slot in linked list */
15108 + int num_hits; /* number of hits to this bucket */
15109 + time_t creation_time; /* time slot was initialized */
15110 + time_t deletion_time; /* time slot was removed from cache */
15111 + time_t access_time; /* time slot was last accessed */
15112 + };
15113 +
15114 + The slot_t *next there is a linked list to other slots that happened to hash to the
15115 + same array position.
15116 +
15117 + apc_cache_insert() shows what happens on a new cache insert.
15118 +
15119 + slot = &cache->slots[hash(key) % cache->num_slots];
15120 +
15121 + cache->slots is our array of slots in the segment. hash() is simply:
15122 +
15123 + static unsigned int hash(apc_cache_key_t key)
15124 + {
15125 + return key.data.file.device + key.data.file.inode;
15126 + }
15127 +
15128 + That is, we use the file's device and inode to uniquely identify it. Initially
15129 + we had used the file's full path, but getting that requires a realpath() call which
15130 + is amazingly expensive since it has to stat each component of the path to resolve
15131 + symlinks and get rid of relative path components. By using the device+inode we
15132 + can uniquely identify a file with a single stat.
15133 +
15134 + So, on an insert we find the array position in the slots array by hasing the device+inode.
15135 + If there are currently no other slots there, we just create the slot and stick it into
15136 + the array:
15137 +
15138 + *slot = make_slot(key, value, *slot, t)
15139 +
15140 + If there are other slots already at this position we walk the link list to get to
15141 + the end. Here is the loop:
15142 +
15143 + while (*slot) {
15144 + if (key_equals((*slot)->key.data.file, key.data.file)) {
15145 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
15146 + if ((*slot)->key.mtime != key.mtime) {
15147 + remove_slot(cache, slot);
15148 + break;
15149 + }
15150 + UNLOCK(cache);
15151 + return 0;
15152 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
15153 + remove_slot(cache, slot);
15154 + continue;
15155 + }
15156 + slot = &(*slot)->next;
15157 + }
15158 +
15159 + That first key_equals() check sees if we have an exact match meaning the file
15160 + is already in the cache. Since we try to find the file in the cache before doing
15161 + an insert, this will generally only happen if another process managed to beat us
15162 + to inserting it. If we have a newer version of the file at this point we remove
15163 + it an insert the new version. If our version is not newer we just return without
15164 + doing anything.
15165 +
15166 + While walking the linked list we also check to see if the cache has a TTL defined.
15167 + If while walking the linked list we see a slot that has expired, we remove it
15168 + since we are right there looking at it. This is the only place we remove stale
15169 + entries unless the shared memory segment fills up and we force a full expunge via
15170 + apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks
15171 + down every linked list removing stale slots to free up room. This is obviously
15172 + slow and thus only happens when we have run out of room.
15173 +
15174 + apc_cache_find() simply hashes and returns the entry if it is there. If it is there
15175 + but older than the mtime in the entry we are looking for, we delete the one that is
15176 + there and return indicating we didn't find it.
15177 +
15178 + Next we need to understand what an actual cache entry looks like. Have a look at
15179 + apc_cache.h for the structs. I sort of glossed over the key part earlier saying
15180 + that we just used the device+inode to find a hash slot. It is actually a bit more
15181 + complex than that because we have two kinds of caches. We have the standard file
15182 + cache containing opcode arrays, but we also have a user-controlled cache that the
15183 + user can insert whatever they want into via apc_store(). For the user cache we
15184 + obviously don't have a device+inode. The actual identifier is provided by the user
15185 + as a char *. So the key is actually a union that looks like this:
15186 +
15187 + typedef union _apc_cache_key_data_t {
15188 + struct {
15189 + int device; /* the filesystem device */
15190 + int inode; /* the filesystem inode */
15191 + } file;
15192 + struct {
15193 + char *identifier;
15194 + } user;
15195 + } apc_cache_key_data_t;
15196 +
15197 + struct apc_cache_key_t {
15198 + apc_cache_key_data_t data;
15199 + int mtime; /* the mtime of this cached entry */
15200 + };
15201 +
15202 + And we have two sets of functions to do inserts and finds. apc_cache_user_find()
15203 + and apc_cache_user_insert() operate on the user cache.
15204 +
15205 + Ok, on to the actual cache entry. Again, because we have two kinds of caches, we
15206 + also have the corresponding two kinds of cache entries described by this union:
15207 +
15208 + typedef union _apc_cache_entry_value_t {
15209 + struct {
15210 + char *filename; /* absolute path to source file */
15211 + zend_op_array* op_array; /* op_array allocated in shared memory */
15212 + apc_function_t* functions; /* array of apc_function_t's */
15213 + apc_class_t* classes; /* array of apc_class_t's */
15214 + } file;
15215 + struct {
15216 + char *info;
15217 + zval *val;
15218 + unsigned int ttl;
15219 + } user;
15220 + } apc_cache_entry_value_t;
15221 +
15222 + And then the actual cache entry:
15223 +
15224 + struct apc_cache_entry_t {
15225 + apc_cache_entry_value_t data;
15226 + unsigned char type;
15227 + int ref_count;
15228 + };
15229 +
15230 + The user entry is pretty simple and not all that important for now. I will
15231 + concentrate on the file entries since that is what holds the actual compiled
15232 + opcode arrays along with the functions and classes required by the executor.
15233 +
15234 + apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
15235 + The main thing to understand here is that we need more than just the opcode
15236 + array, we also need the functions and classes created by the compiler when it
15237 + created the opcode array. As far as the executor is concerned, it doesn't know
15238 + that it isn't operating in normal mode being called right after the parse/compile
15239 + phase, so we need to recreate everything so it looks exactly like it would at
15240 + that point.
15241 +
15242 +7. my_compile_file() and apc_compile.c
15243 +
15244 + my_compile_file() in apc_main.c controls where we get the opcodes from. If
15245 + the user-specified filters exclude the file from being cached, then we just
15246 + call the original compile function and return. Otherwise we fetch the request
15247 + time from Apache to avoid an extra syscall, create the key so we can look up
15248 + the file in the cache. If we find it we stick it on a local stack which we
15249 + use at cleanup time to make sure we return everything back to normal after a
15250 + request and call cached_compile() which installs the functions and classes
15251 + associated with the op_array in this entry and then copy the op_array down
15252 + into our memory space for execution.
15253 +
15254 + If we didn't find the file in the cache, we need to compile it and insert it.
15255 + To compile it we simply call the original compile function:
15256 +
15257 + op_array = old_compile_file(h, type TSRMLS_CC);
15258 +
15259 + To do the insert we need to copy the functions, classes and the opcode array
15260 + the compile phase created into shared memory. This all happens in apc_compile.c
15261 + in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
15262 + functions. Then we make the file entry and do the insert. Both of these
15263 + operations were described in the previous section.
15264 +
15265 +8. The Optimizer
15266 +
15267 + The optimizer has been deprecated.
15268 +
15269 +If you made it to the end of this, you should have a pretty good idea of where things are in
15270 +the code. I skimmed over a lot of things, so plan on spending some time reading through the code.
15271 +
15272 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_001.phpt php-5.2.5/ext/apc/tests/apc_001.phpt
15273 --- php-5.2.5-orig/ext/apc/tests/apc_001.phpt 1969-12-31 18:00:00.000000000 -0600
15274 +++ php-5.2.5/ext/apc/tests/apc_001.phpt 2007-12-26 16:51:32.000000000 -0600
15275 @@ -0,0 +1,27 @@
15276 +--TEST--
15277 +APC: apc_store/fetch with strings
15278 +--SKIPIF--
15279 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15280 +--INI--
15281 +apc.enabled=1
15282 +apc.enable_cli=1
15283 +apc.file_update_protection=0
15284 +--FILE--
15285 +<?php
15286 +
15287 +$foo = 'hello world';
15288 +var_dump($foo);
15289 +apc_store('foo',$foo);
15290 +$bar = apc_fetch('foo');
15291 +var_dump($bar);
15292 +$bar = 'nice';
15293 +var_dump($bar);
15294 +
15295 +?>
15296 +===DONE===
15297 +<?php exit(0); ?>
15298 +--EXPECTF--
15299 +string(11) "hello world"
15300 +string(11) "hello world"
15301 +string(4) "nice"
15302 +===DONE===
15303 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_002.phpt php-5.2.5/ext/apc/tests/apc_002.phpt
15304 --- php-5.2.5-orig/ext/apc/tests/apc_002.phpt 1969-12-31 18:00:00.000000000 -0600
15305 +++ php-5.2.5/ext/apc/tests/apc_002.phpt 2007-12-26 16:51:32.000000000 -0600
15306 @@ -0,0 +1,34 @@
15307 +--TEST--
15308 +APC: apc_store/fetch with objects
15309 +--SKIPIF--
15310 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15311 +--INI--
15312 +apc.enabled=1
15313 +apc.enable_cli=1
15314 +apc.file_update_protection=0
15315 +--FILE--
15316 +<?php
15317 +
15318 +class foo { }
15319 +$foo = new foo;
15320 +var_dump($foo);
15321 +apc_store('foo',$foo);
15322 +unset($foo);
15323 +$bar = apc_fetch('foo');
15324 +var_dump($bar);
15325 +$bar->a = true;
15326 +var_dump($bar);
15327 +
15328 +?>
15329 +===DONE===
15330 +<?php exit(0); ?>
15331 +--EXPECTF--
15332 +object(foo)#%d (0) {
15333 +}
15334 +object(foo)#%d (0) {
15335 +}
15336 +object(foo)#%d (1) {
15337 + ["a"]=>
15338 + bool(true)
15339 +}
15340 +===DONE===
15341 diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_003.phpt php-5.2.5/ext/apc/tests/apc_003.phpt
15342 --- php-5.2.5-orig/ext/apc/tests/apc_003.phpt 1969-12-31 18:00:00.000000000 -0600
15343 +++ php-5.2.5/ext/apc/tests/apc_003.phpt 2007-12-26 16:51:32.000000000 -0600
15344 @@ -0,0 +1,112 @@
15345 +--TEST--
15346 +APC: apc_store/fetch with objects
15347 +--SKIPIF--
15348 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
15349 +--INI--
15350 +apc.enabled=1
15351 +apc.enable_cli=1
15352 +apc.file_update_protection=0
15353 +--FILE--
15354 +<?php
15355 +
15356 +class foo { }
15357 +$foo = new foo;
15358 +var_dump($foo);
15359 +apc_store('foo',$foo);
15360 +unset($foo);
15361 +$bar = apc_fetch('foo');
15362 +var_dump($bar);
15363 +$bar->a = true;
15364 +var_dump($bar);
15365 +
15366 +class bar extends foo
15367 +{
15368 + public $pub = 'bar';
15369 + protected $pro = 'bar';
15370 + private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
15371 +
15372 + function __construct()
15373 + {
15374 + $this->bar = true;
15375 + }
15376 +
15377 + function change()
15378 + {
15379 + $this->pri = 'mod';
15380 + }
15381 +}
15382 +
15383 +class baz extends bar
15384 +{
15385 + private $pri = 'baz';
15386 +
15387 + function __construct()
15388 + {
15389 + parent::__construct();
15390 + $this->baz = true;
15391 + }
15392 +}
15393 +
15394 +$baz = new baz;
15395 +var_dump($baz);
15396 +$baz->change();
15397 +var_dump($baz);
15398 +apc_store('baz', $baz);
15399 +unset($baz);
15400 +var_dump(apc_fetch('baz'));
15401 +
15402 +?>
15403 +===DONE===
15404 +<?php exit(0); ?>
15405 +--EXPECTF--
15406 +object(foo)#%d (0) {
15407 +}
15408 +object(foo)#%d (0) {
15409 +}
15410 +object(foo)#%d (1) {
15411 + ["a"]=>
15412 + bool(true)
15413 +}
15414 +object(baz)#%d (6) {
15415 + ["pri:private"]=>
15416 + string(3) "baz"
15417 + ["pub"]=>
15418 + string(3) "bar"
15419 + ["pro:protected"]=>
15420 + string(3) "bar"
15421 + ["pri:private"]=>
15422 + string(3) "bar"
15423 + ["bar"]=>
15424 + bool(true)
15425 + ["baz"]=>
15426 + bool(true)
15427 +}
15428 +object(baz)#%d (6) {
15429 + ["pri:private"]=>
15430 + string(3) "baz"
15431 + ["pub"]=>
15432 + string(3) "bar"
15433 + ["pro:protected"]=>
15434 + string(3) "bar"
15435 + ["pri:private"]=>
15436 + string(3) "mod"
15437 + ["bar"]=>
15438 + bool(true)
15439 + ["baz"]=>
15440 + bool(true)
15441 +}
15442 +object(baz)#%d (6) {
15443 + ["pri:private"]=>
15444 + string(3) "baz"
15445 + ["pub"]=>
15446 + string(3) "bar"
15447 + ["pro:protected"]=>
15448 + string(3) "bar"
15449 + ["pri:private"]=>
15450 + string(3) "mod"
15451 + ["bar"]=>
15452 + bool(true)
15453 + ["baz"]=>
15454 + bool(true)
15455 +}
15456 +===DONE===
15457 diff -ubrN php-5.2.5-orig/ext/apc/tests/skipif.inc php-5.2.5/ext/apc/tests/skipif.inc
15458 --- php-5.2.5-orig/ext/apc/tests/skipif.inc 1969-12-31 18:00:00.000000000 -0600
15459 +++ php-5.2.5/ext/apc/tests/skipif.inc 2007-12-26 16:51:32.000000000 -0600
15460 @@ -0,0 +1,6 @@
15461 +<?php
15462 +
15463 +if (!extension_loaded("apc")) die("skip");
15464 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
15465 +
15466 +?>
15467 diff -ubrN php-5.2.5-orig/ext/apc/TODO php-5.2.5/ext/apc/TODO
15468 --- php-5.2.5-orig/ext/apc/TODO 1969-12-31 18:00:00.000000000 -0600
15469 +++ php-5.2.5/ext/apc/TODO 2007-12-26 16:51:32.000000000 -0600
15470 @@ -0,0 +1,30 @@
15471 +Known Bugs
15472 +
15473 +1. Gallery2 doesn't work with PHP5+APC. There is something wrong
15474 + with the way methods are restored in some edge case I haven't
15475 + been able to figure out yet.
15476 + To reproduce install gallery2 and click down to an individual photo.
15477 +
15478 +2. apc_store() probably needs some checks to skip trying to store
15479 + internal classes. Something along the lines of:
15480 +
15481 + if(Z_TYPE_P(val) == IS_OBJECT) {
15482 + zend_class_entry *ce = Z_OBJCE_P(val);
15483 + if(ce->type == ZEND_INTERNAL_CLASS) {
15484 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
15485 + RETURN_FALSE;
15486 + }
15487 + }
15488 +
15489 + in the apc_store() function in php_apc.c but I am wondering if it needs to do more
15490 + than that.
15491 +
15492 +Enhancements
15493 +
15494 +1. Some faster platform-specific locking mechanisms wouldd be nice. futex support
15495 + for the 2.6 Linux kernels, and/or x86-specific spinlock support.
15496 +
15497 +2. The optimizer needs a lot of work.
15498 +
15499 +3. Assert() elimination in the optimizer when some debug flag somewhere isn't set.
15500 +