php5:
[openwrt/svn-archive/archive.git] / lang / php5 / patches / 005-APC.patch
1 Index: php-5.2.4/ext/apc/apc.c
2 ===================================================================
3 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4 +++ php-5.2.4/ext/apc/apc.c 2007-09-02 12:24:46.000000000 +0200
5 @@ -0,0 +1,554 @@
6 +/*
7 + +----------------------------------------------------------------------+
8 + | APC |
9 + +----------------------------------------------------------------------+
10 + | Copyright (c) 2006 The PHP Group |
11 + +----------------------------------------------------------------------+
12 + | This source file is subject to version 3.01 of the PHP license, |
13 + | that is bundled with this package in the file LICENSE, and is |
14 + | available through the world-wide-web at the following url: |
15 + | http://www.php.net/license/3_01.txt |
16 + | If you did not receive a copy of the PHP license and are unable to |
17 + | obtain it through the world-wide-web, please send a note to |
18 + | license@php.net so we can mail you a copy immediately. |
19 + +----------------------------------------------------------------------+
20 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
21 + | George Schlossnagle <george@omniti.com> |
22 + | Rasmus Lerdorf <rasmus@php.net> |
23 + | Arun C. Murthy <arunc@yahoo-inc.com> |
24 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
25 + +----------------------------------------------------------------------+
26 +
27 + This software was contributed to PHP by Community Connect Inc. in 2002
28 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
29 + Future revisions and derivatives of this source code must acknowledge
30 + Community Connect Inc. as the original contributor of this module by
31 + leaving this note intact in the source code.
32 +
33 + All other licensing and usage conditions are those of the PHP Group.
34 +
35 + */
36 +
37 +/* $Id: apc.c,v 3.17 2007/03/17 14:01:41 gopalv Exp $ */
38 +
39 +#include "apc.h"
40 +#include <regex.h> /* for POSIX regular expressions */
41 +#include "php.h"
42 +
43 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
44 +
45 +/* {{{ memory allocation wrappers */
46 +
47 +void* apc_emalloc(size_t n)
48 +{
49 + void* p = malloc(n);
50 + if (p == NULL) {
51 + apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
52 + }
53 + return p;
54 +}
55 +
56 +void* apc_erealloc(void* p, size_t n)
57 +{
58 + p = realloc(p, n);
59 + if (p == NULL) {
60 + apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
61 + }
62 + return p;
63 +}
64 +
65 +void apc_efree(void* p)
66 +{
67 + if (p == NULL) {
68 + apc_eprint("apc_efree: attempt to free null pointer");
69 + }
70 + free(p);
71 +}
72 +
73 +char* apc_estrdup(const char* s)
74 +{
75 + int len;
76 + char* dup;
77 +
78 + if (s == NULL) {
79 + return NULL;
80 + }
81 + len = strlen(s);
82 + dup = (char*) malloc(len+1);
83 + if (dup == NULL) {
84 + apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
85 + }
86 + memcpy(dup, s, len);
87 + dup[len] = '\0';
88 + return dup;
89 +}
90 +
91 +void* apc_xstrdup(const char* s, apc_malloc_t f)
92 +{
93 + return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
94 +}
95 +
96 +void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
97 +{
98 + void* q;
99 +
100 + if (p != NULL && (q = f(n)) != NULL) {
101 + memcpy(q, p, n);
102 + return q;
103 + }
104 + return NULL;
105 +}
106 +
107 +/* }}} */
108 +
109 +/* {{{ console display functions */
110 +
111 +static void my_log(int level, const char* fmt, va_list args)
112 +{
113 + static const char* level_strings[] = {
114 + "apc-debug",
115 + "apc-notice",
116 + "apc-warning",
117 + "apc-error"
118 + };
119 + static const int num_levels = NELEMS(level_strings);
120 +
121 + time_t now;
122 + char* buf; /* for ctime */
123 +
124 + fflush(stdout);
125 +
126 + if (level < 0)
127 + level = 0;
128 + else if (level >= num_levels)
129 + level = num_levels-1;
130 +
131 + now = time(0);
132 + buf = ctime(&now); /* TODO: replace with reentrant impl */
133 + buf[24] = '\0';
134 +
135 + fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
136 + vfprintf(stderr, fmt, args);
137 +
138 + if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
139 + fprintf(stderr, " %s", strerror(errno));
140 + }
141 + fprintf(stderr, "\n");
142 +
143 + if (level == APC_ERROR) {
144 + exit(2);
145 + }
146 +}
147 +
148 +void apc_log(int level, const char* fmt, ...)
149 +{
150 + va_list args;
151 + va_start(args, fmt);
152 + my_log(level, fmt, args);
153 + va_end(args);
154 +}
155 +
156 +void apc_eprint(const char* fmt, ...)
157 +{
158 + va_list args;
159 + va_start(args, fmt);
160 + my_log(APC_ERROR, fmt, args);
161 + va_end(args);
162 +}
163 +
164 +void apc_wprint(const char* fmt, ...)
165 +{
166 + va_list args;
167 + va_start(args, fmt);
168 + my_log(APC_WARNING, fmt, args);
169 + va_end(args);
170 +}
171 +
172 +void apc_nprint(const char* fmt, ...)
173 +{
174 + va_list args;
175 + va_start(args, fmt);
176 + my_log(APC_NOTICE, fmt, args);
177 + va_end(args);
178 +}
179 +
180 +void apc_dprint(const char* fmt, ...)
181 +{
182 +#ifdef APC_DBG
183 + va_list args;
184 + va_start(args, fmt);
185 + my_log(APC_DBG, fmt, args);
186 + va_end(args);
187 +#endif
188 +}
189 +
190 +/* }}} */
191 +
192 +/* {{{ string and text manipulation */
193 +
194 +char* apc_append(const char* s, const char* t)
195 +{
196 + int slen;
197 + int tlen;
198 + char* p;
199 +
200 + slen = strlen(s);
201 + tlen = strlen(t);
202 +
203 + p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
204 + memcpy(p, s, slen);
205 + memcpy(p + slen, t, tlen + 1);
206 +
207 + return p;
208 +}
209 +
210 +char* apc_substr(const char* s, int start, int length)
211 +{
212 + char* substr;
213 + int src_len = strlen(s);
214 +
215 + /* bring start into range */
216 + if (start < 0) {
217 + start = 0;
218 + }
219 + else if (start >= src_len) {
220 + start = src_len - 1;
221 + }
222 +
223 + /* bring length into range */
224 + if (length < 0 || src_len - start < length) {
225 + length = src_len - start;
226 + }
227 +
228 + /* create the substring */
229 + substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
230 + substr[length] = '\0';
231 + return substr;
232 +}
233 +
234 +char** apc_tokenize(const char* s, char delim)
235 +{
236 + char** tokens; /* array of tokens, NULL terminated */
237 + int size; /* size of tokens array */
238 + int n; /* index of next token in tokens array */
239 + int cur; /* current position in input string */
240 + int end; /* final legal position in input string */
241 + int next; /* position of next delimiter in input */
242 +
243 + if (!s) {
244 + return NULL;
245 + }
246 +
247 + size = 2;
248 + n = 0;
249 + cur = 0;
250 + end = strlen(s) - 1;
251 +
252 + tokens = (char**) apc_emalloc(size * sizeof(char*));
253 + tokens[n] = NULL;
254 +
255 + while (cur <= end) {
256 + /* search for the next delimiter */
257 + char* p = strchr(s + cur, delim);
258 + next = p ? p-s : end+1;
259 +
260 + /* resize token array if necessary */
261 + if (n == size-1) {
262 + size *= 2;
263 + tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
264 + }
265 +
266 + /* save the current token */
267 + tokens[n] = apc_substr(s, cur, next-cur);
268 +
269 + tokens[++n] = NULL;
270 + cur = next + 1;
271 + }
272 +
273 + return tokens;
274 +}
275 +
276 +/* }}} */
277 +
278 +/* {{{ filesystem functions */
279 +
280 +#ifdef PHP_WIN32
281 +int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
282 +{
283 + char rpath[MAXPATHLEN];
284 + BY_HANDLE_FILE_INFORMATION fi;
285 + HANDLE f;
286 +
287 + if (VCWD_STAT(path, buf)) {
288 + return -1;
289 + }
290 +
291 + VCWD_REALPATH(path, rpath);
292 + f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
293 + GetFileInformationByHandle(f, &fi);
294 + buf->st_ino = (ino_t)fi.nFileIndexLow;
295 + CloseHandle (f);
296 + return 0;
297 +}
298 +#endif
299 +
300 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
301 +{
302 + char** paths;
303 + char *exec_fname;
304 + int exec_fname_length;
305 + int found = 0;
306 + int i;
307 + TSRMLS_FETCH();
308 +
309 + assert(filename && fileinfo);
310 +
311 + if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
312 + strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
313 + return 0;
314 + }
315 +
316 + paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
317 + if (!paths)
318 + return -1;
319 +
320 + /* for each directory in paths, look for filename inside */
321 + for (i = 0; paths[i]; i++) {
322 + snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
323 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
324 + found = 1;
325 + break;
326 + }
327 + }
328 +
329 + /* check in path of the calling scripts' current working directory */
330 + /* modified from main/streams/plain_wrapper.c */
331 + if(!found && zend_is_executing(TSRMLS_C)) {
332 + exec_fname = zend_get_executed_filename(TSRMLS_C);
333 + exec_fname_length = strlen(exec_fname);
334 + while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
335 + if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
336 + /* not: [no active file] or no path */
337 + memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
338 + fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
339 + strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
340 + /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
341 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
342 + found = 1;
343 + }
344 + }
345 + }
346 +
347 + /* free the value returned by apc_tokenize */
348 + for (i = 0; paths[i]; i++) {
349 + apc_efree(paths[i]);
350 + }
351 + apc_efree(paths);
352 +
353 + return found ? 0 : -1;
354 +}
355 +
356 +/* }}} */
357 +
358 +/* {{{ regular expression wrapper functions */
359 +
360 +typedef struct {
361 + regex_t *reg;
362 + unsigned char type;
363 +} apc_regex;
364 +
365 +void* apc_regex_compile_array(char* patterns[])
366 +{
367 + apc_regex** regs;
368 + int npat;
369 + int i;
370 +
371 + if (!patterns)
372 + return NULL;
373 +
374 + /* count the number of patterns in patterns */
375 + for (npat = 0; patterns[npat] != NULL; npat++) {}
376 +
377 + if (npat == 0)
378 + return NULL;
379 +
380 + /* allocate the array of compiled expressions */
381 + regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
382 + for (i = 0; i <= npat; i++) {
383 + regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
384 + regs[i]->reg = NULL;
385 + regs[i]->type = APC_NEGATIVE_MATCH;
386 + }
387 +
388 + /* compile the expressions */
389 + for (i = 0; i < npat; i++) {
390 + char *pattern = patterns[i];
391 + if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
392 + else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
393 +
394 + regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
395 +
396 + if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
397 + apc_wprint("apc_regex_compile_array: invalid expression '%s'",
398 + pattern);
399 +
400 + apc_regex_destroy_array(regs);
401 +
402 + return NULL;
403 + }
404 + }
405 +
406 + return (void*) regs;
407 +}
408 +
409 +void apc_regex_destroy_array(void* p)
410 +{
411 + if (p != NULL) {
412 + apc_regex** regs = (apc_regex**) p;
413 + int i;
414 +
415 + for (i = 0; regs[i]->reg != NULL; i++) {
416 + regfree(regs[i]->reg);
417 + apc_efree(regs[i]->reg);
418 + apc_efree(regs[i]);
419 + }
420 + apc_efree(regs);
421 + }
422 +}
423 +
424 +int apc_regex_match_array(void* p, const char* input)
425 +{
426 + apc_regex** regs;
427 + int i;
428 +
429 + if (!p)
430 + return 0;
431 +
432 + regs = (apc_regex**) p;
433 + for (i = 0; regs[i]->reg != NULL; i++)
434 + if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
435 + return (int)(regs[i]->type);
436 +
437 + return 0;
438 +}
439 +
440 +/* }}} */
441 +
442 +/* {{{ crc32 implementation */
443 +
444 +/* this table was generated by crc32gen() */
445 +static unsigned int crc32tab[] = {
446 + /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
447 + /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
448 + /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
449 + /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
450 + /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
451 + /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
452 + /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
453 + /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
454 + /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
455 + /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
456 + /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
457 + /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
458 + /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
459 + /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
460 + /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
461 + /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
462 + /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
463 + /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
464 + /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
465 + /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
466 + /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
467 + /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
468 + /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
469 + /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
470 + /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
471 + /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
472 + /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
473 + /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
474 + /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
475 + /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
476 + /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
477 + /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
478 + /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
479 + /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
480 + /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
481 + /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
482 + /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
483 + /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
484 + /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
485 + /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
486 + /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
487 + /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
488 + /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
489 + /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
490 + /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
491 + /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
492 + /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
493 + /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
494 + /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
495 + /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
496 + /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
497 + /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
498 + /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
499 + /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
500 + /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
501 + /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
502 + /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
503 + /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
504 + /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
505 + /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
506 + /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
507 + /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
508 + /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
509 + /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
510 +};
511 +
512 +unsigned int apc_crc32(const char* buf, int len)
513 +{
514 + int i;
515 + int k;
516 + unsigned int crc;
517 +
518 + /* preconditioning */
519 + crc = 0xFFFFFFFF;
520 +
521 + for (i = 0; i < len; i++) {
522 + k = (crc ^ buf[i]) & 0x000000FF;
523 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
524 + }
525 +
526 + /* postconditioning */
527 + return ~crc;
528 +}
529 +
530 +/* crc32gen: generate the nth (0..255) crc32 table value */
531 +#if 0
532 +static unsigned long crc32gen(int n)
533 +{
534 + int i;
535 + unsigned long crc;
536 +
537 + crc = n;
538 + for (i = 8; i >= 0; i--) {
539 + if (crc & 1) {
540 + crc = (crc >> 1) ^ 0xEDB88320;
541 + }
542 + else {
543 + crc >>= 1;
544 + }
545 + }
546 + return crc;
547 +}
548 +#endif
549 +
550 +/* }}} */
551 +
552 +/*
553 + * Local variables:
554 + * tab-width: 4
555 + * c-basic-offset: 4
556 + * End:
557 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
558 + * vim<600: expandtab sw=4 ts=4 sts=4
559 + */
560 Index: php-5.2.4/ext/apc/apc_cache.c
561 ===================================================================
562 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
563 +++ php-5.2.4/ext/apc/apc_cache.c 2007-09-02 12:24:46.000000000 +0200
564 @@ -0,0 +1,1328 @@
565 +/*
566 + +----------------------------------------------------------------------+
567 + | APC |
568 + +----------------------------------------------------------------------+
569 + | Copyright (c) 2006 The PHP Group |
570 + +----------------------------------------------------------------------+
571 + | This source file is subject to version 3.01 of the PHP license, |
572 + | that is bundled with this package in the file LICENSE, and is |
573 + | available through the world-wide-web at the following url: |
574 + | http://www.php.net/license/3_01.txt |
575 + | If you did not receive a copy of the PHP license and are unable to |
576 + | obtain it through the world-wide-web, please send a note to |
577 + | license@php.net so we can mail you a copy immediately. |
578 + +----------------------------------------------------------------------+
579 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
580 + | Rasmus Lerdorf <rasmus@php.net> |
581 + | Arun C. Murthy <arunc@yahoo-inc.com> |
582 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
583 + +----------------------------------------------------------------------+
584 +
585 + This software was contributed to PHP by Community Connect Inc. in 2002
586 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
587 + Future revisions and derivatives of this source code must acknowledge
588 + Community Connect Inc. as the original contributor of this module by
589 + leaving this note intact in the source code.
590 +
591 + All other licensing and usage conditions are those of the PHP Group.
592 +
593 + */
594 +
595 +/* $Id: apc_cache.c,v 3.140 2007/04/02 22:57:10 rasmus Exp $ */
596 +
597 +#include "apc_cache.h"
598 +#include "apc_lock.h"
599 +#include "apc_sma.h"
600 +#include "apc_globals.h"
601 +#include "SAPI.h"
602 +#include "ext/standard/php_var.h"
603 +#include "ext/standard/php_smart_str.h"
604 +
605 +/* TODO: rehash when load factor exceeds threshold */
606 +
607 +#define CHECK(p) { if ((p) == NULL) return NULL; }
608 +
609 +/* {{{ locking macros */
610 +#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock)
611 +#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
612 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
613 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
614 +#define UNLOCK(c) { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
615 +/* }}} */
616 +
617 +/* {{{ struct definition: slot_t */
618 +typedef struct slot_t slot_t;
619 +struct slot_t {
620 + apc_cache_key_t key; /* slot key */
621 + apc_cache_entry_t* value; /* slot value */
622 + slot_t* next; /* next slot in linked list */
623 + int num_hits; /* number of hits to this bucket */
624 + time_t creation_time; /* time slot was initialized */
625 + time_t deletion_time; /* time slot was removed from cache */
626 + time_t access_time; /* time slot was last accessed */
627 +};
628 +/* }}} */
629 +
630 +/* {{{ struct definition: header_t
631 + Any values that must be shared among processes should go in here. */
632 +typedef struct header_t header_t;
633 +struct header_t {
634 + apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */
635 + apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */
636 + int num_hits; /* total successful hits in cache */
637 + int num_misses; /* total unsuccessful hits in cache */
638 + int num_inserts; /* total successful inserts in cache */
639 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
640 + time_t start_time; /* time the above counters were reset */
641 + int expunges; /* total number of expunges */
642 + zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */
643 + int num_entries; /* Statistic on the number of entries */
644 + size_t mem_size; /* Statistic on the memory size used by this cache */
645 +};
646 +/* }}} */
647 +
648 +/* {{{ struct definition: apc_cache_t */
649 +struct apc_cache_t {
650 + void* shmaddr; /* process (local) address of shared cache */
651 + header_t* header; /* cache header (stored in SHM) */
652 + slot_t** slots; /* array of cache slots (stored in SHM) */
653 + int num_slots; /* number of slots in cache */
654 + int gc_ttl; /* maximum time on GC list for a slot */
655 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
656 +};
657 +/* }}} */
658 +
659 +/* {{{ struct definition local_slot_t */
660 +typedef struct local_slot_t local_slot_t;
661 +struct local_slot_t {
662 + slot_t *original; /* the original slot in shm */
663 + int num_hits; /* number of hits */
664 + apc_cache_entry_t *value; /* shallow copy of slot->value */
665 + local_slot_t *next; /* only for dead list */
666 +};
667 +/* }}} */
668 +/* {{{ struct definition apc_local_cache_t */
669 +struct apc_local_cache_t {
670 + apc_cache_t* shmcache; /* the real cache in shm */
671 + local_slot_t* slots; /* process (local) cache of objects */
672 + local_slot_t* dead_list; /* list of objects pending removal */
673 + int num_slots; /* number of slots in cache */
674 + int ttl; /* time to live */
675 + int num_hits; /* number of hits */
676 + int generation; /* every generation lives between expunges */
677 +};
678 +/* }}} */
679 +
680 +/* {{{ key_equals */
681 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
682 +/* }}} */
683 +
684 +/* {{{ hash */
685 +static unsigned int hash(apc_cache_key_t key)
686 +{
687 + return key.data.file.device + key.data.file.inode;
688 +}
689 +/* }}} */
690 +
691 +/* {{{ string_nhash_8 */
692 +static unsigned int string_nhash_8(const char *s, size_t len)
693 +{
694 + register const unsigned int *iv = (const unsigned int *)s;
695 + register unsigned int h = 0;
696 + register const unsigned int *e = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
697 +
698 + for(;iv<e;iv++) {
699 + h += *iv;
700 + h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
701 + }
702 + s = (const char *)iv;
703 + for(len %= sizeof(unsigned int);len;len--) {
704 + h += *(s++);
705 + }
706 + h ^= (h >> 13);
707 + h ^= (h >> 7);
708 + return h;
709 +}
710 +/* }}} */
711 +
712 +/* {{{ make_slot */
713 +slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
714 +{
715 + slot_t* p = apc_sma_malloc(sizeof(slot_t));
716 + if (!p) return NULL;
717 +
718 + if(value->type == APC_CACHE_ENTRY_USER) {
719 + char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
720 + if (!identifier) {
721 + apc_sma_free(p);
722 + return NULL;
723 + }
724 + key.data.user.identifier = identifier;
725 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
726 + char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
727 + if (!fullpath) {
728 + apc_sma_free(p);
729 + return NULL;
730 + }
731 + key.data.fpfile.fullpath = fullpath;
732 + }
733 + p->key = key;
734 + p->value = value;
735 + p->next = next;
736 + p->num_hits = 0;
737 + p->creation_time = t;
738 + p->access_time = t;
739 + p->deletion_time = 0;
740 + return p;
741 +}
742 +/* }}} */
743 +
744 +/* {{{ free_slot */
745 +static void free_slot(slot_t* slot)
746 +{
747 + if(slot->value->type == APC_CACHE_ENTRY_USER) {
748 + apc_sma_free((char *)slot->key.data.user.identifier);
749 + } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
750 + apc_sma_free((char *)slot->key.data.fpfile.fullpath);
751 + }
752 + apc_cache_free_entry(slot->value);
753 + apc_sma_free(slot);
754 +}
755 +/* }}} */
756 +
757 +/* {{{ remove_slot */
758 +static void remove_slot(apc_cache_t* cache, slot_t** slot)
759 +{
760 + slot_t* dead = *slot;
761 + *slot = (*slot)->next;
762 +
763 + cache->header->mem_size -= dead->value->mem_size;
764 + cache->header->num_entries--;
765 + if (dead->value->ref_count <= 0) {
766 + free_slot(dead);
767 + }
768 + else {
769 + dead->next = cache->header->deleted_list;
770 + dead->deletion_time = time(0);
771 + cache->header->deleted_list = dead;
772 + }
773 +}
774 +/* }}} */
775 +
776 +/* {{{ process_pending_removals */
777 +static void process_pending_removals(apc_cache_t* cache)
778 +{
779 + slot_t** slot;
780 + time_t now;
781 +
782 + /* This function scans the list of removed cache entries and deletes any
783 + * entry whose reference count is zero (indicating that it is no longer
784 + * being executed) or that has been on the pending list for more than
785 + * cache->gc_ttl seconds (we issue a warning in the latter case).
786 + */
787 +
788 + if (!cache->header->deleted_list)
789 + return;
790 +
791 + slot = &cache->header->deleted_list;
792 + now = time(0);
793 +
794 + while (*slot != NULL) {
795 + int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
796 +
797 + if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
798 + slot_t* dead = *slot;
799 +
800 + if (dead->value->ref_count > 0) {
801 + switch(dead->value->type) {
802 + case APC_CACHE_ENTRY_FILE:
803 + apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
804 + "was on gc-list for %d seconds", dead->value->data.file.filename,
805 + dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
806 + break;
807 + case APC_CACHE_ENTRY_USER:
808 + apc_log(APC_WARNING, "GC cache entry '%s' "
809 + "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
810 + break;
811 + }
812 + }
813 + *slot = dead->next;
814 + free_slot(dead);
815 + }
816 + else {
817 + slot = &(*slot)->next;
818 + }
819 + }
820 +}
821 +/* }}} */
822 +
823 +/* {{{ prevent_garbage_collection */
824 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
825 +{
826 + /* set reference counts on zend objects to an arbitrarily high value to
827 + * prevent garbage collection after execution */
828 +
829 + enum { BIG_VALUE = 1000 };
830 +
831 + if(entry->data.file.op_array) {
832 + entry->data.file.op_array->refcount[0] = BIG_VALUE;
833 + }
834 + if (entry->data.file.functions) {
835 + int i;
836 + apc_function_t* fns = entry->data.file.functions;
837 + for (i=0; fns[i].function != NULL; i++) {
838 +#ifdef ZEND_ENGINE_2
839 + *(fns[i].function->op_array.refcount) = BIG_VALUE;
840 +#else
841 + fns[i].function->op_array.refcount[0] = BIG_VALUE;
842 +#endif
843 + }
844 + }
845 + if (entry->data.file.classes) {
846 + int i;
847 + apc_class_t* classes = entry->data.file.classes;
848 + for (i=0; classes[i].class_entry != NULL; i++) {
849 +#ifdef ZEND_ENGINE_2
850 + classes[i].class_entry->refcount = BIG_VALUE;
851 +#else
852 + classes[i].class_entry->refcount[0] = BIG_VALUE;
853 +#endif
854 + }
855 + }
856 +}
857 +/* }}} */
858 +
859 +/* {{{ apc_cache_create */
860 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
861 +{
862 + apc_cache_t* cache;
863 + int cache_size;
864 + int num_slots;
865 + int i;
866 +
867 + num_slots = size_hint > 0 ? size_hint*2 : 2000;
868 +
869 + cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
870 + cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
871 +
872 + cache->shmaddr = apc_sma_malloc(cache_size);
873 + memset(cache->shmaddr, 0, cache_size);
874 +
875 + cache->header = (header_t*) cache->shmaddr;
876 + cache->header->num_hits = 0;
877 + cache->header->num_misses = 0;
878 + cache->header->deleted_list = NULL;
879 + cache->header->start_time = time(NULL);
880 + cache->header->expunges = 0;
881 + cache->header->busy = 0;
882 +
883 + cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
884 + cache->num_slots = num_slots;
885 + cache->gc_ttl = gc_ttl;
886 + cache->ttl = ttl;
887 + CREATE_LOCK(cache->header->lock);
888 +#if NONBLOCKING_LOCK_AVAILABLE
889 + CREATE_LOCK(cache->header->wrlock);
890 +#endif
891 + for (i = 0; i < num_slots; i++) {
892 + cache->slots[i] = NULL;
893 + }
894 +
895 + return cache;
896 +}
897 +/* }}} */
898 +
899 +/* {{{ apc_cache_destroy */
900 +void apc_cache_destroy(apc_cache_t* cache)
901 +{
902 + DESTROY_LOCK(cache);
903 + apc_efree(cache);
904 +}
905 +/* }}} */
906 +
907 +/* {{{ apc_cache_clear */
908 +void apc_cache_clear(apc_cache_t* cache)
909 +{
910 + int i;
911 +
912 + if(!cache) return;
913 +
914 + LOCK(cache);
915 + cache->header->busy = 1;
916 + cache->header->num_hits = 0;
917 + cache->header->num_misses = 0;
918 + cache->header->start_time = time(NULL);
919 + cache->header->expunges = 0;
920 +
921 + for (i = 0; i < cache->num_slots; i++) {
922 + slot_t* p = cache->slots[i];
923 + while (p) {
924 + remove_slot(cache, &p);
925 + }
926 + cache->slots[i] = NULL;
927 + }
928 +
929 + cache->header->busy = 0;
930 + UNLOCK(cache);
931 +}
932 +/* }}} */
933 +
934 +/* {{{ apc_cache_expunge */
935 +void apc_cache_expunge(apc_cache_t* cache, time_t t)
936 +{
937 + int i;
938 +
939 + if(!cache) return;
940 +
941 + if(!cache->ttl) {
942 + /*
943 + * If cache->ttl is not set, we wipe out the entire cache when
944 + * we run out of space.
945 + */
946 + LOCK(cache);
947 + cache->header->busy = 1;
948 + cache->header->expunges++;
949 + for (i = 0; i < cache->num_slots; i++) {
950 + slot_t* p = cache->slots[i];
951 + while (p) {
952 + remove_slot(cache, &p);
953 + }
954 + cache->slots[i] = NULL;
955 + }
956 + cache->header->busy = 0;
957 + UNLOCK(cache);
958 + } else {
959 + slot_t **p;
960 +
961 + /*
962 + * If the ttl for the cache is set we walk through and delete stale
963 + * entries. For the user cache that is slightly confusing since
964 + * we have the individual entry ttl's we can look at, but that would be
965 + * too much work. So if you want the user cache expunged, set a high
966 + * default apc.user_ttl and still provide a specific ttl for each entry
967 + * on insert
968 + */
969 +
970 + LOCK(cache);
971 + cache->header->busy = 1;
972 + cache->header->expunges++;
973 + for (i = 0; i < cache->num_slots; i++) {
974 + p = &cache->slots[i];
975 + while(*p) {
976 + /*
977 + * For the user cache we look at the individual entry ttl values
978 + * and if not set fall back to the default ttl for the user cache
979 + */
980 + if((*p)->value->type == APC_CACHE_ENTRY_USER) {
981 + if((*p)->value->data.user.ttl) {
982 + if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
983 + remove_slot(cache, p);
984 + continue;
985 + }
986 + } else if(cache->ttl) {
987 + if((*p)->creation_time + cache->ttl < t) {
988 + remove_slot(cache, p);
989 + continue;
990 + }
991 + }
992 + } else if((*p)->access_time < (t - cache->ttl)) {
993 + remove_slot(cache, p);
994 + continue;
995 + }
996 + p = &(*p)->next;
997 + }
998 + }
999 + cache->header->busy = 0;
1000 + UNLOCK(cache);
1001 + }
1002 +}
1003 +/* }}} */
1004 +
1005 +/* {{{ apc_cache_insert */
1006 +int apc_cache_insert(apc_cache_t* cache,
1007 + apc_cache_key_t key,
1008 + apc_cache_entry_t* value,
1009 + time_t t)
1010 +{
1011 + slot_t** slot;
1012 +
1013 + if (!value) {
1014 + return 0;
1015 + }
1016 +
1017 +#ifdef __DEBUG_APC__
1018 + fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
1019 +#endif
1020 +
1021 + LOCK(cache);
1022 + process_pending_removals(cache);
1023 +
1024 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1025 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1026 +
1027 + while(*slot) {
1028 + if(key.type == (*slot)->key.type) {
1029 + if(key.type == APC_CACHE_KEY_FILE) {
1030 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1031 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
1032 + if ((*slot)->key.mtime != key.mtime) {
1033 + remove_slot(cache, slot);
1034 + break;
1035 + }
1036 + UNLOCK(cache);
1037 + return 0;
1038 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1039 + remove_slot(cache, slot);
1040 + continue;
1041 + }
1042 + } else { /* APC_CACHE_KEY_FPFILE */
1043 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1044 + /* Hrm.. it's already here, remove it and insert new one */
1045 + remove_slot(cache, slot);
1046 + break;
1047 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1048 + remove_slot(cache, slot);
1049 + continue;
1050 + }
1051 + }
1052 + }
1053 + slot = &(*slot)->next;
1054 + }
1055 +
1056 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1057 + UNLOCK(cache);
1058 + return -1;
1059 + }
1060 +
1061 + cache->header->mem_size += value->mem_size;
1062 + cache->header->num_entries++;
1063 + cache->header->num_inserts++;
1064 +
1065 + UNLOCK(cache);
1066 + return 1;
1067 +}
1068 +/* }}} */
1069 +
1070 +/* {{{ apc_cache_user_insert */
1071 +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)
1072 +{
1073 + slot_t** slot;
1074 + size_t* mem_size_ptr = NULL;
1075 +
1076 + if (!value) {
1077 + return 0;
1078 + }
1079 +
1080 + LOCK(cache);
1081 + process_pending_removals(cache);
1082 +
1083 + slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
1084 +
1085 + if (APCG(mem_size_ptr) != NULL) {
1086 + mem_size_ptr = APCG(mem_size_ptr);
1087 + APCG(mem_size_ptr) = NULL;
1088 + }
1089 +
1090 + while (*slot) {
1091 + if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
1092 + /*
1093 + * At this point we have found the user cache entry. If we are doing
1094 + * an exclusive insert (apc_add) we are going to bail right away if
1095 + * the user entry already exists and it has no ttl, or
1096 + * there is a ttl and the entry has not timed out yet.
1097 + */
1098 + if(exclusive && ( !(*slot)->value->data.user.ttl ||
1099 + ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t )
1100 + ) ) {
1101 + UNLOCK(cache);
1102 + return 0;
1103 + }
1104 + remove_slot(cache, slot);
1105 + break;
1106 + } else
1107 + /*
1108 + * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of
1109 + * slot entries so we don't always have to skip past a bunch of stale entries. We check
1110 + * for staleness here and get rid of them by first checking to see if the cache has a global
1111 + * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
1112 + * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
1113 + */
1114 + if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) ||
1115 + ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
1116 + remove_slot(cache, slot);
1117 + continue;
1118 + }
1119 + slot = &(*slot)->next;
1120 + }
1121 +
1122 + if (mem_size_ptr != NULL) {
1123 + APCG(mem_size_ptr) = mem_size_ptr;
1124 + }
1125 +
1126 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1127 + UNLOCK(cache);
1128 + return 0;
1129 + }
1130 + if (APCG(mem_size_ptr) != NULL) {
1131 + value->mem_size = *APCG(mem_size_ptr);
1132 + cache->header->mem_size += *APCG(mem_size_ptr);
1133 + }
1134 + cache->header->num_entries++;
1135 + cache->header->num_inserts++;
1136 +
1137 + UNLOCK(cache);
1138 + return 1;
1139 +}
1140 +/* }}} */
1141 +
1142 +/* {{{ apc_cache_find_slot */
1143 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1144 +{
1145 + slot_t** slot;
1146 + volatile slot_t* retval = NULL;
1147 +
1148 + LOCK(cache);
1149 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1150 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1151 +
1152 + while (*slot) {
1153 + if(key.type == (*slot)->key.type) {
1154 + if(key.type == APC_CACHE_KEY_FILE) {
1155 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1156 + if((*slot)->key.mtime != key.mtime) {
1157 + remove_slot(cache, slot);
1158 + cache->header->num_misses++;
1159 + UNLOCK(cache);
1160 + return NULL;
1161 + }
1162 + (*slot)->num_hits++;
1163 + (*slot)->value->ref_count++;
1164 + (*slot)->access_time = t;
1165 + prevent_garbage_collection((*slot)->value);
1166 + cache->header->num_hits++;
1167 + retval = *slot;
1168 + UNLOCK(cache);
1169 + return (slot_t*)retval;
1170 + }
1171 + } else { /* APC_CACHE_KEY_FPFILE */
1172 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1173 + /* TTL Check ? */
1174 + (*slot)->num_hits++;
1175 + (*slot)->value->ref_count++;
1176 + (*slot)->access_time = t;
1177 + prevent_garbage_collection((*slot)->value);
1178 + cache->header->num_hits++;
1179 + retval = *slot;
1180 + UNLOCK(cache);
1181 + return (slot_t*)retval;
1182 + }
1183 + }
1184 + }
1185 + slot = &(*slot)->next;
1186 + }
1187 + cache->header->num_misses++;
1188 + UNLOCK(cache);
1189 + return NULL;
1190 +}
1191 +/* }}} */
1192 +
1193 +/* {{{ apc_cache_find */
1194 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1195 +{
1196 + slot_t * slot = apc_cache_find_slot(cache, key, t);
1197 + return (slot) ? slot->value : NULL;
1198 +}
1199 +/* }}} */
1200 +
1201 +/* {{{ apc_cache_user_find */
1202 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
1203 +{
1204 + slot_t** slot;
1205 + volatile apc_cache_entry_t* value = NULL;
1206 +
1207 + LOCK(cache);
1208 +
1209 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1210 +
1211 + while (*slot) {
1212 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1213 + /* Check to make sure this entry isn't expired by a hard TTL */
1214 + if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
1215 + remove_slot(cache, slot);
1216 + UNLOCK(cache);
1217 + return NULL;
1218 + }
1219 + /* Otherwise we are fine, increase counters and return the cache entry */
1220 + (*slot)->num_hits++;
1221 + (*slot)->value->ref_count++;
1222 + (*slot)->access_time = t;
1223 +
1224 + cache->header->num_hits++;
1225 + value = (*slot)->value;
1226 + UNLOCK(cache);
1227 + return (apc_cache_entry_t*)value;
1228 + }
1229 + slot = &(*slot)->next;
1230 + }
1231 +
1232 + UNLOCK(cache);
1233 + return NULL;
1234 +}
1235 +/* }}} */
1236 +
1237 +/* {{{ apc_cache_user_delete */
1238 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
1239 +{
1240 + slot_t** slot;
1241 +
1242 + LOCK(cache);
1243 +
1244 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1245 +
1246 + while (*slot) {
1247 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1248 + remove_slot(cache, slot);
1249 + UNLOCK(cache);
1250 + return 1;
1251 + }
1252 + slot = &(*slot)->next;
1253 + }
1254 +
1255 + UNLOCK(cache);
1256 + return 0;
1257 +}
1258 +/* }}} */
1259 +
1260 +/* {{{ apc_cache_release */
1261 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
1262 +{
1263 + /* local cache refcount-- is done in apc_local_cache_cleanup */
1264 + if(entry->local) return;
1265 +
1266 + LOCK(cache);
1267 + entry->ref_count--;
1268 + UNLOCK(cache);
1269 +}
1270 +/* }}} */
1271 +
1272 +/* {{{ apc_cache_make_file_key */
1273 +int apc_cache_make_file_key(apc_cache_key_t* key,
1274 + const char* filename,
1275 + const char* include_path,
1276 + time_t t
1277 + TSRMLS_DC)
1278 +{
1279 + static char canon_path[MAXPATHLEN];
1280 + struct stat *tmp_buf=NULL;
1281 + struct apc_fileinfo_t fileinfo = { {0}, };
1282 + int len;
1283 +
1284 + assert(key != NULL);
1285 +
1286 + if (!filename || !SG(request_info).path_translated) {
1287 +#ifdef __DEBUG_APC__
1288 + fprintf(stderr,"No filename and no path_translated - bailing\n");
1289 +#endif
1290 + return 0;
1291 + }
1292 +
1293 + len = strlen(filename);
1294 + if(APCG(fpstat)==0) {
1295 + if(IS_ABSOLUTE_PATH(filename,len)) {
1296 + key->data.fpfile.fullpath = filename;
1297 + key->data.fpfile.fullpath_len = len;
1298 + key->mtime = t;
1299 + key->type = APC_CACHE_KEY_FPFILE;
1300 + } else {
1301 + if(!realpath(filename, canon_path)) {
1302 + fprintf(stderr, "realpath failed to canonicalize %s - bailing\n", filename);
1303 + return 0;
1304 + }
1305 + key->data.fpfile.fullpath = canon_path;
1306 + key->data.fpfile.fullpath_len = strlen(canon_path);
1307 + key->mtime = t;
1308 + key->type = APC_CACHE_KEY_FPFILE;
1309 + }
1310 + return 1;
1311 + }
1312 +
1313 + if(!strcmp(SG(request_info).path_translated, filename)) {
1314 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
1315 + }
1316 + if(tmp_buf) {
1317 + fileinfo.st_buf = *tmp_buf;
1318 + } else {
1319 + if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1320 +#ifdef __DEBUG_APC__
1321 + fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
1322 +#endif
1323 + return 0;
1324 + }
1325 + }
1326 +
1327 + if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
1328 +#ifdef __DEBUG_APC__
1329 + fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
1330 +#endif
1331 + return 0;
1332 + }
1333 +
1334 + /*
1335 + * This is a bit of a hack.
1336 + *
1337 + * Here I am checking to see if the file is at least 2 seconds old.
1338 + * The idea is that if the file is currently being written to then its
1339 + * mtime is going to match or at most be 1 second off of the current
1340 + * request time and we want to avoid caching files that have not been
1341 + * completely written. Of course, people should be using atomic
1342 + * mechanisms to push files onto live web servers, but adding this
1343 + * tiny safety is easier than educating the world. This is now
1344 + * configurable, but the default is still 2 seconds.
1345 + */
1346 + if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) {
1347 +#ifdef __DEBUG_APC__
1348 + fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
1349 +#endif
1350 + return 0;
1351 + }
1352 +
1353 + key->data.file.device = fileinfo.st_buf.st_dev;
1354 + key->data.file.inode = fileinfo.st_buf.st_ino;
1355 + /*
1356 + * If working with content management systems that like to munge the mtime,
1357 + * it might be appropriate to key off of the ctime to be immune to systems
1358 + * that try to backdate a template. If the mtime is set to something older
1359 + * than the previous mtime of a template we will obviously never see this
1360 + * "older" template. At some point the Smarty templating system did this.
1361 + * I generally disagree with using the ctime here because you lose the
1362 + * ability to warm up new content by saving it to a temporary file, hitting
1363 + * it once to cache it and then renaming it into its permanent location so
1364 + * set the apc.stat_ctime=true to enable this check.
1365 + */
1366 + if(APCG(stat_ctime)) {
1367 + key->mtime = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime;
1368 + } else {
1369 + key->mtime = fileinfo.st_buf.st_mtime;
1370 + }
1371 + key->type = APC_CACHE_KEY_FILE;
1372 + return 1;
1373 +}
1374 +/* }}} */
1375 +
1376 +/* {{{ apc_cache_make_user_key */
1377 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
1378 +{
1379 + assert(key != NULL);
1380 +
1381 + if (!identifier)
1382 + return 0;
1383 +
1384 + key->data.user.identifier = identifier;
1385 + key->data.user.identifier_len = identifier_len;
1386 + key->mtime = t;
1387 + key->type = APC_CACHE_KEY_USER;
1388 + return 1;
1389 +}
1390 +/* }}} */
1391 +
1392 +/* {{{ apc_cache_make_file_entry */
1393 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
1394 + zend_op_array* op_array,
1395 + apc_function_t* functions,
1396 + apc_class_t* classes)
1397 +{
1398 + apc_cache_entry_t* entry;
1399 +
1400 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1401 + if (!entry) return NULL;
1402 +
1403 + entry->data.file.filename = apc_xstrdup(filename, apc_sma_malloc);
1404 + if(!entry->data.file.filename) {
1405 +#ifdef __DEBUG_APC__
1406 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
1407 +#endif
1408 + apc_sma_free(entry);
1409 + return NULL;
1410 + }
1411 +#ifdef __DEBUG_APC__
1412 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
1413 +#endif
1414 + entry->data.file.op_array = op_array;
1415 + entry->data.file.functions = functions;
1416 + entry->data.file.classes = classes;
1417 + entry->type = APC_CACHE_ENTRY_FILE;
1418 + entry->ref_count = 0;
1419 + entry->mem_size = 0;
1420 + entry->autofiltered = 0;
1421 + entry->local = 0;
1422 + return entry;
1423 +}
1424 +/* }}} */
1425 +
1426 +/* {{{ apc_cache_store_zval */
1427 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1428 +{
1429 + smart_str buf = {0};
1430 + php_serialize_data_t var_hash;
1431 + TSRMLS_FETCH();
1432 +
1433 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1434 + if(!dst) {
1435 + CHECK(dst = (zval*) allocate(sizeof(zval)));
1436 + }
1437 +
1438 + PHP_VAR_SERIALIZE_INIT(var_hash);
1439 + php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
1440 + PHP_VAR_SERIALIZE_DESTROY(var_hash);
1441 +
1442 + dst->type = IS_NULL; /* in case we fail */
1443 + if(buf.c) {
1444 + dst->type = src->type & ~IS_CONSTANT_INDEX;
1445 + dst->value.str.len = buf.len;
1446 + CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
1447 + dst->type = src->type;
1448 + smart_str_free(&buf);
1449 + }
1450 + return dst;
1451 + } else {
1452 +
1453 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1454 + HashTable *old = APCG(copied_zvals);
1455 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1456 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1457 +
1458 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1459 +
1460 + if(APCG(copied_zvals)) {
1461 + zend_hash_destroy(APCG(copied_zvals));
1462 + efree(APCG(copied_zvals));
1463 + }
1464 +
1465 + APCG(copied_zvals) = old;
1466 +
1467 + return dst;
1468 + }
1469 +}
1470 +/* }}} */
1471 +
1472 +/* {{{ apc_cache_fetch_zval */
1473 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1474 +{
1475 + TSRMLS_FETCH();
1476 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1477 + php_unserialize_data_t var_hash;
1478 + const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
1479 +
1480 + PHP_VAR_UNSERIALIZE_INIT(var_hash);
1481 + if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
1482 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1483 + zval_dtor(dst);
1484 + 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));
1485 + dst->type = IS_NULL;
1486 + }
1487 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1488 + return dst;
1489 + } else {
1490 +
1491 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1492 + HashTable *old = APCG(copied_zvals);
1493 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1494 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1495 +
1496 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1497 +
1498 + if(APCG(copied_zvals)) {
1499 + zend_hash_destroy(APCG(copied_zvals));
1500 + efree(APCG(copied_zvals));
1501 + }
1502 +
1503 + APCG(copied_zvals) = old;
1504 +
1505 + return dst;
1506 + }
1507 +}
1508 +/* }}} */
1509 +
1510 +/* {{{ apc_cache_free_zval */
1511 +void apc_cache_free_zval(zval* src, apc_free_t deallocate)
1512 +{
1513 + TSRMLS_FETCH();
1514 + if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1515 + if (src->value.str.val) {
1516 + deallocate(src->value.str.val);
1517 + }
1518 + deallocate(src);
1519 + } else {
1520 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1521 + HashTable *old = APCG(copied_zvals);
1522 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1523 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1524 +
1525 + apc_free_zval(src, deallocate);
1526 +
1527 + if(APCG(copied_zvals)) {
1528 + zend_hash_destroy(APCG(copied_zvals));
1529 + efree(APCG(copied_zvals));
1530 + }
1531 +
1532 + APCG(copied_zvals) = old;
1533 + }
1534 +}
1535 +/* }}} */
1536 +
1537 +/* {{{ apc_cache_make_user_entry */
1538 +apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
1539 +{
1540 + apc_cache_entry_t* entry;
1541 +
1542 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1543 + if (!entry) return NULL;
1544 +
1545 + entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
1546 + entry->data.user.info_len = info_len;
1547 + if(!entry->data.user.info) {
1548 + apc_sma_free(entry);
1549 + return NULL;
1550 + }
1551 + entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
1552 + if(!entry->data.user.val) {
1553 + apc_sma_free(entry->data.user.info);
1554 + apc_sma_free(entry);
1555 + return NULL;
1556 + }
1557 + INIT_PZVAL(entry->data.user.val);
1558 + entry->data.user.ttl = ttl;
1559 + entry->type = APC_CACHE_ENTRY_USER;
1560 + entry->ref_count = 0;
1561 + entry->mem_size = 0;
1562 + entry->autofiltered = 0;
1563 + entry->local = 0;
1564 + return entry;
1565 +}
1566 +/* }}} */
1567 +
1568 +/* {{{ apc_cache_free_entry */
1569 +void apc_cache_free_entry(apc_cache_entry_t* entry)
1570 +{
1571 + if (entry != NULL) {
1572 + assert(entry->ref_count == 0);
1573 + switch(entry->type) {
1574 + case APC_CACHE_ENTRY_FILE:
1575 + apc_sma_free(entry->data.file.filename);
1576 + apc_free_op_array(entry->data.file.op_array, apc_sma_free);
1577 + apc_free_functions(entry->data.file.functions, apc_sma_free);
1578 + apc_free_classes(entry->data.file.classes, apc_sma_free);
1579 + break;
1580 + case APC_CACHE_ENTRY_USER:
1581 + apc_sma_free(entry->data.user.info);
1582 + apc_cache_free_zval(entry->data.user.val, apc_sma_free);
1583 + break;
1584 + }
1585 + apc_sma_free(entry);
1586 + }
1587 +}
1588 +/* }}} */
1589 +
1590 +/* {{{ apc_cache_info */
1591 +apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
1592 +{
1593 + apc_cache_info_t* info;
1594 + slot_t* p;
1595 + int i;
1596 +
1597 + if(!cache) return NULL;
1598 +
1599 + LOCK(cache);
1600 +
1601 + info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
1602 + if(!info) {
1603 + UNLOCK(cache);
1604 + return NULL;
1605 + }
1606 + info->num_slots = cache->num_slots;
1607 + info->ttl = cache->ttl;
1608 + info->num_hits = cache->header->num_hits;
1609 + info->num_misses = cache->header->num_misses;
1610 + info->list = NULL;
1611 + info->deleted_list = NULL;
1612 + info->start_time = cache->header->start_time;
1613 + info->expunges = cache->header->expunges;
1614 + info->mem_size = cache->header->mem_size;
1615 + info->num_entries = cache->header->num_entries;
1616 + info->num_inserts = cache->header->num_inserts;
1617 +
1618 + if(!limited) {
1619 + /* For each hashtable slot */
1620 + for (i = 0; i < info->num_slots; i++) {
1621 + p = cache->slots[i];
1622 + for (; p != NULL; p = p->next) {
1623 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1624 +
1625 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1626 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1627 + link->data.file.device = p->key.data.file.device;
1628 + link->data.file.inode = p->key.data.file.inode;
1629 + link->type = APC_CACHE_ENTRY_FILE;
1630 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1631 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1632 + link->data.user.ttl = p->value->data.user.ttl;
1633 + link->type = APC_CACHE_ENTRY_USER;
1634 + }
1635 + link->num_hits = p->num_hits;
1636 + link->mtime = p->key.mtime;
1637 + link->creation_time = p->creation_time;
1638 + link->deletion_time = p->deletion_time;
1639 + link->access_time = p->access_time;
1640 + link->ref_count = p->value->ref_count;
1641 + link->mem_size = p->value->mem_size;
1642 + link->next = info->list;
1643 + info->list = link;
1644 + }
1645 + }
1646 +
1647 + /* For each slot pending deletion */
1648 + for (p = cache->header->deleted_list; p != NULL; p = p->next) {
1649 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1650 +
1651 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1652 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1653 + if(p->key.type == APC_CACHE_KEY_FILE) {
1654 + link->data.file.device = p->key.data.file.device;
1655 + link->data.file.inode = p->key.data.file.inode;
1656 + } else { /* This is a no-stat fullpath file entry */
1657 + link->data.file.device = 0;
1658 + link->data.file.inode = 0;
1659 + }
1660 + link->type = APC_CACHE_ENTRY_FILE;
1661 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1662 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1663 + link->data.user.ttl = p->value->data.user.ttl;
1664 + link->type = APC_CACHE_ENTRY_USER;
1665 + }
1666 + link->num_hits = p->num_hits;
1667 + link->mtime = p->key.mtime;
1668 + link->creation_time = p->creation_time;
1669 + link->deletion_time = p->deletion_time;
1670 + link->access_time = p->access_time;
1671 + link->ref_count = p->value->ref_count;
1672 + link->mem_size = p->value->mem_size;
1673 + link->next = info->deleted_list;
1674 + info->deleted_list = link;
1675 + }
1676 + }
1677 +
1678 + UNLOCK(cache);
1679 + return info;
1680 +}
1681 +/* }}} */
1682 +
1683 +/* {{{ apc_cache_free_info */
1684 +void apc_cache_free_info(apc_cache_info_t* info)
1685 +{
1686 + apc_cache_link_t* p = info->list;
1687 + apc_cache_link_t* q = NULL;
1688 + while (p != NULL) {
1689 + q = p;
1690 + p = p->next;
1691 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1692 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1693 + apc_efree(q);
1694 + }
1695 + p = info->deleted_list;
1696 + while (p != NULL) {
1697 + q = p;
1698 + p = p->next;
1699 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1700 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1701 + apc_efree(q);
1702 + }
1703 + apc_efree(info);
1704 +}
1705 +/* }}} */
1706 +
1707 +/* {{{ apc_cache_unlock */
1708 +void apc_cache_unlock(apc_cache_t* cache)
1709 +{
1710 + UNLOCK(cache);
1711 +}
1712 +/* }}} */
1713 +
1714 +/* {{{ apc_cache_busy */
1715 +zend_bool apc_cache_busy(apc_cache_t* cache)
1716 +{
1717 + return cache->header->busy;
1718 +}
1719 +/* }}} */
1720 +
1721 +#if NONBLOCKING_LOCK_AVAILABLE
1722 +/* {{{ apc_cache_write_lock */
1723 +zend_bool apc_cache_write_lock(apc_cache_t* cache)
1724 +{
1725 + return apc_lck_nb_lock(cache->header->wrlock);
1726 +}
1727 +/* }}} */
1728 +
1729 +/* {{{ apc_cache_write_unlock */
1730 +void apc_cache_write_unlock(apc_cache_t* cache)
1731 +{
1732 + apc_lck_unlock(cache->header->wrlock);
1733 +}
1734 +/* }}} */
1735 +#endif
1736 +
1737 +/* {{{ make_local_slot */
1738 +static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot)
1739 +{
1740 + apc_cache_entry_t* value;
1741 +
1742 + value = apc_emalloc(sizeof(apc_cache_entry_t));
1743 + memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
1744 + value->local = 1;
1745 +
1746 + lslot->original = slot;
1747 + lslot->value = value;
1748 + lslot->num_hits++;
1749 +
1750 + return lslot; /* for what joy ? ... consistency */
1751 +}
1752 +/* }}} */
1753 +
1754 +/* {{{ free_local_slot */
1755 +static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot)
1756 +{
1757 + local_slot_t * dead = NULL;
1758 + if(!lslot->original) return;
1759 +
1760 + /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
1761 + dead = apc_emalloc(sizeof(local_slot_t));
1762 + memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
1763 +
1764 + lslot->original = NULL;
1765 + lslot->value = NULL;
1766 +
1767 + dead->next = cache->dead_list;
1768 + cache->dead_list = dead;
1769 +}
1770 +/* }}} */
1771 +
1772 +/* {{{ apc_local_cache_create */
1773 +apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
1774 +{
1775 + apc_local_cache_t* cache = NULL;
1776 +
1777 + cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
1778 +
1779 + cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
1780 + memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
1781 +
1782 + cache->shmcache = shmcache;
1783 + cache->num_slots = num_slots;
1784 + cache->ttl = ttl;
1785 + cache->num_hits = 0;
1786 + cache->generation = shmcache->header->expunges;
1787 + cache->dead_list = NULL;
1788 +
1789 + return cache;
1790 +}
1791 +/* }}} */
1792 +
1793 +/* {{{ apc_local_cache_cleanup */
1794 +void apc_local_cache_cleanup(apc_local_cache_t* cache) {
1795 + local_slot_t * lslot;
1796 + time_t t = time(0);
1797 +
1798 + int i;
1799 + for(i = 0; i < cache->num_slots; i++) {
1800 + slot_t * slot = cache->slots[i].original;
1801 + if((slot && slot->access_time < (t - cache->ttl)) ||
1802 + cache->generation != cache->shmcache->header->expunges) {
1803 + free_local_slot(cache, &cache->slots[i]);
1804 + }
1805 + }
1806 +
1807 + LOCK(cache->shmcache);
1808 + for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
1809 + lslot->original->num_hits += lslot->num_hits;
1810 + lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
1811 + apc_efree(lslot->value);
1812 + }
1813 + UNLOCK(cache->shmcache);
1814 +
1815 + cache->dead_list = NULL;
1816 +}
1817 +/* }}} */
1818 +
1819 +/* {{{ apc_local_cache_destroy */
1820 +void apc_local_cache_destroy(apc_local_cache_t* cache)
1821 +{
1822 + int i;
1823 + for(i = 0; i < cache->num_slots; i++) {
1824 + free_local_slot(cache, &cache->slots[i]);
1825 + }
1826 +
1827 + apc_local_cache_cleanup(cache);
1828 +
1829 + LOCK(cache->shmcache);
1830 + cache->shmcache->header->num_hits += cache->num_hits;
1831 + UNLOCK(cache->shmcache);
1832 +
1833 + apc_efree(cache->slots);
1834 + apc_efree(cache);
1835 +}
1836 +/* }}} */
1837 +
1838 +/* {{{ apc_local_cache_find */
1839 +apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
1840 +{
1841 + slot_t* slot;
1842 + local_slot_t* lslot;
1843 +
1844 + if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
1845 + else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1846 +
1847 + slot = lslot->original;
1848 +
1849 + if(slot && key.type == slot->key.type) {
1850 + if(slot->access_time < (t - cache->ttl)) {
1851 + goto not_found;
1852 + }
1853 + if(key.type == APC_CACHE_KEY_FILE &&
1854 + key_equals(slot->key.data.file, key.data.file)) {
1855 + if(slot->key.mtime != key.mtime) {
1856 + free_local_slot(cache, lslot);
1857 + goto not_found;
1858 + }
1859 + return lslot->value;
1860 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
1861 + if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1862 + return lslot->value;
1863 + }
1864 + }
1865 + }
1866 +not_found:
1867 + if(apc_cache_busy(cache->shmcache)) {
1868 + return NULL;
1869 + }
1870 +
1871 + slot = apc_cache_find_slot(cache->shmcache, key, t);
1872 +
1873 + if(!slot) return NULL;
1874 +
1875 + /* i.e maintain a sort of top list */
1876 + if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits) < slot->num_hits) {
1877 + free_local_slot(cache, lslot);
1878 + make_local_slot(cache, lslot, slot);
1879 + return lslot->value;
1880 + }
1881 + return slot->value;
1882 +}
1883 +/* }}} */
1884 +
1885 +/*
1886 + * Local variables:
1887 + * tab-width: 4
1888 + * c-basic-offset: 4
1889 + * End:
1890 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1891 + * vim<600: expandtab sw=4 ts=4 sts=4
1892 + */
1893 Index: php-5.2.4/ext/apc/apc_cache.h
1894 ===================================================================
1895 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
1896 +++ php-5.2.4/ext/apc/apc_cache.h 2007-09-02 12:24:46.000000000 +0200
1897 @@ -0,0 +1,313 @@
1898 +/*
1899 + +----------------------------------------------------------------------+
1900 + | APC |
1901 + +----------------------------------------------------------------------+
1902 + | Copyright (c) 2006 The PHP Group |
1903 + +----------------------------------------------------------------------+
1904 + | This source file is subject to version 3.01 of the PHP license, |
1905 + | that is bundled with this package in the file LICENSE, and is |
1906 + | available through the world-wide-web at the following url: |
1907 + | http://www.php.net/license/3_01.txt. |
1908 + | If you did not receive a copy of the PHP license and are unable to |
1909 + | obtain it through the world-wide-web, please send a note to |
1910 + | license@php.net so we can mail you a copy immediately. |
1911 + +----------------------------------------------------------------------+
1912 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
1913 + | Rasmus Lerdorf <rasmus@php.net> |
1914 + +----------------------------------------------------------------------+
1915 +
1916 + This software was contributed to PHP by Community Connect Inc. in 2002
1917 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1918 + Future revisions and derivatives of this source code must acknowledge
1919 + Community Connect Inc. as the original contributor of this module by
1920 + leaving this note intact in the source code.
1921 +
1922 + All other licensing and usage conditions are those of the PHP Group.
1923 +
1924 + */
1925 +
1926 +/* $Id: apc_cache.h,v 3.45 2007/03/22 16:03:59 gopalv Exp $ */
1927 +
1928 +#ifndef APC_CACHE_H
1929 +#define APC_CACHE_H
1930 +
1931 +/*
1932 + * This module defines the shared memory file cache. Basically all of the
1933 + * logic for storing and retrieving cache entries lives here.
1934 + */
1935 +
1936 +#include "apc.h"
1937 +#include "apc_compile.h"
1938 +
1939 +#define APC_CACHE_ENTRY_FILE 1
1940 +#define APC_CACHE_ENTRY_USER 2
1941 +
1942 +#define APC_CACHE_KEY_FILE 1
1943 +#define APC_CACHE_KEY_USER 2
1944 +#define APC_CACHE_KEY_FPFILE 3
1945 +
1946 +/* {{{ struct definition: apc_cache_key_t */
1947 +#define T apc_cache_t*
1948 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
1949 +
1950 +typedef union _apc_cache_key_data_t {
1951 + struct {
1952 + dev_t device; /* the filesystem device */
1953 + ino_t inode; /* the filesystem inode */
1954 + } file;
1955 + struct {
1956 + const char *identifier;
1957 + int identifier_len;
1958 + } user;
1959 + struct {
1960 + const char *fullpath;
1961 + int fullpath_len;
1962 + } fpfile;
1963 +} apc_cache_key_data_t;
1964 +
1965 +typedef struct apc_cache_key_t apc_cache_key_t;
1966 +struct apc_cache_key_t {
1967 + apc_cache_key_data_t data;
1968 + time_t mtime; /* the mtime of this cached entry */
1969 + unsigned char type;
1970 +};
1971 +/* }}} */
1972 +
1973 +/* {{{ struct definition: apc_cache_entry_t */
1974 +typedef union _apc_cache_entry_value_t {
1975 + struct {
1976 + char *filename; /* absolute path to source file */
1977 + zend_op_array* op_array; /* op_array allocated in shared memory */
1978 + apc_function_t* functions; /* array of apc_function_t's */
1979 + apc_class_t* classes; /* array of apc_class_t's */
1980 + } file;
1981 + struct {
1982 + char *info;
1983 + int info_len;
1984 + zval *val;
1985 + unsigned int ttl;
1986 + } user;
1987 +} apc_cache_entry_value_t;
1988 +
1989 +typedef struct apc_cache_entry_t apc_cache_entry_t;
1990 +struct apc_cache_entry_t {
1991 + apc_cache_entry_value_t data;
1992 + unsigned char type;
1993 + unsigned char autofiltered;
1994 + unsigned char local;
1995 + int ref_count;
1996 + size_t mem_size;
1997 +};
1998 +/* }}} */
1999 +
2000 +/*
2001 + * apc_cache_create creates the shared memory compiler cache. This function
2002 + * should be called just once (ideally in the web server parent process, e.g.
2003 + * in apache), otherwise you will end up with multiple caches (which won't
2004 + * necessarily break anything). Returns a pointer to the cache object.
2005 + *
2006 + * size_hint is a "hint" at the total number of source files that will be
2007 + * cached. It determines the physical size of the hash table. Passing 0 for
2008 + * this argument will use a reasonable default value.
2009 + *
2010 + * gc_ttl is the maximum time a cache entry may speed on the garbage
2011 + * collection list. This is basically a work around for the inherent
2012 + * unreliability of our reference counting mechanism (see apc_cache_release).
2013 + *
2014 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
2015 + * is needed. This helps in cleaning up the cache and ensuring that entries
2016 + * hit frequently stay cached and ones not hit very often eventually disappear.
2017 + */
2018 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
2019 +
2020 +/*
2021 + * apc_cache_destroy releases any OS resources associated with a cache object.
2022 + * Under apache, this function can be safely called by the child processes
2023 + * when they exit.
2024 + */
2025 +extern void apc_cache_destroy(T cache);
2026 +
2027 +/*
2028 + * apc_cache_clear empties a cache. This can safely be called at any time,
2029 + * even while other server processes are executing cached source files.
2030 + */
2031 +extern void apc_cache_clear(T cache);
2032 +
2033 +/*
2034 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
2035 + * Internally, the filename is translated to a canonical representation, so
2036 + * that relative and absolute filenames will map to a single key. Returns
2037 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
2038 + * returned, the caller must free the cache entry by calling
2039 + * apc_cache_free_entry (see below).
2040 + *
2041 + * key is the value created by apc_cache_make_file_key for file keys.
2042 + *
2043 + * value is a cache entry returned by apc_cache_make_entry (see below).
2044 + */
2045 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
2046 + apc_cache_entry_t* value, time_t t);
2047 +
2048 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
2049 + apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
2050 +
2051 +/*
2052 + * apc_cache_find searches for a cache entry by filename, and returns a
2053 + * pointer to the entry if found, NULL otherwise.
2054 + *
2055 + * key is a value created by apc_cache_make_file_key for file keys.
2056 + */
2057 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
2058 +
2059 +/*
2060 + * apc_cache_user_find searches for a cache entry by its hashed identifier,
2061 + * and returns a pointer to the entry if found, NULL otherwise.
2062 + *
2063 + */
2064 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
2065 +
2066 +/*
2067 + * apc_cache_user_delete finds an entry in the user cache and deletes it.
2068 + */
2069 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
2070 +
2071 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
2072 + * zval from it.
2073 + *
2074 + */
2075 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
2076 +
2077 +/*
2078 + * apc_cache_release decrements the reference count associated with a cache
2079 + * entry. Calling apc_cache_find automatically increments the reference count,
2080 + * and this function must be called post-execution to return the count to its
2081 + * original value. Failing to do so will prevent the entry from being
2082 + * garbage-collected.
2083 + *
2084 + * entry is the cache entry whose ref count you want to decrement.
2085 + */
2086 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
2087 +
2088 +/*
2089 + * apc_cache_make_file_key creates a key object given a relative or absolute
2090 + * filename and an optional list of auxillary paths to search. include_path is
2091 + * searched if the filename cannot be found relative to the current working
2092 + * directory.
2093 + *
2094 + * key points to caller-allocated storage (must not be null).
2095 + *
2096 + * filename is the path to the source file.
2097 + *
2098 + * include_path is a colon-separated list of directories to search.
2099 + *
2100 + * and finally we pass in the current request time so we can avoid
2101 + * caching files with a current mtime which tends to indicate that
2102 + * they are still being written to.
2103 + */
2104 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
2105 + const char* filename,
2106 + const char* include_path,
2107 + time_t t
2108 + TSRMLS_DC);
2109 +
2110 +/*
2111 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
2112 + * and the compilation results returned by the PHP compiler.
2113 + */
2114 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2115 + zend_op_array* op_array,
2116 + apc_function_t* functions,
2117 + apc_class_t* classes);
2118 +/*
2119 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
2120 + * and the zval to be stored.
2121 + */
2122 +extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
2123 +
2124 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
2125 +
2126 +/*
2127 + * Frees all memory associated with an object returned by apc_cache_make_entry
2128 + * (see above).
2129 + */
2130 +extern void apc_cache_free_entry(apc_cache_entry_t* entry);
2131 +
2132 +/* {{{ struct definition: apc_cache_link_data_t */
2133 +typedef union _apc_cache_link_data_t {
2134 + struct {
2135 + char *filename;
2136 + dev_t device;
2137 + ino_t inode;
2138 + } file;
2139 + struct {
2140 + char *info;
2141 + unsigned int ttl;
2142 + } user;
2143 +} apc_cache_link_data_t;
2144 +/* }}} */
2145 +
2146 +/* {{{ struct definition: apc_cache_link_t */
2147 +typedef struct apc_cache_link_t apc_cache_link_t;
2148 +struct apc_cache_link_t {
2149 + apc_cache_link_data_t data;
2150 + unsigned char type;
2151 + int num_hits;
2152 + time_t mtime;
2153 + time_t creation_time;
2154 + time_t deletion_time;
2155 + time_t access_time;
2156 + int ref_count;
2157 + size_t mem_size;
2158 + apc_cache_link_t* next;
2159 +};
2160 +/* }}} */
2161 +
2162 +/* {{{ struct definition: apc_cache_info_t */
2163 +typedef struct apc_cache_info_t apc_cache_info_t;
2164 +struct apc_cache_info_t {
2165 + int num_slots;
2166 + int num_hits;
2167 + int num_misses;
2168 + int ttl;
2169 + apc_cache_link_t* list;
2170 + apc_cache_link_t* deleted_list;
2171 + time_t start_time;
2172 + int expunges;
2173 + int num_entries;
2174 + int num_inserts;
2175 + size_t mem_size;
2176 +};
2177 +/* }}} */
2178 +
2179 +extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
2180 +extern void apc_cache_free_info(apc_cache_info_t* info);
2181 +extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
2182 +extern void apc_cache_unlock(apc_cache_t* cache);
2183 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
2184 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
2185 +extern void apc_cache_write_unlock(apc_cache_t* cache);
2186 +
2187 +/*
2188 + * Process local cache, which keeps a refcount hungry version of the slots
2189 + * for quick access without a lock - as long as the entry exists in local
2190 + * cache, the refcount of the shm version will be +1 more than required.
2191 + * It holds no data, only a shallow copy of apc_cache_entry.
2192 + */
2193 +typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */
2194 +
2195 +extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
2196 +extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
2197 +extern void apc_local_cache_destroy(apc_local_cache_t* cache);
2198 +extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
2199 +
2200 +#undef T
2201 +#endif
2202 +
2203 +/*
2204 + * Local variables:
2205 + * tab-width: 4
2206 + * c-basic-offset: 4
2207 + * End:
2208 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
2209 + * vim<600: expandtab sw=4 ts=4 sts=4
2210 + */
2211 Index: php-5.2.4/ext/apc/apc_compile.c
2212 ===================================================================
2213 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2214 +++ php-5.2.4/ext/apc/apc_compile.c 2007-09-02 12:24:46.000000000 +0200
2215 @@ -0,0 +1,2530 @@
2216 +/*
2217 + +----------------------------------------------------------------------+
2218 + | APC |
2219 + +----------------------------------------------------------------------+
2220 + | Copyright (c) 2006 The PHP Group |
2221 + +----------------------------------------------------------------------+
2222 + | This source file is subject to version 3.01 of the PHP license, |
2223 + | that is bundled with this package in the file LICENSE, and is |
2224 + | available through the world-wide-web at the following url: |
2225 + | http://www.php.net/license/3_01.txt. |
2226 + | If you did not receive a copy of the PHP license and are unable to |
2227 + | obtain it through the world-wide-web, please send a note to |
2228 + | license@php.net so we can mail you a copy immediately. |
2229 + +----------------------------------------------------------------------+
2230 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
2231 + | Rasmus Lerdorf <rasmus@php.net> |
2232 + | Arun C. Murthy <arunc@yahoo-inc.com> |
2233 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
2234 + +----------------------------------------------------------------------+
2235 +
2236 + This software was contributed to PHP by Community Connect Inc. in 2002
2237 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
2238 + Future revisions and derivatives of this source code must acknowledge
2239 + Community Connect Inc. as the original contributor of this module by
2240 + leaving this note intact in the source code.
2241 +
2242 + All other licensing and usage conditions are those of the PHP Group.
2243 +
2244 + */
2245 +
2246 +/* $Id: apc_compile.c,v 3.85 2007/03/28 07:35:55 gopalv Exp $ */
2247 +
2248 +#include "apc_compile.h"
2249 +#include "apc_globals.h"
2250 +#include "apc_zend.h"
2251 +
2252 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
2253 +typedef void (*ht_free_fun_t)(void*, apc_free_t);
2254 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
2255 +
2256 +#ifdef ZEND_ENGINE_2
2257 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
2258 +#endif
2259 +
2260 +#define CHECK(p) { if ((p) == NULL) return NULL; }
2261 +
2262 +/* {{{ internal function declarations */
2263 +
2264 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
2265 +
2266 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
2267 +
2268 +/*
2269 + * The "copy" functions perform deep-copies on a particular data structure
2270 + * (passed as the second argument). They also optionally allocate space for
2271 + * the destination data structure if the first argument is null.
2272 + */
2273 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
2274 +static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
2275 +static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
2276 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
2277 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
2278 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
2279 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
2280 +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, ...);
2281 +#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
2282 + my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
2283 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
2284 +#ifdef ZEND_ENGINE_2
2285 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
2286 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
2287 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
2288 +#endif
2289 +/*
2290 + * The "destroy" functions free the memory associated with a particular data
2291 + * structure but do not free the pointer to the data structure.
2292 + *
2293 + * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
2294 + * the zval* has other references elsewhere
2295 + */
2296 +static int my_destroy_zval(zval*, apc_free_t);
2297 +static void my_destroy_zval_ptr(zval**, apc_free_t);
2298 +static void my_destroy_zend_op(zend_op*, apc_free_t);
2299 +static void my_destroy_znode(znode*, apc_free_t);
2300 +static void my_destroy_function(zend_function*, apc_free_t);
2301 +static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
2302 +static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
2303 +static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2304 +static void my_destroy_op_array(zend_op_array*, apc_free_t);
2305 +#ifdef ZEND_ENGINE_2
2306 +static void my_destroy_property_info(zend_property_info*, apc_free_t);
2307 +static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
2308 +static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
2309 +#endif
2310 +
2311 +/*
2312 + * The "free" functions work exactly like their "destroy" counterparts (see
2313 + * above) but also free the pointer to the data structure.
2314 + */
2315 +static void my_free_zval_ptr(zval**, apc_free_t);
2316 +static void my_free_function(zend_function*, apc_free_t);
2317 +static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2318 +#ifdef ZEND_ENGINE_2
2319 +static void my_free_property_info(zend_property_info* src, apc_free_t);
2320 +static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
2321 +static void my_free_arg_info(zend_arg_info*, apc_free_t);
2322 +#endif
2323 +
2324 +/*
2325 + * The "fixup" functions need for ZEND_ENGINE_2
2326 + */
2327 +#ifdef ZEND_ENGINE_2
2328 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2329 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
2330 +/* my_fixup_function_for_execution is the same as my_fixup_function
2331 + * but named differently for clarity
2332 + */
2333 +#define my_fixup_function_for_execution my_fixup_function
2334 +
2335 +#ifdef ZEND_ENGINE_2_2
2336 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2337 +#define my_fixup_property_info_for_execution my_fixup_property_info
2338 +#endif
2339 +
2340 +#endif
2341 +
2342 +/*
2343 + * These functions return "1" if the member/function is
2344 + * defined/overridden in the 'current' class and not inherited.
2345 + */
2346 +static int my_check_copy_function(Bucket* src, va_list args);
2347 +static int my_check_copy_default_property(Bucket* p, va_list args);
2348 +#ifdef ZEND_ENGINE_2
2349 +static int my_check_copy_property_info(Bucket* src, va_list args);
2350 +static int my_check_copy_static_member(Bucket* src, va_list args);
2351 +#endif
2352 +
2353 +/* }}} */
2354 +
2355 +/* {{{ check_op_array_integrity */
2356 +#if 0
2357 +static void check_op_array_integrity(zend_op_array* src)
2358 +{
2359 + int i, j;
2360 +
2361 + /* These sorts of checks really aren't particularly effective, but they
2362 + * can provide a welcome sanity check when debugging. Just don't enable
2363 + * for production use! */
2364 +
2365 + assert(src->refcount != NULL);
2366 + assert(src->opcodes != NULL);
2367 + assert(src->last > 0);
2368 +
2369 + for (i = 0; i < src->last; i++) {
2370 + zend_op* op = &src->opcodes[i];
2371 + znode* nodes[] = { &op->result, &op->op1, &op->op2 };
2372 + for (j = 0; j < 3; j++) {
2373 + assert(nodes[j]->op_type == IS_CONST ||
2374 + nodes[j]->op_type == IS_VAR ||
2375 + nodes[j]->op_type == IS_TMP_VAR ||
2376 + nodes[j]->op_type == IS_UNUSED);
2377 +
2378 + if (nodes[j]->op_type == IS_CONST) {
2379 + int type = nodes[j]->u.constant.type;
2380 + assert(type == IS_RESOURCE ||
2381 + type == IS_BOOL ||
2382 + type == IS_LONG ||
2383 + type == IS_DOUBLE ||
2384 + type == IS_NULL ||
2385 + type == IS_CONSTANT ||
2386 + type == IS_STRING ||
2387 + type == FLAG_IS_BC ||
2388 + type == IS_ARRAY ||
2389 + type == IS_CONSTANT_ARRAY ||
2390 + type == IS_OBJECT);
2391 + }
2392 + }
2393 + }
2394 +}
2395 +#endif
2396 +/* }}} */
2397 +
2398 +/* {{{ is_derived_class */
2399 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
2400 +{
2401 + int i;
2402 +
2403 + /*
2404 + * Scan the op_array for execution-time class declarations of derived
2405 + * classes. If we find one whose key matches our current class key, we
2406 + * know the current class is a derived class.
2407 + *
2408 + * This check is exceedingly inefficient (fortunately it only has to occur
2409 + * once, when the source file is first compiled and cached), but the
2410 + * compiler should save this information for us -- definitely a candidate
2411 + * for a Zend Engine patch.
2412 + *
2413 + * XXX checking for derived classes provides a minimal (albeit measurable)
2414 + * speed up. It may not be worth the added complexity -- considere
2415 + * removing this optimization.
2416 + */
2417 +
2418 + for (i = 0; i < op_array->last; i++) {
2419 + zend_op* op = &op_array->opcodes[i];
2420 +
2421 +#ifdef ZEND_ENGINE_2
2422 + if (op->opcode == ZEND_DECLARE_CLASS &&
2423 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2424 +#else
2425 + if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
2426 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2427 +#endif
2428 + {
2429 + if (op->op1.u.constant.value.str.len == key_size &&
2430 + !memcmp(op->op1.u.constant.value.str.val, key, key_size))
2431 + {
2432 + return 1;
2433 + }
2434 + }
2435 + }
2436 +
2437 + return 0;
2438 +}
2439 +/* }}} */
2440 +
2441 +/* {{{ my_bitwise_copy_function */
2442 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
2443 +{
2444 + assert(src != NULL);
2445 +
2446 + if (!dst) {
2447 + CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
2448 + }
2449 +
2450 + /* We only need to do a bitwise copy */
2451 + memcpy(dst, src, sizeof(src[0]));
2452 +
2453 + return dst;
2454 +}
2455 +/* }}} */
2456 +
2457 +/* {{{ my_copy_zval_ptr */
2458 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
2459 +{
2460 + int local_dst_alloc = 0;
2461 + zval* dst_new;
2462 +
2463 + assert(src != NULL);
2464 +
2465 + if (!dst) {
2466 + CHECK(dst = (zval**) allocate(sizeof(zval*)));
2467 + local_dst_alloc = 1;
2468 + }
2469 +
2470 + if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
2471 + if(local_dst_alloc) deallocate(dst);
2472 + return NULL;
2473 + }
2474 + dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
2475 + if(dst_new != *dst) {
2476 + deallocate(*dst);
2477 + *dst = dst_new;
2478 + }
2479 +
2480 + (*dst)->refcount = (*src)->refcount;
2481 + (*dst)->is_ref = (*src)->is_ref;
2482 +
2483 + return dst;
2484 +}
2485 +/* }}} */
2486 +
2487 +/* {{{ my_copy_zval */
2488 +static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
2489 +{
2490 + zval **tmp;
2491 + TSRMLS_FETCH();
2492 +
2493 + assert(dst != NULL);
2494 + assert(src != NULL);
2495 +
2496 + memcpy(dst, src, sizeof(src[0]));
2497 +
2498 + switch (src->type & ~IS_CONSTANT_INDEX) {
2499 + case IS_RESOURCE:
2500 + case IS_BOOL:
2501 + case IS_LONG:
2502 + case IS_DOUBLE:
2503 + case IS_NULL:
2504 + break;
2505 +
2506 + case IS_CONSTANT:
2507 + case IS_STRING:
2508 +#ifndef ZEND_ENGINE_2
2509 + case FLAG_IS_BC:
2510 +#endif
2511 + if (src->value.str.val) {
2512 + CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
2513 + src->value.str.len+1,
2514 + allocate));
2515 + }
2516 + break;
2517 +
2518 + case IS_ARRAY:
2519 +
2520 + if(APCG(copied_zvals)) {
2521 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
2522 + (*tmp)->refcount++;
2523 + return *tmp;
2524 + }
2525 +
2526 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
2527 + }
2528 + /* fall through */
2529 +
2530 + case IS_CONSTANT_ARRAY:
2531 +
2532 + CHECK(dst->value.ht =
2533 + my_copy_hashtable(NULL,
2534 + src->value.ht,
2535 + (ht_copy_fun_t) my_copy_zval_ptr,
2536 + (ht_free_fun_t) my_free_zval_ptr,
2537 + 1,
2538 + allocate, deallocate));
2539 + break;
2540 +
2541 + case IS_OBJECT:
2542 +#ifndef ZEND_ENGINE_2
2543 + CHECK(dst->value.obj.ce =
2544 + my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
2545 +
2546 + if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
2547 + src->value.obj.properties,
2548 + (ht_copy_fun_t) my_copy_zval_ptr,
2549 + (ht_free_fun_t) my_free_zval_ptr,
2550 + 1,
2551 + allocate, deallocate))) {
2552 + my_destroy_class_entry(dst->value.obj.ce, deallocate);
2553 + return NULL;
2554 + }
2555 + break;
2556 +#else
2557 + dst->type = IS_NULL;
2558 +#endif
2559 + break;
2560 +
2561 + default:
2562 + assert(0);
2563 + }
2564 +
2565 + return dst;
2566 +}
2567 +/* }}} */
2568 +
2569 +/* {{{ my_copy_znode */
2570 +static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
2571 +{
2572 + assert(dst != NULL);
2573 + assert(src != NULL);
2574 +
2575 + memcpy(dst, src, sizeof(src[0]));
2576 +
2577 +#ifdef IS_CV
2578 + assert(dst ->op_type == IS_CONST ||
2579 + dst ->op_type == IS_VAR ||
2580 + dst ->op_type == IS_CV ||
2581 + dst ->op_type == IS_TMP_VAR ||
2582 + dst ->op_type == IS_UNUSED);
2583 +#else
2584 + assert(dst ->op_type == IS_CONST ||
2585 + dst ->op_type == IS_VAR ||
2586 + dst ->op_type == IS_TMP_VAR ||
2587 + dst ->op_type == IS_UNUSED);
2588 +#endif
2589 +
2590 + if (src->op_type == IS_CONST) {
2591 + if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
2592 + return NULL;
2593 + }
2594 + }
2595 +
2596 + return dst;
2597 +}
2598 +/* }}} */
2599 +
2600 +/* {{{ my_copy_zend_op */
2601 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
2602 +{
2603 + assert(dst != NULL);
2604 + assert(src != NULL);
2605 +
2606 + memcpy(dst, src, sizeof(src[0]));
2607 +
2608 + if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL
2609 + || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
2610 + || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
2611 + {
2612 + return NULL;
2613 + }
2614 +
2615 + return dst;
2616 +}
2617 +/* }}} */
2618 +
2619 +/* {{{ my_copy_function */
2620 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
2621 +{
2622 + int local_dst_alloc = 0;
2623 + TSRMLS_FETCH();
2624 +
2625 + assert(src != NULL);
2626 +
2627 + if(!dst) local_dst_alloc = 1;
2628 + CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
2629 +
2630 + switch (src->type) {
2631 + case ZEND_INTERNAL_FUNCTION:
2632 + case ZEND_OVERLOADED_FUNCTION:
2633 + /* shallow copy because op_array is internal */
2634 + dst->op_array = src->op_array;
2635 + break;
2636 +
2637 + case ZEND_USER_FUNCTION:
2638 + case ZEND_EVAL_CODE:
2639 + if(!apc_copy_op_array(&dst->op_array,
2640 + &src->op_array,
2641 + allocate, deallocate TSRMLS_CC)) {
2642 + if(local_dst_alloc) deallocate(dst);
2643 + return NULL;
2644 + }
2645 + break;
2646 +
2647 + default:
2648 + assert(0);
2649 + }
2650 +#ifdef ZEND_ENGINE_2
2651 + /*
2652 + * op_array bitwise copying overwrites what ever you modified
2653 + * before apc_copy_op_array - which is why this code is outside
2654 + * my_bitwise_copy_function.
2655 + */
2656 +
2657 + /* zend_do_inheritance will re-look this up, because the pointers
2658 + * in prototype are from a function table of another class. It just
2659 + * helps if that one is from EG(class_table).
2660 + */
2661 + dst->common.prototype = NULL;
2662 +
2663 + /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
2664 + * have to carry around a prototype. Thankfully zend_do_inheritance
2665 + * sets this properly as well
2666 + */
2667 + dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
2668 +#endif
2669 +
2670 +
2671 + return dst;
2672 +}
2673 +/* }}} */
2674 +
2675 +/* {{{ my_copy_function_entry */
2676 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2677 +{
2678 + int local_dst_alloc = 0;
2679 + assert(src != NULL);
2680 +
2681 + if (!dst) {
2682 + CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
2683 + local_dst_alloc = 1;
2684 + }
2685 +
2686 + /* Start with a bitwise copy */
2687 + memcpy(dst, src, sizeof(src[0]));
2688 +
2689 + dst->fname = NULL;
2690 +#ifdef ZEND_ENGINE_2
2691 + dst->arg_info = NULL;
2692 +#else
2693 + dst->func_arg_types = NULL;
2694 +#endif
2695 +
2696 + if (src->fname) {
2697 + if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
2698 + goto cleanup;
2699 + }
2700 + }
2701 +
2702 +#ifdef ZEND_ENGINE_2
2703 + if (src->arg_info) {
2704 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
2705 + src->arg_info,
2706 + src->num_args,
2707 + allocate,
2708 + deallocate))) {
2709 + goto cleanup;
2710 + }
2711 + }
2712 +#else
2713 + if (src->func_arg_types) {
2714 + if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
2715 + src->func_arg_types[0]+1,
2716 + allocate))) {
2717 + goto cleanup;
2718 + }
2719 + }
2720 +#endif
2721 +
2722 + return dst;
2723 +
2724 +cleanup:
2725 + if(dst->fname) deallocate(dst->fname);
2726 + if(local_dst_alloc) deallocate(dst);
2727 + return NULL;
2728 +}
2729 +/* }}} */
2730 +
2731 +#ifdef ZEND_ENGINE_2
2732 +/* {{{ my_copy_property_info */
2733 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2734 +{
2735 + int local_dst_alloc = 0;
2736 +
2737 + assert(src != NULL);
2738 +
2739 + if (!dst) {
2740 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2741 + local_dst_alloc = 1;
2742 + }
2743 +
2744 + /* Start with a bitwise copy */
2745 + memcpy(dst, src, sizeof(*src));
2746 +
2747 + dst->name = NULL;
2748 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2749 + dst->doc_comment = NULL;
2750 +#endif
2751 +
2752 + if (src->name) {
2753 + /* private members are stored inside property_info as a mangled
2754 + * string of the form:
2755 + * \0<classname>\0<membername>\0
2756 + */
2757 + if(!(dst->name =
2758 + apc_xmemcpy(src->name, src->name_length+1, allocate))) {
2759 + goto cleanup;
2760 + }
2761 + }
2762 +
2763 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2764 + if (src->doc_comment) {
2765 + if( !(dst->doc_comment =
2766 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
2767 + goto cleanup;
2768 + }
2769 + }
2770 +#endif
2771 +
2772 + return dst;
2773 +
2774 +cleanup:
2775 + if(dst->name) deallocate(dst->name);
2776 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2777 + if(dst->doc_comment) deallocate(dst->doc_comment);
2778 +#endif
2779 + if(local_dst_alloc) deallocate(dst);
2780 + return NULL;
2781 +}
2782 +/* }}} */
2783 +
2784 +/* {{{ my_copy_property_info_for_execution */
2785 +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)
2786 +{
2787 + int local_dst_alloc = 0;
2788 +
2789 + assert(src != NULL);
2790 +
2791 + if (!dst) {
2792 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2793 + local_dst_alloc = 1;
2794 + }
2795 +
2796 + /* We need only a shallow copy */
2797 + memcpy(dst, src, sizeof(*src));
2798 +
2799 + return dst;
2800 +}
2801 +/* }}} */
2802 +
2803 +/* {{{ my_copy_arg_info_array */
2804 +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)
2805 +{
2806 + int local_dst_alloc = 0;
2807 + int i = 0;
2808 +
2809 +
2810 + if (!dst) {
2811 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
2812 + local_dst_alloc = 1;
2813 + }
2814 +
2815 + /* Start with a bitwise copy */
2816 + memcpy(dst, src, sizeof(*src)*num_args);
2817 +
2818 + for(i=0; i < num_args; i++) {
2819 + if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {
2820 + if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
2821 + if(local_dst_alloc) deallocate(dst);
2822 + return NULL;
2823 + }
2824 + }
2825 +
2826 + return dst;
2827 +}
2828 +/* }}} */
2829 +
2830 +/* {{{ my_copy_arg_info */
2831 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2832 +{
2833 + int local_dst_alloc = 0;
2834 +
2835 + assert(src != NULL);
2836 +
2837 + if (!dst) {
2838 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
2839 + local_dst_alloc = 1;
2840 + }
2841 +
2842 + /* Start with a bitwise copy */
2843 + memcpy(dst, src, sizeof(*src));
2844 +
2845 + dst->name = NULL;
2846 + dst->class_name = NULL;
2847 +
2848 + if (src->name) {
2849 + if(!(dst->name =
2850 + apc_xmemcpy(src->name, src->name_len+1, allocate))) {
2851 + goto cleanup;
2852 + }
2853 + }
2854 +
2855 + if (src->class_name) {
2856 + if(!(dst->class_name =
2857 + apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
2858 + goto cleanup;
2859 + }
2860 + }
2861 +
2862 + return dst;
2863 +
2864 +cleanup:
2865 + if(dst->name) deallocate(dst->name);
2866 + if(dst->class_name) deallocate(dst->name);
2867 + if(local_dst_alloc) deallocate(dst);
2868 + return NULL;
2869 +}
2870 +/* }}} */
2871 +#endif
2872 +
2873 +/* {{{ my_copy_class_entry */
2874 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2875 +{
2876 + int local_dst_alloc = 0;
2877 + int i = 0;
2878 +
2879 + assert(src != NULL);
2880 +
2881 + if (!dst) {
2882 + CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
2883 + local_dst_alloc = 1;
2884 + }
2885 +
2886 + /* Start with a bitwise copy */
2887 + memcpy(dst, src, sizeof(*src));
2888 +
2889 + dst->name = NULL;
2890 + dst->builtin_functions = NULL;
2891 + memset(&dst->function_table, 0, sizeof(dst->function_table));
2892 + memset(&dst->default_properties, 0, sizeof(dst->default_properties));
2893 +#ifndef ZEND_ENGINE_2
2894 + dst->refcount = NULL;
2895 +#else
2896 + dst->static_members = NULL;
2897 + dst->doc_comment = NULL;
2898 + dst->filename = NULL;
2899 + memset(&dst->properties_info, 0, sizeof(dst->properties_info));
2900 + memset(&dst->constants_table, 0, sizeof(dst->constants_table));
2901 + memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
2902 +#endif
2903 +
2904 + if (src->name) {
2905 + if(!(dst->name = apc_xstrdup(src->name, allocate))) {
2906 + goto cleanup;
2907 + }
2908 + }
2909 +
2910 +#ifndef ZEND_ENGINE_2
2911 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
2912 + sizeof(src->refcount[0]),
2913 + allocate))) {
2914 + goto cleanup;
2915 + }
2916 +#endif
2917 +
2918 + if(!(my_copy_hashtable_ex(&dst->function_table,
2919 + &src->function_table,
2920 + (ht_copy_fun_t) my_copy_function,
2921 + (ht_free_fun_t) my_free_function,
2922 + 0,
2923 + allocate, deallocate,
2924 + (ht_check_copy_fun_t) my_check_copy_function,
2925 + src))) {
2926 + goto cleanup;
2927 + }
2928 +
2929 +#ifdef ZEND_ENGINE_2
2930 +
2931 + /* the interfaces are populated at runtime using ADD_INTERFACE */
2932 + dst->interfaces = NULL;
2933 +
2934 + /* the current count includes inherited interfaces as well,
2935 + the real dynamic ones are the first <n> which are zero'd
2936 + out in zend_do_end_class_declaration */
2937 + for(i = 0 ; i < src->num_interfaces ; i++) {
2938 + if(src->interfaces[i])
2939 + {
2940 + dst->num_interfaces = i;
2941 + break;
2942 + }
2943 + }
2944 +
2945 + /* these will either be set inside my_fixup_hashtable or
2946 + * they will be copied out from parent inside zend_do_inheritance
2947 + */
2948 + dst->constructor = NULL;
2949 + dst->destructor = NULL;
2950 + dst->clone = NULL;
2951 + dst->__get = NULL;
2952 + dst->__set = NULL;
2953 + dst->__unset = NULL;
2954 + dst->__isset = NULL;
2955 + dst->__call = NULL;
2956 +#ifdef ZEND_ENGINE_2_2
2957 + dst->__tostring = NULL;
2958 +#endif
2959 +
2960 + /* unset function proxies */
2961 + dst->serialize_func = NULL;
2962 + dst->unserialize_func = NULL;
2963 +
2964 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
2965 +#endif
2966 +
2967 + if(!(my_copy_hashtable_ex(&dst->default_properties,
2968 + &src->default_properties,
2969 + (ht_copy_fun_t) my_copy_zval_ptr,
2970 + (ht_free_fun_t) my_free_zval_ptr,
2971 + 1,
2972 + allocate,deallocate,
2973 + (ht_check_copy_fun_t) my_check_copy_default_property,
2974 + src))) {
2975 + goto cleanup;
2976 + }
2977 +
2978 +#ifdef ZEND_ENGINE_2
2979 +
2980 + if(!(my_copy_hashtable_ex(&dst->properties_info,
2981 + &src->properties_info,
2982 + (ht_copy_fun_t) my_copy_property_info,
2983 + (ht_free_fun_t) my_free_property_info,
2984 + 0,
2985 + allocate, deallocate,
2986 + (ht_check_copy_fun_t) my_check_copy_property_info,
2987 + src))) {
2988 + goto cleanup;
2989 + }
2990 +
2991 +#ifdef ZEND_ENGINE_2_2
2992 + /* php5.2 introduced a scope attribute for property info */
2993 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
2994 +#endif
2995 +
2996 + if(!my_copy_hashtable_ex(&dst->default_static_members,
2997 + &src->default_static_members,
2998 + (ht_copy_fun_t) my_copy_zval_ptr,
2999 + (ht_free_fun_t) my_free_zval_ptr,
3000 + 1,
3001 + allocate, deallocate,
3002 + (ht_check_copy_fun_t) my_check_copy_static_member,
3003 + src,
3004 + &src->default_static_members)) {
3005 + goto cleanup;
3006 + }
3007 + if(src->static_members != &src->default_static_members)
3008 + {
3009 + if(!(dst->static_members = my_copy_hashtable_ex(NULL,
3010 + src->static_members,
3011 + (ht_copy_fun_t) my_copy_zval_ptr,
3012 + (ht_free_fun_t) my_free_zval_ptr,
3013 + 1,
3014 + allocate, deallocate,
3015 + (ht_check_copy_fun_t) my_check_copy_static_member,
3016 + src,
3017 + src->static_members))) {
3018 + goto cleanup;
3019 + }
3020 + }
3021 + else
3022 + {
3023 + dst->static_members = &dst->default_static_members;
3024 + }
3025 +
3026 + if(!(my_copy_hashtable(&dst->constants_table,
3027 + &src->constants_table,
3028 + (ht_copy_fun_t) my_copy_zval_ptr,
3029 + (ht_free_fun_t) my_free_zval_ptr,
3030 + 1,
3031 + allocate, deallocate))) {
3032 + goto cleanup;
3033 + }
3034 +
3035 + if (src->doc_comment) {
3036 + if(!(dst->doc_comment =
3037 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3038 + goto cleanup;
3039 + }
3040 + }
3041 +#endif
3042 +
3043 + if (src->builtin_functions) {
3044 + int i, n;
3045 +
3046 + for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
3047 +
3048 + if(!(dst->builtin_functions =
3049 + (zend_function_entry*)
3050 + allocate((n + 1) * sizeof(zend_function_entry)))) {
3051 + goto cleanup;
3052 + }
3053 +
3054 +
3055 + for (i = 0; i < n; i++) {
3056 + if(!my_copy_function_entry(&dst->builtin_functions[i],
3057 + &src->builtin_functions[i],
3058 + allocate, deallocate)) {
3059 + int ii;
3060 +
3061 + for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
3062 + goto cleanup;
3063 + }
3064 + }
3065 + dst->builtin_functions[n].fname = NULL;
3066 + }
3067 +
3068 +#ifdef ZEND_ENGINE_2
3069 + if (src->filename) {
3070 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3071 + goto cleanup;
3072 + }
3073 + }
3074 +#endif
3075 +
3076 + return dst;
3077 +
3078 +
3079 +cleanup:
3080 + if(dst->name) deallocate(dst->name);
3081 +#ifdef ZEND_ENGINE_2
3082 + if(dst->doc_comment) deallocate(dst->doc_comment);
3083 + if(dst->filename) deallocate(dst->filename);
3084 +#else
3085 + if(dst->refcount) deallocate(dst->refcount);
3086 +#endif
3087 +
3088 + if(dst->builtin_functions) deallocate(dst->builtin_functions);
3089 + if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
3090 + if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3091 +
3092 +#ifdef ZEND_ENGINE_2
3093 + if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
3094 + if(dst->default_static_members.arBuckets)
3095 + {
3096 + my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3097 + }
3098 + if(dst->static_members && dst->static_members != &(dst->default_static_members))
3099 + {
3100 + my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3101 + deallocate(dst->static_members);
3102 + }
3103 + if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3104 +#endif
3105 + if(local_dst_alloc) deallocate(dst);
3106 +
3107 + return NULL;
3108 +}
3109 +/* }}} */
3110 +
3111 +/* {{{ my_copy_hashtable */
3112 +static HashTable* my_copy_hashtable_ex(HashTable* dst,
3113 + HashTable* src,
3114 + ht_copy_fun_t copy_fn,
3115 + ht_free_fun_t free_fn,
3116 + int holds_ptrs,
3117 + apc_malloc_t allocate,
3118 + apc_free_t deallocate,
3119 + ht_check_copy_fun_t check_fn,
3120 + ...)
3121 +{
3122 + Bucket* curr = NULL;
3123 + Bucket* prev = NULL;
3124 + Bucket* newp = NULL;
3125 + int first = 1;
3126 + int local_dst_alloc = 0;
3127 + int index = 0;
3128 +
3129 + assert(src != NULL);
3130 +
3131 + if (!dst) {
3132 + CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
3133 + local_dst_alloc = 1;
3134 + }
3135 +
3136 + memcpy(dst, src, sizeof(src[0]));
3137 +
3138 + /* allocate buckets for the new hashtable */
3139 + if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
3140 + if(local_dst_alloc) deallocate(dst);
3141 + return NULL;
3142 + }
3143 +
3144 + memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
3145 + dst->pInternalPointer = NULL;
3146 + dst->pListHead = NULL;
3147 +
3148 + for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
3149 + int n = curr->h % dst->nTableSize;
3150 +
3151 + if(check_fn) {
3152 + va_list args;
3153 + va_start(args, check_fn);
3154 +
3155 + /* Call the check_fn to see if the current bucket
3156 + * needs to be copied out
3157 + */
3158 + if(!check_fn(curr, args)) {
3159 + dst->nNumOfElements--;
3160 + continue;
3161 + }
3162 +
3163 + va_end(args);
3164 + }
3165 +
3166 + /* create a copy of the bucket 'curr' */
3167 + if(!(newp =
3168 + (Bucket*) apc_xmemcpy(curr,
3169 + sizeof(Bucket) + curr->nKeyLength - 1,
3170 + allocate))) {
3171 + goto cleanup;
3172 + }
3173 +
3174 + /* insert 'newp' into the linked list at its hashed index */
3175 + if (dst->arBuckets[n]) {
3176 + newp->pNext = dst->arBuckets[n];
3177 + newp->pLast = NULL;
3178 + newp->pNext->pLast = newp;
3179 + }
3180 + else {
3181 + newp->pNext = newp->pLast = NULL;
3182 + }
3183 +
3184 + dst->arBuckets[n] = newp;
3185 +
3186 + /* copy the bucket data using our 'copy_fn' callback function */
3187 + if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
3188 + goto cleanup;
3189 + }
3190 +
3191 + if (holds_ptrs) {
3192 + memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
3193 + }
3194 + else {
3195 + newp->pDataPtr = NULL;
3196 + }
3197 +
3198 + /* insert 'newp' into the table-thread linked list */
3199 + newp->pListLast = prev;
3200 + newp->pListNext = NULL;
3201 +
3202 + if (prev) {
3203 + prev->pListNext = newp;
3204 + }
3205 +
3206 + if (first) {
3207 + dst->pListHead = newp;
3208 + first = 0;
3209 + }
3210 +
3211 + prev = newp;
3212 + }
3213 +
3214 + dst->pListTail = newp;
3215 +
3216 + return dst;
3217 +
3218 + cleanup:
3219 + for(index = 0; index < dst->nTableSize; index++)
3220 + {
3221 + curr = dst->arBuckets[index];
3222 + while(curr != NULL)
3223 + {
3224 + Bucket * tmp = curr;
3225 + if(curr->pData && free_fn)
3226 + {
3227 + free_fn(curr->pData, deallocate);
3228 + }
3229 + curr = curr->pNext;
3230 + deallocate(tmp);
3231 + }
3232 + }
3233 + deallocate(dst->arBuckets);
3234 + if(local_dst_alloc) deallocate(dst);
3235 + else dst->arBuckets = NULL;
3236 +
3237 + return NULL;
3238 +}
3239 +/* }}} */
3240 +
3241 +/* {{{ my_copy_static_variables */
3242 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
3243 +{
3244 + if (src->static_variables == NULL) {
3245 + return NULL;
3246 + }
3247 +
3248 + return my_copy_hashtable(NULL,
3249 + src->static_variables,
3250 + (ht_copy_fun_t) my_copy_zval_ptr,
3251 + (ht_free_fun_t) my_free_zval_ptr,
3252 + 1,
3253 + allocate, deallocate);
3254 +}
3255 +/* }}} */
3256 +
3257 +/* {{{ apc_copy_zval */
3258 +zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
3259 +{
3260 + int local_dst_alloc = 0;
3261 + assert(src != NULL);
3262 +
3263 + if (!dst) {
3264 + CHECK(dst = (zval*) allocate(sizeof(zval)));
3265 + local_dst_alloc = 1;
3266 + }
3267 +
3268 + dst = my_copy_zval(dst, src, allocate, deallocate);
3269 + if(!dst) {
3270 + if(local_dst_alloc) deallocate(dst);
3271 + return NULL;
3272 + }
3273 + return dst;
3274 +}
3275 +/* }}} */
3276 +
3277 +#ifdef ZEND_ENGINE_2
3278 +/* {{{ apc_fixup_op_array_jumps */
3279 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
3280 +{
3281 + int i;
3282 +
3283 + for (i=0; i < dst->last; ++i) {
3284 + zend_op *zo = &(dst->opcodes[i]);
3285 + /*convert opline number to jump address*/
3286 + switch (zo->opcode) {
3287 + case ZEND_JMP:
3288 + /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
3289 + zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
3290 + break;
3291 + case ZEND_JMPZ:
3292 + case ZEND_JMPNZ:
3293 + case ZEND_JMPZ_EX:
3294 + case ZEND_JMPNZ_EX:
3295 + zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
3296 + break;
3297 + default:
3298 + break;
3299 + }
3300 + }
3301 +}
3302 +/* }}} */
3303 +#endif
3304 +
3305 +/* {{{ apc_copy_op_array */
3306 +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)
3307 +{
3308 + int i;
3309 + int local_dst_alloc = 0;
3310 + apc_fileinfo_t fileinfo;
3311 + char canon_path[MAXPATHLEN];
3312 + char *fullpath = NULL;
3313 +#ifdef ZEND_ENGINE_2
3314 + apc_opflags_t * flags = NULL;
3315 +#endif
3316 +
3317 + assert(src != NULL);
3318 +
3319 + if (!dst) {
3320 + CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
3321 + local_dst_alloc = 1;
3322 + }
3323 +
3324 + if(APCG(apc_optimize_function)) {
3325 + APCG(apc_optimize_function)(src TSRMLS_CC);
3326 + }
3327 +
3328 + /* start with a bitwise copy of the array */
3329 + memcpy(dst, src, sizeof(src[0]));
3330 +
3331 + dst->function_name = NULL;
3332 + dst->filename = NULL;
3333 + dst->refcount = NULL;
3334 + dst->opcodes = NULL;
3335 + dst->brk_cont_array = NULL;
3336 + dst->static_variables = NULL;
3337 +#ifdef ZEND_ENGINE_2
3338 + dst->try_catch_array = NULL;
3339 + dst->arg_info = NULL;
3340 + dst->doc_comment = NULL;
3341 +#else
3342 + dst->arg_types = NULL;
3343 +#endif
3344 +#ifdef ZEND_ENGINE_2_1
3345 + dst->vars = NULL;
3346 +#endif
3347 +
3348 + /* copy the arg types array (if set) */
3349 +#ifdef ZEND_ENGINE_2
3350 + if (src->arg_info) {
3351 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
3352 + src->arg_info,
3353 + src->num_args,
3354 + allocate,
3355 + deallocate))) {
3356 + goto cleanup;
3357 + }
3358 + }
3359 +#else
3360 + if (src->arg_types) {
3361 + if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
3362 + sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
3363 + allocate))) {
3364 + goto cleanup;
3365 + }
3366 + }
3367 +#endif
3368 +
3369 + if (src->function_name) {
3370 + if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
3371 + goto cleanup;
3372 + }
3373 + }
3374 + if (src->filename) {
3375 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3376 + goto cleanup;
3377 + }
3378 + }
3379 +
3380 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
3381 + sizeof(src->refcount[0]),
3382 + allocate))) {
3383 + goto cleanup;
3384 + }
3385 +
3386 + /* deep-copy the opcodes */
3387 + if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
3388 + goto cleanup;
3389 + }
3390 +
3391 +#ifdef ZEND_ENGINE_2
3392 + if(APCG(reserved_offset) != -1) {
3393 + /* Insanity alert: the void* pointer is cast into an apc_opflags_t
3394 + * struct. apc_zend_init() checks to ensure that it fits in a void* */
3395 + flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
3396 + memset(flags, 0, sizeof(apc_opflags_t));
3397 + /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
3398 + }
3399 +#endif
3400 +
3401 + for (i = 0; i < src->last; i++) {
3402 +#ifdef ZEND_ENGINE_2
3403 + zend_op *zo = &(src->opcodes[i]);
3404 + /* a lot of files are merely constant arrays with no jumps */
3405 + switch (zo->opcode) {
3406 + case ZEND_JMP:
3407 + case ZEND_JMPZ:
3408 + case ZEND_JMPNZ:
3409 + case ZEND_JMPZ_EX:
3410 + case ZEND_JMPNZ_EX:
3411 + if(flags != NULL) {
3412 + flags->has_jumps = 1;
3413 + }
3414 + break;
3415 +#ifdef ZEND_ENGINE_2
3416 + /* auto_globals_jit was not in php-4.3.* */
3417 + case ZEND_FETCH_R:
3418 + case ZEND_FETCH_W:
3419 + case ZEND_FETCH_IS:
3420 + case ZEND_FETCH_FUNC_ARG:
3421 + if(PG(auto_globals_jit) && flags != NULL)
3422 + {
3423 + /* The fetch is only required if auto_globals_jit=1 */
3424 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
3425 + zo->op1.op_type == IS_CONST &&
3426 + zo->op1.u.constant.type == IS_STRING) {
3427 + znode * varname = &zo->op1;
3428 + if (varname->u.constant.value.str.val[0] == '_') {
3429 +#define SET_IF_AUTOGLOBAL(member) \
3430 + if(!strcmp(varname->u.constant.value.str.val, #member)) \
3431 + flags->member = 1 /* no ';' here */
3432 + SET_IF_AUTOGLOBAL(_GET);
3433 + else SET_IF_AUTOGLOBAL(_POST);
3434 + else SET_IF_AUTOGLOBAL(_COOKIE);
3435 + else SET_IF_AUTOGLOBAL(_SERVER);
3436 + else SET_IF_AUTOGLOBAL(_ENV);
3437 + else SET_IF_AUTOGLOBAL(_FILES);
3438 + else SET_IF_AUTOGLOBAL(_REQUEST);
3439 + else if(zend_is_auto_global(
3440 + varname->u.constant.value.str.val,
3441 + varname->u.constant.value.str.len
3442 + TSRMLS_CC))
3443 + {
3444 + flags->unknown_global = 1;
3445 + }
3446 + }
3447 + }
3448 + }
3449 + break;
3450 +#endif
3451 + case ZEND_RECV_INIT:
3452 + if(zo->op2.op_type == IS_CONST &&
3453 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
3454 + if(flags != NULL) {
3455 + flags->deep_copy = 1;
3456 + }
3457 + }
3458 + break;
3459 + default:
3460 + if((zo->op1.op_type == IS_CONST &&
3461 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
3462 + (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 + }
3470 +#endif
3471 + if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
3472 + int ii;
3473 + for(ii = i-1; ii>=0; ii--) {
3474 + my_destroy_zend_op(dst->opcodes+ii, deallocate);
3475 + }
3476 + goto cleanup;
3477 + }
3478 +#ifdef ZEND_ENGINE_2
3479 +/* This code breaks apc's rule#1 - cache what you compile */
3480 + if(APCG(fpstat)==0) {
3481 + if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
3482 + (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
3483 + /* constant includes */
3484 + if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),len)) {
3485 + if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
3486 + if((IS_ABSOLUTE_PATH(fileinfo.fullpath, strlen(fileinfo.fullpath)) && (fullpath = fileinfo.fullpath))
3487 + || (fullpath = realpath(fileinfo.fullpath, canon_path))) {
3488 + /* is either an absolute path or it goes through a realpath() */
3489 + zend_op *dzo = &(dst->opcodes[i]);
3490 + deallocate(dzo->op1.u.constant.value.str.val);
3491 + dzo->op1.u.constant.value.str.len = strlen(fullpath);
3492 + dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
3493 + }
3494 + }
3495 + }
3496 + }
3497 + }
3498 +#endif
3499 + }
3500 +
3501 +#ifdef ZEND_ENGINE_2
3502 + if(flags == NULL || flags->has_jumps) {
3503 + apc_fixup_op_array_jumps(dst,src);
3504 + }
3505 +#endif
3506 +
3507 + /* copy the break-continue array */
3508 + if (src->brk_cont_array) {
3509 + if(!(dst->brk_cont_array =
3510 + apc_xmemcpy(src->brk_cont_array,
3511 + sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
3512 + allocate))) {
3513 + goto cleanup_opcodes;
3514 + }
3515 + }
3516 +
3517 + /* copy the table of static variables */
3518 + if (src->static_variables) {
3519 + if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
3520 + goto cleanup_opcodes;
3521 + }
3522 + }
3523 +
3524 +#ifdef ZEND_ENGINE_2
3525 + if (src->try_catch_array) {
3526 + if(!(dst->try_catch_array =
3527 + apc_xmemcpy(src->try_catch_array,
3528 + sizeof(src->try_catch_array[0]) * src->last_try_catch,
3529 + allocate))) {
3530 + goto cleanup_opcodes;
3531 + }
3532 + }
3533 +#endif
3534 +
3535 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
3536 + if (src->vars) {
3537 + if(!(dst->vars = apc_xmemcpy(src->vars,
3538 + sizeof(src->vars[0]) * src->last_var,
3539 + allocate))) {
3540 + goto cleanup_opcodes;
3541 + }
3542 +
3543 + for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
3544 +
3545 + for(i = 0; i < src->last_var; i++) {
3546 + if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
3547 + src->vars[i].name_len + 1,
3548 + allocate))) {
3549 + dst->last_var = i;
3550 + goto cleanup_opcodes;
3551 + }
3552 + }
3553 + }
3554 +#endif
3555 +
3556 +#ifdef ZEND_ENGINE_2
3557 + if (src->doc_comment) {
3558 + if (!(dst->doc_comment
3559 + = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3560 + goto cleanup_opcodes;
3561 + }
3562 + }
3563 +#endif
3564 +
3565 + return dst;
3566 +
3567 +cleanup_opcodes:
3568 + if(dst->opcodes) {
3569 + for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
3570 + }
3571 +cleanup:
3572 + if(dst->function_name) deallocate(dst->function_name);
3573 + if(dst->refcount) deallocate(dst->refcount);
3574 + if(dst->filename) deallocate(dst->filename);
3575 +#ifdef ZEND_ENGINE_2
3576 + if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
3577 + if(dst->try_catch_array) deallocate(dst->try_catch_array);
3578 + if(dst->doc_comment) deallocate(dst->doc_comment);
3579 +#else
3580 + if(dst->arg_types) deallocate(dst->arg_types);
3581 +#endif
3582 + if(dst->opcodes) deallocate(dst->opcodes);
3583 + if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
3584 + if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
3585 +#ifdef ZEND_ENGINE_2_1
3586 + if (dst->vars) {
3587 + for(i=0; i < dst->last_var; i++) {
3588 + if(dst->vars[i].name) deallocate(dst->vars[i].name);
3589 + }
3590 + deallocate(dst->vars);
3591 + }
3592 +#endif
3593 + if(local_dst_alloc) deallocate(dst);
3594 + return NULL;
3595 +}
3596 +/* }}} */
3597 +
3598 +/* {{{ apc_copy_new_functions */
3599 +apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3600 +{
3601 + apc_function_t* array;
3602 + int new_count; /* number of new functions in table */
3603 + int i;
3604 +
3605 + new_count = zend_hash_num_elements(CG(function_table)) - old_count;
3606 + assert(new_count >= 0);
3607 +
3608 + CHECK(array =
3609 + (apc_function_t*)
3610 + allocate(sizeof(apc_function_t) * (new_count+1)));
3611 +
3612 + if (new_count == 0) {
3613 + array[0].function = NULL;
3614 + return array;
3615 + }
3616 +
3617 + /* Skip the first `old_count` functions in the table */
3618 + zend_hash_internal_pointer_reset(CG(function_table));
3619 + for (i = 0; i < old_count; i++) {
3620 + zend_hash_move_forward(CG(function_table));
3621 + }
3622 +
3623 + /* Add the next `new_count` functions to our array */
3624 + for (i = 0; i < new_count; i++) {
3625 + char* key;
3626 + uint key_size;
3627 + zend_function* fun;
3628 +
3629 + zend_hash_get_current_key_ex(CG(function_table),
3630 + &key,
3631 + &key_size,
3632 + NULL,
3633 + 0,
3634 + NULL);
3635 +
3636 + zend_hash_get_current_data(CG(function_table), (void**) &fun);
3637 +
3638 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3639 + int ii;
3640 + for(ii=i-1; ii>=0; ii--) {
3641 + deallocate(array[ii].name);
3642 + my_free_function(array[ii].function, deallocate);
3643 + }
3644 + deallocate(array);
3645 + return NULL;
3646 + }
3647 + array[i].name_len = (int) key_size-1;
3648 + if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
3649 + int ii;
3650 + deallocate(array[i].name);
3651 + for(ii=i-1; ii>=0; ii--) {
3652 + deallocate(array[ii].name);
3653 + my_free_function(array[ii].function, deallocate);
3654 + }
3655 + deallocate(array);
3656 + return NULL;
3657 + }
3658 + zend_hash_move_forward(CG(function_table));
3659 + }
3660 +
3661 + array[i].function = NULL;
3662 + return array;
3663 +}
3664 +/* }}} */
3665 +
3666 +/* {{{ apc_copy_new_classes */
3667 +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)
3668 +{
3669 + apc_class_t* array;
3670 + int new_count; /* number of new classes in table */
3671 + int i;
3672 +
3673 + new_count = zend_hash_num_elements(CG(class_table)) - old_count;
3674 + assert(new_count >= 0);
3675 +
3676 + CHECK(array =
3677 + (apc_class_t*)
3678 + allocate(sizeof(apc_class_t)*(new_count+1)));
3679 +
3680 + if (new_count == 0) {
3681 + array[0].class_entry = NULL;
3682 + return array;
3683 + }
3684 +
3685 + /* Skip the first `old_count` classes in the table */
3686 + zend_hash_internal_pointer_reset(CG(class_table));
3687 + for (i = 0; i < old_count; i++) {
3688 + zend_hash_move_forward(CG(class_table));
3689 + }
3690 +
3691 + /* Add the next `new_count` classes to our array */
3692 + for (i = 0; i < new_count; i++) {
3693 + char* key;
3694 + uint key_size;
3695 + zend_class_entry* elem = NULL;
3696 +
3697 + array[i].class_entry = NULL;
3698 +
3699 + zend_hash_get_current_key_ex(CG(class_table),
3700 + &key,
3701 + &key_size,
3702 + NULL,
3703 + 0,
3704 + NULL);
3705 +
3706 + zend_hash_get_current_data(CG(class_table), (void**) &elem);
3707 +
3708 +
3709 +#ifdef ZEND_ENGINE_2
3710 + elem = *((zend_class_entry**)elem);
3711 +#endif
3712 +
3713 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3714 + int ii;
3715 +
3716 + for(ii=i-1; ii>=0; ii--) {
3717 + deallocate(array[ii].name);
3718 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3719 + deallocate(array[ii].class_entry);
3720 + }
3721 + deallocate(array);
3722 + return NULL;
3723 + }
3724 + array[i].name_len = (int) key_size-1;
3725 + if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
3726 + int ii;
3727 +
3728 + deallocate(array[i].name);
3729 + for(ii=i-1; ii>=0; ii--) {
3730 + deallocate(array[ii].name);
3731 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3732 + deallocate(array[ii].class_entry);
3733 + }
3734 + deallocate(array);
3735 + return NULL;
3736 + }
3737 +
3738 + /*
3739 + * If the class has a pointer to its parent class, save the parent
3740 + * name so that we can enable compile-time inheritance when we reload
3741 + * the child class; otherwise, set the parent name to null and scan
3742 + * the op_array to determine if this class inherits from some base
3743 + * class at execution-time.
3744 + */
3745 +
3746 + if (elem->parent) {
3747 + if(!(array[i].parent_name =
3748 + apc_xstrdup(elem->parent->name, allocate))) {
3749 + int ii;
3750 +
3751 + for(ii=i; ii>=0; ii--) {
3752 + deallocate(array[ii].name);
3753 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3754 + deallocate(array[ii].class_entry);
3755 + if(ii==i) continue;
3756 + if(array[ii].parent_name) deallocate(array[ii].parent_name);
3757 + }
3758 + deallocate(array);
3759 + return NULL;
3760 + }
3761 + array[i].is_derived = 1;
3762 + }
3763 + else {
3764 + array[i].parent_name = NULL;
3765 + array[i].is_derived = is_derived_class(op_array, key, key_size);
3766 + }
3767 +
3768 + zend_hash_move_forward(CG(class_table));
3769 + }
3770 +
3771 + array[i].class_entry = NULL;
3772 + return array;
3773 +}
3774 +/* }}} */
3775 +
3776 +/* {{{ my_destroy_zval_ptr */
3777 +static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
3778 +{
3779 + assert(src != NULL);
3780 + if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
3781 + deallocate(src[0]);
3782 + }
3783 +}
3784 +/* }}} */
3785 +
3786 +/* {{{ my_destroy_zval */
3787 +static int my_destroy_zval(zval* src, apc_free_t deallocate)
3788 +{
3789 + zval **tmp;
3790 + TSRMLS_FETCH();
3791 +
3792 + switch (src->type & ~IS_CONSTANT_INDEX) {
3793 + case IS_RESOURCE:
3794 + case IS_BOOL:
3795 + case IS_LONG:
3796 + case IS_DOUBLE:
3797 + case IS_NULL:
3798 + break;
3799 +
3800 + case IS_CONSTANT:
3801 + case IS_STRING:
3802 +#ifndef ZEND_ENGINE_2
3803 + case FLAG_IS_BC:
3804 +#endif
3805 + deallocate(src->value.str.val);
3806 + break;
3807 +
3808 + case IS_ARRAY:
3809 +
3810 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
3811 + if(APCG(copied_zvals)) {
3812 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3813 + (*tmp)->refcount--;
3814 + return FAILURE;
3815 + }
3816 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
3817 + }
3818 + /* fall through */
3819 +
3820 + case IS_CONSTANT_ARRAY:
3821 + my_free_hashtable(src->value.ht,
3822 + (ht_free_fun_t) my_free_zval_ptr,
3823 + deallocate);
3824 + break;
3825 +
3826 + case IS_OBJECT:
3827 +#ifndef ZEND_ENGINE_2
3828 + my_destroy_class_entry(src->value.obj.ce, deallocate);
3829 + deallocate(src->value.obj.ce);
3830 + my_free_hashtable(src->value.obj.properties,
3831 + (ht_free_fun_t) my_free_zval_ptr,
3832 + deallocate);
3833 +#endif
3834 + break;
3835 +
3836 + default:
3837 + assert(0);
3838 + }
3839 +
3840 + return SUCCESS;
3841 +}
3842 +/* }}} */
3843 +
3844 +/* {{{ my_destroy_znode */
3845 +static void my_destroy_znode(znode* src, apc_free_t deallocate)
3846 +{
3847 + if (src->op_type == IS_CONST) {
3848 + my_destroy_zval(&src->u.constant, deallocate);
3849 + }
3850 +}
3851 +/* }}} */
3852 +
3853 +/* {{{ my_destroy_zend_op */
3854 +static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
3855 +{
3856 + my_destroy_znode(&src->result, deallocate);
3857 + my_destroy_znode(&src->op1, deallocate);
3858 + my_destroy_znode(&src->op2, deallocate);
3859 +}
3860 +/* }}} */
3861 +
3862 +/* {{{ my_destroy_function */
3863 +static void my_destroy_function(zend_function* src, apc_free_t deallocate)
3864 +{
3865 + assert(src != NULL);
3866 +
3867 + switch (src->type) {
3868 + case ZEND_INTERNAL_FUNCTION:
3869 + case ZEND_OVERLOADED_FUNCTION:
3870 + break;
3871 +
3872 + case ZEND_USER_FUNCTION:
3873 + case ZEND_EVAL_CODE:
3874 + my_destroy_op_array(&src->op_array, deallocate);
3875 + break;
3876 +
3877 + default:
3878 + assert(0);
3879 + }
3880 +}
3881 +/* }}} */
3882 +
3883 +/* {{{ my_destroy_function_entry */
3884 +static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
3885 +{
3886 + assert(src != NULL);
3887 +
3888 + deallocate(src->fname);
3889 +#ifdef ZEND_ENGINE_2
3890 + if (src->arg_info) {
3891 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
3892 + }
3893 +#else
3894 + if (src->func_arg_types) {
3895 + deallocate(src->func_arg_types);
3896 + }
3897 +#endif
3898 +}
3899 +/* }}} */
3900 +
3901 +#ifdef ZEND_ENGINE_2
3902 +/* {{{ my_destroy_property_info*/
3903 +static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
3904 +{
3905 + assert(src != NULL);
3906 +
3907 + deallocate(src->name);
3908 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
3909 + if(src->doc_comment) deallocate(src->doc_comment);
3910 +#endif
3911 +}
3912 +/* }}} */
3913 +
3914 +/* {{{ my_destroy_arg_info_array */
3915 +static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
3916 +{
3917 + int i = 0;
3918 +
3919 + assert(src != NULL);
3920 +
3921 + for(i=0; i < num_args; i++) {
3922 + my_destroy_arg_info(&src[i], deallocate);
3923 + }
3924 +}
3925 +/* }}} */
3926 +
3927 +/* {{{ my_destroy_arg_info */
3928 +static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
3929 +{
3930 + assert(src != NULL);
3931 +
3932 + deallocate(src->name);
3933 + deallocate(src->class_name);
3934 +}
3935 +/* }}} */
3936 +#endif
3937 +
3938 +/* {{{ my_destroy_class_entry */
3939 +static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
3940 +{
3941 + uint i;
3942 +
3943 + assert(src != NULL);
3944 +
3945 + deallocate(src->name);
3946 +#ifndef ZEND_ENGINE_2
3947 + deallocate(src->refcount);
3948 +#else
3949 + if(src->doc_comment) deallocate(src->doc_comment);
3950 + if(src->filename) deallocate(src->filename);
3951 +#endif
3952 +
3953 + my_destroy_hashtable(&src->function_table,
3954 + (ht_free_fun_t) my_free_function,
3955 + deallocate);
3956 +
3957 + my_destroy_hashtable(&src->default_properties,
3958 + (ht_free_fun_t) my_free_zval_ptr,
3959 + deallocate);
3960 +
3961 +#ifdef ZEND_ENGINE_2
3962 + my_destroy_hashtable(&src->properties_info,
3963 + (ht_free_fun_t) my_free_property_info,
3964 + deallocate);
3965 + if(src->static_members)
3966 + {
3967 + my_destroy_hashtable(src->static_members,
3968 + (ht_free_fun_t) my_free_zval_ptr,
3969 + deallocate);
3970 + if(src->static_members != &(src->default_static_members))
3971 + {
3972 + deallocate(src->static_members);
3973 + }
3974 + }
3975 +
3976 + my_destroy_hashtable(&src->constants_table,
3977 + (ht_free_fun_t) my_free_zval_ptr,
3978 + deallocate);
3979 +#endif
3980 +
3981 + if (src->builtin_functions) {
3982 + for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
3983 + my_destroy_function_entry(&src->builtin_functions[i], deallocate);
3984 + }
3985 + deallocate(src->builtin_functions);
3986 + }
3987 +}
3988 +/* }}} */
3989 +
3990 +/* {{{ my_destroy_hashtable */
3991 +static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
3992 +{
3993 + int i;
3994 +
3995 + assert(src != NULL);
3996 +
3997 + for (i = 0; i < src->nTableSize; i++) {
3998 + Bucket* p = src->arBuckets[i];
3999 + while (p != NULL) {
4000 + Bucket* q = p;
4001 + p = p->pNext;
4002 + free_fn(q->pData, deallocate);
4003 + deallocate(q);
4004 + }
4005 + }
4006 +
4007 + deallocate(src->arBuckets);
4008 +}
4009 +/* }}} */
4010 +
4011 +/* {{{ my_destroy_op_array */
4012 +static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
4013 +{
4014 + int i;
4015 +
4016 + assert(src != NULL);
4017 +
4018 +#ifdef ZEND_ENGINE_2
4019 + if (src->arg_info) {
4020 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
4021 + }
4022 +#else
4023 + if (src->arg_types) {
4024 + deallocate(src->arg_types);
4025 + }
4026 +#endif
4027 +
4028 + deallocate(src->function_name);
4029 + deallocate(src->filename);
4030 + deallocate(src->refcount);
4031 +
4032 + for (i = 0; i < src->last; i++) {
4033 + my_destroy_zend_op(src->opcodes + i, deallocate);
4034 + }
4035 + deallocate(src->opcodes);
4036 +
4037 + if (src->brk_cont_array) {
4038 + deallocate(src->brk_cont_array);
4039 + }
4040 +
4041 + if (src->static_variables) {
4042 + my_free_hashtable(src->static_variables,
4043 + (ht_free_fun_t) my_free_zval_ptr,
4044 + deallocate);
4045 + }
4046 +
4047 +#ifdef ZEND_ENGINE_2_1
4048 + if (src->vars) {
4049 + for(i=0; i < src->last_var; i++) {
4050 + if(src->vars[i].name) deallocate(src->vars[i].name);
4051 + }
4052 + deallocate(src->vars);
4053 + }
4054 +#endif
4055 +#ifdef ZEND_ENGINE_2
4056 + if(src->try_catch_array) {
4057 + deallocate(src->try_catch_array);
4058 + }
4059 + if (src->doc_comment) {
4060 + deallocate(src->doc_comment);
4061 + }
4062 +#endif
4063 +}
4064 +/* }}} */
4065 +
4066 +/* {{{ my_free_zval_ptr */
4067 +static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
4068 +{
4069 + my_destroy_zval_ptr(src, deallocate);
4070 + deallocate(src);
4071 +}
4072 +/* }}} */
4073 +
4074 +#ifdef ZEND_ENGINE_2
4075 +/* {{{ my_free_property_info */
4076 +static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
4077 +{
4078 + my_destroy_property_info(src, deallocate);
4079 + deallocate(src);
4080 +}
4081 +/* }}} */
4082 +
4083 +/* {{{ my_free_arg_info_array */
4084 +static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
4085 +{
4086 + my_destroy_arg_info_array(src, num_args, deallocate);
4087 + deallocate(src);
4088 +}
4089 +/* }}} */
4090 +
4091 +/* {{{ my_free_arg_info */
4092 +static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
4093 +{
4094 + my_destroy_arg_info(src, deallocate);
4095 + deallocate(src);
4096 +}
4097 +/* }}} */
4098 +#endif
4099 +
4100 +/* {{{ my_free_function */
4101 +static void my_free_function(zend_function* src, apc_free_t deallocate)
4102 +{
4103 + my_destroy_function(src, deallocate);
4104 + deallocate(src);
4105 +}
4106 +/* }}} */
4107 +
4108 +/* {{{ my_free_hashtable */
4109 +static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4110 +{
4111 + my_destroy_hashtable(src, free_fn, deallocate);
4112 + deallocate(src);
4113 +}
4114 +/* }}} */
4115 +
4116 +/* {{{ apc_free_op_array */
4117 +void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
4118 +{
4119 + if (src != NULL) {
4120 + my_destroy_op_array(src, deallocate);
4121 + deallocate(src);
4122 + }
4123 +}
4124 +/* }}} */
4125 +
4126 +/* {{{ apc_free_functions */
4127 +void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
4128 +{
4129 + int i;
4130 +
4131 + if (src != NULL) {
4132 + for (i = 0; src[i].function != NULL; i++) {
4133 + deallocate(src[i].name);
4134 + my_destroy_function(src[i].function, deallocate);
4135 + deallocate(src[i].function);
4136 + }
4137 + deallocate(src);
4138 + }
4139 +}
4140 +/* }}} */
4141 +
4142 +/* {{{ apc_free_classes */
4143 +void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
4144 +{
4145 + int i;
4146 +
4147 + if (src != NULL) {
4148 + for (i = 0; src[i].class_entry != NULL; i++) {
4149 + deallocate(src[i].name);
4150 + deallocate(src[i].parent_name);
4151 + my_destroy_class_entry(src[i].class_entry, deallocate);
4152 + deallocate(src[i].class_entry);
4153 + }
4154 + deallocate(src);
4155 + }
4156 +}
4157 +/* }}} */
4158 +
4159 +/* {{{ apc_free_zval */
4160 +void apc_free_zval(zval* src, apc_free_t deallocate)
4161 +{
4162 + if (src != NULL) {
4163 + if(my_destroy_zval(src, deallocate) == SUCCESS) {
4164 + deallocate(src);
4165 + }
4166 + }
4167 +}
4168 +/* }}} */
4169 +
4170 +
4171 +/* Used only by my_prepare_op_array_for_execution */
4172 +#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
4173 + /* The fetch is only required if auto_globals_jit=1 */ \
4174 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
4175 + zo->op1.op_type == IS_CONST && \
4176 + zo->op1.u.constant.type == IS_STRING && \
4177 + zo->op1.u.constant.value.str.val[0] == '_') { \
4178 + \
4179 + znode* varname = &zo->op1; \
4180 + (void)zend_is_auto_global(varname->u.constant.value.str.val, \
4181 + varname->u.constant.value.str.len \
4182 + TSRMLS_CC); \
4183 + } \
4184 +
4185 +/* {{{ my_prepare_op_array_for_execution */
4186 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4187 +{
4188 + /* combine my_fetch_global_vars and my_copy_data_exceptions.
4189 + * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4190 + * - If the opcode stream contain mutable data, ensure a copy.
4191 + * - Fixup array jumps in the same loop.
4192 + */
4193 + int i=src->last;
4194 + zend_op *zo;
4195 + zend_op *dzo;
4196 +#ifdef ZEND_ENGINE_2
4197 + apc_opflags_t * flags = APCG(reserved_offset) != -1 ?
4198 + (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
4199 + int needcopy = flags ? flags->deep_copy : 1;
4200 + /* auto_globals_jit was not in php4 */
4201 + int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
4202 +
4203 +#define FETCH_AUTOGLOBAL(member) do { \
4204 + if(flags && flags->member == 1) { \
4205 + zend_is_auto_global(#member,\
4206 + (sizeof(#member) - 1)\
4207 + TSRMLS_CC);\
4208 + } \
4209 +}while(0);
4210 +
4211 + FETCH_AUTOGLOBAL(_GET);
4212 + FETCH_AUTOGLOBAL(_POST);
4213 + FETCH_AUTOGLOBAL(_COOKIE);
4214 + FETCH_AUTOGLOBAL(_SERVER);
4215 + FETCH_AUTOGLOBAL(_ENV);
4216 + FETCH_AUTOGLOBAL(_FILES);
4217 + FETCH_AUTOGLOBAL(_REQUEST);
4218 +
4219 +#else
4220 + int needcopy = 0;
4221 + int do_prepare_fetch_global = 0;
4222 + int j = 0;
4223 +
4224 + for(j = 0; j < src->last; j++) {
4225 + zo = &src->opcodes[j];
4226 +
4227 + if( ((zo->op1.op_type == IS_CONST &&
4228 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4229 + ((zo->op2.op_type == IS_CONST &&
4230 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4231 + needcopy = 1;
4232 + }
4233 + }
4234 +#endif
4235 +
4236 + if(needcopy) {
4237 +
4238 + dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
4239 + sizeof(zend_op) * src->last,
4240 + apc_php_malloc);
4241 + zo = src->opcodes;
4242 + dzo = dst->opcodes;
4243 + while(i > 0) {
4244 +
4245 + if( ((zo->op1.op_type == IS_CONST &&
4246 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4247 + ((zo->op2.op_type == IS_CONST &&
4248 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4249 +
4250 + if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
4251 + assert(0); /* emalloc failed or a bad constant array */
4252 + }
4253 + }
4254 +
4255 +#ifdef ZEND_ENGINE_2
4256 + switch(zo->opcode) {
4257 + case ZEND_JMP:
4258 + dzo->op1.u.jmp_addr = dst->opcodes +
4259 + (zo->op1.u.jmp_addr - src->opcodes);
4260 + break;
4261 + case ZEND_JMPZ:
4262 + case ZEND_JMPNZ:
4263 + case ZEND_JMPZ_EX:
4264 + case ZEND_JMPNZ_EX:
4265 + dzo->op2.u.jmp_addr = dst->opcodes +
4266 + (zo->op2.u.jmp_addr - src->opcodes);
4267 + break;
4268 + case ZEND_FETCH_R:
4269 + case ZEND_FETCH_W:
4270 + case ZEND_FETCH_IS:
4271 + case ZEND_FETCH_FUNC_ARG:
4272 + if(do_prepare_fetch_global)
4273 + {
4274 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4275 + }
4276 + break;
4277 + default:
4278 + break;
4279 + }
4280 +#endif
4281 + i--;
4282 + zo++;
4283 + dzo++;
4284 + }
4285 +#ifdef ZEND_ENGINE_2
4286 + } else { /* !needcopy */
4287 + /* The fetch is only required if auto_globals_jit=1 */
4288 + if(do_prepare_fetch_global)
4289 + {
4290 + zo = src->opcodes;
4291 + while(i > 0) {
4292 +
4293 + if(zo->opcode == ZEND_FETCH_R ||
4294 + zo->opcode == ZEND_FETCH_W ||
4295 + zo->opcode == ZEND_FETCH_IS ||
4296 + zo->opcode == ZEND_FETCH_FUNC_ARG
4297 + ) {
4298 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4299 + }
4300 +
4301 + i--;
4302 + zo++;
4303 + }
4304 + }
4305 +#endif
4306 + }
4307 + return 1;
4308 +}
4309 +/* }}} */
4310 +
4311 +/* {{{ apc_copy_op_array_for_execution */
4312 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4313 +{
4314 + if(dst == NULL) {
4315 + dst = (zend_op_array*) emalloc(sizeof(src[0]));
4316 + }
4317 + memcpy(dst, src, sizeof(src[0]));
4318 + dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
4319 +
4320 + dst->refcount = apc_xmemcpy(src->refcount,
4321 + sizeof(src->refcount[0]),
4322 + apc_php_malloc);
4323 +
4324 + my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
4325 +
4326 + return dst;
4327 +}
4328 +/* }}} */
4329 +
4330 +/* {{{ apc_copy_function_for_execution */
4331 +zend_function* apc_copy_function_for_execution(zend_function* src)
4332 +{
4333 + zend_function* dst;
4334 + TSRMLS_FETCH();
4335 +
4336 + dst = (zend_function*) emalloc(sizeof(src[0]));
4337 + memcpy(dst, src, sizeof(src[0]));
4338 + apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
4339 + return dst;
4340 +}
4341 +/* }}} */
4342 +
4343 +/* {{{ apc_copy_function_for_execution_ex */
4344 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
4345 +{
4346 + if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
4347 + return apc_copy_function_for_execution(src);
4348 +}
4349 +/* }}} */
4350 +
4351 +/* {{{ apc_copy_class_entry_for_execution */
4352 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
4353 +{
4354 + zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
4355 + memcpy(dst, src, sizeof(src[0]));
4356 +
4357 +#ifdef ZEND_ENGINE_2
4358 + if(src->num_interfaces)
4359 + {
4360 + /* These are slots to be populated later by ADD_INTERFACE insns */
4361 + dst->interfaces = apc_php_malloc(
4362 + sizeof(zend_class_entry*) * src->num_interfaces);
4363 + memset(dst->interfaces, 0,
4364 + sizeof(zend_class_entry*) * src->num_interfaces);
4365 + }
4366 + else
4367 + {
4368 + /* assert(dst->interfaces == NULL); */
4369 + }
4370 +#endif
4371 +
4372 +#ifndef ZEND_ENGINE_2
4373 + dst->refcount = apc_xmemcpy(src->refcount,
4374 + sizeof(src->refcount[0]),
4375 + apc_php_malloc);
4376 +#endif
4377 +
4378 + /* Deep-copy the class properties, because they will be modified */
4379 +
4380 + my_copy_hashtable(&dst->default_properties,
4381 + &src->default_properties,
4382 + (ht_copy_fun_t) my_copy_zval_ptr,
4383 + (ht_free_fun_t) my_free_zval_ptr,
4384 + 1,
4385 + apc_php_malloc, apc_php_free);
4386 +
4387 + /* For derived classes, we must also copy the function hashtable (although
4388 + * we can merely bitwise copy the functions it contains) */
4389 +
4390 + my_copy_hashtable(&dst->function_table,
4391 + &src->function_table,
4392 + (ht_copy_fun_t) apc_copy_function_for_execution_ex,
4393 + NULL,
4394 + 0,
4395 + apc_php_malloc, apc_php_free);
4396 +#ifdef ZEND_ENGINE_2
4397 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
4398 +
4399 + /* zend_do_inheritance merges properties_info.
4400 + * Need only shallow copying as it doesn't hold the pointers.
4401 + */
4402 + my_copy_hashtable(&dst->properties_info,
4403 + &src->properties_info,
4404 + (ht_copy_fun_t) my_copy_property_info_for_execution,
4405 + NULL,
4406 + 0,
4407 + apc_php_malloc, apc_php_free);
4408 +
4409 +#ifdef ZEND_ENGINE_2_2
4410 + /* php5.2 introduced a scope attribute for property info */
4411 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4412 +#endif
4413 +
4414 + /* if inheritance results in a hash_del, it might result in
4415 + * a pefree() of the pointers here. Deep copying required.
4416 + */
4417 +
4418 + my_copy_hashtable(&dst->constants_table,
4419 + &src->constants_table,
4420 + (ht_copy_fun_t) my_copy_zval_ptr,
4421 + NULL,
4422 + 1,
4423 + apc_php_malloc, apc_php_free);
4424 +
4425 + my_copy_hashtable(&dst->default_static_members,
4426 + &src->default_static_members,
4427 + (ht_copy_fun_t) my_copy_zval_ptr,
4428 + (ht_free_fun_t) my_free_zval_ptr,
4429 + 1,
4430 + apc_php_malloc, apc_php_free);
4431 +
4432 + if(src->static_members != &(src->default_static_members))
4433 + {
4434 + dst->static_members = my_copy_hashtable(NULL,
4435 + src->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 + else
4442 + {
4443 + dst->static_members = &(dst->default_static_members);
4444 + }
4445 +
4446 +#endif
4447 +
4448 + return dst;
4449 +}
4450 +/* }}} */
4451 +
4452 +/* {{{ apc_free_class_entry_after_execution */
4453 +void apc_free_class_entry_after_execution(zend_class_entry* src)
4454 +{
4455 +#ifdef ZEND_ENGINE_2
4456 + if(src->num_interfaces > 0 && src->interfaces) {
4457 + apc_php_free(src->interfaces);
4458 + src->interfaces = NULL;
4459 + src->num_interfaces = 0;
4460 + }
4461 + /* my_destroy_hashtable() does not play nice with refcounts */
4462 +
4463 + zend_hash_clean(&src->default_static_members);
4464 + if(src->static_members != &(src->default_static_members))
4465 + {
4466 + zend_hash_destroy(src->static_members);
4467 + apc_php_free(src->static_members);
4468 + src->static_members = NULL;
4469 + }
4470 + else
4471 + {
4472 + src->static_members = NULL;
4473 + }
4474 + zend_hash_clean(&src->default_properties);
4475 + zend_hash_clean(&src->constants_table);
4476 +#endif
4477 +
4478 + /* TODO: more cleanup */
4479 +}
4480 +/* }}} */
4481 +
4482 +#ifdef ZEND_ENGINE_2
4483 +
4484 +/* {{{ my_fixup_function */
4485 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4486 +{
4487 + zend_function* zf = p->pData;
4488 +
4489 + #define SET_IF_SAME_NAME(member) \
4490 + do { \
4491 + if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
4492 + dst->member = zf; \
4493 + } \
4494 + } \
4495 + while(0)
4496 +
4497 + if(zf->common.scope == src)
4498 + {
4499 +
4500 + /* Fixing up the default functions for objects here since
4501 + * we need to compare with the newly allocated functions
4502 + *
4503 + * caveat: a sub-class method can have the same name as the
4504 + * parent's constructor and create problems.
4505 + */
4506 +
4507 + if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
4508 + else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
4509 + else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
4510 + else
4511 + {
4512 + SET_IF_SAME_NAME(__get);
4513 + SET_IF_SAME_NAME(__set);
4514 + SET_IF_SAME_NAME(__unset);
4515 + SET_IF_SAME_NAME(__isset);
4516 + SET_IF_SAME_NAME(__call);
4517 +#ifdef ZEND_ENGINE_2_2
4518 + SET_IF_SAME_NAME(__tostring);
4519 +#endif
4520 + }
4521 + zf->common.scope = dst;
4522 + }
4523 + else
4524 + {
4525 + /* no other function should reach here */
4526 + assert(0);
4527 + }
4528 +
4529 + #undef SET_IF_SAME_NAME
4530 +}
4531 +/* }}} */
4532 +
4533 +#ifdef ZEND_ENGINE_2_2
4534 +/* {{{ my_fixup_property_info */
4535 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4536 +{
4537 + zend_property_info* property_info = (zend_property_info*)p->pData;
4538 +
4539 + if(property_info->ce == src)
4540 + {
4541 + property_info->ce = dst;
4542 + }
4543 + else
4544 + {
4545 + assert(0); /* should never happen */
4546 + }
4547 +}
4548 +/* }}} */
4549 +#endif
4550 +
4551 +/* {{{ my_fixup_hashtable */
4552 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
4553 +{
4554 + Bucket *p;
4555 +
4556 + uint i;
4557 +
4558 + for (i = 0; i < ht->nTableSize; i++) {
4559 + if(!ht->arBuckets) break;
4560 + p = ht->arBuckets[i];
4561 + while (p != NULL) {
4562 + fixup(p, src, dst);
4563 + p = p->pNext;
4564 + }
4565 + }
4566 +}
4567 +/* }}} */
4568 +
4569 +#endif
4570 +
4571 +/* {{{ my_check_copy_function */
4572 +static int my_check_copy_function(Bucket* p, va_list args)
4573 +{
4574 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4575 + zend_function* zf = (zend_function*)p->pData;
4576 +#ifndef ZEND_ENGINE_2
4577 + zend_class_entry* parent = src->parent;
4578 + zend_function* parent_fn = NULL;
4579 +#endif
4580 +
4581 +#ifdef ZEND_ENGINE_2
4582 + return (zf->common.scope == src);
4583 +#else
4584 + if (parent &&
4585 + zend_hash_quick_find(&parent->function_table, p->arKey,
4586 + p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
4587 +
4588 + if((parent_fn && zf) &&
4589 + (parent_fn->op_array.refcount == zf->op_array.refcount))
4590 + {
4591 + return 0;
4592 + }
4593 + }
4594 + return 1;
4595 +#endif
4596 +}
4597 +/* }}} */
4598 +
4599 +/* {{{ my_check_copy_default_property */
4600 +static int my_check_copy_default_property(Bucket* p, va_list args)
4601 +{
4602 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4603 + zend_class_entry* parent = src->parent;
4604 + zval ** child_prop = (zval**)p->pData;
4605 + zval ** parent_prop = NULL;
4606 +
4607 + if (parent &&
4608 + zend_hash_quick_find(&parent->default_properties, p->arKey,
4609 + p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
4610 +
4611 + if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
4612 + {
4613 + return 0;
4614 + }
4615 + }
4616 +
4617 + /* possibly not in the parent */
4618 + return 1;
4619 +}
4620 +/* }}} */
4621 +
4622 +#ifdef ZEND_ENGINE_2
4623 +
4624 +/* {{{ my_check_copy_property_info */
4625 +static int my_check_copy_property_info(Bucket* p, va_list args)
4626 +{
4627 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4628 + zend_class_entry* parent = src->parent;
4629 + zend_property_info* child_info = (zend_property_info*)p->pData;
4630 + zend_property_info* parent_info = NULL;
4631 +
4632 +#ifdef ZEND_ENGINE_2_2
4633 + /* so much easier */
4634 + return (child_info->ce == src);
4635 +#endif
4636 +
4637 + if (parent &&
4638 + zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
4639 + p->h, (void **) &parent_info)==SUCCESS) {
4640 + if(parent_info->flags & ZEND_ACC_PRIVATE)
4641 + {
4642 + return 1;
4643 + }
4644 + if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
4645 + (child_info->flags & ZEND_ACC_PPP_MASK))
4646 + {
4647 + /* TODO: figure out whether ACC_CHANGED is more appropriate
4648 + * here */
4649 + return 1;
4650 + }
4651 + return 0;
4652 + }
4653 +
4654 + /* property doesn't exist in parent, copy into cached child */
4655 + return 1;
4656 +}
4657 +/* }}} */
4658 +
4659 +/* {{{ my_check_copy_static_member */
4660 +static int my_check_copy_static_member(Bucket* p, va_list args)
4661 +{
4662 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4663 + HashTable * ht = va_arg(args, HashTable*);
4664 + zend_class_entry* parent = src->parent;
4665 + HashTable * parent_ht = NULL;
4666 + char * member_name;
4667 + char * class_name = NULL;
4668 +
4669 + zend_property_info *parent_info = NULL;
4670 + zend_property_info *child_info = NULL;
4671 + zval ** parent_prop = NULL;
4672 + zval ** child_prop = (zval**)(p->pData);
4673 +
4674 + if(!parent) {
4675 + return 1;
4676 + }
4677 +
4678 + /* these do not need free'ing */
4679 +#ifdef ZEND_ENGINE_2_2
4680 + zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
4681 +#else
4682 + zend_unmangle_property_name(p->arKey, &class_name, &member_name);
4683 +#endif
4684 +
4685 + /* please refer do_inherit_property_access_check in zend_compile.c
4686 + * to understand why we lookup in properties_info.
4687 + */
4688 + if((zend_hash_find(&parent->properties_info, member_name,
4689 + strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
4690 + &&
4691 + (zend_hash_find(&src->properties_info, member_name,
4692 + strlen(member_name)+1, (void**)&child_info) == SUCCESS))
4693 + {
4694 + if(child_info->flags & ZEND_ACC_STATIC &&
4695 + (parent_info->flags & ZEND_ACC_PROTECTED &&
4696 + child_info->flags & ZEND_ACC_PUBLIC))
4697 + {
4698 + /* Do not copy into static_members. zend_do_inheritance
4699 + * will automatically insert a NULL value.
4700 + * TODO: decrement refcount or fixup when copying out for exec ?
4701 + */
4702 + return 0;
4703 + }
4704 + if(ht == &(src->default_static_members))
4705 + {
4706 + parent_ht = &parent->default_static_members;
4707 + }
4708 + else
4709 + {
4710 + parent_ht = parent->static_members;
4711 + }
4712 +
4713 + if(zend_hash_quick_find(parent_ht, p->arKey,
4714 + p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
4715 + {
4716 + /* they point to the same zval */
4717 + if(*parent_prop == *child_prop)
4718 + {
4719 + return 0;
4720 + }
4721 + }
4722 + }
4723 +
4724 + return 1;
4725 +}
4726 +/* }}} */
4727 +#endif
4728 +
4729 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
4730 + * register a optimizer callback function, returns the previous callback
4731 + */
4732 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
4733 + apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
4734 + APCG(apc_optimize_function) = optimizer;
4735 + return old_optimizer;
4736 +}
4737 +
4738 +/*
4739 + * Local variables:
4740 + * tab-width: 4
4741 + * c-basic-offset: 4
4742 + * End:
4743 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4744 + * vim<600: expandtab sw=4 ts=4 sts=4
4745 + */
4746 Index: php-5.2.4/ext/apc/apc_compile.h
4747 ===================================================================
4748 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4749 +++ php-5.2.4/ext/apc/apc_compile.h 2007-09-02 12:24:46.000000000 +0200
4750 @@ -0,0 +1,134 @@
4751 +/*
4752 + +----------------------------------------------------------------------+
4753 + | APC |
4754 + +----------------------------------------------------------------------+
4755 + | Copyright (c) 2006 The PHP Group |
4756 + +----------------------------------------------------------------------+
4757 + | This source file is subject to version 3.01 of the PHP license, |
4758 + | that is bundled with this package in the file LICENSE, and is |
4759 + | available through the world-wide-web at the following url: |
4760 + | http://www.php.net/license/3_01.txt |
4761 + | If you did not receive a copy of the PHP license and are unable to |
4762 + | obtain it through the world-wide-web, please send a note to |
4763 + | license@php.net so we can mail you a copy immediately. |
4764 + +----------------------------------------------------------------------+
4765 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4766 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4767 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4768 + +----------------------------------------------------------------------+
4769 +
4770 + This software was contributed to PHP by Community Connect Inc. in 2002
4771 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4772 + Future revisions and derivatives of this source code must acknowledge
4773 + Community Connect Inc. as the original contributor of this module by
4774 + leaving this note intact in the source code.
4775 +
4776 + All other licensing and usage conditions are those of the PHP Group.
4777 +
4778 + */
4779 +
4780 +/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
4781 +
4782 +#ifndef APC_COMPILE_H
4783 +#define APC_COMPILE_H
4784 +
4785 +/*
4786 + * This module encapsulates most of the complexity involved in deep-copying
4787 + * the Zend compiler data structures. The routines are allocator-agnostic, so
4788 + * the same function can be used for copying to and from shared memory.
4789 + */
4790 +
4791 +#include "apc.h"
4792 +#include "apc_php.h"
4793 +
4794 +/* {{{ struct definition: apc_function_t */
4795 +typedef struct apc_function_t apc_function_t;
4796 +struct apc_function_t {
4797 + char* name; /* the function name */
4798 + int name_len; /* length of name */
4799 + zend_function* function; /* the zend function data structure */
4800 +};
4801 +/* }}} */
4802 +
4803 +/* {{{ struct definition: apc_class_t */
4804 +typedef struct apc_class_t apc_class_t;
4805 +struct apc_class_t {
4806 + char* name; /* the class name */
4807 + int name_len; /* length of name */
4808 + int is_derived; /* true if this is a derived class */
4809 + char* parent_name; /* the parent class name */
4810 + zend_class_entry* class_entry; /* the zend class data structure */
4811 +};
4812 +/* }}} */
4813 +
4814 +/* {{{ struct definition: apc_opflags_t */
4815 +typedef struct apc_opflags_t apc_opflags_t;
4816 +struct apc_opflags_t {
4817 + unsigned int has_jumps : 1; /* has jump offsets */
4818 + unsigned int deep_copy : 1; /* needs deep copy */
4819 +
4820 + /* autoglobal bits */
4821 + unsigned int _POST : 1;
4822 + unsigned int _GET : 1;
4823 + unsigned int _COOKIE : 1;
4824 + unsigned int _SERVER : 1;
4825 + unsigned int _ENV : 1;
4826 + unsigned int _FILES : 1;
4827 + unsigned int _REQUEST : 1;
4828 + unsigned int unknown_global : 1;
4829 +};
4830 +/* }}} */
4831 +
4832 +/*
4833 + * These are the top-level copy functions.
4834 + */
4835 +
4836 +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);
4837 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
4838 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4839 +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);
4840 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
4841 +
4842 +/*
4843 + * Deallocation functions corresponding to the copy functions above.
4844 + */
4845 +
4846 +extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
4847 +extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
4848 +extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
4849 +extern void apc_free_zval(zval* src, apc_free_t deallocate);
4850 +
4851 +/*
4852 + * These "copy-for-execution" functions must be called after retrieving an
4853 + * object from the shared cache. They do the minimal amount of work necessary
4854 + * to allow multiple processes to concurrently execute the same VM data
4855 + * structures.
4856 + */
4857 +
4858 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
4859 +extern zend_function* apc_copy_function_for_execution(zend_function* src);
4860 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
4861 +
4862 +/*
4863 + * The "free-after-execution" function performs a cursory clean up of the class data
4864 + * This is required to minimize memory leak warnings and to ensure correct destructor
4865 + * ordering of some variables.
4866 + */
4867 +extern void apc_free_class_entry_after_execution(zend_class_entry* src);
4868 +
4869 +/*
4870 + * Optimization callback definition and registration function.
4871 + */
4872 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
4873 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
4874 +
4875 +#endif
4876 +
4877 +/*
4878 + * Local variables:
4879 + * tab-width: 4
4880 + * c-basic-offset: 4
4881 + * End:
4882 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4883 + * vim<600: expandtab sw=4 ts=4 sts=4
4884 + */
4885 Index: php-5.2.4/ext/apc/apc_debug.c
4886 ===================================================================
4887 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4888 +++ php-5.2.4/ext/apc/apc_debug.c 2007-09-02 12:24:46.000000000 +0200
4889 @@ -0,0 +1,57 @@
4890 +/*
4891 + +----------------------------------------------------------------------+
4892 + | APC |
4893 + +----------------------------------------------------------------------+
4894 + | Copyright (c) 2006 The PHP Group |
4895 + +----------------------------------------------------------------------+
4896 + | This source file is subject to version 3.01 of the PHP license, |
4897 + | that is bundled with this package in the file LICENSE, and is |
4898 + | available through the world-wide-web at the following url: |
4899 + | http://www.php.net/license/3_01.txt |
4900 + | If you did not receive a copy of the PHP license and are unable to |
4901 + | obtain it through the world-wide-web, please send a note to |
4902 + | license@php.net so we can mail you a copy immediately. |
4903 + +----------------------------------------------------------------------+
4904 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4905 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4906 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4907 + +----------------------------------------------------------------------+
4908 +
4909 + This software was contributed to PHP by Community Connect Inc. in 2002
4910 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4911 + Future revisions and derivatives of this source code must acknowledge
4912 + Community Connect Inc. as the original contributor of this module by
4913 + leaving this note intact in the source code.
4914 +
4915 + All other licensing and usage conditions are those of the PHP Group.
4916 +*/
4917 +
4918 +/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
4919 +#include "apc.h"
4920 +#include <stdio.h>
4921 +#include "zend_compile.h"
4922 +
4923 +#ifdef __DEBUG_APC__
4924 +
4925 +#include <dlfcn.h>
4926 +
4927 +/* keep track of vld_dump_oparray() signature */
4928 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
4929 +
4930 +#endif
4931 +
4932 +void dump(zend_op_array *op_array TSRMLS_DC)
4933 +{
4934 +#ifdef __DEBUG_APC__
4935 + vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
4936 +
4937 + if(dump_op_array)
4938 + {
4939 + dump_op_array(op_array TSRMLS_CC);
4940 + }
4941 + else
4942 + {
4943 + apc_wprint("vld is not installed or something even worse.");
4944 + }
4945 +#endif
4946 +}
4947 Index: php-5.2.4/ext/apc/apc_debug.h
4948 ===================================================================
4949 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4950 +++ php-5.2.4/ext/apc/apc_debug.h 2007-09-02 12:24:46.000000000 +0200
4951 @@ -0,0 +1 @@
4952 +void dump(zend_op_array * TSRMLS_DC);
4953 Index: php-5.2.4/ext/apc/apc.dsp
4954 ===================================================================
4955 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4956 +++ php-5.2.4/ext/apc/apc.dsp 2007-09-02 12:24:46.000000000 +0200
4957 @@ -0,0 +1,207 @@
4958 +# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
4959 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
4960 +# ** DO NOT EDIT **
4961 +
4962 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
4963 +
4964 +CFG=apc - Win32 Debug_TS
4965 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
4966 +!MESSAGE use the Export Makefile command and run
4967 +!MESSAGE
4968 +!MESSAGE NMAKE /f "apc.mak".
4969 +!MESSAGE
4970 +!MESSAGE You can specify a configuration when running NMAKE
4971 +!MESSAGE by defining the macro CFG on the command line. For example:
4972 +!MESSAGE
4973 +!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
4974 +!MESSAGE
4975 +!MESSAGE Possible choices for configuration are:
4976 +!MESSAGE
4977 +!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
4978 +!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
4979 +!MESSAGE
4980 +
4981 +# Begin Project
4982 +# PROP AllowPerConfigDependencies 0
4983 +# PROP Scc_ProjName ""
4984 +# PROP Scc_LocalPath ""
4985 +CPP=cl.exe
4986 +MTL=midl.exe
4987 +RSC=rc.exe
4988 +
4989 +!IF "$(CFG)" == "apc - Win32 Debug_TS"
4990 +
4991 +# PROP BASE Use_MFC 0
4992 +# PROP BASE Use_Debug_Libraries 1
4993 +# PROP BASE Output_Dir "Debug_TS"
4994 +# PROP BASE Intermediate_Dir "Debug_TS"
4995 +# PROP BASE Target_Dir ""
4996 +# PROP Use_MFC 0
4997 +# PROP Use_Debug_Libraries 1
4998 +# PROP Output_Dir "Debug_TS"
4999 +# PROP Intermediate_Dir "Debug_TS"
5000 +# PROP Ignore_Export_Lib 0
5001 +# PROP Target_Dir ""
5002 +# 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
5003 +# 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
5004 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
5005 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
5006 +# ADD BASE RSC /l 0x409 /d "_DEBUG"
5007 +# ADD RSC /l 0x409 /d "_DEBUG"
5008 +BSC32=bscmake.exe
5009 +# ADD BASE BSC32 /nologo
5010 +# ADD BSC32 /nologo
5011 +LINK32=link.exe
5012 +# 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
5013 +# 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"
5014 +
5015 +!ELSEIF "$(CFG)" == "apc - Win32 Release_TS"
5016 +
5017 +# PROP BASE Use_MFC 0
5018 +# PROP BASE Use_Debug_Libraries 0
5019 +# PROP BASE Output_Dir "Release_TS"
5020 +# PROP BASE Intermediate_Dir "Release_TS"
5021 +# PROP BASE Target_Dir ""
5022 +# PROP Use_MFC 0
5023 +# PROP Use_Debug_Libraries 0
5024 +# PROP Output_Dir "Release_TS"
5025 +# PROP Intermediate_Dir "Release_TS"
5026 +# PROP Ignore_Export_Lib 0
5027 +# PROP Target_Dir ""
5028 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5029 +# 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
5030 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5031 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5032 +# ADD BASE RSC /l 0x409 /d "NDEBUG"
5033 +# ADD RSC /l 0x409 /d "NDEBUG"
5034 +BSC32=bscmake.exe
5035 +# ADD BASE BSC32 /nologo
5036 +# ADD BSC32 /nologo
5037 +LINK32=link.exe
5038 +# 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
5039 +# 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"
5040 +
5041 +!ENDIF
5042 +
5043 +# Begin Target
5044 +
5045 +# Name "apc - Win32 Debug_TS"
5046 +# Name "apc - Win32 Release_TS"
5047 +# Begin Group "Source Files"
5048 +
5049 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
5050 +# Begin Source File
5051 +
5052 +SOURCE=.\apc.c
5053 +# End Source File
5054 +# Begin Source File
5055 +
5056 +SOURCE=.\apc_cache.c
5057 +# End Source File
5058 +# Begin Source File
5059 +
5060 +SOURCE=.\apc_compile.c
5061 +# End Source File
5062 +# Begin Source File
5063 +
5064 +SOURCE=.\apc_debug.c
5065 +# End Source File
5066 +# Begin Source File
5067 +
5068 +SOURCE=.\apc_fcntl_win32.c
5069 +# End Source File
5070 +# Begin Source File
5071 +
5072 +SOURCE=.\apc_main.c
5073 +# End Source File
5074 +# Begin Source File
5075 +
5076 +SOURCE=.\apc_rfc1867.c
5077 +# End Source File
5078 +# Begin Source File
5079 +
5080 +SOURCE=.\apc_shm.c
5081 +# End Source File
5082 +# Begin Source File
5083 +
5084 +SOURCE=.\apc_sma.c
5085 +# End Source File
5086 +# Begin Source File
5087 +
5088 +SOURCE=.\apc_stack.c
5089 +# End Source File
5090 +# Begin Source File
5091 +
5092 +SOURCE=.\apc_zend.c
5093 +# End Source File
5094 +# Begin Source File
5095 +
5096 +SOURCE=.\php_apc.c
5097 +# End Source File
5098 +# End Group
5099 +# Begin Group "Header Files"
5100 +
5101 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
5102 +# Begin Source File
5103 +
5104 +SOURCE=.\apc.h
5105 +# End Source File
5106 +# Begin Source File
5107 +
5108 +SOURCE=.\apc_cache.h
5109 +# End Source File
5110 +# Begin Source File
5111 +
5112 +SOURCE=.\apc_compile.h
5113 +# End Source File
5114 +# Begin Source File
5115 +
5116 +SOURCE=.\apc_debug.h
5117 +# End Source File
5118 +# Begin Source File
5119 +
5120 +SOURCE=.\apc_fcntl.h
5121 +# End Source File
5122 +# Begin Source File
5123 +
5124 +SOURCE=.\apc_globals.h
5125 +# End Source File
5126 +# Begin Source File
5127 +
5128 +SOURCE=.\apc_lock.h
5129 +# End Source File
5130 +# Begin Source File
5131 +
5132 +SOURCE=.\apc_main.h
5133 +# End Source File
5134 +# Begin Source File
5135 +
5136 +SOURCE=.\apc_php.h
5137 +# End Source File
5138 +# Begin Source File
5139 +
5140 +SOURCE=.\apc_shm.h
5141 +# End Source File
5142 +# Begin Source File
5143 +
5144 +SOURCE=.\apc_sma.h
5145 +# End Source File
5146 +# Begin Source File
5147 +
5148 +SOURCE=.\apc_stack.h
5149 +# End Source File
5150 +# Begin Source File
5151 +
5152 +SOURCE=.\apc_zend.h
5153 +# End Source File
5154 +# Begin Source File
5155 +
5156 +SOURCE=.\php_apc.h
5157 +# End Source File
5158 +# End Group
5159 +# Begin Group "Resource Files"
5160 +
5161 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
5162 +# End Group
5163 +# End Target
5164 +# End Project
5165 Index: php-5.2.4/ext/apc/apc_fcntl.c
5166 ===================================================================
5167 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5168 +++ php-5.2.4/ext/apc/apc_fcntl.c 2007-09-02 12:24:46.000000000 +0200
5169 @@ -0,0 +1,118 @@
5170 +/*
5171 + +----------------------------------------------------------------------+
5172 + | APC |
5173 + +----------------------------------------------------------------------+
5174 + | Copyright (c) 2006 The PHP Group |
5175 + +----------------------------------------------------------------------+
5176 + | This source file is subject to version 3.01 of the PHP license, |
5177 + | that is bundled with this package in the file LICENSE, and is |
5178 + | available through the world-wide-web at the following url: |
5179 + | http://www.php.net/license/3_01.txt |
5180 + | If you did not receive a copy of the PHP license and are unable to |
5181 + | obtain it through the world-wide-web, please send a note to |
5182 + | license@php.net so we can mail you a copy immediately. |
5183 + +----------------------------------------------------------------------+
5184 + | Authors: George Schlossnagle <george@omniti.com> |
5185 + | Rasmus Lerdorf <rasmus@php.net> |
5186 + +----------------------------------------------------------------------+
5187 +
5188 + This software was contributed to PHP by Community Connect Inc. in 2002
5189 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5190 + Future revisions and derivatives of this source code must acknowledge
5191 + Community Connect Inc. as the original contributor of this module by
5192 + leaving this note intact in the source code.
5193 +
5194 + All other licensing and usage conditions are those of the PHP Group.
5195 +
5196 + */
5197 +
5198 +/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
5199 +
5200 +#include "apc_fcntl.h"
5201 +#include "apc.h"
5202 +#include <unistd.h>
5203 +#include <fcntl.h>
5204 +
5205 +int apc_fcntl_create(const char* pathname)
5206 +{
5207 + int fd;
5208 + if(pathname == NULL) {
5209 + char lock_path[] = "/tmp/.apc.XXXXXX";
5210 + mktemp(lock_path);
5211 + fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5212 + if(fd > 0 ) {
5213 + unlink(lock_path);
5214 + return fd;
5215 + } else {
5216 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
5217 + return -1;
5218 + }
5219 + }
5220 + fd = open(pathname, O_RDWR|O_CREAT, 0666);
5221 + if(fd > 0 ) {
5222 + unlink(pathname);
5223 + return fd;
5224 + }
5225 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
5226 + return -1;
5227 +}
5228 +
5229 +void apc_fcntl_destroy(int fd)
5230 +{
5231 + close(fd);
5232 +}
5233 +
5234 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5235 +{
5236 + int ret;
5237 + struct flock lock;
5238 +
5239 + lock.l_type = type;
5240 + lock.l_start = offset;
5241 + lock.l_whence = whence;
5242 + lock.l_len = len;
5243 + lock.l_pid = 0;
5244 +
5245 + do { ret = fcntl(fd, cmd, &lock) ; }
5246 + while(ret < 0 && errno == EINTR);
5247 + return(ret);
5248 +}
5249 +
5250 +void apc_fcntl_lock(int fd)
5251 +{
5252 + if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5253 + apc_eprint("apc_fcntl_lock failed:");
5254 + }
5255 +}
5256 +
5257 +void apc_fcntl_rdlock(int fd)
5258 +{
5259 + if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
5260 + apc_eprint("apc_fcntl_rdlock failed:");
5261 + }
5262 +}
5263 +
5264 +zend_bool apc_fcntl_nonblocking_lock(int fd)
5265 +{
5266 + if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5267 + if(errno==EACCES||errno==EAGAIN) return 0;
5268 + else apc_eprint("apc_fcntl_lock failed:");
5269 + }
5270 + return 1;
5271 +}
5272 +
5273 +void apc_fcntl_unlock(int fd)
5274 +{
5275 + if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
5276 + apc_eprint("apc_fcntl_unlock failed:");
5277 + }
5278 +}
5279 +
5280 +/*
5281 + * Local variables:
5282 + * tab-width: 4
5283 + * c-basic-offset: 4
5284 + * End:
5285 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5286 + * vim<600: expandtab sw=4 ts=4 sts=4
5287 + */
5288 Index: php-5.2.4/ext/apc/apc_fcntl.h
5289 ===================================================================
5290 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5291 +++ php-5.2.4/ext/apc/apc_fcntl.h 2007-09-02 12:24:46.000000000 +0200
5292 @@ -0,0 +1,50 @@
5293 +/*
5294 + +----------------------------------------------------------------------+
5295 + | APC |
5296 + +----------------------------------------------------------------------+
5297 + | Copyright (c) 2006 The PHP Group |
5298 + +----------------------------------------------------------------------+
5299 + | This source file is subject to version 3.01 of the PHP license, |
5300 + | that is bundled with this package in the file LICENSE, and is |
5301 + | available through the world-wide-web at the following url: |
5302 + | http://www.php.net/license/3_01.txt. |
5303 + | If you did not receive a copy of the PHP license and are unable to |
5304 + | obtain it through the world-wide-web, please send a note to |
5305 + | license@php.net so we can mail you a copy immediately. |
5306 + +----------------------------------------------------------------------+
5307 + | Authors: George Schlossnagle <george@omniti.com> |
5308 + | Rasmus Lerdorf <rasmus@php.net> |
5309 + +----------------------------------------------------------------------+
5310 +
5311 + This software was contributed to PHP by Community Connect Inc. in 2002
5312 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5313 + Future revisions and derivatives of this source code must acknowledge
5314 + Community Connect Inc. as the original contributor of this module by
5315 + leaving this note intact in the source code.
5316 +
5317 + All other licensing and usage conditions are those of the PHP Group.
5318 +
5319 + */
5320 +
5321 +/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
5322 +
5323 +#ifndef APC_FCNTL_H
5324 +#define APC_FCNTL_H
5325 +
5326 +
5327 +extern int apc_fcntl_create(const char* pathname);
5328 +extern void apc_fcntl_destroy(int fd);
5329 +extern void apc_fcntl_lock(int fd);
5330 +extern void apc_fcntl_rdlock(int fd);
5331 +extern void apc_fcntl_unlock(int fd);
5332 +extern unsigned char apc_fcntl_nonblocking_lock(int fd);
5333 +#endif
5334 +
5335 +/*
5336 + * Local variables:
5337 + * tab-width: 4
5338 + * c-basic-offset: 4
5339 + * End:
5340 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5341 + * vim<600: expandtab sw=4 ts=4 sts=4
5342 + */
5343 Index: php-5.2.4/ext/apc/apc_fcntl_win32.c
5344 ===================================================================
5345 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5346 +++ php-5.2.4/ext/apc/apc_fcntl_win32.c 2007-09-02 12:24:46.000000000 +0200
5347 @@ -0,0 +1,117 @@
5348 +/*
5349 + +----------------------------------------------------------------------+
5350 + | APC |
5351 + +----------------------------------------------------------------------+
5352 + | Copyright (c) 2006 The PHP Group |
5353 + +----------------------------------------------------------------------+
5354 + | This source file is subject to version 3.01 of the PHP license, |
5355 + | that is bundled with this package in the file LICENSE, and is |
5356 + | available through the world-wide-web at the following url: |
5357 + | http://www.php.net/license/3_01.txt |
5358 + | If you did not receive a copy of the PHP license and are unable to |
5359 + | obtain it through the world-wide-web, please send a note to |
5360 + | license@php.net so we can mail you a copy immediately. |
5361 + +----------------------------------------------------------------------+
5362 + | Authors: George Schlossnagle <george@omniti.com> |
5363 + | Edin Kadribasic <edink@php.net> |
5364 + +----------------------------------------------------------------------+
5365 +
5366 + This software was contributed to PHP by Community Connect Inc. in 2002
5367 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5368 + Future revisions and derivatives of this source code must acknowledge
5369 + Community Connect Inc. as the original contributor of this module by
5370 + leaving this note intact in the source code.
5371 +
5372 + All other licensing and usage conditions are those of the PHP Group.
5373 +
5374 + */
5375 +
5376 +/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
5377 +
5378 +#include "apc_fcntl.h"
5379 +#include "apc.h"
5380 +#include <php.h>
5381 +#include <win32/flock.h>
5382 +#include <io.h>
5383 +#include <fcntl.h>
5384 +#include <sys/types.h>
5385 +#include <sys/stat.h>
5386 +
5387 +int apc_fcntl_create(const char* pathname)
5388 +{
5389 + char *lock_file = emalloc(MAXPATHLEN);
5390 + HANDLE fd;
5391 + DWORD tmplen;
5392 + static int i=0;
5393 +
5394 + tmplen = GetTempPath(MAXPATHLEN, lock_file);
5395 + if (!tmplen) {
5396 + efree(lock_file);
5397 + return -1;
5398 + }
5399 +
5400 + snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
5401 +
5402 + fd = CreateFile(lock_file,
5403 + GENERIC_READ | GENERIC_WRITE,
5404 + FILE_SHARE_READ | FILE_SHARE_WRITE,
5405 + NULL,
5406 + OPEN_ALWAYS,
5407 + FILE_ATTRIBUTE_NORMAL,
5408 + NULL);
5409 +
5410 +
5411 + if (fd == INVALID_HANDLE_VALUE) {
5412 + apc_eprint("apc_fcntl_create: could not open %s", lock_file);
5413 + efree(lock_file);
5414 + return -1;
5415 + }
5416 +
5417 + efree(lock_file);
5418 + return (int)fd;
5419 +}
5420 +
5421 +void apc_fcntl_destroy(int fd)
5422 +{
5423 + CloseHandle((HANDLE)fd);
5424 +}
5425 +
5426 +void apc_fcntl_lock(int fd)
5427 +{
5428 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5429 +
5430 + if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
5431 + apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
5432 + }
5433 +}
5434 +
5435 +void apc_fcntl_rdlock(int fd)
5436 +{
5437 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5438 +
5439 + if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
5440 + apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
5441 + }
5442 +}
5443 +
5444 +void apc_fcntl_unlock(int fd)
5445 +{
5446 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5447 +
5448 + if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
5449 + DWORD error_code = GetLastError();
5450 + /* Ignore already unlocked error */
5451 + if (error_code != ERROR_NOT_LOCKED) {
5452 + apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
5453 + }
5454 + }
5455 +}
5456 +
5457 +/*
5458 + * Local variables:
5459 + * tab-width: 4
5460 + * c-basic-offset: 4
5461 + * End:
5462 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5463 + * vim<600: expandtab sw=4 ts=4 sts=4
5464 + */
5465 Index: php-5.2.4/ext/apc/apc_futex.c
5466 ===================================================================
5467 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5468 +++ php-5.2.4/ext/apc/apc_futex.c 2007-09-02 12:24:46.000000000 +0200
5469 @@ -0,0 +1,116 @@
5470 +/*
5471 + +----------------------------------------------------------------------+
5472 + | APC |
5473 + +----------------------------------------------------------------------+
5474 + | Copyright (c) 2006 The PHP Group |
5475 + +----------------------------------------------------------------------+
5476 + | This source file is subject to version 3.01 of the PHP license, |
5477 + | that is bundled with this package in the file LICENSE, and is |
5478 + | available through the world-wide-web at the following url: |
5479 + | http://www.php.net/license/3_01.txt |
5480 + | If you did not receive a copy of the PHP license and are unable to |
5481 + | obtain it through the world-wide-web, please send a note to |
5482 + | license@php.net so we can mail you a copy immediately. |
5483 + +----------------------------------------------------------------------+
5484 + | Authors: Brian Shire <shire@php.net> |
5485 + +----------------------------------------------------------------------+
5486 +
5487 + */
5488 +
5489 +/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5490 +
5491 +/***************************************************************************
5492 +* Futex (Fast Userspace Mutex) support for APC
5493 +*
5494 +* Futex support provides user space locking with system calls only
5495 +* for the contended cases. Some required reading for this functionality is:
5496 +*
5497 +* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux'
5498 +* by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
5499 +* http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
5500 +*
5501 +* 'Futexes are Tricky' by Ulrich Drepper
5502 +* http://people.redhat.com/drepper/futex.pdf
5503 +*
5504 +*
5505 +* This implementation is optimized and designed for the i386 and x86_64
5506 +* architectures. Other architectures may require additional design
5507 +* to efficiently and safely implement this functionality.
5508 +*
5509 +* Lock values are:
5510 +* 0 = Unlocked
5511 +* 1 = Locked without any waiting processes
5512 +* 2 = Locked with an unknown number of waiting processes
5513 +*
5514 +***************************************************************************/
5515 +
5516 +#include "apc.h"
5517 +#include "apc_futex.h"
5518 +
5519 +#ifdef APC_FUTEX_LOCKS
5520 +
5521 +
5522 +inline int apc_futex_create()
5523 +{
5524 + return 0;
5525 +}
5526 +
5527 +inline void apc_futex_destroy(volatile int* lock)
5528 +{
5529 + return;
5530 +}
5531 +
5532 +void apc_futex_lock(volatile int* lock)
5533 +{
5534 + int c;
5535 +
5536 + /* Attempt to obtain a lock if not currently locked. If the previous
5537 + * value was not 0 then we did not obtain the lock, and must wait.
5538 + * If the previous value was 1 (has no waiting processes) then we
5539 + * set the lock to 2 before blocking on the futex wait operation.
5540 + * This implementation suffers from the possible difficulty of
5541 + * efficently implementing the atomic xchg operation on some
5542 + * architectures, and could also cause unecessary wake operations by
5543 + * setting the lock to 2 when there are no additional waiters.
5544 + */
5545 + if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
5546 + if(c != 2) {
5547 + c = apc_xchg(lock, 2);
5548 + }
5549 + while(c != 0) {
5550 + apc_futex_wait(lock, 2);
5551 + c = apc_xchg(lock, 2);
5552 + }
5553 + }
5554 +
5555 +}
5556 +
5557 +/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
5558 +inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
5559 +{
5560 + return apc_cmpxchg(lock, 0, 1) == 0;
5561 +}
5562 +
5563 +
5564 +inline void apc_futex_unlock(volatile int* lock)
5565 +{
5566 + /* set the lock to 0, if it's previous values was not 1 (no waiters)
5567 + * then perform a wake operation on one process letting it know the lock
5568 + * is available. This is an optimization to save wake calls if there
5569 + * are no waiting processes for the lock
5570 + */
5571 + if(apc_xchg(lock,0) != 1) {
5572 + apc_futex_wake(lock, 1);
5573 + }
5574 +}
5575 +
5576 +#endif
5577 +
5578 +/*
5579 + * Local variables:
5580 + * tab-width: 4
5581 + * c-basic-offset: 4
5582 + * End:
5583 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5584 + * vim<600: expandtab sw=4 ts=4 sts=4
5585 + */
5586 Index: php-5.2.4/ext/apc/apc_futex.h
5587 ===================================================================
5588 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5589 +++ php-5.2.4/ext/apc/apc_futex.h 2007-09-02 12:24:46.000000000 +0200
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 Index: php-5.2.4/ext/apc/apc_globals.h
5647 ===================================================================
5648 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5649 +++ php-5.2.4/ext/apc/apc_globals.h 2007-09-02 12:24:46.000000000 +0200
5650 @@ -0,0 +1,110 @@
5651 +/*
5652 + +----------------------------------------------------------------------+
5653 + | APC |
5654 + +----------------------------------------------------------------------+
5655 + | Copyright (c) 2006 The PHP Group |
5656 + +----------------------------------------------------------------------+
5657 + | This source file is subject to version 3.01 of the PHP license, |
5658 + | that is bundled with this package in the file LICENSE, and is |
5659 + | available through the world-wide-web at the following url: |
5660 + | http://www.php.net/license/3_01.txt. |
5661 + | If you did not receive a copy of the PHP license and are unable to |
5662 + | obtain it through the world-wide-web, please send a note to |
5663 + | license@php.net so we can mail you a copy immediately. |
5664 + +----------------------------------------------------------------------+
5665 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5666 + | George Schlossnagle <george@omniti.com> |
5667 + | Rasmus Lerdorf <rasmus@php.net> |
5668 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5669 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5670 + +----------------------------------------------------------------------+
5671 +
5672 + This software was contributed to PHP by Community Connect Inc. in 2002
5673 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5674 + Future revisions and derivatives of this source code must acknowledge
5675 + Community Connect Inc. as the original contributor of this module by
5676 + leaving this note intact in the source code.
5677 +
5678 + All other licensing and usage conditions are those of the PHP Group.
5679 +
5680 + */
5681 +
5682 +/* $Id: apc_globals.h,v 3.59 2007/03/21 21:07:28 rasmus Exp $ */
5683 +
5684 +#ifndef APC_GLOBALS_H
5685 +#define APC_GLOBALS_H
5686 +
5687 +#define APC_VERSION "3.0.14"
5688 +
5689 +#include "apc_cache.h"
5690 +#include "apc_stack.h"
5691 +#include "apc_php.h"
5692 +
5693 +ZEND_BEGIN_MODULE_GLOBALS(apc)
5694 + /* configuration parameters */
5695 + zend_bool enabled; /* if true, apc is enabled (defaults to true) */
5696 + long shm_segments; /* number of shared memory segments to use */
5697 + long shm_size; /* size of each shared memory segment (in MB) */
5698 + long num_files_hint; /* parameter to apc_cache_create */
5699 + long user_entries_hint;
5700 + long gc_ttl; /* parameter to apc_cache_create */
5701 + long ttl; /* parameter to apc_cache_create */
5702 + long user_ttl;
5703 +#if APC_MMAP
5704 + char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */
5705 +#endif
5706 + char** filters; /* array of regex filters that prevent caching */
5707 +
5708 + /* module variables */
5709 + zend_bool initialized; /* true if module was initialized */
5710 + apc_stack_t* cache_stack; /* the stack of cached executable code */
5711 + zend_bool cache_by_default; /* true if files should be cached unless filtered out */
5712 + /* false if files should only be cached if filtered in */
5713 + long slam_defense; /* Probability of a process not caching an uncached file */
5714 + size_t* mem_size_ptr; /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
5715 + long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
5716 + zend_bool enable_cli; /* Flag to override turning APC off for CLI */
5717 + long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */
5718 + long slam_rand; /* A place to store the slam rand value for the request */
5719 + zend_bool fpstat; /* true if fullpath includes should be stat'ed */
5720 + zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */
5721 + zend_bool write_lock; /* true for a global write lock */
5722 + zend_bool report_autofilter; /* true for auto-filter warnings */
5723 + zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
5724 + apc_optimize_function_t apc_optimize_function; /* optimizer function callback */
5725 +#ifdef MULTIPART_EVENT_FORMDATA
5726 + zend_bool rfc1867; /* Flag to enable rfc1867 handler */
5727 +#endif
5728 + HashTable *copied_zvals; /* my_copy recursion detection list */
5729 +#ifdef ZEND_ENGINE_2
5730 + int reserved_offset; /* offset for apc info in op_array->reserved[] */
5731 +#endif
5732 + zend_bool localcache; /* enable local cache */
5733 + long localcache_size; /* size of fast cache */
5734 + apc_local_cache_t* lcache; /* unlocked local cache */
5735 +ZEND_END_MODULE_GLOBALS(apc)
5736 +
5737 +/* (the following declaration is defined in php_apc.c) */
5738 +ZEND_EXTERN_MODULE_GLOBALS(apc)
5739 +
5740 +#ifdef ZTS
5741 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
5742 +#else
5743 +# define APCG(v) (apc_globals.v)
5744 +#endif
5745 +
5746 +/* True globals */
5747 +extern apc_cache_t* apc_cache; /* the global compiler cache */
5748 +extern apc_cache_t* apc_user_cache; /* the global user content cache */
5749 +extern void* apc_compiled_filters; /* compiled filters */
5750 +
5751 +#endif
5752 +
5753 +/*
5754 + * Local variables:
5755 + * tab-width: 4
5756 + * c-basic-offset: 4
5757 + * End:
5758 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5759 + * vim<600: expandtab sw=4 ts=4 sts=4
5760 + */
5761 Index: php-5.2.4/ext/apc/apc.h
5762 ===================================================================
5763 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5764 +++ php-5.2.4/ext/apc/apc.h 2007-09-02 12:24:46.000000000 +0200
5765 @@ -0,0 +1,126 @@
5766 +/*
5767 + +----------------------------------------------------------------------+
5768 + | APC |
5769 + +----------------------------------------------------------------------+
5770 + | Copyright (c) 2006 The PHP Group |
5771 + +----------------------------------------------------------------------+
5772 + | This source file is subject to version 3.01 of the PHP license, |
5773 + | that is bundled with this package in the file LICENSE, and is |
5774 + | available through the world-wide-web at the following url: |
5775 + | http://www.php.net/license/3_01.txt |
5776 + | If you did not receive a copy of the PHP license and are unable to |
5777 + | obtain it through the world-wide-web, please send a note to |
5778 + | license@php.net so we can mail you a copy immediately. |
5779 + +----------------------------------------------------------------------+
5780 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5781 + | George Schlossnagle <george@omniti.com> |
5782 + | Rasmus Lerdorf <rasmus@php.net> |
5783 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5784 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5785 + +----------------------------------------------------------------------+
5786 +
5787 + This software was contributed to PHP by Community Connect Inc. in 2002
5788 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5789 + Future revisions and derivatives of this source code must acknowledge
5790 + Community Connect Inc. as the original contributor of this module by
5791 + leaving this note intact in the source code.
5792 +
5793 + All other licensing and usage conditions are those of the PHP Group.
5794 +
5795 + */
5796 +
5797 +/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
5798 +
5799 +#ifndef APC_H
5800 +#define APC_H
5801 +
5802 +/*
5803 + * This module defines utilities and helper functions used elsewhere in APC.
5804 + */
5805 +
5806 +/* Commonly needed C library headers. */
5807 +#include <assert.h>
5808 +#include <errno.h>
5809 +#include <stdarg.h>
5810 +#include <stdio.h>
5811 +#include <stdlib.h>
5812 +#include <string.h>
5813 +#include <time.h>
5814 +
5815 +/* UNIX headers (needed for struct stat) */
5816 +#include <sys/types.h>
5817 +#include <sys/stat.h>
5818 +#ifndef PHP_WIN32
5819 +#include <unistd.h>
5820 +#endif
5821 +
5822 +#ifdef HAVE_CONFIG_H
5823 +#include <config.h>
5824 +#endif
5825 +
5826 +#include "php.h"
5827 +
5828 +/* log levels constants (see apc_log) */
5829 +enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
5830 +
5831 +/* typedefs for extensible memory allocators */
5832 +typedef void* (*apc_malloc_t)(size_t);
5833 +typedef void (*apc_free_t) (void*);
5834 +
5835 +/* wrappers for memory allocation routines */
5836 +extern void* apc_emalloc(size_t n);
5837 +extern void* apc_erealloc(void* p, size_t n);
5838 +extern void apc_efree(void* p);
5839 +extern char* apc_estrdup(const char* s);
5840 +extern void* apc_xstrdup(const char* s, apc_malloc_t f);
5841 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
5842 +
5843 +/* console display functions */
5844 +extern void apc_log(int level, const char* fmt, ...);
5845 +extern void apc_eprint(const char* fmt, ...);
5846 +extern void apc_wprint(const char* fmt, ...);
5847 +extern void apc_dprint(const char* fmt, ...);
5848 +extern void apc_nprint(const char* fmt, ...);
5849 +
5850 +/* string and text manipulation */
5851 +extern char* apc_append(const char* s, const char* t);
5852 +extern char* apc_substr(const char* s, int start, int length);
5853 +extern char** apc_tokenize(const char* s, char delim);
5854 +
5855 +/* filesystem functions */
5856 +
5857 +typedef struct apc_fileinfo_t
5858 +{
5859 + char fullpath[MAXPATHLEN+1];
5860 + struct stat st_buf;
5861 +} apc_fileinfo_t;
5862 +
5863 +#ifndef PHP_WIN32
5864 +#define apc_stat(f, b) stat(f, b)
5865 +#else
5866 +#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
5867 +extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
5868 +#endif
5869 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
5870 +
5871 +/* regular expression wrapper functions */
5872 +extern void* apc_regex_compile_array(char* patterns[]);
5873 +extern void apc_regex_destroy_array(void* p);
5874 +extern int apc_regex_match_array(void* p, const char* input);
5875 +
5876 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
5877 +extern unsigned int apc_crc32(const char* buf, int len);
5878 +
5879 +#define APC_NEGATIVE_MATCH 1
5880 +#define APC_POSITIVE_MATCH 2
5881 +
5882 +#endif
5883 +
5884 +/*
5885 + * Local variables:
5886 + * tab-width: 4
5887 + * c-basic-offset: 4
5888 + * End:
5889 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5890 + * vim<600: expandtab sw=4 ts=4 sts=4
5891 + */
5892 Index: php-5.2.4/ext/apc/apc_lock.h
5893 ===================================================================
5894 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5895 +++ php-5.2.4/ext/apc/apc_lock.h 2007-09-02 12:24:46.000000000 +0200
5896 @@ -0,0 +1,105 @@
5897 +/*
5898 + +----------------------------------------------------------------------+
5899 + | APC |
5900 + +----------------------------------------------------------------------+
5901 + | Copyright (c) 2006 The PHP Group |
5902 + +----------------------------------------------------------------------+
5903 + | This source file is subject to version 3.01 of the PHP license, |
5904 + | that is bundled with this package in the file LICENSE, and is |
5905 + | available through the world-wide-web at the following url: |
5906 + | http://www.php.net/license/3_01.txt |
5907 + | If you did not receive a copy of the PHP license and are unable to |
5908 + | obtain it through the world-wide-web, please send a note to |
5909 + | license@php.net so we can mail you a copy immediately. |
5910 + +----------------------------------------------------------------------+
5911 + | Authors: George Schlossnagle <george@omniti.com> |
5912 + | Rasmus Lerdorf <rasmus@php.net> |
5913 + +----------------------------------------------------------------------+
5914 +
5915 + This software was contributed to PHP by Community Connect Inc. in 2002
5916 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5917 + Future revisions and derivatives of this source code must acknowledge
5918 + Community Connect Inc. as the original contributor of this module by
5919 + leaving this note intact in the source code.
5920 +
5921 + All other licensing and usage conditions are those of the PHP Group.
5922 +
5923 + */
5924 +
5925 +/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
5926 +
5927 +#ifndef APC_LOCK
5928 +#define APC_LOCK
5929 +
5930 +#include "apc_sem.h"
5931 +#include "apc_fcntl.h"
5932 +#include "apc_pthreadmutex.h"
5933 +#include "apc_futex.h"
5934 +#include "apc_spin.h"
5935 +#ifdef HAVE_CONFIG_H
5936 +#include <config.h>
5937 +#endif
5938 +
5939 +#ifdef TSRM_LOCKS
5940 +#define RDLOCK_AVAILABLE 0
5941 +#define NONBLOCKING_LOCK_AVAILABLE 0
5942 +/* quick & dirty: use TSRM mutex locks for now */
5943 +#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
5944 +#define apc_lck_destroy(a) tsrm_mutex_free((MUTEX_T)a)
5945 +#define apc_lck_lock(a) tsrm_mutex_lock((MUTEX_T)a)
5946 +#define apc_lck_rdlock(a) tsrm_mutex_lock((MUTEX_T)a)
5947 +#define apc_lck_unlock(a) tsrm_mutex_unlock((MUTEX_T)a)
5948 +#elif defined(APC_SEM_LOCKS)
5949 +#define RDLOCK_AVAILABLE 0
5950 +#define NONBLOCKING_LOCK_AVAILABLE 0
5951 +#define apc_lck_t int
5952 +#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
5953 +#define apc_lck_destroy(a) apc_sem_destroy(a)
5954 +#define apc_lck_lock(a) apc_sem_lock(a)
5955 +#define apc_lck_rdlock(a) apc_sem_lock(a)
5956 +#define apc_lck_unlock(a) apc_sem_unlock(a)
5957 +#elif defined(APC_PTHREADMUTEX_LOCKS)
5958 +#define RDLOCK_AVAILABLE 0
5959 +#define NONBLOCKING_LOCK_AVAILABLE 1
5960 +#define apc_lck_t pthread_mutex_t
5961 +#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
5962 +#define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a)
5963 +#define apc_lck_lock(a) apc_pthreadmutex_lock(&a)
5964 +#define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a)
5965 +#define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a)
5966 +#define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a)
5967 +#elif defined(APC_FUTEX_LOCKS)
5968 +#define NONBLOCKING_LOCK_AVAILABLE 1
5969 +#define apc_lck_t int
5970 +#define apc_lck_create(a,b,c,d) d=apc_futex_create()
5971 +#define apc_lck_destroy(a) apc_futex_destroy(&a)
5972 +#define apc_lck_lock(a) apc_futex_lock(&a)
5973 +#define apc_lck_nb_lock(a) apc_futex_nonblocking_lock(&a)
5974 +#define apc_lck_rdlock(a) apc_futex_lock(&a)
5975 +#define apc_lck_unlock(a) apc_futex_unlock(&a)
5976 +#elif defined(APC_SPIN_LOCKS)
5977 +#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
5978 +#define apc_lck_t slock_t
5979 +#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
5980 +#define apc_lck_destroy(a) apc_slock_destroy(&a)
5981 +#define apc_lck_lock(a) apc_slock_lock(&a)
5982 +#define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a)
5983 +#define apc_lck_rdlock(a) apc_slock_lock(&a)
5984 +#define apc_lck_unlock(a) apc_slock_unlock(&a)
5985 +#else
5986 +#define RDLOCK_AVAILABLE 1
5987 +#ifdef PHP_WIN32
5988 +#define NONBLOCKING_LOCK_AVAILABLE 0
5989 +#else
5990 +#define NONBLOCKING_LOCK_AVAILABLE 1
5991 +#endif
5992 +#define apc_lck_t int
5993 +#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
5994 +#define apc_lck_destroy(a) apc_fcntl_destroy(a)
5995 +#define apc_lck_lock(a) apc_fcntl_lock(a)
5996 +#define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a)
5997 +#define apc_lck_rdlock(a) apc_fcntl_rdlock(a)
5998 +#define apc_lck_unlock(a) apc_fcntl_unlock(a)
5999 +#endif
6000 +
6001 +#endif
6002 Index: php-5.2.4/ext/apc/apc_main.c
6003 ===================================================================
6004 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6005 +++ php-5.2.4/ext/apc/apc_main.c 2007-09-02 12:24:46.000000000 +0200
6006 @@ -0,0 +1,681 @@
6007 +/*
6008 + +----------------------------------------------------------------------+
6009 + | APC |
6010 + +----------------------------------------------------------------------+
6011 + | Copyright (c) 2006 The PHP Group |
6012 + +----------------------------------------------------------------------+
6013 + | This source file is subject to version 3.01 of the PHP license, |
6014 + | that is bundled with this package in the file LICENSE, and is |
6015 + | available through the world-wide-web at the following url: |
6016 + | http://www.php.net/license/3_01.txt |
6017 + | If you did not receive a copy of the PHP license and are unable to |
6018 + | obtain it through the world-wide-web, please send a note to |
6019 + | license@php.net so we can mail you a copy immediately. |
6020 + +----------------------------------------------------------------------+
6021 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6022 + | Rasmus Lerdorf <rasmus@php.net> |
6023 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6024 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6025 + +----------------------------------------------------------------------+
6026 +
6027 + This software was contributed to PHP by Community Connect Inc. in 2002
6028 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6029 + Future revisions and derivatives of this source code must acknowledge
6030 + Community Connect Inc. as the original contributor of this module by
6031 + leaving this note intact in the source code.
6032 +
6033 + All other licensing and usage conditions are those of the PHP Group.
6034 +
6035 + */
6036 +
6037 +/* $Id: apc_main.c,v 3.97 2007/03/22 16:03:59 gopalv Exp $ */
6038 +
6039 +#include "apc_php.h"
6040 +#include "apc_main.h"
6041 +#include "apc.h"
6042 +#include "apc_lock.h"
6043 +#include "apc_cache.h"
6044 +#include "apc_compile.h"
6045 +#include "apc_globals.h"
6046 +#include "apc_sma.h"
6047 +#include "apc_stack.h"
6048 +#include "apc_zend.h"
6049 +#include "SAPI.h"
6050 +#if PHP_API_VERSION <= 20020918
6051 +#if HAVE_APACHE
6052 +#ifdef APC_PHP4_STAT
6053 +#undef XtOffsetOf
6054 +#include "httpd.h"
6055 +#endif
6056 +#endif
6057 +#endif
6058 +
6059 +/* {{{ module variables */
6060 +
6061 +/* pointer to the original Zend engine compile_file function */
6062 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
6063 +static zend_compile_t *old_compile_file;
6064 +
6065 +/* }}} */
6066 +
6067 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
6068 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
6069 +{
6070 + zend_compile_t *retval = old_compile_file;
6071 +
6072 + if (ptr != NULL) old_compile_file = ptr;
6073 + return retval;
6074 +}
6075 +/* }}} */
6076 +
6077 +/* {{{ install_function */
6078 +static int install_function(apc_function_t fn TSRMLS_DC)
6079 +{
6080 + int status =
6081 + zend_hash_add(EG(function_table),
6082 + fn.name,
6083 + fn.name_len+1,
6084 + apc_copy_function_for_execution(fn.function),
6085 + sizeof(fn.function[0]),
6086 + NULL);
6087 +
6088 + if (status == FAILURE) {
6089 + /* apc_eprint("Cannot redeclare %s()", fn.name); */
6090 + }
6091 +
6092 + return status;
6093 +}
6094 +/* }}} */
6095 +
6096 +/* {{{ install_class */
6097 +static int install_class(apc_class_t cl TSRMLS_DC)
6098 +{
6099 + zend_class_entry* class_entry = cl.class_entry;
6100 + zend_class_entry* parent = NULL;
6101 + int status;
6102 +#ifdef ZEND_ENGINE_2
6103 + zend_class_entry** allocated_ce = NULL;
6104 +#endif
6105 +
6106 +
6107 + /* Special case for mangled names. Mangled names are unique to a file.
6108 + * There is no way two classes with the same mangled name will occur,
6109 + * unless a file is included twice. And if in case, a file is included
6110 + * twice, all mangled name conflicts can be ignored and the class redeclaration
6111 + * error may be deferred till runtime of the corresponding DECLARE_CLASS
6112 + * calls.
6113 + */
6114 +
6115 + if(cl.name_len != 0 && cl.name[0] == '\0') {
6116 + if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
6117 + return SUCCESS;
6118 + }
6119 + }
6120 +
6121 +#ifdef ZEND_ENGINE_2
6122 + /*
6123 + * XXX: We need to free this somewhere...
6124 + */
6125 + allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
6126 +
6127 + if(!allocated_ce) {
6128 + return FAILURE;
6129 + }
6130 +
6131 + *allocated_ce =
6132 +#endif
6133 + class_entry =
6134 + apc_copy_class_entry_for_execution(cl.class_entry,
6135 + cl.is_derived);
6136 +
6137 +
6138 + /* restore parent class pointer for compile-time inheritance */
6139 + if (cl.parent_name != NULL) {
6140 +#ifdef ZEND_ENGINE_2
6141 + zend_class_entry** parent_ptr = NULL;
6142 + /*
6143 + * zend_lookup_class has to be due to presence of __autoload,
6144 + * just looking up the EG(class_table) is not enough in php5!
6145 + * Even more dangerously, thanks to __autoload and people using
6146 + * class names as filepaths for inclusion, this has to be case
6147 + * sensitive. zend_lookup_class automatically does a case_fold
6148 + * internally, but passes the case preserved version to __autoload.
6149 + * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
6150 + * zend_lookup_class does it internally anyway!
6151 + */
6152 + status = zend_lookup_class(cl.parent_name,
6153 + strlen(cl.parent_name),
6154 + &parent_ptr TSRMLS_CC);
6155 +#else
6156 + status = zend_hash_find(EG(class_table),
6157 + cl.parent_name,
6158 + strlen(cl.parent_name)+1,
6159 + (void**) &parent);
6160 +#endif
6161 + if (status == FAILURE) {
6162 + if(APCG(report_autofilter)) {
6163 + apc_wprint("Dynamic inheritance detected for class %s", cl.name);
6164 + }
6165 + class_entry->parent = NULL;
6166 + return status;
6167 + }
6168 + else {
6169 +#ifdef ZEND_ENGINE_2
6170 + parent = *parent_ptr;
6171 +#endif
6172 + class_entry->parent = parent;
6173 +#ifdef ZEND_ENGINE_2
6174 + zend_do_inheritance(class_entry, parent TSRMLS_CC);
6175 +#else
6176 + zend_do_inheritance(class_entry, parent);
6177 +#endif
6178 + }
6179 +
6180 +
6181 + }
6182 +
6183 +#ifdef ZEND_ENGINE_2
6184 + status = zend_hash_add(EG(class_table),
6185 + cl.name,
6186 + cl.name_len+1,
6187 + allocated_ce,
6188 + sizeof(zend_class_entry*),
6189 + NULL);
6190 +#else
6191 + status = zend_hash_add(EG(class_table),
6192 + cl.name,
6193 + cl.name_len+1,
6194 + class_entry,
6195 + sizeof(zend_class_entry),
6196 + NULL);
6197 +#endif
6198 +
6199 + if (status == FAILURE) {
6200 + apc_eprint("Cannot redeclare class %s", cl.name);
6201 + }
6202 + return status;
6203 +}
6204 +/* }}} */
6205 +
6206 +/* {{{ uninstall_class */
6207 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
6208 +{
6209 + int status;
6210 +
6211 +#ifdef ZEND_ENGINE_2
6212 + status = zend_hash_del(EG(class_table),
6213 + cl.name,
6214 + cl.name_len+1);
6215 +#else
6216 + status = zend_hash_del(EG(class_table),
6217 + cl.name,
6218 + cl.name_len+1);
6219 +#endif
6220 + if (status == FAILURE) {
6221 + apc_eprint("Cannot delete class %s", cl.name);
6222 + }
6223 + return status;
6224 +}
6225 +/* }}} */
6226 +
6227 +/* {{{ compare_file_handles */
6228 +static int compare_file_handles(void* a, void* b)
6229 +{
6230 + zend_file_handle* fh1 = (zend_file_handle*)a;
6231 + zend_file_handle* fh2 = (zend_file_handle*)b;
6232 + return (fh1->type == fh2->type &&
6233 + fh1->filename == fh2->filename &&
6234 + fh1->opened_path == fh2->opened_path);
6235 +}
6236 +/* }}} */
6237 +
6238 +/* {{{ cached_compile */
6239 +static zend_op_array* cached_compile(zend_file_handle* h,
6240 + int type TSRMLS_DC)
6241 +{
6242 + apc_cache_entry_t* cache_entry;
6243 + int i, ii;
6244 +
6245 + cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
6246 + assert(cache_entry != NULL);
6247 +
6248 + if (cache_entry->data.file.classes) {
6249 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6250 + if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
6251 + goto default_compile;
6252 + }
6253 + }
6254 + }
6255 +
6256 + if (cache_entry->data.file.functions) {
6257 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6258 + install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
6259 + }
6260 + }
6261 +
6262 +
6263 + return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
6264 +
6265 +default_compile:
6266 +
6267 + cache_entry->autofiltered = 1;
6268 + if(APCG(report_autofilter)) {
6269 + apc_wprint("Autofiltering %s", h->opened_path);
6270 + }
6271 +
6272 + if(cache_entry->data.file.classes) {
6273 + for(ii = 0; ii < i ; ii++) {
6274 + uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
6275 + }
6276 + }
6277 +
6278 + apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
6279 +
6280 + /* cannot free up cache data yet, it maybe in use */
6281 +
6282 + zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
6283 +
6284 + h->type = ZEND_HANDLE_FILENAME;
6285 +
6286 + return old_compile_file(h, type TSRMLS_CC);
6287 +}
6288 +/* }}} */
6289 +
6290 +/* {{{ my_compile_file
6291 + Overrides zend_compile_file */
6292 +static zend_op_array* my_compile_file(zend_file_handle* h,
6293 + int type TSRMLS_DC)
6294 +{
6295 + apc_cache_key_t key;
6296 + apc_cache_entry_t* cache_entry;
6297 + zend_op_array* op_array;
6298 + int num_functions, num_classes, ret;
6299 + zend_op_array* alloc_op_array;
6300 + apc_function_t* alloc_functions;
6301 + apc_class_t* alloc_classes;
6302 + time_t t;
6303 + char *path;
6304 + size_t mem_size;
6305 +
6306 + if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
6307 + return old_compile_file(h, type TSRMLS_CC);
6308 + }
6309 +
6310 + /* check our regular expression filters */
6311 + if (APCG(filters) && apc_compiled_filters) {
6312 + int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
6313 + if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
6314 + return old_compile_file(h, type TSRMLS_CC);
6315 + }
6316 + } else if(!APCG(cache_by_default)) {
6317 + return old_compile_file(h, type TSRMLS_CC);
6318 + }
6319 +
6320 +#if PHP_API_VERSION <= 20041225
6321 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
6322 + t = ((request_rec *)SG(server_context))->request_time;
6323 +#else
6324 + t = time(0);
6325 +#endif
6326 +#else
6327 + t = sapi_get_request_time(TSRMLS_C);
6328 +#endif
6329 +
6330 +#ifdef __DEBUG_APC__
6331 + fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6332 +#endif
6333 +
6334 + /* try to create a cache key; if we fail, give up on caching */
6335 + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
6336 + return old_compile_file(h, type TSRMLS_CC);
6337 + }
6338 +
6339 + if(APCG(localcache)) {
6340 + /* search for the file in the local cache */
6341 + cache_entry = apc_local_cache_find(APCG(lcache), key, t);
6342 + } else {
6343 + /* search for the file in the cache */
6344 + cache_entry = apc_cache_find(apc_cache, key, t);
6345 + }
6346 +
6347 + if (cache_entry != NULL && !cache_entry->autofiltered) {
6348 + int dummy = 1;
6349 + if (h->opened_path == NULL) {
6350 + h->opened_path = estrdup(cache_entry->data.file.filename);
6351 + }
6352 + zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
6353 + zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
6354 + apc_stack_push(APCG(cache_stack), cache_entry);
6355 + return cached_compile(h, type TSRMLS_CC);
6356 + }
6357 + else if(cache_entry != NULL && cache_entry->autofiltered) {
6358 + /* nobody else is using this cache_entry */
6359 + if(cache_entry->ref_count == 1) {
6360 + if(cache_entry->data.file.op_array) {
6361 + apc_free_op_array(cache_entry->data.file.op_array, apc_sma_free);
6362 + cache_entry->data.file.op_array = NULL;
6363 + }
6364 + if(cache_entry->data.file.functions) {
6365 + apc_free_functions(cache_entry->data.file.functions, apc_sma_free);
6366 + cache_entry->data.file.functions = NULL;
6367 + }
6368 + if(cache_entry->data.file.classes) {
6369 + apc_free_classes(cache_entry->data.file.classes, apc_sma_free);
6370 + cache_entry->data.file.classes = NULL;
6371 + }
6372 + }
6373 + /* We never push this into the cache_stack, so we have to do a release */
6374 + apc_cache_release(apc_cache, cache_entry);
6375 + return old_compile_file(h, type TSRMLS_CC);
6376 + }
6377 +
6378 + if(apc_cache_busy(apc_cache) && APCG(localcache)) {
6379 + /* possibly local cache returned NULL because cache is busy */
6380 + return old_compile_file(h, type TSRMLS_CC);
6381 + }
6382 +
6383 + /* remember how many functions and classes existed before compilation */
6384 + num_functions = zend_hash_num_elements(CG(function_table));
6385 + num_classes = zend_hash_num_elements(CG(class_table));
6386 +
6387 + /* compile the file using the default compile function */
6388 + op_array = old_compile_file(h, type TSRMLS_CC);
6389 + if (op_array == NULL) {
6390 + return NULL;
6391 + }
6392 + /*
6393 + * Basically this will cause a file only to be cached on a percentage
6394 + * of the attempts. This is to avoid cache slams when starting up a
6395 + * very busy server or when modifying files on a very busy live server.
6396 + * There is no point having many processes all trying to cache the same
6397 + * file at the same time. By introducing a chance of being cached
6398 + * we theoretically cut the cache slam problem by the given percentage.
6399 + * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
6400 + * to cache an uncached file will be ignored.
6401 + */
6402 + if(APCG(slam_defense)) {
6403 + if(APCG(slam_rand)==-1) {
6404 + APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
6405 + }
6406 + if(APCG(slam_rand) < APCG(slam_defense)) {
6407 + return op_array;
6408 + }
6409 + }
6410 +
6411 + HANDLE_BLOCK_INTERRUPTIONS();
6412 +
6413 +#if NONBLOCKING_LOCK_AVAILABLE
6414 + if(APCG(write_lock)) {
6415 + if(!apc_cache_write_lock(apc_cache)) {
6416 + HANDLE_UNBLOCK_INTERRUPTIONS();
6417 + return op_array;
6418 + }
6419 + }
6420 +#endif
6421 +
6422 + mem_size = 0;
6423 + APCG(mem_size_ptr) = &mem_size;
6424 + if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6425 + apc_cache_expunge(apc_cache,t);
6426 + apc_cache_expunge(apc_user_cache,t);
6427 + APCG(mem_size_ptr) = NULL;
6428 +#if NONBLOCKING_LOCK_AVAILABLE
6429 + if(APCG(write_lock)) {
6430 + apc_cache_write_unlock(apc_cache);
6431 + }
6432 +#endif
6433 + HANDLE_UNBLOCK_INTERRUPTIONS();
6434 + return op_array;
6435 + }
6436 +
6437 + if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6438 + apc_free_op_array(alloc_op_array, apc_sma_free);
6439 + apc_cache_expunge(apc_cache,t);
6440 + apc_cache_expunge(apc_user_cache,t);
6441 + APCG(mem_size_ptr) = NULL;
6442 +#if NONBLOCKING_LOCK_AVAILABLE
6443 + if(APCG(write_lock)) {
6444 + apc_cache_write_unlock(apc_cache);
6445 + }
6446 +#endif
6447 + HANDLE_UNBLOCK_INTERRUPTIONS();
6448 + return op_array;
6449 + }
6450 + if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6451 + apc_free_op_array(alloc_op_array, apc_sma_free);
6452 + apc_free_functions(alloc_functions, apc_sma_free);
6453 + apc_cache_expunge(apc_cache,t);
6454 + apc_cache_expunge(apc_user_cache,t);
6455 + APCG(mem_size_ptr) = NULL;
6456 +#if NONBLOCKING_LOCK_AVAILABLE
6457 + if(APCG(write_lock)) {
6458 + apc_cache_write_unlock(apc_cache);
6459 + }
6460 +#endif
6461 + HANDLE_UNBLOCK_INTERRUPTIONS();
6462 + return op_array;
6463 + }
6464 +
6465 + path = h->opened_path;
6466 + if(!path) path=h->filename;
6467 +
6468 +#ifdef __DEBUG_APC__
6469 + fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6470 +#endif
6471 +
6472 + if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
6473 + apc_free_op_array(alloc_op_array, apc_sma_free);
6474 + apc_free_functions(alloc_functions, apc_sma_free);
6475 + apc_free_classes(alloc_classes, apc_sma_free);
6476 + apc_cache_expunge(apc_cache,t);
6477 + apc_cache_expunge(apc_user_cache,t);
6478 + APCG(mem_size_ptr) = NULL;
6479 +#if NONBLOCKING_LOCK_AVAILABLE
6480 + if(APCG(write_lock)) {
6481 + apc_cache_write_unlock(apc_cache);
6482 + }
6483 +#endif
6484 + HANDLE_UNBLOCK_INTERRUPTIONS();
6485 + return op_array;
6486 + }
6487 + APCG(mem_size_ptr) = NULL;
6488 + cache_entry->mem_size = mem_size;
6489 +
6490 + if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
6491 + apc_cache_free_entry(cache_entry);
6492 + if(ret==-1) {
6493 + apc_cache_expunge(apc_cache,t);
6494 + apc_cache_expunge(apc_user_cache,t);
6495 + }
6496 + }
6497 +
6498 +#if NONBLOCKING_LOCK_AVAILABLE
6499 + if(APCG(write_lock)) {
6500 + apc_cache_write_unlock(apc_cache);
6501 + }
6502 +#endif
6503 + HANDLE_UNBLOCK_INTERRUPTIONS();
6504 +
6505 + return op_array;
6506 +}
6507 +/* }}} */
6508 +
6509 +/* {{{ module init and shutdown */
6510 +
6511 +int apc_module_init(int module_number TSRMLS_DC)
6512 +{
6513 + /* apc initialization */
6514 +#if APC_MMAP
6515 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
6516 +#else
6517 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
6518 +#endif
6519 + apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
6520 + apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
6521 +
6522 + apc_compiled_filters = apc_regex_compile_array(APCG(filters));
6523 +
6524 + /* override compilation */
6525 + old_compile_file = zend_compile_file;
6526 + zend_compile_file = my_compile_file;
6527 + REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
6528 +
6529 + APCG(initialized) = 1;
6530 + return 0;
6531 +}
6532 +
6533 +int apc_module_shutdown(TSRMLS_D)
6534 +{
6535 + if (!APCG(initialized))
6536 + return 0;
6537 +
6538 + /* restore compilation */
6539 + zend_compile_file = old_compile_file;
6540 +
6541 + /*
6542 + * In case we got interrupted by a SIGTERM or something else during execution
6543 + * we may have cache entries left on the stack that we need to check to make
6544 + * sure that any functions or classes these may have added to the global function
6545 + * and class tables are removed before we blow away the memory that hold them.
6546 + *
6547 + * This is merely to remove memory leak warnings - as the process is terminated
6548 + * immediately after shutdown. The following while loop can be removed without
6549 + * affecting anything else.
6550 + */
6551 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6552 + int i;
6553 + apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6554 + if (cache_entry->data.file.functions) {
6555 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6556 + zend_hash_del(EG(function_table),
6557 + cache_entry->data.file.functions[i].name,
6558 + cache_entry->data.file.functions[i].name_len+1);
6559 + }
6560 + }
6561 + if (cache_entry->data.file.classes) {
6562 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6563 + zend_hash_del(EG(class_table),
6564 + cache_entry->data.file.classes[i].name,
6565 + cache_entry->data.file.classes[i].name_len+1);
6566 + }
6567 + }
6568 + apc_cache_release(apc_cache, cache_entry);
6569 + }
6570 +
6571 + apc_cache_destroy(apc_cache);
6572 + apc_cache_destroy(apc_user_cache);
6573 + apc_sma_cleanup();
6574 +
6575 + APCG(initialized) = 0;
6576 + return 0;
6577 +}
6578 +
6579 +/* }}} */
6580 +
6581 +/* {{{ process init and shutdown */
6582 +int apc_process_init(int module_number TSRMLS_DC)
6583 +{
6584 + int minttl = (APCG(gc_ttl) > APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
6585 + int size = APCG(localcache_size);
6586 + if(APCG(initialized) && APCG(localcache)) {
6587 + /* TTL is 2 mins by default */
6588 + APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120);
6589 + }
6590 + return 0;
6591 +}
6592 +
6593 +int apc_process_shutdown(TSRMLS_D)
6594 +{
6595 + if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
6596 + apc_local_cache_destroy(APCG(lcache));
6597 + APCG(lcache) = NULL;
6598 + }
6599 + return 0;
6600 +}
6601 +/* }}} */
6602 +
6603 +/* {{{ request init and shutdown */
6604 +
6605 +int apc_request_init(TSRMLS_D)
6606 +{
6607 + apc_stack_clear(APCG(cache_stack));
6608 + APCG(slam_rand) = -1;
6609 + APCG(copied_zvals) = NULL;
6610 + return 0;
6611 +}
6612 +
6613 +int apc_request_shutdown(TSRMLS_D)
6614 +{
6615 + apc_deactivate(TSRMLS_C);
6616 + return 0;
6617 +}
6618 +
6619 +/* }}} */
6620 +
6621 +/* {{{ apc_deactivate */
6622 +void apc_deactivate(TSRMLS_D)
6623 +{
6624 + /* The execution stack was unwound, which prevented us from decrementing
6625 + * the reference counts on active cache entries in `my_execute`.
6626 + */
6627 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6628 + int i;
6629 + zend_class_entry* zce = NULL;
6630 + void ** centry = (void*)(&zce);
6631 +#ifdef ZEND_ENGINE_2
6632 + zend_class_entry** pzce = NULL;
6633 +#endif
6634 +
6635 + apc_cache_entry_t* cache_entry =
6636 + (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6637 +
6638 + if (cache_entry->data.file.functions) {
6639 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6640 + zend_hash_del(EG(function_table),
6641 + cache_entry->data.file.functions[i].name,
6642 + cache_entry->data.file.functions[i].name_len+1);
6643 + }
6644 + }
6645 +
6646 + if (cache_entry->data.file.classes) {
6647 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6648 +#ifdef ZEND_ENGINE_2
6649 + centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
6650 +#endif
6651 + if(zend_hash_find(EG(class_table),
6652 + cache_entry->data.file.classes[i].name,
6653 + cache_entry->data.file.classes[i].name_len+1,
6654 + (void**)centry) == FAILURE)
6655 + {
6656 + /* double inclusion of conditional classes ends up failing
6657 + * this lookup the second time around.
6658 + */
6659 + continue;
6660 + }
6661 +
6662 +#ifdef ZEND_ENGINE_2
6663 + zce = *pzce;
6664 +#endif
6665 + zend_hash_del(EG(class_table),
6666 + cache_entry->data.file.classes[i].name,
6667 + cache_entry->data.file.classes[i].name_len+1);
6668 +
6669 + apc_free_class_entry_after_execution(zce);
6670 + }
6671 + }
6672 + apc_cache_release(apc_cache, cache_entry);
6673 + }
6674 + if(APCG(localcache)) {
6675 + apc_local_cache_cleanup(APCG(lcache));
6676 + }
6677 +}
6678 +/* }}} */
6679 +
6680 +/*
6681 + * Local variables:
6682 + * tab-width: 4
6683 + * c-basic-offset: 4
6684 + * End:
6685 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6686 + * vim<600: expandtab sw=4 ts=4 sts=4
6687 + */
6688 Index: php-5.2.4/ext/apc/apc_main.h
6689 ===================================================================
6690 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6691 +++ php-5.2.4/ext/apc/apc_main.h 2007-09-02 12:24:46.000000000 +0200
6692 @@ -0,0 +1,67 @@
6693 +/*
6694 + +----------------------------------------------------------------------+
6695 + | APC |
6696 + +----------------------------------------------------------------------+
6697 + | Copyright (c) 2006 The PHP Group |
6698 + +----------------------------------------------------------------------+
6699 + | This source file is subject to version 3.01 of the PHP license, |
6700 + | that is bundled with this package in the file LICENSE, and is |
6701 + | available through the world-wide-web at the following url: |
6702 + | http://www.php.net/license/3_01.txt |
6703 + | If you did not receive a copy of the PHP license and are unable to |
6704 + | obtain it through the world-wide-web, please send a note to |
6705 + | license@php.net so we can mail you a copy immediately. |
6706 + +----------------------------------------------------------------------+
6707 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6708 + | George Schlossnagle <george@omniti.com> |
6709 + | Rasmus Lerdorf <rasmus@php.net> |
6710 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6711 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6712 + +----------------------------------------------------------------------+
6713 +
6714 + This software was contributed to PHP by Community Connect Inc. in 2002
6715 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6716 + Future revisions and derivatives of this source code must acknowledge
6717 + Community Connect Inc. as the original contributor of this module by
6718 + leaving this note intact in the source code.
6719 +
6720 + All other licensing and usage conditions are those of the PHP Group.
6721 +
6722 + */
6723 +
6724 +/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
6725 +
6726 +#ifndef APC_MAIN_H
6727 +#define APC_MAIN_H
6728 +
6729 +/*
6730 + * This module provides the primary interface between PHP and APC.
6731 + */
6732 +
6733 +extern int apc_module_init(int module_number TSRMLS_DC);
6734 +extern int apc_module_shutdown(TSRMLS_D);
6735 +extern int apc_process_init(int module_number TSRMLS_DC);
6736 +extern int apc_process_shutdown(TSRMLS_D);
6737 +extern int apc_request_init(TSRMLS_D);
6738 +extern int apc_request_shutdown(TSRMLS_D);
6739 +
6740 +/*
6741 + * apc_deactivate is called by the PHP interpreter when an "exception" is
6742 + * raised (e.g., a call to the exit function) that unwinds the execution
6743 + * stack.
6744 + */
6745 +extern void apc_deactivate();
6746 +
6747 +
6748 +extern const char* apc_version();
6749 +
6750 +#endif
6751 +
6752 +/*
6753 + * Local variables:
6754 + * tab-width: 4
6755 + * c-basic-offset: 4
6756 + * End:
6757 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6758 + * vim<600: expandtab sw=4 ts=4 sts=4
6759 + */
6760 Index: php-5.2.4/ext/apc/apc_mmap.c
6761 ===================================================================
6762 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6763 +++ php-5.2.4/ext/apc/apc_mmap.c 2007-09-02 12:24:46.000000000 +0200
6764 @@ -0,0 +1,137 @@
6765 +/*
6766 + +----------------------------------------------------------------------+
6767 + | APC |
6768 + +----------------------------------------------------------------------+
6769 + | Copyright (c) 2006 The PHP Group |
6770 + +----------------------------------------------------------------------+
6771 + | This source file is subject to version 3.01 of the PHP license, |
6772 + | that is bundled with this package in the file LICENSE, and is |
6773 + | available through the world-wide-web at the following url: |
6774 + | http://www.php.net/license/3_01.txt |
6775 + | If you did not receive a copy of the PHP license and are unable to |
6776 + | obtain it through the world-wide-web, please send a note to |
6777 + | license@php.net so we can mail you a copy immediately. |
6778 + +----------------------------------------------------------------------+
6779 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
6780 + +----------------------------------------------------------------------+
6781 +
6782 + This software was contributed to PHP by Community Connect Inc. in 2002
6783 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6784 + Future revisions and derivatives of this source code must acknowledge
6785 + Community Connect Inc. as the original contributor of this module by
6786 + leaving this note intact in the source code.
6787 +
6788 + All other licensing and usage conditions are those of the PHP Group.
6789 +
6790 + */
6791 +
6792 +/* $Id: apc_mmap.c,v 3.5 2006/03/12 00:31:45 rasmus Exp $ */
6793 +
6794 +#include "apc.h"
6795 +
6796 +#if APC_MMAP
6797 +
6798 +#include <fcntl.h>
6799 +#include <sys/types.h>
6800 +#include <sys/mman.h>
6801 +
6802 +/*
6803 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
6804 + * tells whatever update daemons might be running to not flush dirty
6805 + * vm pages to disk unless absolutely necessary. My guess is that
6806 + * most systems that don't have this probably default to only synching
6807 + * to disk when absolutely necessary.
6808 + */
6809 +#ifndef MAP_NOSYNC
6810 +#define MAP_NOSYNC 0
6811 +#endif
6812 +
6813 +void *apc_mmap(char *file_mask, int size)
6814 +{
6815 + void* shmaddr; /* the shared memory address */
6816 +
6817 + /* If no filename was provided, do an anonymous mmap */
6818 + if(!file_mask || (file_mask && !strlen(file_mask))) {
6819 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
6820 + } else {
6821 + int fd;
6822 +
6823 + /*
6824 + * If the filemask contains .shm we try to do a POSIX-compliant shared memory
6825 + * backed mmap which should avoid synchs on some platforms. At least on
6826 + * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
6827 + * a file in a mounted shmfs. For this to work on Linux you need to make sure
6828 + * you actually have shmfs mounted. Also on Linux, make sure the file_mask you
6829 + * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX
6830 + * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
6831 + * path you want here.
6832 + */
6833 + if(strstr(file_mask,".shm")) {
6834 + mktemp(file_mask);
6835 + fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
6836 + if(fd == -1) {
6837 + apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
6838 + return (void *)-1;
6839 + }
6840 + if (ftruncate(fd, size) < 0) {
6841 + close(fd);
6842 + shm_unlink(file_mask);
6843 + apc_eprint("apc_mmap: ftruncate failed:");
6844 + return (void *)-1;
6845 + }
6846 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6847 + shm_unlink(file_mask);
6848 + close(fd);
6849 + }
6850 + /*
6851 + * Support anonymous mmap through the /dev/zero interface as well
6852 + */
6853 + else if(!strcmp(file_mask,"/dev/zero")) {
6854 + fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
6855 + if(fd == -1) {
6856 + apc_eprint("apc_mmap: open on /dev/zero failed:");
6857 + return (void *)-1;
6858 + }
6859 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6860 + close(fd);
6861 + }
6862 + /*
6863 + * Otherwise we do a normal filesystem mmap
6864 + */
6865 + else {
6866 + fd = mkstemp(file_mask);
6867 + if(fd == -1) {
6868 + apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
6869 + return (void *)-1;
6870 + }
6871 + if (ftruncate(fd, size) < 0) {
6872 + close(fd);
6873 + unlink(file_mask);
6874 + apc_eprint("apc_mmap: ftruncate failed:");
6875 + }
6876 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
6877 + close(fd);
6878 + unlink(file_mask);
6879 + }
6880 + }
6881 + if((int)shmaddr == -1) {
6882 + apc_eprint("apc_mmap: mmap failed:");
6883 + }
6884 + return shmaddr;
6885 +}
6886 +
6887 +void apc_unmap(void* shmaddr, int size)
6888 +{
6889 + munmap(shmaddr, size);
6890 +}
6891 +
6892 +#endif
6893 +
6894 +/*
6895 + * Local variables:
6896 + * tab-width: 4
6897 + * c-basic-offset: 4
6898 + * End:
6899 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6900 + * vim<600: expandtab sw=4 ts=4 sts=4
6901 + */
6902 Index: php-5.2.4/ext/apc/apc.php
6903 ===================================================================
6904 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6905 +++ php-5.2.4/ext/apc/apc.php 2007-09-02 12:24:46.000000000 +0200
6906 @@ -0,0 +1,1313 @@
6907 +<?php
6908 +/*
6909 + +----------------------------------------------------------------------+
6910 + | APC |
6911 + +----------------------------------------------------------------------+
6912 + | Copyright (c) 2006 The PHP Group |
6913 + +----------------------------------------------------------------------+
6914 + | This source file is subject to version 3.01 of the PHP license, |
6915 + | that is bundled with this package in the file LICENSE, and is |
6916 + | available through the world-wide-web at the following url: |
6917 + | http://www.php.net/license/3_01.txt |
6918 + | If you did not receive a copy of the PHP license and are unable to |
6919 + | obtain it through the world-wide-web, please send a note to |
6920 + | license@php.net so we can mail you a copy immediately. |
6921 + +----------------------------------------------------------------------+
6922 + | Authors: Ralf Becker <beckerr@php.net> |
6923 + | Rasmus Lerdorf <rasmus@php.net> |
6924 + | Ilia Alshanetsky <ilia@prohost.org> |
6925 + +----------------------------------------------------------------------+
6926 +
6927 + All other licensing and usage conditions are those of the PHP Group.
6928 +
6929 + */
6930 +
6931 +$VERSION='$Id: apc.php,v 3.65 2006/10/27 18:32:52 shire Exp $';
6932 +
6933 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
6934 +if (file_exists("apc.conf.php")) include("apc.conf.php");
6935 +////////////////////////////////////////////////////////
6936 +
6937 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
6938 +
6939 +defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if
6940 + // no other authentication is available
6941 + // If set to 0:
6942 + // There will be no further authentication. You
6943 + // will have to handle this by yourself!
6944 + // If set to 1:
6945 + // You need to change ADMIN_PASSWORD to make
6946 + // this work!
6947 +defaults('ADMIN_USERNAME','apc'); // Admin Username
6948 +defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!!
6949 +
6950 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let
6951 +// users generate a md5 or crypt password in a easy way to fill it in above
6952 +
6953 +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German
6954 +defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
6955 +
6956 +defaults('GRAPH_SIZE',200); // Image size
6957 +
6958 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
6959 +
6960 +
6961 +// "define if not defined"
6962 +function defaults($d,$v) {
6963 + if (!defined($d)) define($d,$v); // or just @define(...)
6964 +}
6965 +
6966 +// rewrite $PHP_SELF to block XSS attacks
6967 +//
6968 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : '';
6969 +$time = time();
6970 +$host = getenv('HOSTNAME');
6971 +if($host) { $host = '('.$host.')'; }
6972 +
6973 +// operation constants
6974 +define('OB_HOST_STATS',1);
6975 +define('OB_SYS_CACHE',2);
6976 +define('OB_USER_CACHE',3);
6977 +define('OB_SYS_CACHE_DIR',4);
6978 +define('OB_VERSION_CHECK',9);
6979 +
6980 +// check validity of input variables
6981 +$vardom=array(
6982 + 'OB' => '/^\d+$/', // operational mode switch
6983 + 'CC' => '/^[01]$/', // clear cache requested
6984 + 'SH' => '/^[a-z0-9]+$/', // shared object description
6985 +
6986 + 'IMG' => '/^[123]$/', // image to generate
6987 + 'LO' => '/^1$/', // login requested
6988 +
6989 + 'COUNT' => '/^\d+$/', // number of line displayed in list
6990 + 'SCOPE' => '/^[AD]$/', // list view scope
6991 + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key
6992 + 'SORT2' => '/^[DA]$/', // second sort key
6993 + 'AGGR' => '/^\d+$/', // aggregation by dir level
6994 + 'SEARCH' => '/^.*$/' // aggregation by dir level
6995 +);
6996 +
6997 +// default cache mode
6998 +$cache_mode='opcode';
6999 +
7000 +// cache scope
7001 +$scope_list=array(
7002 + 'A' => 'cache_list',
7003 + 'D' => 'deleted_list'
7004 +);
7005 +
7006 +// handle POST and GET requests
7007 +if (empty($_REQUEST)) {
7008 + if (!empty($_GET) && !empty($_POST)) {
7009 + $_REQUEST = array_merge($_GET, $_POST);
7010 + } else if (!empty($_GET)) {
7011 + $_REQUEST = $_GET;
7012 + } else if (!empty($_POST)) {
7013 + $_REQUEST = $_POST;
7014 + } else {
7015 + $_REQUEST = array();
7016 + }
7017 +}
7018 +
7019 +// check parameter syntax
7020 +foreach($vardom as $var => $dom) {
7021 + if (!isset($_REQUEST[$var])) {
7022 + $MYREQUEST[$var]=NULL;
7023 + } else if (!is_array($_REQUEST[$var]) && preg_match($dom,$_REQUEST[$var])) {
7024 + $MYREQUEST[$var]=$_REQUEST[$var];
7025 + } else {
7026 + $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
7027 + }
7028 +}
7029 +
7030 +// check parameter sematics
7031 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
7032 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
7033 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
7034 +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS;
7035 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
7036 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
7037 +
7038 +$MY_SELF=
7039 + "$PHP_SELF".
7040 + "?SCOPE=".$MYREQUEST['SCOPE'].
7041 + "&SORT1=".$MYREQUEST['SORT1'].
7042 + "&SORT2=".$MYREQUEST['SORT2'].
7043 + "&COUNT=".$MYREQUEST['COUNT'];
7044 +$MY_SELF_WO_SORT=
7045 + "$PHP_SELF".
7046 + "?SCOPE=".$MYREQUEST['SCOPE'].
7047 + "&COUNT=".$MYREQUEST['COUNT'];
7048 +
7049 +// authentication needed?
7050 +//
7051 +if (!USE_AUTHENTICATION) {
7052 + $AUTHENTICATED=1;
7053 +} else {
7054 + $AUTHENTICATED=0;
7055 + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
7056 +
7057 + if (!isset($_SERVER['PHP_AUTH_USER']) ||
7058 + !isset($_SERVER['PHP_AUTH_PW']) ||
7059 + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
7060 + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
7061 + Header("WWW-Authenticate: Basic realm=\"APC Login\"");
7062 + Header("HTTP/1.0 401 Unauthorized");
7063 +
7064 + echo <<<EOB
7065 + <html><body>
7066 + <h1>Rejected!</h1>
7067 + <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
7068 + <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
7069 + </body></html>
7070 +EOB;
7071 + exit;
7072 +
7073 + } else {
7074 + $AUTHENTICATED=1;
7075 + }
7076 + }
7077 +}
7078 +
7079 +// select cache mode
7080 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
7081 + $cache_mode='user';
7082 +}
7083 +// clear cache
7084 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
7085 + apc_clear_cache($cache_mode);
7086 +}
7087 +
7088 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
7089 + echo "No cache info available. APC does not appear to be running.";
7090 + exit;
7091 +}
7092 +
7093 +$cache_user = apc_cache_info('user', 1);
7094 +$mem=apc_sma_info();
7095 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear
7096 +
7097 +// don't cache this page
7098 +//
7099 +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
7100 +header("Cache-Control: post-check=0, pre-check=0", false);
7101 +header("Pragma: no-cache"); // HTTP/1.0
7102 +
7103 +function duration($ts) {
7104 + global $time;
7105 + $years = (int)((($time - $ts)/(7*86400))/52.177457);
7106 + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
7107 + $weeks = (int)(($rem)/(7*86400));
7108 + $days = (int)(($rem)/86400) - $weeks*7;
7109 + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
7110 + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
7111 + $str = '';
7112 + if($years==1) $str .= "$years year, ";
7113 + if($years>1) $str .= "$years years, ";
7114 + if($weeks==1) $str .= "$weeks week, ";
7115 + if($weeks>1) $str .= "$weeks weeks, ";
7116 + if($days==1) $str .= "$days day,";
7117 + if($days>1) $str .= "$days days,";
7118 + if($hours == 1) $str .= " $hours hour and";
7119 + if($hours>1) $str .= " $hours hours and";
7120 + if($mins == 1) $str .= " 1 minute";
7121 + else $str .= " $mins minutes";
7122 + return $str;
7123 +}
7124 +
7125 +// create graphics
7126 +//
7127 +function graphics_avail() {
7128 + return extension_loaded('gd');
7129 +}
7130 +if (isset($MYREQUEST['IMG']))
7131 +{
7132 + if (!graphics_avail()) {
7133 + exit(0);
7134 + }
7135 +
7136 + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
7137 + $r=$diameter/2;
7138 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7139 +
7140 +
7141 + if (function_exists("imagefilledarc")) {
7142 + // exists only if GD 2.0.1 is avaliable
7143 + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
7144 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
7145 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
7146 + } else {
7147 + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
7148 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7149 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7150 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7151 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7152 + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
7153 + }
7154 + if ($text) {
7155 + if ($placeindex>0) {
7156 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7157 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7158 +
7159 + } else {
7160 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7161 + }
7162 + }
7163 + }
7164 +
7165 + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
7166 + $r=$diameter/2;
7167 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7168 +
7169 + if ($placeindex>0) {
7170 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7171 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7172 +
7173 + } else {
7174 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7175 + }
7176 + }
7177 +
7178 + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
7179 + global $col_black;
7180 + $x1=$x+$w-1;
7181 + $y1=$y+$h-1;
7182 +
7183 + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
7184 + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
7185 + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
7186 + imagerectangle($im, $x, $y1, $x1, $y, $color1);
7187 + if ($text) {
7188 + if ($placeindex>0) {
7189 +
7190 + if ($placeindex<16)
7191 + {
7192 + $px=5;
7193 + $py=$placeindex*12+6;
7194 + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
7195 + imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
7196 + imagestring($im,2,$px,$py-6,$text,$color1);
7197 +
7198 + } else {
7199 + if ($placeindex<31) {
7200 + $px=$x+40*2;
7201 + $py=($placeindex-15)*12+6;
7202 + } else {
7203 + $px=$x+40*2+100*intval(($placeindex-15)/15);
7204 + $py=($placeindex%15)*12+6;
7205 + }
7206 + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
7207 + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
7208 + imagestring($im,2,$px+2,$py-6,$text,$color1);
7209 + }
7210 + } else {
7211 + imagestring($im,4,$x+5,$y1-16,$text,$color1);
7212 + }
7213 + }
7214 + }
7215 +
7216 +
7217 + $size = GRAPH_SIZE; // image size
7218 + if ($MYREQUEST['IMG']==3)
7219 + $image = imagecreate(2*$size+150, $size+10);
7220 + else
7221 + $image = imagecreate($size+50, $size+10);
7222 +
7223 + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
7224 + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
7225 + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
7226 + $col_black = imagecolorallocate($image, 0, 0, 0);
7227 + imagecolortransparent($image,$col_white);
7228 +
7229 + switch ($MYREQUEST['IMG']) {
7230 +
7231 + case 1:
7232 + $s=$mem['num_seg']*$mem['seg_size'];
7233 + $a=$mem['avail_mem'];
7234 + $x=$y=$size/2;
7235 + $fuzz = 0.000001;
7236 +
7237 + // This block of code creates the pie chart. It is a lot more complex than you
7238 + // would expect because we try to visualize any memory fragmentation as well.
7239 + $angle_from = 0;
7240 + $string_placement=array();
7241 + for($i=0; $i<$mem['num_seg']; $i++) {
7242 + $ptr = 0;
7243 + $free = $mem['block_lists'][$i];
7244 + foreach($free as $block) {
7245 + if($block['offset']!=$ptr) { // Used block
7246 + $angle_to = $angle_from+($block['offset']-$ptr)/$s;
7247 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7248 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7249 + if (($angle_to-$angle_from)>0.05) {
7250 + array_push($string_placement, array($angle_from,$angle_to));
7251 + }
7252 + $angle_from = $angle_to;
7253 + }
7254 + $angle_to = $angle_from+($block['size'])/$s;
7255 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7256 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
7257 + if (($angle_to-$angle_from)>0.05) {
7258 + array_push($string_placement, array($angle_from,$angle_to));
7259 + }
7260 + $angle_from = $angle_to;
7261 + $ptr = $block['offset']+$block['size'];
7262 + }
7263 + if ($ptr < $mem['seg_size']) { // memory at the end
7264 + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
7265 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7266 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7267 + if (($angle_to-$angle_from)>0.05) {
7268 + array_push($string_placement, array($angle_from,$angle_to));
7269 + }
7270 + }
7271 + }
7272 + foreach ($string_placement as $angle) {
7273 + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
7274 + }
7275 + break;
7276 +
7277 + case 2:
7278 + $s=$cache['num_hits']+$cache['num_misses'];
7279 + $a=$cache['num_hits'];
7280 +
7281 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7282 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7283 + break;
7284 +
7285 + case 3:
7286 + $s=$mem['num_seg']*$mem['seg_size'];
7287 + $a=$mem['avail_mem'];
7288 + $x=130;
7289 + $y=1;
7290 + $j=1;
7291 +
7292 + // This block of code creates the bar chart. It is a lot more complex than you
7293 + // would expect because we try to visualize any memory fragmentation as well.
7294 + for($i=0; $i<$mem['num_seg']; $i++) {
7295 + $ptr = 0;
7296 + $free = $mem['block_lists'][$i];
7297 + foreach($free as $block) {
7298 + if($block['offset']!=$ptr) { // Used block
7299 + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
7300 + if ($h>0) {
7301 + $j++;
7302 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
7303 + else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
7304 + }
7305 + $y+=$h;
7306 + }
7307 + $h=(GRAPH_SIZE-5)*($block['size'])/$s;
7308 + if ($h>0) {
7309 + $j++;
7310 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
7311 + else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
7312 + }
7313 + $y+=$h;
7314 + $ptr = $block['offset']+$block['size'];
7315 + }
7316 + if ($ptr < $mem['seg_size']) { // memory at the end
7317 + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
7318 + if ($h > 0) {
7319 + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
7320 + }
7321 + }
7322 + }
7323 + break;
7324 + case 4:
7325 + $s=$cache['num_hits']+$cache['num_misses'];
7326 + $a=$cache['num_hits'];
7327 +
7328 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7329 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7330 + break;
7331 +
7332 + }
7333 + header("Content-type: image/png");
7334 + imagepng($image);
7335 + exit;
7336 +}
7337 +
7338 +// pretty printer for byte values
7339 +//
7340 +function bsize($s) {
7341 + foreach (array('','K','M','G') as $i => $k) {
7342 + if ($s < 1024) break;
7343 + $s/=1024;
7344 + }
7345 + return sprintf("%5.1f %sBytes",$s,$k);
7346 +}
7347 +
7348 +// sortable table header in "scripts for this host" view
7349 +function sortheader($key,$name,$extra='') {
7350 + global $MYREQUEST, $MY_SELF_WO_SORT;
7351 +
7352 + if ($MYREQUEST['SORT1']==$key) {
7353 + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
7354 + }
7355 + return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
7356 +
7357 +}
7358 +
7359 +// create menu entry
7360 +function menu_entry($ob,$title) {
7361 + global $MYREQUEST,$MY_SELF;
7362 + if ($MYREQUEST['OB']!=$ob) {
7363 + return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7364 + } else if (empty($MYREQUEST['SH'])) {
7365 + return "<li><span class=active>$title</span></li>";
7366 + } else {
7367 + return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7368 + }
7369 +}
7370 +
7371 +function put_login_link($s="Login")
7372 +{
7373 + global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
7374 + // needs ADMIN_PASSWORD to be changed!
7375 + //
7376 + if (!USE_AUTHENTICATION) {
7377 + return;
7378 + } else if (ADMIN_PASSWORD=='password')
7379 + {
7380 + print <<<EOB
7381 + <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>
7382 +EOB;
7383 + } else if ($AUTHENTICATED) {
7384 + print <<<EOB
7385 + '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
7386 +EOB;
7387 + } else{
7388 + print <<<EOB
7389 + <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
7390 +EOB;
7391 + }
7392 +}
7393 +
7394 +
7395 +?>
7396 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7397 +<html>
7398 +<head><title>APC INFO <?php echo $host ?></title>
7399 +<style><!--
7400 +body { background:white; font-size:100.01%; margin:0; padding:0; }
7401 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
7402 +* html body {font-size:0.8em}
7403 +* html p {font-size:0.8em}
7404 +* html td {font-size:0.8em}
7405 +* html th {font-size:0.8em}
7406 +* html input {font-size:0.8em}
7407 +* html submit {font-size:0.8em}
7408 +td { vertical-align:top }
7409 +a { color:black; font-weight:none; text-decoration:none; }
7410 +a:hover { text-decoration:underline; }
7411 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
7412 +
7413 +
7414 +div.head div.login {
7415 + position:absolute;
7416 + right: 1em;
7417 + top: 1.2em;
7418 + color:white;
7419 + width:6em;
7420 + }
7421 +div.head div.login a {
7422 + position:absolute;
7423 + right: 0em;
7424 + background:rgb(119,123,180);
7425 + border:solid rgb(102,102,153) 2px;
7426 + color:white;
7427 + font-weight:bold;
7428 + padding:0.1em 0.5em 0.1em 0.5em;
7429 + text-decoration:none;
7430 + }
7431 +div.head div.login a:hover {
7432 + background:rgb(193,193,244);
7433 + }
7434 +
7435 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
7436 +* html h1.apc { margin-bottom:-7px; }
7437 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
7438 +h1.apc div.logo span.logo {
7439 + background:rgb(119,123,180);
7440 + color:black;
7441 + border-right: solid black 1px;
7442 + border-bottom: solid black 1px;
7443 + font-style:italic;
7444 + font-size:1em;
7445 + padding-left:1.2em;
7446 + padding-right:1.2em;
7447 + text-align:right;
7448 + }
7449 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
7450 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
7451 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
7452 +hr.apc {
7453 + background:white;
7454 + border-bottom:solid rgb(102,102,153) 1px;
7455 + border-style:none;
7456 + border-top:solid rgb(102,102,153) 10px;
7457 + height:12px;
7458 + margin:0;
7459 + margin-top:1px;
7460 + padding:0;
7461 +}
7462 +
7463 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
7464 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
7465 +ol.menu a {
7466 + background:rgb(153,153,204);
7467 + border:solid rgb(102,102,153) 2px;
7468 + color:white;
7469 + font-weight:bold;
7470 + margin-right:0em;
7471 + padding:0.1em 0.5em 0.1em 0.5em;
7472 + text-decoration:none;
7473 + margin-left: 5px;
7474 + }
7475 +ol.menu a.child_active {
7476 + background:rgb(153,153,204);
7477 + border:solid rgb(102,102,153) 2px;
7478 + color:white;
7479 + font-weight:bold;
7480 + margin-right:0em;
7481 + padding:0.1em 0.5em 0.1em 0.5em;
7482 + text-decoration:none;
7483 + border-left: solid black 5px;
7484 + margin-left: 0px;
7485 + }
7486 +ol.menu span.active {
7487 + background:rgb(153,153,204);
7488 + border:solid rgb(102,102,153) 2px;
7489 + color:black;
7490 + font-weight:bold;
7491 + margin-right:0em;
7492 + padding:0.1em 0.5em 0.1em 0.5em;
7493 + text-decoration:none;
7494 + border-left: solid black 5px;
7495 + }
7496 +ol.menu span.inactive {
7497 + background:rgb(193,193,244);
7498 + border:solid rgb(182,182,233) 2px;
7499 + color:white;
7500 + font-weight:bold;
7501 + margin-right:0em;
7502 + padding:0.1em 0.5em 0.1em 0.5em;
7503 + text-decoration:none;
7504 + margin-left: 5px;
7505 + }
7506 +ol.menu a:hover {
7507 + background:rgb(193,193,244);
7508 + text-decoration:none;
7509 + }
7510 +
7511 +
7512 +div.info {
7513 + background:rgb(204,204,204);
7514 + border:solid rgb(204,204,204) 1px;
7515 + margin-bottom:1em;
7516 + }
7517 +div.info h2 {
7518 + background:rgb(204,204,204);
7519 + color:black;
7520 + font-size:1em;
7521 + margin:0;
7522 + padding:0.1em 1em 0.1em 1em;
7523 + }
7524 +div.info table {
7525 + border:solid rgb(204,204,204) 1px;
7526 + border-spacing:0;
7527 + width:100%;
7528 + }
7529 +div.info table th {
7530 + background:rgb(204,204,204);
7531 + color:white;
7532 + margin:0;
7533 + padding:0.1em 1em 0.1em 1em;
7534 + }
7535 +div.info table th a.sortable { color:black; }
7536 +div.info table tr.tr-0 { background:rgb(238,238,238); }
7537 +div.info table tr.tr-1 { background:rgb(221,221,221); }
7538 +div.info table td { padding:0.3em 1em 0.3em 1em; }
7539 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
7540 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
7541 +div.info table td h3 {
7542 + color:black;
7543 + font-size:1.1em;
7544 + margin-left:-0.3em;
7545 + }
7546 +
7547 +div.graph { margin-bottom:1em }
7548 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
7549 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
7550 +div.graph table td.td-0 { background:rgb(238,238,238); }
7551 +div.graph table td.td-1 { background:rgb(221,221,221); }
7552 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
7553 +
7554 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
7555 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
7556 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
7557 +
7558 +div.sorting { margin:1.5em 0em 1.5em 2em }
7559 +.center { text-align:center }
7560 +.aright { position:absolute;right:1em }
7561 +.right { text-align:right }
7562 +.ok { color:rgb(0,200,0); font-weight:bold}
7563 +.failed { color:rgb(200,0,0); font-weight:bold}
7564 +
7565 +span.box {
7566 + border: black solid 1px;
7567 + border-right:solid black 2px;
7568 + border-bottom:solid black 2px;
7569 + padding:0 0.5em 0 0.5em;
7570 + margin-right:1em;
7571 +}
7572 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
7573 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
7574 +
7575 +div.authneeded {
7576 + background:rgb(238,238,238);
7577 + border:solid rgb(204,204,204) 1px;
7578 + color:rgb(200,0,0);
7579 + font-size:1.2em;
7580 + font-weight:bold;
7581 + padding:2em;
7582 + text-align:center;
7583 + }
7584 +
7585 +input {
7586 + background:rgb(153,153,204);
7587 + border:solid rgb(102,102,153) 2px;
7588 + color:white;
7589 + font-weight:bold;
7590 + margin-right:1em;
7591 + padding:0.1em 0.5em 0.1em 0.5em;
7592 + }
7593 +//-->
7594 +</style>
7595 +</head>
7596 +<body>
7597 +<div class="head">
7598 + <h1 class="apc">
7599 + <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
7600 + <div class="nameinfo">Opcode Cache</div>
7601 + </h1>
7602 + <div class="login">
7603 + <?php put_login_link(); ?>
7604 + </div>
7605 + <hr class="apc">
7606 +</div>
7607 +<?php
7608 +
7609 +
7610 +// Display main Menu
7611 +echo <<<EOB
7612 + <ol class=menu>
7613 + <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
7614 +EOB;
7615 +echo
7616 + menu_entry(1,'View Host Stats'),
7617 + menu_entry(2,'System Cache Entries');
7618 +if ($AUTHENTICATED) {
7619 + echo menu_entry(4,'Per-Directory Entries');
7620 +}
7621 +echo
7622 + menu_entry(3,'User Cache Entries'),
7623 + menu_entry(9,'Version Check');
7624 +
7625 +if ($AUTHENTICATED) {
7626 + echo <<<EOB
7627 + <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>
7628 +EOB;
7629 +}
7630 +echo <<<EOB
7631 + </ol>
7632 +EOB;
7633 +
7634 +
7635 +// CONTENT
7636 +echo <<<EOB
7637 + <div class=content>
7638 +EOB;
7639 +
7640 +// MAIN SWITCH STATEMENT
7641 +
7642 +switch ($MYREQUEST['OB']) {
7643 +
7644 +
7645 +
7646 +
7647 +
7648 +// -----------------------------------------------
7649 +// Host Stats
7650 +// -----------------------------------------------
7651 +case OB_HOST_STATS:
7652 + $mem_size = $mem['num_seg']*$mem['seg_size'];
7653 + $mem_avail= $mem['avail_mem'];
7654 + $mem_used = $mem_size-$mem_avail;
7655 + $seg_size = bsize($mem['seg_size']);
7656 + $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
7657 + $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
7658 + $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
7659 + $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
7660 + $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
7661 + $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
7662 + $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
7663 + $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
7664 + $apcversion = phpversion('apc');
7665 + $phpversion = phpversion();
7666 + $number_files = $cache['num_entries'];
7667 + $size_files = bsize($cache['mem_size']);
7668 + $number_vars = $cache_user['num_entries'];
7669 + $size_vars = bsize($cache_user['mem_size']);
7670 + $i=0;
7671 + echo <<< EOB
7672 + <div class="info div1"><h2>General Cache Information</h2>
7673 + <table cellspacing=0><tbody>
7674 + <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
7675 + <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
7676 +EOB;
7677 +
7678 + if(!empty($_SERVER['SERVER_NAME']))
7679 + echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
7680 + if(!empty($_SERVER['SERVER_SOFTWARE']))
7681 + echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
7682 +
7683 + echo <<<EOB
7684 + <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
7685 + <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
7686 + </td></tr>
7687 +EOB;
7688 + echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
7689 + echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
7690 + echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
7691 + echo <<<EOB
7692 + </tbody></table>
7693 + </div>
7694 +
7695 + <div class="info div1"><h2>File Cache Information</h2>
7696 + <table cellspacing=0><tbody>
7697 + <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
7698 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
7699 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
7700 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
7701 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
7702 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
7703 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
7704 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
7705 + </tbody></table>
7706 + </div>
7707 +
7708 + <div class="info div1"><h2>User Cache Information</h2>
7709 + <table cellspacing=0><tbody>
7710 + <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
7711 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
7712 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
7713 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
7714 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
7715 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
7716 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
7717 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
7718 +
7719 + </tbody></table>
7720 + </div>
7721 +
7722 + <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
7723 +EOB;
7724 +
7725 + $j = 0;
7726 + foreach (ini_get_all('apc') as $k => $v) {
7727 + echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
7728 + $j = 1 - $j;
7729 + }
7730 +
7731 + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
7732 + $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
7733 + else
7734 + $mem_note = "Memory Usage";
7735 +
7736 + echo <<< EOB
7737 + </tbody></table>
7738 + </div>
7739 +
7740 + <div class="graph div3"><h2>Host Status Diagrams</h2>
7741 + <table cellspacing=0><tbody>
7742 +EOB;
7743 + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
7744 + echo <<<EOB
7745 + <tr>
7746 + <td class=td-0>$mem_note</td>
7747 + <td class=td-1>Hits &amp; Misses</td>
7748 + </tr>
7749 +EOB;
7750 +
7751 + echo
7752 + graphics_avail() ?
7753 + '<tr>'.
7754 + "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
7755 + "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
7756 + : "",
7757 + '<tr>',
7758 + '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
7759 + '<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",
7760 + '</tr>',
7761 + '<tr>',
7762 + '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
7763 + '<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";
7764 + echo <<< EOB
7765 + </tr>
7766 + </tbody></table>
7767 +
7768 + <br/>
7769 + <h2>Detailed Memory Usage and Fragmentation</h2>
7770 + <table cellspacing=0><tbody>
7771 + <tr>
7772 + <td class=td-0 colspan=2><br/>
7773 +EOB;
7774 +
7775 + // Fragementation: (freeseg - 1) / total_seg
7776 + $nseg = $freeseg = $fragsize = $freetotal = 0;
7777 + for($i=0; $i<$mem['num_seg']; $i++) {
7778 + $ptr = 0;
7779 + foreach($mem['block_lists'][$i] as $block) {
7780 + if ($block['offset'] != $ptr) {
7781 + ++$nseg;
7782 + }
7783 + $ptr = $block['offset'] + $block['size'];
7784 + /* Only consider blocks <5M for the fragmentation % */
7785 + if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
7786 + $freetotal+=$block['size'];
7787 + }
7788 + $freeseg += count($mem['block_lists'][$i]);
7789 + }
7790 +
7791 + if ($freeseg > 1) {
7792 + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
7793 + } else {
7794 + $frag = "0%";
7795 + }
7796 +
7797 + if (graphics_avail()) {
7798 + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
7799 + echo <<<EOB
7800 + <img alt="" $size src="$PHP_SELF?IMG=3&$time">
7801 +EOB;
7802 + }
7803 + echo <<<EOB
7804 + </br>Fragmentation: $frag
7805 + </td>
7806 + </tr>
7807 +EOB;
7808 + if(isset($mem['adist'])) {
7809 + foreach($mem['adist'] as $i=>$v) {
7810 + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
7811 + if($i==0) $range = "1";
7812 + else $range = "$cur - $nxt";
7813 + echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
7814 + }
7815 + }
7816 + echo <<<EOB
7817 + </tbody></table>
7818 + </div>
7819 +EOB;
7820 +
7821 + break;
7822 +
7823 +
7824 +// -----------------------------------------------
7825 +// User Cache Entries
7826 +// -----------------------------------------------
7827 +case OB_USER_CACHE:
7828 + if (!$AUTHENTICATED) {
7829 + echo '<div class="authneeded">You need to login to see the user values here!<br/>&nbsp;<br/>';
7830 + put_login_link("Login now!");
7831 + echo '</div>';
7832 + break;
7833 + }
7834 + $fieldname='info';
7835 + $fieldheading='User Entry Label';
7836 + $fieldkey='info';
7837 +
7838 +
7839 +// -----------------------------------------------
7840 +// System Cache Entries
7841 +// -----------------------------------------------
7842 +case OB_SYS_CACHE:
7843 + if (!isset($fieldname))
7844 + {
7845 + $fieldname='filename';
7846 + $fieldheading='Script Filename';
7847 + if(ini_get("apc.stat")) $fieldkey='inode';
7848 + else $fieldkey='filename';
7849 + }
7850 + if (!empty($MYREQUEST['SH']))
7851 + {
7852 + echo <<< EOB
7853 + <div class="info"><table cellspacing=0><tbody>
7854 + <tr><th>Attribute</th><th>Value</th></tr>
7855 +EOB;
7856 +
7857 + $m=0;
7858 + foreach($scope_list as $j => $list) {
7859 + foreach($cache[$list] as $i => $entry) {
7860 + if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
7861 + foreach($entry as $k => $value) {
7862 + if (!$AUTHENTICATED) {
7863 + // hide all path entries if not logged in
7864 + $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
7865 + }
7866 +
7867 + if ($k == "num_hits") {
7868 + $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
7869 + }
7870 + if ($k == 'deletion_time') {
7871 + if(!$entry['deletion_time']) $value = "None";
7872 + }
7873 + echo
7874 + "<tr class=tr-$m>",
7875 + "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
7876 + "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
7877 + "</tr>";
7878 + $m=1-$m;
7879 + }
7880 + if($fieldkey=='info') {
7881 + echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
7882 + $output = var_export(apc_fetch($entry[$fieldkey]),true);
7883 + echo htmlspecialchars($output);
7884 + echo "</pre></td></tr>\n";
7885 + }
7886 + break;
7887 + }
7888 + }
7889 +
7890 + echo <<<EOB
7891 + </tbody></table>
7892 + </div>
7893 +EOB;
7894 + break;
7895 + }
7896 +
7897 + $cols=6;
7898 + echo <<<EOB
7899 + <div class=sorting><form>Scope:
7900 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
7901 + <select name=SCOPE>
7902 +EOB;
7903 + echo
7904 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
7905 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
7906 + "</select>",
7907 + ", Sorting:<select name=SORT1>",
7908 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
7909 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
7910 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
7911 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
7912 + "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
7913 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
7914 + "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
7915 + if($fieldname=='info') echo
7916 + "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
7917 + echo
7918 + '</select>',
7919 + '<select name=SORT2>',
7920 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
7921 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
7922 + '</select>',
7923 + '<select name=COUNT onChange="form.submit()">',
7924 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
7925 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
7926 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
7927 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
7928 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
7929 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
7930 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
7931 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
7932 + '</select>',
7933 + '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
7934 + '&nbsp;<input type=submit value="GO!">',
7935 + '</form></div>',
7936 +
7937 + '<div class="info"><table cellspacing=0><tbody>',
7938 + '<tr>',
7939 + '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>',
7940 + '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>',
7941 + '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>',
7942 + '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
7943 + '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
7944 + '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>';
7945 +
7946 + if($fieldname=='info') {
7947 + $cols+=2;
7948 + echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
7949 + }
7950 + echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
7951 +
7952 + // builds list with alpha numeric sortable keys
7953 + //
7954 + $list = array();
7955 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
7956 + switch($MYREQUEST['SORT1']) {
7957 + case 'A': $k=sprintf('%015d-',$entry['access_time']); break;
7958 + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break;
7959 + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break;
7960 + case 'M': $k=sprintf('%015d-',$entry['mtime']); break;
7961 + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
7962 + case 'T': $k=sprintf('%015d-',$entry['ttl']); break;
7963 + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
7964 + case 'S': $k=''; break;
7965 + }
7966 + if (!$AUTHENTICATED) {
7967 + // hide all path entries if not logged in
7968 + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
7969 + } else {
7970 + $list[$k.$entry[$fieldname]]=$entry;
7971 + }
7972 + }
7973 +
7974 + if ($list) {
7975 +
7976 + // sort list
7977 + //
7978 + switch ($MYREQUEST['SORT2']) {
7979 + case "A": krsort($list); break;
7980 + case "D": ksort($list); break;
7981 + }
7982 +
7983 + // output list
7984 + $i=0;
7985 + foreach($list as $k => $entry) {
7986 + if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {
7987 + echo
7988 + '<tr class=tr-',$i%2,'>',
7989 + "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
7990 + '<td class="td-n center">',$entry['num_hits'],'</td>',
7991 + '<td class="td-n right">',$entry['mem_size'],'</td>',
7992 + '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
7993 + '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
7994 + '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
7995 +
7996 + if($fieldname=='info') {
7997 + if($entry['ttl'])
7998 + echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
7999 + else
8000 + echo '<td class="td-n center">None</td>';
8001 + }
8002 + echo
8003 + '<td class="td-last center">',$entry['deletion_time'] ? date(DATE_FORMAT,$entry['deletion_time']) : '-','</td>',
8004 + '</tr>';
8005 + $i++;
8006 + if ($i == $MYREQUEST['COUNT'])
8007 + break;
8008 + }
8009 + }
8010 +
8011 + } else {
8012 + echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
8013 + }
8014 + echo <<< EOB
8015 + </tbody></table>
8016 +EOB;
8017 +
8018 + if ($list && $i < count($list)) {
8019 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8020 + }
8021 +
8022 + echo <<< EOB
8023 + </div>
8024 +EOB;
8025 + break;
8026 +
8027 +
8028 +// -----------------------------------------------
8029 +// Per-Directory System Cache Entries
8030 +// -----------------------------------------------
8031 +case OB_SYS_CACHE_DIR:
8032 + if (!$AUTHENTICATED) {
8033 + break;
8034 + }
8035 +
8036 + echo <<<EOB
8037 + <div class=sorting><form>Scope:
8038 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
8039 + <select name=SCOPE>
8040 +EOB;
8041 + echo
8042 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
8043 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
8044 + "</select>",
8045 + ", Sorting:<select name=SORT1>",
8046 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
8047 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
8048 + "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
8049 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
8050 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
8051 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
8052 + '</select>',
8053 + '<select name=SORT2>',
8054 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
8055 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
8056 + '</select>',
8057 + '<select name=COUNT onChange="form.submit()">',
8058 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
8059 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
8060 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
8061 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
8062 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
8063 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
8064 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
8065 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
8066 + '</select>',
8067 + ", Group By Dir Level:<select name=AGGR>",
8068 + "<option value='' selected>None</option>";
8069 + for ($i = 1; $i < 10; $i++)
8070 + echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
8071 + echo '</select>',
8072 + '&nbsp;<input type=submit value="GO!">',
8073 + '</form></div>',
8074 +
8075 + '<div class="info"><table cellspacing=0><tbody>',
8076 + '<tr>',
8077 + '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
8078 + '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
8079 + '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8080 + '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>',
8081 + '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8082 + '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>',
8083 + '</tr>';
8084 +
8085 + // builds list with alpha numeric sortable keys
8086 + //
8087 + $tmp = $list = array();
8088 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
8089 + $n = dirname($entry['filename']);
8090 + if ($MYREQUEST['AGGR'] > 0) {
8091 + $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
8092 + }
8093 + if (!isset($tmp[$n])) {
8094 + $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
8095 + }
8096 + $tmp[$n]['hits'] += $entry['num_hits'];
8097 + $tmp[$n]['size'] += $entry['mem_size'];
8098 + ++$tmp[$n]['ents'];
8099 + }
8100 +
8101 + foreach ($tmp as $k => $v) {
8102 + switch($MYREQUEST['SORT1']) {
8103 + case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
8104 + case 'T': $kn=sprintf('%015d-',$v['ents']); break;
8105 + case 'H': $kn=sprintf('%015d-',$v['hits']); break;
8106 + case 'Z': $kn=sprintf('%015d-',$v['size']); break;
8107 + case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
8108 + case 'S': $kn = $k; break;
8109 + }
8110 + $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
8111 + }
8112 +
8113 + if ($list) {
8114 +
8115 + // sort list
8116 + //
8117 + switch ($MYREQUEST['SORT2']) {
8118 + case "A": krsort($list); break;
8119 + case "D": ksort($list); break;
8120 + }
8121 +
8122 + // output list
8123 + $i = 0;
8124 + foreach($list as $entry) {
8125 + echo
8126 + '<tr class=tr-',$i%2,'>',
8127 + "<td class=td-0>",$entry[0],'</a></td>',
8128 + '<td class="td-n center">',$entry[1],'</td>',
8129 + '<td class="td-n center">',$entry[2],'</td>',
8130 + '<td class="td-n center">',$entry[3],'</td>',
8131 + '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
8132 + '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
8133 + '</tr>';
8134 +
8135 + if (++$i == $MYREQUEST['COUNT']) break;
8136 + }
8137 +
8138 + } else {
8139 + echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
8140 + }
8141 + echo <<< EOB
8142 + </tbody></table>
8143 +EOB;
8144 +
8145 + if ($list && $i < count($list)) {
8146 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8147 + }
8148 +
8149 + echo <<< EOB
8150 + </div>
8151 +EOB;
8152 + break;
8153 +
8154 +// -----------------------------------------------
8155 +// Version check
8156 +// -----------------------------------------------
8157 +case OB_VERSION_CHECK:
8158 + echo <<<EOB
8159 + <div class="info"><h2>APC Version Information</h2>
8160 + <table cellspacing=0><tbody>
8161 + <tr>
8162 + <th></th>
8163 + </tr>
8164 +EOB;
8165 +
8166 + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
8167 + if (!$rss) {
8168 + echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
8169 + } else {
8170 + $apcversion = phpversion('apc');
8171 +
8172 + preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
8173 + echo '<tr class="tr-0 center"><td>';
8174 + if (version_compare($apcversion, $match[1], '>=')) {
8175 + echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
8176 + $i = 3;
8177 + } else {
8178 + echo '<div class="failed">You are running an older version of APC ('.$apcversion.'),
8179 + newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
8180 + http://pecl.php.net/package/APC/'.$match[1].'</a>
8181 + </div>';
8182 + $i = -1;
8183 + }
8184 + echo '</td></tr>';
8185 + echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
8186 +
8187 + preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
8188 + next($match[2]); next($match[2]);
8189 +
8190 + while (list(,$v) = each($match[2])) {
8191 + list(,$ver) = explode(' ', $v, 2);
8192 + if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
8193 + break;
8194 + } else if (!$i--) {
8195 + break;
8196 + }
8197 + echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
8198 + echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
8199 + next($match[2]);
8200 + }
8201 + echo '</td></tr>';
8202 + }
8203 + echo <<< EOB
8204 + </tbody></table>
8205 + </div>
8206 +EOB;
8207 + break;
8208 +
8209 +}
8210 +
8211 +echo <<< EOB
8212 + </div>
8213 +EOB;
8214 +
8215 +?>
8216 +
8217 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
8218 +</body>
8219 +</html>
8220 Index: php-5.2.4/ext/apc/apc_php.h
8221 ===================================================================
8222 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8223 +++ php-5.2.4/ext/apc/apc_php.h 2007-09-02 12:24:46.000000000 +0200
8224 @@ -0,0 +1,71 @@
8225 +/*
8226 + +----------------------------------------------------------------------+
8227 + | APC |
8228 + +----------------------------------------------------------------------+
8229 + | Copyright (c) 2006 The PHP Group |
8230 + +----------------------------------------------------------------------+
8231 + | This source file is subject to version 3.01 of the PHP license, |
8232 + | that is bundled with this package in the file LICENSE, and is |
8233 + | available through the world-wide-web at the following url: |
8234 + | http://www.php.net/license/3_01.txt |
8235 + | If you did not receive a copy of the PHP license and are unable to |
8236 + | obtain it through the world-wide-web, please send a note to |
8237 + | license@php.net so we can mail you a copy immediately. |
8238 + +----------------------------------------------------------------------+
8239 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8240 + | George Schlossnagle <george@omniti.com> |
8241 + | Rasmus Lerdorf <rasmus@php.net> |
8242 + | Arun C. Murthy <arunc@yahoo-inc.com> |
8243 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
8244 + +----------------------------------------------------------------------+
8245 +
8246 + This software was contributed to PHP by Community Connect Inc. in 2002
8247 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8248 + Future revisions and derivatives of this source code must acknowledge
8249 + Community Connect Inc. as the original contributor of this module by
8250 + leaving this note intact in the source code.
8251 +
8252 + All other licensing and usage conditions are those of the PHP Group.
8253 +
8254 + */
8255 +
8256 +/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
8257 +
8258 +#ifndef APC_PHP_H
8259 +#define APC_PHP_H
8260 +
8261 +/*
8262 + * The purpose of this header file is to include all PHP and Zend headers that
8263 + * are typically needed elsewhere in APC. This makes it easy to insure that
8264 + * all required headers are available.
8265 + */
8266 +
8267 +#include "php.h"
8268 +#include "zend.h"
8269 +#include "zend_API.h"
8270 +#include "zend_compile.h"
8271 +#include "zend_hash.h"
8272 +#include "zend_extensions.h"
8273 +
8274 +#if ZEND_MODULE_API_NO > 20050922
8275 +#define ZEND_ENGINE_2_2
8276 +#endif
8277 +#if ZEND_MODULE_API_NO > 20050921
8278 +#define ZEND_ENGINE_2_1
8279 +#endif
8280 +#ifdef ZEND_ENGINE_2_1
8281 +#include "zend_vm.h"
8282 +#endif
8283 +
8284 +#include "rfc1867.h"
8285 +
8286 +#endif
8287 +
8288 +/*
8289 + * Local variables:
8290 + * tab-width: 4
8291 + * c-basic-offset: 4
8292 + * End:
8293 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8294 + * vim<600: expandtab sw=4 ts=4 sts=4
8295 + */
8296 Index: php-5.2.4/ext/apc/apc_pthreadmutex.c
8297 ===================================================================
8298 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8299 +++ php-5.2.4/ext/apc/apc_pthreadmutex.c 2007-09-02 12:24:46.000000000 +0200
8300 @@ -0,0 +1,104 @@
8301 +/*
8302 + +----------------------------------------------------------------------+
8303 + | APC |
8304 + +----------------------------------------------------------------------+
8305 + | Copyright (c) 2006 The PHP Group |
8306 + +----------------------------------------------------------------------+
8307 + | This source file is subject to version 3.01 of the PHP license, |
8308 + | that is bundled with this package in the file LICENSE, and is |
8309 + | available through the world-wide-web at the following url: |
8310 + | http://www.php.net/license/3_01.txt |
8311 + | If you did not receive a copy of the PHP license and are unable to |
8312 + | obtain it through the world-wide-web, please send a note to |
8313 + | license@php.net so we can mail you a copy immediately. |
8314 + +----------------------------------------------------------------------+
8315 + | Authors: Brian Shire <shire@php.net> |
8316 + +----------------------------------------------------------------------+
8317 +
8318 + */
8319 +
8320 +/* $Id: apc_pthreadmutex.c,v 3.2 2007/02/15 21:40:45 shire Exp $ */
8321 +
8322 +#include "apc_pthreadmutex.h"
8323 +
8324 +#ifdef APC_PTHREADMUTEX_LOCKS
8325 +
8326 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock)
8327 +{
8328 + int result;
8329 + pthread_mutexattr_t* attr;
8330 + attr = malloc(sizeof(pthread_mutexattr_t));
8331 +
8332 + result = pthread_mutexattr_init(attr);
8333 + if(result == ENOMEM) {
8334 + apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
8335 + } else if(result == EINVAL) {
8336 + apc_eprint("pthread mutex error: attr does not point to writeable memory.");
8337 + } else if(result == EFAULT) {
8338 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8339 + }
8340 +
8341 + /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
8342 + result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
8343 + if(result == EINVAL) {
8344 + apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
8345 + } else if(result == EFAULT) {
8346 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8347 + } else if(result == ENOTSUP) {
8348 + apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
8349 + }
8350 +
8351 + if(pthread_mutex_init(lock, attr)) {
8352 + apc_eprint("unable to initialize pthread lock");
8353 + }
8354 + return lock;
8355 +}
8356 +
8357 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
8358 +{
8359 + return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
8360 +}
8361 +
8362 +void apc_pthreadmutex_lock(pthread_mutex_t *lock)
8363 +{
8364 + int result;
8365 + result = pthread_mutex_lock(lock);
8366 + if(result == EINVAL) {
8367 + apc_eprint("unable to obtain pthread lock (EINVAL)");
8368 + } else if(result == EDEADLK) {
8369 + apc_eprint("unable to obtain pthread lock (EDEADLK)");
8370 + }
8371 +}
8372 +
8373 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
8374 +{
8375 + if(pthread_mutex_unlock(lock)) {
8376 + apc_eprint("unable to unlock pthread lock");
8377 + }
8378 +}
8379 +
8380 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
8381 +{
8382 + int rval;
8383 + rval = pthread_mutex_trylock(lock);
8384 + if(rval == EBUSY) { /* Lock is already held */
8385 + return 0;
8386 + } else if(rval == 0) { /* Obtained lock */
8387 + return 1;
8388 + } else { /* Other error */
8389 + apc_eprint("unable to obtain pthread trylock");
8390 + return 0;
8391 + }
8392 +}
8393 +
8394 +
8395 +#endif
8396 +
8397 +/*
8398 + * Local variables:
8399 + * tab-width: 4
8400 + * c-basic-offset: 4
8401 + * End:
8402 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8403 + * vim<600: expandtab sw=4 ts=4 sts=4
8404 + */
8405 Index: php-5.2.4/ext/apc/apc_pthreadmutex.h
8406 ===================================================================
8407 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8408 +++ php-5.2.4/ext/apc/apc_pthreadmutex.h 2007-09-02 12:24:46.000000000 +0200
8409 @@ -0,0 +1,48 @@
8410 +/*
8411 + +----------------------------------------------------------------------+
8412 + | APC |
8413 + +----------------------------------------------------------------------+
8414 + | Copyright (c) 2006 The PHP Group |
8415 + +----------------------------------------------------------------------+
8416 + | This source file is subject to version 3.01 of the PHP license, |
8417 + | that is bundled with this package in the file LICENSE, and is |
8418 + | available through the world-wide-web at the following url: |
8419 + | http://www.php.net/license/3_01.txt |
8420 + | If you did not receive a copy of the PHP license and are unable to |
8421 + | obtain it through the world-wide-web, please send a note to |
8422 + | license@php.net so we can mail you a copy immediately. |
8423 + +----------------------------------------------------------------------+
8424 + | Authors: Brian Shire <shire@php.net> |
8425 + +----------------------------------------------------------------------+
8426 +
8427 + */
8428 +
8429 +/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
8430 +
8431 +#ifndef APC_PTHREADMUTEX_H
8432 +#define APC_PTHREADMUTEX_H
8433 +
8434 +#include "apc.h"
8435 +
8436 +#ifdef APC_PTHREADMUTEX_LOCKS
8437 +
8438 +#include <pthread.h>
8439 +
8440 +pthread_mutex_t *apc_pthreadmutex_create();
8441 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
8442 +void apc_pthreadmutex_lock(pthread_mutex_t *lock);
8443 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
8444 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
8445 +
8446 +#endif
8447 +
8448 +#endif
8449 +
8450 +/*
8451 + * Local variables:
8452 + * tab-width: 4
8453 + * c-basic-offset: 4
8454 + * End:
8455 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8456 + * vim<600: expandtab sw=4 ts=4 sts=4
8457 + */
8458 Index: php-5.2.4/ext/apc/apc_rfc1867.c
8459 ===================================================================
8460 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8461 +++ php-5.2.4/ext/apc/apc_rfc1867.c 2007-09-02 12:24:46.000000000 +0200
8462 @@ -0,0 +1,175 @@
8463 +/*
8464 + +----------------------------------------------------------------------+
8465 + | APC |
8466 + +----------------------------------------------------------------------+
8467 + | Copyright (c) 2006 The PHP Group |
8468 + +----------------------------------------------------------------------+
8469 + | This source file is subject to version 3.01 of the PHP license, |
8470 + | that is bundled with this package in the file LICENSE, and is |
8471 + | available through the world-wide-web at the following url: |
8472 + | http://www.php.net/license/3_01.txt |
8473 + | If you did not receive a copy of the PHP license and are unable to |
8474 + | obtain it through the world-wide-web, please send a note to |
8475 + | license@php.net so we can mail you a copy immediately. |
8476 + +----------------------------------------------------------------------+
8477 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
8478 + +----------------------------------------------------------------------+
8479 +
8480 + This software was contributed to PHP by Community Connect Inc. in 2002
8481 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8482 + Future revisions and derivatives of this source code must acknowledge
8483 + Community Connect Inc. as the original contributor of this module by
8484 + leaving this note intact in the source code.
8485 +
8486 + All other licensing and usage conditions are those of the PHP Group.
8487 +
8488 + */
8489 +
8490 +/* $Id: apc_rfc1867.c,v 3.4 2007/02/24 11:45:29 rasmus Exp $*/
8491 +
8492 +#include "apc.h"
8493 +#include "rfc1867.h"
8494 +
8495 +#ifdef MULTIPART_EVENT_FORMDATA
8496 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8497 +
8498 +static double my_time() {
8499 + struct timeval a;
8500 + double t;
8501 + gettimeofday(&a, NULL);
8502 + t = a.tv_sec + (a.tv_usec/1000000);
8503 + return t;
8504 +}
8505 +
8506 +void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
8507 + static char tracking_key[64];
8508 + static int key_length = 0;
8509 + static size_t content_length = 0;
8510 + static char filename[128];
8511 + static char name[64];
8512 + static char *temp_filename=NULL;
8513 + static int cancel_upload = 0;
8514 + static double start_time;
8515 + static size_t bytes_processed = 0;
8516 + static double rate;
8517 + zval *track = NULL;
8518 +
8519 + switch (event) {
8520 + case MULTIPART_EVENT_START:
8521 + {
8522 + multipart_event_start *data = (multipart_event_start *) event_data;
8523 + content_length = data->content_length;
8524 + *tracking_key = '\0';
8525 + *name = '\0';
8526 + cancel_upload = 0;
8527 + temp_filename = NULL;
8528 + *filename= '\0';
8529 + key_length = 0;
8530 + start_time = my_time();
8531 + bytes_processed = 0;
8532 + rate = 0;
8533 + }
8534 + break;
8535 +
8536 + case MULTIPART_EVENT_FORMDATA:
8537 + {
8538 + multipart_event_formdata *data = (multipart_event_formdata *) event_data;
8539 +
8540 + if(data->name && !strncasecmp(data->name,"apc_upload_progress",19) && data->value && data->length && data->length < 58) {
8541 + strlcat(tracking_key, "upload_", 63);
8542 + strlcat(tracking_key, *data->value, 63);
8543 + key_length = data->length+7;
8544 + bytes_processed = data->post_bytes_processed;
8545 + }
8546 + }
8547 + break;
8548 +
8549 + case MULTIPART_EVENT_FILE_START:
8550 + if(*tracking_key) {
8551 + multipart_event_file_start *data = (multipart_event_file_start *) event_data;
8552 +
8553 + bytes_processed = data->post_bytes_processed;
8554 + strncpy(filename,*data->filename,127);
8555 + temp_filename = NULL;
8556 + strncpy(name,data->name,63);
8557 + ALLOC_INIT_ZVAL(track);
8558 + array_init(track);
8559 + add_assoc_long(track, "total", content_length);
8560 + add_assoc_long(track, "current", bytes_processed);
8561 + add_assoc_string(track, "filename", filename, 1);
8562 + add_assoc_string(track, "name", name, 1);
8563 + add_assoc_long(track, "done", 0);
8564 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8565 + zval_ptr_dtor(&track);
8566 + }
8567 + break;
8568 +
8569 + case MULTIPART_EVENT_FILE_DATA:
8570 + if(*tracking_key) {
8571 + multipart_event_file_data *data = (multipart_event_file_data *) event_data;
8572 + bytes_processed = data->post_bytes_processed;
8573 + ALLOC_INIT_ZVAL(track);
8574 + array_init(track);
8575 + add_assoc_long(track, "total", content_length);
8576 + add_assoc_long(track, "current", bytes_processed);
8577 + add_assoc_string(track, "filename", filename, 1);
8578 + add_assoc_string(track, "name", name, 1);
8579 + add_assoc_long(track, "done", 0);
8580 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8581 + zval_ptr_dtor(&track);
8582 + }
8583 + break;
8584 +
8585 + case MULTIPART_EVENT_FILE_END:
8586 + if(*tracking_key) {
8587 + multipart_event_file_end *data = (multipart_event_file_end *) event_data;
8588 + bytes_processed = data->post_bytes_processed;
8589 + cancel_upload = data->cancel_upload;
8590 + temp_filename = data->temp_filename;
8591 + ALLOC_INIT_ZVAL(track);
8592 + array_init(track);
8593 + add_assoc_long(track, "total", content_length);
8594 + add_assoc_long(track, "current", bytes_processed);
8595 + add_assoc_string(track, "filename", filename, 1);
8596 + add_assoc_string(track, "name", name, 1);
8597 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8598 + add_assoc_long(track, "cancel_upload", cancel_upload);
8599 + add_assoc_long(track, "done", 0);
8600 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8601 + zval_ptr_dtor(&track);
8602 + }
8603 + break;
8604 +
8605 + case MULTIPART_EVENT_END:
8606 + if(*tracking_key) {
8607 + double now = my_time();
8608 + multipart_event_end *data = (multipart_event_end *) event_data;
8609 + bytes_processed = data->post_bytes_processed;
8610 + if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
8611 + else rate = 8.0*bytes_processed; /* Too quick */
8612 + ALLOC_INIT_ZVAL(track);
8613 + array_init(track);
8614 + add_assoc_long(track, "total", content_length);
8615 + add_assoc_long(track, "current", bytes_processed);
8616 + add_assoc_double(track, "rate", rate);
8617 + add_assoc_string(track, "filename", filename, 1);
8618 + add_assoc_string(track, "name", name, 1);
8619 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8620 + add_assoc_long(track, "cancel_upload", cancel_upload);
8621 + add_assoc_long(track, "done", 1);
8622 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8623 + zval_ptr_dtor(&track);
8624 + }
8625 + break;
8626 + }
8627 +}
8628 +
8629 +#endif
8630 +/*
8631 + * Local variables:
8632 + * tab-width: 4
8633 + * c-basic-offset: 4
8634 + * End:
8635 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8636 + * vim<600: expandtab sw=4 ts=4 sts=4
8637 + */
8638 Index: php-5.2.4/ext/apc/apc_sem.c
8639 ===================================================================
8640 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8641 +++ php-5.2.4/ext/apc/apc_sem.c 2007-09-02 12:24:46.000000000 +0200
8642 @@ -0,0 +1,177 @@
8643 +/*
8644 + +----------------------------------------------------------------------+
8645 + | APC |
8646 + +----------------------------------------------------------------------+
8647 + | Copyright (c) 2006 The PHP Group |
8648 + +----------------------------------------------------------------------+
8649 + | This source file is subject to version 3.01 of the PHP license, |
8650 + | that is bundled with this package in the file LICENSE, and is |
8651 + | available through the world-wide-web at the following url: |
8652 + | http://www.php.net/license/3_01.txt |
8653 + | If you did not receive a copy of the PHP license and are unable to |
8654 + | obtain it through the world-wide-web, please send a note to |
8655 + | license@php.net so we can mail you a copy immediately. |
8656 + +----------------------------------------------------------------------+
8657 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8658 + +----------------------------------------------------------------------+
8659 +
8660 + This software was contributed to PHP by Community Connect Inc. in 2002
8661 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8662 + Future revisions and derivatives of this source code must acknowledge
8663 + Community Connect Inc. as the original contributor of this module by
8664 + leaving this note intact in the source code.
8665 +
8666 + All other licensing and usage conditions are those of the PHP Group.
8667 +
8668 + */
8669 +
8670 +/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
8671 +
8672 +#include "apc_sem.h"
8673 +#include "apc.h"
8674 +#include "php.h"
8675 +#include <sys/types.h>
8676 +#include <sys/ipc.h>
8677 +#include <sys/sem.h>
8678 +#include <sys/stat.h>
8679 +#include <unistd.h>
8680 +
8681 +#if HAVE_SEMUN
8682 +/* we have semun, no need to define */
8683 +#else
8684 +#undef HAVE_SEMUN
8685 +union semun {
8686 + int val; /* value for SETVAL */
8687 + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
8688 + unsigned short *array; /* array for GETALL, SETALL */
8689 + /* Linux specific part: */
8690 + struct seminfo *__buf; /* buffer for IPC_INFO */
8691 +};
8692 +#define HAVE_SEMUN 1
8693 +#endif
8694 +
8695 +#ifndef SEM_R
8696 +# define SEM_R 0444
8697 +#endif
8698 +#ifndef SEM_A
8699 +# define SEM_A 0222
8700 +#endif
8701 +
8702 +/* always use SEM_UNDO, otherwise we risk deadlock */
8703 +#define USE_SEM_UNDO
8704 +
8705 +#ifdef USE_SEM_UNDO
8706 +# define UNDO SEM_UNDO
8707 +#else
8708 +# define UNDO 0
8709 +#endif
8710 +
8711 +int apc_sem_create(const char* pathname, int proj, int initval)
8712 +{
8713 + int semid;
8714 + int perms;
8715 + union semun arg;
8716 + key_t key;
8717 +
8718 + perms = 0777;
8719 +
8720 + key = IPC_PRIVATE;
8721 + if (pathname != NULL) {
8722 + if ((key = ftok(pathname, proj)) < 0) {
8723 + apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
8724 + }
8725 + }
8726 +
8727 + if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
8728 + /* sempahore created for the first time, initialize now */
8729 + arg.val = initval;
8730 + if (semctl(semid, 0, SETVAL, arg) < 0) {
8731 + apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
8732 + }
8733 + }
8734 + else if (errno == EEXIST) {
8735 + /* sempahore already exists, don't initialize */
8736 + if ((semid = semget(key, 1, perms)) < 0) {
8737 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8738 + }
8739 + /* insert <sleazy way to avoid race condition> here */
8740 + }
8741 + else {
8742 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8743 + }
8744 +
8745 + return semid;
8746 +}
8747 +
8748 +void apc_sem_destroy(int semid)
8749 +{
8750 + /* we expect this call to fail often, so we do not check */
8751 + union semun arg;
8752 + semctl(semid, 0, IPC_RMID, arg);
8753 +}
8754 +
8755 +void apc_sem_lock(int semid)
8756 +{
8757 + struct sembuf op;
8758 +
8759 + op.sem_num = 0;
8760 + op.sem_op = -1;
8761 + op.sem_flg = UNDO;
8762 +
8763 + if (semop(semid, &op, 1) < 0) {
8764 + if (errno != EINTR) {
8765 + apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
8766 + }
8767 + }
8768 +}
8769 +
8770 +void apc_sem_unlock(int semid)
8771 +{
8772 + struct sembuf op;
8773 +
8774 + op.sem_num = 0;
8775 + op.sem_op = 1;
8776 + op.sem_flg = UNDO;
8777 +
8778 + if (semop(semid, &op, 1) < 0) {
8779 + if (errno != EINTR) {
8780 + apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
8781 + }
8782 + }
8783 +}
8784 +
8785 +void apc_sem_wait_for_zero(int semid)
8786 +{
8787 + struct sembuf op;
8788 +
8789 + op.sem_num = 0;
8790 + op.sem_op = 0;
8791 + op.sem_flg = UNDO;
8792 +
8793 + if (semop(semid, &op, 1) < 0) {
8794 + if (errno != EINTR) {
8795 + apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
8796 + }
8797 + }
8798 +}
8799 +
8800 +int apc_sem_get_value(int semid)
8801 +{
8802 + union semun arg;
8803 + unsigned short val[1];
8804 +
8805 + arg.array = val;
8806 + if (semctl(semid, 0, GETALL, arg) < 0) {
8807 + apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
8808 + }
8809 + return val[0];
8810 +}
8811 +
8812 +/*
8813 + * Local variables:
8814 + * tab-width: 4
8815 + * c-basic-offset: 4
8816 + * End:
8817 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8818 + * vim<600: expandtab sw=4 ts=4 sts=4
8819 + */
8820 Index: php-5.2.4/ext/apc/apc_sem.h
8821 ===================================================================
8822 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8823 +++ php-5.2.4/ext/apc/apc_sem.h 2007-09-02 12:24:46.000000000 +0200
8824 @@ -0,0 +1,51 @@
8825 +/*
8826 + +----------------------------------------------------------------------+
8827 + | APC |
8828 + +----------------------------------------------------------------------+
8829 + | Copyright (c) 2006 The PHP Group |
8830 + +----------------------------------------------------------------------+
8831 + | This source file is subject to version 3.01 of the PHP license, |
8832 + | that is bundled with this package in the file LICENSE, and is |
8833 + | available through the world-wide-web at the following url: |
8834 + | http://www.php.net/license/3_01.txt |
8835 + | If you did not receive a copy of the PHP license and are unable to |
8836 + | obtain it through the world-wide-web, please send a note to |
8837 + | license@php.net so we can mail you a copy immediately. |
8838 + +----------------------------------------------------------------------+
8839 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8840 + +----------------------------------------------------------------------+
8841 +
8842 + This software was contributed to PHP by Community Connect Inc. in 2002
8843 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8844 + Future revisions and derivatives of this source code must acknowledge
8845 + Community Connect Inc. as the original contributor of this module by
8846 + leaving this note intact in the source code.
8847 +
8848 + All other licensing and usage conditions are those of the PHP Group.
8849 +
8850 + */
8851 +
8852 +/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8853 +
8854 +#ifndef APC_SEM_H
8855 +#define APC_SEM_H
8856 +
8857 +/* Wrapper functions for SysV sempahores */
8858 +
8859 +extern int apc_sem_create(const char* pathname, int proj, int initval);
8860 +extern void apc_sem_destroy(int semid);
8861 +extern void apc_sem_lock(int semid);
8862 +extern void apc_sem_unlock(int semid);
8863 +extern void apc_sem_wait_for_zero(int semid);
8864 +extern int apc_sem_get_value(int semid);
8865 +
8866 +#endif
8867 +
8868 +/*
8869 + * Local variables:
8870 + * tab-width: 4
8871 + * c-basic-offset: 4
8872 + * End:
8873 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8874 + * vim<600: expandtab sw=4 ts=4 sts=4
8875 + */
8876 Index: php-5.2.4/ext/apc/apc_shm.c
8877 ===================================================================
8878 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8879 +++ php-5.2.4/ext/apc/apc_shm.c 2007-09-02 12:24:46.000000000 +0200
8880 @@ -0,0 +1,111 @@
8881 +/*
8882 + +----------------------------------------------------------------------+
8883 + | APC |
8884 + +----------------------------------------------------------------------+
8885 + | Copyright (c) 2006 The PHP Group |
8886 + +----------------------------------------------------------------------+
8887 + | This source file is subject to version 3.01 of the PHP license, |
8888 + | that is bundled with this package in the file LICENSE, and is |
8889 + | available through the world-wide-web at the following url: |
8890 + | http://www.php.net/license/3_01.txt |
8891 + | If you did not receive a copy of the PHP license and are unable to |
8892 + | obtain it through the world-wide-web, please send a note to |
8893 + | license@php.net so we can mail you a copy immediately. |
8894 + +----------------------------------------------------------------------+
8895 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8896 + | Rasmus Lerdorf <rasmus@php.net> |
8897 + +----------------------------------------------------------------------+
8898 +
8899 + This software was contributed to PHP by Community Connect Inc. in 2002
8900 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8901 + Future revisions and derivatives of this source code must acknowledge
8902 + Community Connect Inc. as the original contributor of this module by
8903 + leaving this note intact in the source code.
8904 +
8905 + All other licensing and usage conditions are those of the PHP Group.
8906 +
8907 + */
8908 +
8909 +/* $Id: apc_shm.c,v 3.10 2006/05/31 22:24:48 rasmus Exp $ */
8910 +
8911 +#include "apc_shm.h"
8912 +#include "apc.h"
8913 +#include <sys/types.h>
8914 +#ifdef PHP_WIN32
8915 +/* shm functions are available in TSRM */
8916 +#include <tsrm/tsrm_win32.h>
8917 +#define key_t long
8918 +#else
8919 +#include <sys/ipc.h>
8920 +#include <sys/shm.h>
8921 +#include <sys/stat.h>
8922 +#endif
8923 +
8924 +#ifndef SHM_R
8925 +# define SHM_R 0444 /* read permission */
8926 +#endif
8927 +#ifndef SHM_A
8928 +# define SHM_A 0222 /* write permission */
8929 +#endif
8930 +
8931 +int apc_shm_create(const char* pathname, int proj, int size)
8932 +{
8933 + int shmid; /* shared memory id */
8934 + int oflag; /* permissions on shm */
8935 + key_t key; /* shm key returned by ftok */
8936 +
8937 + key = IPC_PRIVATE;
8938 +#ifndef PHP_WIN32
8939 + /* no ftok yet for win32 */
8940 + if (pathname != NULL) {
8941 + if ((key = ftok(pathname, proj)) < 0) {
8942 + apc_eprint("apc_shm_create: ftok failed:");
8943 + }
8944 + }
8945 +#endif
8946 +
8947 + oflag = IPC_CREAT | SHM_R | SHM_A;
8948 + if ((shmid = shmget(key, size, oflag)) < 0) {
8949 + 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));
8950 + }
8951 +
8952 + return shmid;
8953 +}
8954 +
8955 +void apc_shm_destroy(int shmid)
8956 +{
8957 + /* we expect this call to fail often, so we do not check */
8958 + shmctl(shmid, IPC_RMID, 0);
8959 +}
8960 +
8961 +void* apc_shm_attach(int shmid)
8962 +{
8963 + void* shmaddr; /* the shared memory address */
8964 +
8965 + if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
8966 + apc_eprint("apc_shm_attach: shmat failed:");
8967 + }
8968 +
8969 + /*
8970 + * We set the shmid for removal immediately after attaching to it. The
8971 + * segment won't disappear until all processes have detached from it.
8972 + */
8973 + apc_shm_destroy(shmid);
8974 + return shmaddr;
8975 +}
8976 +
8977 +void apc_shm_detach(void* shmaddr)
8978 +{
8979 + if (shmdt(shmaddr) < 0) {
8980 + apc_eprint("apc_shm_detach: shmdt failed:");
8981 + }
8982 +}
8983 +
8984 +/*
8985 + * Local variables:
8986 + * tab-width: 4
8987 + * c-basic-offset: 4
8988 + * End:
8989 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8990 + * vim<600: expandtab sw=4 ts=4 sts=4
8991 + */
8992 Index: php-5.2.4/ext/apc/apc_shm.h
8993 ===================================================================
8994 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8995 +++ php-5.2.4/ext/apc/apc_shm.h 2007-09-02 12:24:46.000000000 +0200
8996 @@ -0,0 +1,49 @@
8997 +/*
8998 + +----------------------------------------------------------------------+
8999 + | APC |
9000 + +----------------------------------------------------------------------+
9001 + | Copyright (c) 2006 The PHP Group |
9002 + +----------------------------------------------------------------------+
9003 + | This source file is subject to version 3.01 of the PHP license, |
9004 + | that is bundled with this package in the file LICENSE, and is |
9005 + | available through the world-wide-web at the following url: |
9006 + | http://www.php.net/license/3_01.txt |
9007 + | If you did not receive a copy of the PHP license and are unable to |
9008 + | obtain it through the world-wide-web, please send a note to |
9009 + | license@php.net so we can mail you a copy immediately. |
9010 + +----------------------------------------------------------------------+
9011 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9012 + +----------------------------------------------------------------------+
9013 +
9014 + This software was contributed to PHP by Community Connect Inc. in 2002
9015 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9016 + Future revisions and derivatives of this source code must acknowledge
9017 + Community Connect Inc. as the original contributor of this module by
9018 + leaving this note intact in the source code.
9019 +
9020 + All other licensing and usage conditions are those of the PHP Group.
9021 +
9022 + */
9023 +
9024 +/* $Id: apc_shm.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
9025 +
9026 +#ifndef APC_SHM_H
9027 +#define APC_SHM_H
9028 +
9029 +/* Wrapper functions for unix shared memory */
9030 +
9031 +extern int apc_shm_create(const char* name, int proj, int size);
9032 +extern void apc_shm_destroy(int shmid);
9033 +extern void* apc_shm_attach(int shmid);
9034 +extern void apc_shm_detach(void* shmaddr);
9035 +
9036 +#endif
9037 +
9038 +/*
9039 + * Local variables:
9040 + * tab-width: 4
9041 + * c-basic-offset: 4
9042 + * End:
9043 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9044 + * vim<600: expandtab sw=4 ts=4 sts=4
9045 + */
9046 Index: php-5.2.4/ext/apc/apc_sma.c
9047 ===================================================================
9048 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9049 +++ php-5.2.4/ext/apc/apc_sma.c 2007-09-02 12:24:46.000000000 +0200
9050 @@ -0,0 +1,624 @@
9051 +/*
9052 + +----------------------------------------------------------------------+
9053 + | APC |
9054 + +----------------------------------------------------------------------+
9055 + | Copyright (c) 2006 The PHP Group |
9056 + +----------------------------------------------------------------------+
9057 + | This source file is subject to version 3.01 of the PHP license, |
9058 + | that is bundled with this package in the file LICENSE, and is |
9059 + | available through the world-wide-web at the following url: |
9060 + | http://www.php.net/license/3_01.txt |
9061 + | If you did not receive a copy of the PHP license and are unable to |
9062 + | obtain it through the world-wide-web, please send a note to |
9063 + | license@php.net so we can mail you a copy immediately. |
9064 + +----------------------------------------------------------------------+
9065 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9066 + | Rasmus Lerdorf <rasmus@php.net> |
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_sma.c,v 1.63 2007/04/02 09:02:57 gopalv Exp $ */
9080 +
9081 +#include "apc_sma.h"
9082 +#include "apc.h"
9083 +#include "apc_globals.h"
9084 +#include "apc_lock.h"
9085 +#include "apc_shm.h"
9086 +#include <limits.h>
9087 +#if APC_MMAP
9088 +void *apc_mmap(char *file_mask, int size);
9089 +void apc_unmap(void* shmaddr, int size);
9090 +#endif
9091 +
9092 +/* {{{ locking macros */
9093 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
9094 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
9095 +#define UNLOCK(c) { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
9096 +/* }}} */
9097 +
9098 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
9099 +
9100 +static int sma_initialized = 0; /* true if the sma has been initialized */
9101 +static unsigned int sma_numseg; /* number of shm segments to allow */
9102 +static size_t sma_segsize; /* size of each shm segment */
9103 +static int* sma_segments; /* array of shm segment ids */
9104 +static void** sma_shmaddrs; /* array of shm segment addresses */
9105 +static int sma_lastseg = 0; /* index of MRU segment */
9106 +
9107 +typedef struct header_t header_t;
9108 +struct header_t {
9109 + apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */
9110 + size_t segsize; /* size of entire segment */
9111 + size_t avail; /* bytes available (not necessarily contiguous) */
9112 + size_t nfoffset; /* start next fit search from this offset */
9113 +#if ALLOC_DISTRIBUTION
9114 + size_t adist[30];
9115 +#endif
9116 +};
9117 +
9118 +
9119 +/* do not enable for threaded http servers */
9120 +/* #define __APC_SMA_DEBUG__ 1 */
9121 +
9122 +#ifdef __APC_SMA_DEBUG__
9123 +/* global counter for identifying blocks
9124 + * Technically it is possible to do the same
9125 + * using offsets, but double allocations of the
9126 + * same offset can happen. */
9127 +static volatile size_t block_id = 0;
9128 +#endif
9129 +
9130 +#define APC_SMA_CANARIES 1
9131 +
9132 +typedef struct block_t block_t;
9133 +struct block_t {
9134 + size_t size; /* size of this block */
9135 + size_t next; /* offset in segment of next free block */
9136 +#ifdef APC_SMA_CANARIES
9137 + size_t canary; /* canary to check for memory overwrites */
9138 +#endif
9139 +#ifdef __APC_SMA_DEBUG__
9140 + size_t id; /* identifier for the memory block */
9141 +#endif
9142 +};
9143 +
9144 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
9145 + * module. Both assume the presence of a variable shmaddr that points to the
9146 + * beginning of the shared memory segment in question. */
9147 +
9148 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
9149 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
9150 +
9151 +/* Canary macros for setting, checking and resetting memory canaries */
9152 +#ifdef APC_SMA_CANARIES
9153 + #define SET_CANARY(v) (v)->canary = 0x42424242
9154 + #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
9155 + #define RESET_CANARY(v) (v)->canary = -42
9156 +#else
9157 + #define SET_CANARY(v)
9158 + #define CHECK_CANARY(v)
9159 + #define RESET_CANARY(v)
9160 +#endif
9161 +
9162 +
9163 +#ifdef max
9164 +#undef max
9165 +#endif
9166 +#define max(a, b) ((a) > (b) ? (a) : (b))
9167 +
9168 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
9169 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
9170 +#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
9171 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
9172 +/* }}} */
9173 +
9174 +/* {{{ sma_allocate: tries to allocate size bytes in a segment */
9175 +static int sma_allocate(void* shmaddr, size_t size)
9176 +{
9177 + header_t* header; /* header of shared memory segment */
9178 + block_t* prv; /* block prior to working block */
9179 + block_t* cur; /* working block in list */
9180 + block_t* prvnextfit; /* block before next fit */
9181 + size_t realsize; /* actual size of block needed, including header */
9182 + size_t last_offset; /* save the last search offset */
9183 + int wrapped=0;
9184 + const size_t block_size = ALIGNWORD(sizeof(struct block_t));
9185 +
9186 + realsize = ALIGNWORD(size + block_size);
9187 +
9188 + /*
9189 + * First, insure that the segment contains at least realsize free bytes,
9190 + * even if they are not contiguous.
9191 + */
9192 + header = (header_t*) shmaddr;
9193 + if (header->avail < realsize) {
9194 + return -1;
9195 + }
9196 +
9197 + prvnextfit = 0; /* initially null (no fit) */
9198 + last_offset = 0;
9199 +
9200 + /* If we have a next fit offset, start searching from there */
9201 + if(header->nfoffset) {
9202 + prv = BLOCKAT(header->nfoffset);
9203 + } else {
9204 + prv = BLOCKAT(sizeof(header_t));
9205 + }
9206 +
9207 + CHECK_CANARY(prv);
9208 +
9209 + while (prv->next != header->nfoffset) {
9210 + cur = BLOCKAT(prv->next);
9211 +#ifdef __APC_SMA_DEBUG__
9212 + CHECK_CANARY(cur);
9213 +#endif
9214 + /* If it can fit realiszie bytes in cur block, stop searching */
9215 + if (cur->size >= realsize) {
9216 + prvnextfit = prv;
9217 + break;
9218 + }
9219 + last_offset = prv->next;
9220 + prv = cur;
9221 + if(wrapped && (prv->next >= header->nfoffset)) break;
9222 +
9223 + /* Check to see if we need to wrap around and search from the top */
9224 + if(header->nfoffset && prv->next == 0) {
9225 + prv = BLOCKAT(sizeof(header_t));
9226 +#ifdef __APC_SMA_DEBUG__
9227 + CHECK_CANARY(prv);
9228 +#endif
9229 + last_offset = 0;
9230 + wrapped = 1;
9231 + }
9232 + }
9233 +
9234 + if (prvnextfit == 0) {
9235 + header->nfoffset = 0;
9236 + return -1;
9237 + }
9238 +
9239 + prv = prvnextfit;
9240 + cur = BLOCKAT(prv->next);
9241 +
9242 + CHECK_CANARY(prv);
9243 + CHECK_CANARY(cur);
9244 +
9245 + if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
9246 + /* cur is big enough for realsize, but too small to split - unlink it */
9247 + prv->next = cur->next;
9248 + }
9249 + else {
9250 + block_t* nxt; /* the new block (chopped part of cur) */
9251 + size_t nxtoffset; /* offset of the block currently after cur */
9252 + size_t oldsize; /* size of cur before split */
9253 +
9254 + /* nextfit is too big; split it into two smaller blocks */
9255 + nxtoffset = cur->next;
9256 + oldsize = cur->size;
9257 + prv->next += realsize; /* skip over newly allocated block */
9258 + cur->size = realsize; /* Set the size of this new block */
9259 + nxt = BLOCKAT(prv->next);
9260 + nxt->next = nxtoffset; /* Re-link the shortened block */
9261 + nxt->size = oldsize - realsize; /* and fix the size */
9262 + SET_CANARY(nxt);
9263 +#ifdef __APC_SMA_DEBUG__
9264 + nxt->id = -1;
9265 +#endif
9266 + }
9267 +
9268 + /* update the block header */
9269 + header->avail -= cur->size;
9270 +#if ALLOC_DISTRIBUTION
9271 + header->adist[(int)(log(size)/log(2))]++;
9272 +#endif
9273 +
9274 + header->nfoffset = last_offset;
9275 +
9276 + SET_CANARY(cur);
9277 +#ifdef __APC_SMA_DEBUG__
9278 + cur->id = ++block_id;
9279 + fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
9280 +#endif
9281 +
9282 + return OFFSET(cur) + block_size;
9283 +}
9284 +/* }}} */
9285 +
9286 +/* {{{ sma_deallocate: deallocates the block at the given offset */
9287 +static int sma_deallocate(void* shmaddr, int offset)
9288 +{
9289 + header_t* header; /* header of shared memory segment */
9290 + block_t* cur; /* the new block to insert */
9291 + block_t* prv; /* the block before cur */
9292 + block_t* nxt; /* the block after cur */
9293 + size_t size; /* size of deallocated block */
9294 +
9295 + offset -= ALIGNWORD(sizeof(struct block_t));
9296 + assert(offset >= 0);
9297 +
9298 + /* find position of new block in free list */
9299 + cur = BLOCKAT(offset);
9300 + prv = BLOCKAT(sizeof(header_t));
9301 +
9302 + CHECK_CANARY(cur);
9303 +
9304 +#ifdef __APC_SMA_DEBUG__
9305 + CHECK_CANARY(prv);
9306 + fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
9307 +#endif
9308 + while (prv->next != 0 && prv->next < offset) {
9309 + prv = BLOCKAT(prv->next);
9310 +#ifdef __APC_SMA_DEBUG__
9311 + CHECK_CANARY(prv);
9312 +#endif
9313 + }
9314 +
9315 + CHECK_CANARY(prv);
9316 +
9317 + /* insert new block after prv */
9318 + cur->next = prv->next;
9319 + prv->next = offset;
9320 +
9321 +#ifdef __APC_SMA_DEBUG__
9322 + CHECK_CANARY(cur);
9323 + cur->id = -1;
9324 +#endif
9325 +
9326 + /* update the block header */
9327 + header = (header_t*) shmaddr;
9328 + header->avail += cur->size;
9329 + size = cur->size;
9330 +
9331 + if (((char *)prv) + prv->size == (char *) cur) {
9332 + /* cur and prv share an edge, combine them */
9333 + prv->size += cur->size;
9334 + prv->next = cur->next;
9335 + RESET_CANARY(cur);
9336 + cur = prv;
9337 + }
9338 +
9339 + nxt = BLOCKAT(cur->next);
9340 +
9341 + if (((char *)cur) + cur->size == (char *) nxt) {
9342 + /* cur and nxt shared an edge, combine them */
9343 + cur->size += nxt->size;
9344 + cur->next = nxt->next;
9345 +#ifdef __APC_SMA_DEBUG__
9346 + CHECK_CANARY(nxt);
9347 + nxt->id = -1; /* assert this or set it ? */
9348 +#endif
9349 + RESET_CANARY(nxt);
9350 + }
9351 + header->nfoffset = 0; /* Reset the next fit search marker */
9352 +
9353 + return size;
9354 +}
9355 +/* }}} */
9356 +
9357 +/* {{{ apc_sma_init */
9358 +
9359 +void apc_sma_init(int numseg, int segsize, char *mmap_file_mask)
9360 +{
9361 + int i;
9362 +
9363 + if (sma_initialized) {
9364 + return;
9365 + }
9366 + sma_initialized = 1;
9367 +
9368 +#if APC_MMAP
9369 + /*
9370 + * I don't think multiple anonymous mmaps makes any sense
9371 + * so force sma_numseg to 1 in this case
9372 + */
9373 + if(!mmap_file_mask ||
9374 + (mmap_file_mask && !strlen(mmap_file_mask)) ||
9375 + (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
9376 + sma_numseg = 1;
9377 + } else {
9378 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9379 + }
9380 +#else
9381 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9382 +#endif
9383 +
9384 + sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
9385 +
9386 + sma_segments = (int*) apc_emalloc(sma_numseg*sizeof(int));
9387 + sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
9388 +
9389 + for (i = 0; i < sma_numseg; i++) {
9390 + header_t* header;
9391 + block_t* block;
9392 + void* shmaddr;
9393 +
9394 +#if APC_MMAP
9395 + sma_segments[i] = sma_segsize;
9396 + sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
9397 + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
9398 +#else
9399 + sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
9400 + sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
9401 +#endif
9402 + shmaddr = sma_shmaddrs[i];
9403 +
9404 + header = (header_t*) shmaddr;
9405 + apc_lck_create(NULL, 0, 1, header->sma_lock);
9406 + header->segsize = sma_segsize;
9407 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) -
9408 + ALIGNWORD(sizeof(int));
9409 + header->nfoffset = 0;
9410 +#if ALLOC_DISTRIBUTION
9411 + {
9412 + int j;
9413 + for(j=0; j<30; j++) header->adist[j] = 0;
9414 + }
9415 +#endif
9416 + block = BLOCKAT(sizeof(header_t));
9417 + block->size = 0;
9418 + block->next = sizeof(header_t) + sizeof(block_t);
9419 + SET_CANARY(block);
9420 +#ifdef __APC_SMA_DEBUG__
9421 + block->id = -1;
9422 +#endif
9423 + block = BLOCKAT(block->next);
9424 + block->size = header->avail;
9425 + block->next = 0;
9426 + SET_CANARY(block);
9427 +#ifdef __APC_SMA_DEBUG__
9428 + block->id = -1;
9429 +#endif
9430 + }
9431 +}
9432 +/* }}} */
9433 +
9434 +/* {{{ apc_sma_cleanup */
9435 +void apc_sma_cleanup()
9436 +{
9437 + int i;
9438 +
9439 + assert(sma_initialized);
9440 +
9441 + for (i = 0; i < sma_numseg; i++) {
9442 + apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
9443 +#if APC_MMAP
9444 + apc_unmap(sma_shmaddrs[i], sma_segments[i]);
9445 +#else
9446 + apc_shm_detach(sma_shmaddrs[i]);
9447 +#endif
9448 + }
9449 + sma_initialized = 0;
9450 + apc_efree(sma_segments);
9451 + apc_efree(sma_shmaddrs);
9452 +}
9453 +/* }}} */
9454 +
9455 +/* {{{ apc_sma_malloc */
9456 +void* apc_sma_malloc(size_t n)
9457 +{
9458 + int off;
9459 + int i;
9460 +
9461 + TSRMLS_FETCH();
9462 + assert(sma_initialized);
9463 + LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9464 +
9465 + off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
9466 + if (off != -1) {
9467 + void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
9468 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9469 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9470 + return p;
9471 + }
9472 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9473 +
9474 + for (i = 0; i < sma_numseg; i++) {
9475 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9476 + if (i == sma_lastseg) {
9477 + continue;
9478 + }
9479 + off = sma_allocate(sma_shmaddrs[i], n);
9480 + if (off != -1) {
9481 + void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
9482 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9483 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9484 + sma_lastseg = i;
9485 + return p;
9486 + }
9487 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9488 + }
9489 +
9490 + return NULL;
9491 +}
9492 +/* }}} */
9493 +
9494 +/* {{{ apc_sma_realloc */
9495 +void* apc_sma_realloc(void *p, size_t n)
9496 +{
9497 + apc_sma_free(p);
9498 + return apc_sma_malloc(n);
9499 +}
9500 +/* }}} */
9501 +
9502 +/* {{{ apc_sma_strdup */
9503 +char* apc_sma_strdup(const char* s)
9504 +{
9505 + void* q;
9506 + int len;
9507 +
9508 + if(!s) return NULL;
9509 +
9510 + len = strlen(s)+1;
9511 + q = apc_sma_malloc(len);
9512 + if(!q) return NULL;
9513 + memcpy(q, s, len);
9514 + return q;
9515 +}
9516 +/* }}} */
9517 +
9518 +/* {{{ apc_sma_free */
9519 +void apc_sma_free(void* p)
9520 +{
9521 + int i;
9522 + size_t offset;
9523 + size_t d_size;
9524 + TSRMLS_FETCH();
9525 +
9526 + if (p == NULL) {
9527 + return;
9528 + }
9529 +
9530 + assert(sma_initialized);
9531 +
9532 + for (i = 0; i < sma_numseg; i++) {
9533 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9534 + offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
9535 + if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
9536 + d_size = sma_deallocate(sma_shmaddrs[i], offset);
9537 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
9538 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9539 + return;
9540 + }
9541 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9542 + }
9543 +
9544 + apc_eprint("apc_sma_free: could not locate address %p", p);
9545 +}
9546 +/* }}} */
9547 +
9548 +/* {{{ apc_sma_info */
9549 +apc_sma_info_t* apc_sma_info(zend_bool limited)
9550 +{
9551 + apc_sma_info_t* info;
9552 + apc_sma_link_t** link;
9553 + int i;
9554 + char* shmaddr;
9555 + block_t* prv;
9556 +
9557 + if (!sma_initialized) {
9558 + return NULL;
9559 + }
9560 +
9561 + info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
9562 + info->num_seg = sma_numseg;
9563 + info->seg_size = sma_segsize - sizeof(header_t) - sizeof(block_t) - ALIGNWORD(sizeof(int));
9564 +
9565 + info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
9566 + for (i = 0; i < sma_numseg; i++) {
9567 + info->list[i] = NULL;
9568 + }
9569 +
9570 + if(limited) return info;
9571 +
9572 + /* For each segment */
9573 + for (i = 0; i < sma_numseg; i++) {
9574 + RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9575 + shmaddr = sma_shmaddrs[i];
9576 + prv = BLOCKAT(sizeof(header_t));
9577 +
9578 + link = &info->list[i];
9579 +
9580 + /* For each block in this segment */
9581 + while (prv->next != 0) {
9582 + block_t* cur = BLOCKAT(prv->next);
9583 +#ifdef __APC_SMA_DEBUG__
9584 + CHECK_CANARY(cur);
9585 +#endif
9586 +
9587 + *link = apc_emalloc(sizeof(apc_sma_link_t));
9588 + (*link)->size = cur->size;
9589 + (*link)->offset = prv->next;
9590 + (*link)->next = NULL;
9591 + link = &(*link)->next;
9592 +
9593 + prv = cur;
9594 + }
9595 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9596 + }
9597 +
9598 + return info;
9599 +}
9600 +/* }}} */
9601 +
9602 +/* {{{ apc_sma_free_info */
9603 +void apc_sma_free_info(apc_sma_info_t* info)
9604 +{
9605 + int i;
9606 +
9607 + for (i = 0; i < info->num_seg; i++) {
9608 + apc_sma_link_t* p = info->list[i];
9609 + while (p) {
9610 + apc_sma_link_t* q = p;
9611 + p = p->next;
9612 + apc_efree(q);
9613 + }
9614 + }
9615 + apc_efree(info->list);
9616 + apc_efree(info);
9617 +}
9618 +/* }}} */
9619 +
9620 +/* {{{ apc_sma_get_avail_mem */
9621 +int apc_sma_get_avail_mem()
9622 +{
9623 + int avail_mem = 0;
9624 + int i;
9625 +
9626 + for (i = 0; i < sma_numseg; i++) {
9627 + header_t* header = (header_t*) sma_shmaddrs[i];
9628 + avail_mem += header->avail;
9629 + }
9630 + return avail_mem;
9631 +}
9632 +/* }}} */
9633 +
9634 +#if ALLOC_DISTRIBUTION
9635 +size_t *apc_sma_get_alloc_distribution(void) {
9636 + header_t* header = (header_t*) sma_shmaddrs[0];
9637 + return header->adist;
9638 +}
9639 +#endif
9640 +
9641 +#if 0
9642 +/* {{{ apc_sma_check_integrity */
9643 +void apc_sma_check_integrity()
9644 +{
9645 + int i;
9646 +
9647 + /* For each segment */
9648 + for (i = 0; i < sma_numseg; i++) {
9649 + char* shmaddr = sma_shmaddrs[i];
9650 + header_t* header = (header_t*) shmaddr;
9651 + block_t* prv = BLOCKAT(sizeof(header_t));
9652 + int avail = 0;
9653 +
9654 + /* For each block in this segment */
9655 + while (prv->next != 0) {
9656 + block_t* cur = BLOCKAT(prv->next);
9657 + avail += cur->size;
9658 + prv = cur;
9659 + }
9660 +
9661 + assert(avail == header->avail);
9662 + }
9663 +}
9664 +/* }}} */
9665 +#endif
9666 +
9667 +/*
9668 + * Local variables:
9669 + * tab-width: 4
9670 + * c-basic-offset: 4
9671 + * End:
9672 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9673 + * vim<600: expandtab sw=4 ts=4 sts=4
9674 + */
9675 Index: php-5.2.4/ext/apc/apc_sma.h
9676 ===================================================================
9677 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9678 +++ php-5.2.4/ext/apc/apc_sma.h 2007-09-02 12:24:46.000000000 +0200
9679 @@ -0,0 +1,82 @@
9680 +/*
9681 + +----------------------------------------------------------------------+
9682 + | APC |
9683 + +----------------------------------------------------------------------+
9684 + | Copyright (c) 2006 The PHP Group |
9685 + +----------------------------------------------------------------------+
9686 + | This source file is subject to version 3.01 of the PHP license, |
9687 + | that is bundled with this package in the file LICENSE, and is |
9688 + | available through the world-wide-web at the following url: |
9689 + | http://www.php.net/license/3_01.txt |
9690 + | If you did not receive a copy of the PHP license and are unable to |
9691 + | obtain it through the world-wide-web, please send a note to |
9692 + | license@php.net so we can mail you a copy immediately. |
9693 + +----------------------------------------------------------------------+
9694 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9695 + +----------------------------------------------------------------------+
9696 +
9697 + This software was contributed to PHP by Community Connect Inc. in 2002
9698 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9699 + Future revisions and derivatives of this source code must acknowledge
9700 + Community Connect Inc. as the original contributor of this module by
9701 + leaving this note intact in the source code.
9702 +
9703 + All other licensing and usage conditions are those of the PHP Group.
9704 +
9705 + */
9706 +
9707 +/* $Id: apc_sma.h,v 1.16 2007/02/24 11:59:40 rasmus Exp $ */
9708 +
9709 +#ifndef APC_SMA_H
9710 +#define APC_SMA_H
9711 +
9712 +#define ALLOC_DISTRIBUTION 0
9713 +
9714 +#include "apc.h"
9715 +
9716 +/* Simple shared memory allocator */
9717 +
9718 +extern void apc_sma_init(int numseg, int segsize, char *mmap_file_mask);
9719 +extern void apc_sma_cleanup();
9720 +extern void* apc_sma_malloc(size_t size);
9721 +extern void* apc_sma_realloc(void* p, size_t size);
9722 +extern char* apc_sma_strdup(const char *s);
9723 +extern void apc_sma_free(void* p);
9724 +#if ALLOC_DISTRIBUTION
9725 +extern size_t *apc_sma_get_alloc_distribution();
9726 +#endif
9727 +
9728 +/* {{{ struct definition: apc_sma_link_t */
9729 +typedef struct apc_sma_link_t apc_sma_link_t;
9730 +struct apc_sma_link_t {
9731 + int size; /* size of this free block */
9732 + int offset; /* offset in segment of this block */
9733 + apc_sma_link_t* next; /* link to next free block */
9734 +};
9735 +/* }}} */
9736 +
9737 +/* {{{ struct definition: apc_sma_info_t */
9738 +typedef struct apc_sma_info_t apc_sma_info_t;
9739 +struct apc_sma_info_t {
9740 + int num_seg; /* number of shared memory segments */
9741 + int seg_size; /* size of each shared memory segment */
9742 + apc_sma_link_t** list; /* there is one list per segment */
9743 +};
9744 +/* }}} */
9745 +
9746 +extern apc_sma_info_t* apc_sma_info(zend_bool limited);
9747 +extern void apc_sma_free_info(apc_sma_info_t* info);
9748 +
9749 +extern int apc_sma_get_avail_mem();
9750 +extern void apc_sma_check_integrity();
9751 +
9752 +#endif
9753 +
9754 +/*
9755 + * Local variables:
9756 + * tab-width: 4
9757 + * c-basic-offset: 4
9758 + * End:
9759 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9760 + * vim<600: expandtab sw=4 ts=4 sts=4
9761 + */
9762 Index: php-5.2.4/ext/apc/apc_spin.c
9763 ===================================================================
9764 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9765 +++ php-5.2.4/ext/apc/apc_spin.c 2007-09-02 12:24:46.000000000 +0200
9766 @@ -0,0 +1,65 @@
9767 +/*
9768 + +----------------------------------------------------------------------+
9769 + | APC |
9770 + +----------------------------------------------------------------------+
9771 + | Copyright (c) 2007 The PHP Group |
9772 + +----------------------------------------------------------------------+
9773 + | This source file is subject to version 3.01 of the PHP license, |
9774 + | that is bundled with this package in the file LICENSE, and is |
9775 + | available through the world-wide-web at the following url: |
9776 + | http://www.php.net/license/3_01.txt |
9777 + | If you did not receive a copy of the PHP license and are unable to |
9778 + | obtain it through the world-wide-web, please send a note to |
9779 + | license@php.net so we can mail you a copy immediately. |
9780 + +----------------------------------------------------------------------+
9781 + | Authors: Brian Shire <shire@php.net> |
9782 + +----------------------------------------------------------------------+
9783 +
9784 + */
9785 +
9786 +/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9787 +
9788 +#include "apc_spin.h"
9789 +
9790 +#ifdef APC_SPIN_LOCKS
9791 +
9792 +slock_t *apc_slock_create(slock_t *lock)
9793 +{
9794 + S_INIT_LOCK(lock);
9795 +}
9796 +
9797 +void apc_slock_destroy(slock_t *lock)
9798 +{
9799 + S_LOCK_FREE(lock);
9800 +}
9801 +
9802 +void apc_slock_lock(slock_t *lock)
9803 +{
9804 + S_LOCK(lock);
9805 +}
9806 +
9807 +void apc_slock_unlock(slock_t *lock)
9808 +{
9809 + S_UNLOCK(lock);
9810 +}
9811 +
9812 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
9813 +{
9814 + /* Technically we aren't supposed to call this directly, but the original
9815 + * code provides no method for absolute non-blocking locks, so we'll call into
9816 + * the TAS (test and set) functionality directly
9817 + */
9818 + return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */
9819 +}
9820 +
9821 +
9822 +#endif
9823 +
9824 +/*
9825 + * Local variables:
9826 + * tab-width: 4
9827 + * c-basic-offset: 4
9828 + * End:
9829 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9830 + * vim<600: expandtab sw=4 ts=4 sts=4
9831 + */
9832 Index: php-5.2.4/ext/apc/apc_spin.h
9833 ===================================================================
9834 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9835 +++ php-5.2.4/ext/apc/apc_spin.h 2007-09-02 12:24:46.000000000 +0200
9836 @@ -0,0 +1,48 @@
9837 +/*
9838 + +----------------------------------------------------------------------+
9839 + | APC |
9840 + +----------------------------------------------------------------------+
9841 + | Copyright (c) 2007 The PHP Group |
9842 + +----------------------------------------------------------------------+
9843 + | This source file is subject to version 3.01 of the PHP license, |
9844 + | that is bundled with this package in the file LICENSE, and is |
9845 + | available through the world-wide-web at the following url: |
9846 + | http://www.php.net/license/3_01.txt |
9847 + | If you did not receive a copy of the PHP license and are unable to |
9848 + | obtain it through the world-wide-web, please send a note to |
9849 + | license@php.net so we can mail you a copy immediately. |
9850 + +----------------------------------------------------------------------+
9851 + | Authors: Brian Shire <shire@php.net> |
9852 + +----------------------------------------------------------------------+
9853 +
9854 + */
9855 +
9856 +/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9857 +
9858 +#ifndef APC_SPIN_H
9859 +#define APC_SPIN_H
9860 +
9861 +#include "apc.h"
9862 +
9863 +#ifdef APC_SPIN_LOCKS
9864 +
9865 +#include "pgsql_s_lock.h"
9866 +
9867 +pthread_mutex_t *apc_spin_create();
9868 +void apc_spin_destroy(pthread_mutex_t *lock);
9869 +void apc_spin_lock(pthread_mutex_t *lock);
9870 +void apc_spin_unlock(pthread_mutex_t *lock);
9871 +zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
9872 +
9873 +#endif
9874 +
9875 +#endif
9876 +
9877 +/*
9878 + * Local variables:
9879 + * tab-width: 4
9880 + * c-basic-offset: 4
9881 + * End:
9882 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9883 + * vim<600: expandtab sw=4 ts=4 sts=4
9884 + */
9885 Index: php-5.2.4/ext/apc/apc_stack.c
9886 ===================================================================
9887 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9888 +++ php-5.2.4/ext/apc/apc_stack.c 2007-09-02 12:24:46.000000000 +0200
9889 @@ -0,0 +1,105 @@
9890 +/*
9891 + +----------------------------------------------------------------------+
9892 + | APC |
9893 + +----------------------------------------------------------------------+
9894 + | Copyright (c) 2006 The PHP Group |
9895 + +----------------------------------------------------------------------+
9896 + | This source file is subject to version 3.01 of the PHP license, |
9897 + | that is bundled with this package in the file LICENSE, and is |
9898 + | available through the world-wide-web at the following url: |
9899 + | http://www.php.net/license/3_01.txt |
9900 + | If you did not receive a copy of the PHP license and are unable to |
9901 + | obtain it through the world-wide-web, please send a note to |
9902 + | license@php.net so we can mail you a copy immediately. |
9903 + +----------------------------------------------------------------------+
9904 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9905 + +----------------------------------------------------------------------+
9906 +
9907 + This software was contributed to PHP by Community Connect Inc. in 2002
9908 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9909 + Future revisions and derivatives of this source code must acknowledge
9910 + Community Connect Inc. as the original contributor of this module by
9911 + leaving this note intact in the source code.
9912 +
9913 + All other licensing and usage conditions are those of the PHP Group.
9914 +
9915 + */
9916 +
9917 +/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
9918 +
9919 +#include "apc_stack.h"
9920 +#include "apc.h"
9921 +
9922 +struct apc_stack_t {
9923 + void** data;
9924 + int capacity;
9925 + int size;
9926 +};
9927 +
9928 +apc_stack_t* apc_stack_create(int size_hint)
9929 +{
9930 + apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
9931 +
9932 + stack->capacity = (size_hint > 0) ? size_hint : 10;
9933 + stack->size = 0;
9934 + stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
9935 +
9936 + return stack;
9937 +}
9938 +
9939 +void apc_stack_destroy(apc_stack_t* stack)
9940 +{
9941 + if (stack != NULL) {
9942 + apc_efree(stack->data);
9943 + apc_efree(stack);
9944 + }
9945 +}
9946 +
9947 +void apc_stack_clear(apc_stack_t* stack)
9948 +{
9949 + assert(stack != NULL);
9950 + stack->size = 0;
9951 +}
9952 +
9953 +void apc_stack_push(apc_stack_t* stack, void* item)
9954 +{
9955 + assert(stack != NULL);
9956 + if (stack->size == stack->capacity) {
9957 + stack->capacity *= 2;
9958 + stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
9959 + }
9960 + stack->data[stack->size++] = item;
9961 +}
9962 +
9963 +void* apc_stack_pop(apc_stack_t* stack)
9964 +{
9965 + assert(stack != NULL && stack->size > 0);
9966 + return stack->data[--stack->size];
9967 +}
9968 +
9969 +void* apc_stack_top(apc_stack_t* stack)
9970 +{
9971 + assert(stack != NULL && stack->size > 0);
9972 + return stack->data[stack->size-1];
9973 +}
9974 +
9975 +void* apc_stack_get(apc_stack_t* stack, int n)
9976 +{
9977 + assert(stack != NULL && stack->size > n);
9978 + return stack->data[n];
9979 +}
9980 +
9981 +int apc_stack_size(apc_stack_t* stack)
9982 +{
9983 + assert(stack != NULL);
9984 + return stack->size;
9985 +}
9986 +
9987 +/*
9988 + * Local variables:
9989 + * tab-width: 4
9990 + * c-basic-offset: 4
9991 + * End:
9992 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9993 + * vim<600: expandtab sw=4 ts=4 sts=4
9994 + */
9995 Index: php-5.2.4/ext/apc/apc_stack.h
9996 ===================================================================
9997 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
9998 +++ php-5.2.4/ext/apc/apc_stack.h 2007-09-02 12:24:46.000000000 +0200
9999 @@ -0,0 +1,58 @@
10000 +/*
10001 + +----------------------------------------------------------------------+
10002 + | APC |
10003 + +----------------------------------------------------------------------+
10004 + | Copyright (c) 2006 The PHP Group |
10005 + +----------------------------------------------------------------------+
10006 + | This source file is subject to version 3.01 of the PHP license, |
10007 + | that is bundled with this package in the file LICENSE, and is |
10008 + | available through the world-wide-web at the following url: |
10009 + | http://www.php.net/license/3_01.txt |
10010 + | If you did not receive a copy of the PHP license and are unable to |
10011 + | obtain it through the world-wide-web, please send a note to |
10012 + | license@php.net so we can mail you a copy immediately. |
10013 + +----------------------------------------------------------------------+
10014 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10015 + | George Schlossnagle <george@omniti.com> |
10016 + +----------------------------------------------------------------------+
10017 +
10018 + This software was contributed to PHP by Community Connect Inc. in 2002
10019 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10020 + Future revisions and derivatives of this source code must acknowledge
10021 + Community Connect Inc. as the original contributor of this module by
10022 + leaving this note intact in the source code.
10023 +
10024 + All other licensing and usage conditions are those of the PHP Group.
10025 +
10026 + */
10027 +
10028 +/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
10029 +
10030 +#ifndef APC_STACK_H
10031 +#define APC_STACK_H
10032 +
10033 +/* Basic stack datatype */
10034 +
10035 +#define T apc_stack_t*
10036 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
10037 +
10038 +extern T apc_stack_create(int size_hint);
10039 +extern void apc_stack_destroy(T stack);
10040 +extern void apc_stack_clear(T stack);
10041 +extern void apc_stack_push(T stack, void* item);
10042 +extern void* apc_stack_pop(T stack);
10043 +extern void* apc_stack_top(T stack);
10044 +extern void* apc_stack_get(T stack, int n);
10045 +extern int apc_stack_size(T stack);
10046 +
10047 +#undef T
10048 +#endif
10049 +
10050 +/*
10051 + * Local variables:
10052 + * tab-width: 4
10053 + * c-basic-offset: 4
10054 + * End:
10055 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10056 + * vim<600: expandtab sw=4 ts=4 sts=4
10057 + */
10058 Index: php-5.2.4/ext/apc/apc_zend.c
10059 ===================================================================
10060 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10061 +++ php-5.2.4/ext/apc/apc_zend.c 2007-09-02 12:24:46.000000000 +0200
10062 @@ -0,0 +1,277 @@
10063 +/*
10064 + +----------------------------------------------------------------------+
10065 + | APC |
10066 + +----------------------------------------------------------------------+
10067 + | Copyright (c) 2006 The PHP Group |
10068 + +----------------------------------------------------------------------+
10069 + | This source file is subject to version 3.01 of the PHP license, |
10070 + | that is bundled with this package in the file LICENSE, and is |
10071 + | available through the world-wide-web at the following url: |
10072 + | http://www.php.net/license/3_01.txt |
10073 + | If you did not receive a copy of the PHP license and are unable to |
10074 + | obtain it through the world-wide-web, please send a note to |
10075 + | license@php.net so we can mail you a copy immediately. |
10076 + +----------------------------------------------------------------------+
10077 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10078 + +----------------------------------------------------------------------+
10079 +
10080 + This software was contributed to PHP by Community Connect Inc. in 2002
10081 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10082 + Future revisions and derivatives of this source code must acknowledge
10083 + Community Connect Inc. as the original contributor of this module by
10084 + leaving this note intact in the source code.
10085 +
10086 + All other licensing and usage conditions are those of the PHP Group.
10087 +
10088 + */
10089 +
10090 +/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
10091 +
10092 +#include "apc_zend.h"
10093 +#include "apc_globals.h"
10094 +
10095 +void* apc_php_malloc(size_t n)
10096 +{
10097 + return emalloc(n);
10098 +}
10099 +
10100 +void apc_php_free(void* p)
10101 +{
10102 + efree(p);
10103 +}
10104 +
10105 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
10106 +# define ZEND_VM_KIND_CALL 1
10107 +#endif
10108 +
10109 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
10110 +# define ZEND_VM_KIND ZEND_VM_KIND_CALL
10111 +#endif
10112 +
10113 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
10114 +# define APC_OPCODE_OVERRIDE
10115 +#endif
10116 +
10117 +#ifdef APC_OPCODE_OVERRIDE
10118 +
10119 +#ifdef ZEND_ENGINE_2_1
10120 +/* Taken from Zend/zend_vm_execute.h */
10121 +#define _CONST_CODE 0
10122 +#define _TMP_CODE 1
10123 +#define _VAR_CODE 2
10124 +#define _UNUSED_CODE 3
10125 +#define _CV_CODE 4
10126 +static inline int _apc_opcode_handler_decode(zend_op *opline)
10127 +{
10128 + static const int apc_vm_decode[] = {
10129 + _UNUSED_CODE, /* 0 */
10130 + _CONST_CODE, /* 1 = IS_CONST */
10131 + _TMP_CODE, /* 2 = IS_TMP_VAR */
10132 + _UNUSED_CODE, /* 3 */
10133 + _VAR_CODE, /* 4 = IS_VAR */
10134 + _UNUSED_CODE, /* 5 */
10135 + _UNUSED_CODE, /* 6 */
10136 + _UNUSED_CODE, /* 7 */
10137 + _UNUSED_CODE, /* 8 = IS_UNUSED */
10138 + _UNUSED_CODE, /* 9 */
10139 + _UNUSED_CODE, /* 10 */
10140 + _UNUSED_CODE, /* 11 */
10141 + _UNUSED_CODE, /* 12 */
10142 + _UNUSED_CODE, /* 13 */
10143 + _UNUSED_CODE, /* 14 */
10144 + _UNUSED_CODE, /* 15 */
10145 + _CV_CODE /* 16 = IS_CV */
10146 + };
10147 + return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
10148 +}
10149 +
10150 +# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline;
10151 +# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline)
10152 +# if PHP_MAJOR_VERSION >= 6
10153 +# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1)
10154 +# else
10155 +# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1)
10156 +# endif
10157 +# 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; }
10158 +
10159 +#else /* ZE2.0 */
10160 +# define APC_ZEND_ONLINE
10161 +# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode)
10162 +# define APC_OPCODE_HANDLER_COUNT 512
10163 +# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname;
10164 +#endif
10165 +
10166 +static opcode_handler_t *apc_original_opcode_handlers;
10167 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
10168 +
10169 +#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
10170 +
10171 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
10172 +{
10173 + *freeval = NULL;
10174 +
10175 + switch (node->op_type) {
10176 + case IS_CONST:
10177 + return &(node->u.constant);
10178 + case IS_VAR:
10179 + return APC_EX_T(node->u.var).var.ptr;
10180 + case IS_TMP_VAR:
10181 + return (*freeval = &APC_EX_T(node->u.var).tmp_var);
10182 +#ifdef ZEND_ENGINE_2_1
10183 + case IS_CV:
10184 + {
10185 + zval ***ret = &execute_data->CVs[node->u.var];
10186 +
10187 + if (!*ret) {
10188 + zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
10189 +
10190 + if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
10191 + apc_nprint("Undefined variable: %s", cv->name);
10192 + return &EG(uninitialized_zval);
10193 + }
10194 + }
10195 + return **ret;
10196 + }
10197 +#endif
10198 + case IS_UNUSED:
10199 + default:
10200 + return NULL;
10201 + }
10202 +}
10203 +
10204 +static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
10205 +{
10206 + APC_ZEND_OPLINE
10207 + zval *freeop1 = NULL;
10208 + zval *inc_filename = NULL, tmp_inc_filename;
10209 + char realpath[MAXPATHLEN];
10210 + php_stream_wrapper *wrapper;
10211 + char *path_for_open;
10212 + int ret = 0;
10213 + #ifdef ZEND_ENGINE_2
10214 + apc_opflags_t* flags = NULL;
10215 + #endif
10216 +
10217 + if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
10218 + Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
10219 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10220 + }
10221 +
10222 + inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
10223 + if (Z_TYPE_P(inc_filename) != IS_STRING) {
10224 + tmp_inc_filename = *inc_filename;
10225 + zval_copy_ctor(&tmp_inc_filename);
10226 + convert_to_string(&tmp_inc_filename);
10227 + inc_filename = &tmp_inc_filename;
10228 + }
10229 +
10230 + wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
10231 + if (wrapper != &php_plain_files_wrapper ||
10232 + !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
10233 + !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
10234 + /* Fallback to original handler */
10235 + if (inc_filename == &tmp_inc_filename) {
10236 + zval_dtor(&tmp_inc_filename);
10237 + }
10238 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10239 + }
10240 +
10241 + if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
10242 + if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
10243 + ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
10244 + ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
10245 + }
10246 + if (inc_filename == &tmp_inc_filename) {
10247 + zval_dtor(&tmp_inc_filename);
10248 + }
10249 + if (freeop1) {
10250 + zval_dtor(freeop1);
10251 + }
10252 + execute_data->opline++;
10253 + return 0;
10254 + }
10255 +
10256 + if (inc_filename == &tmp_inc_filename) {
10257 + zval_dtor(&tmp_inc_filename);
10258 + }
10259 +
10260 + if(APCG(reserved_offset) != -1) {
10261 + /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
10262 + flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
10263 + }
10264 +
10265 +#ifdef ZEND_ENGINE_2
10266 + if(flags && flags->deep_copy == 1) {
10267 + /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily
10268 + * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
10269 + */
10270 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
10271 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10272 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
10273 +#else
10274 + if(0) {
10275 + /* do nothing, have nothing, be nothing */
10276 +#endif
10277 + } else {
10278 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10279 + }
10280 +
10281 + return ret;
10282 +}
10283 +
10284 +void apc_zend_init(TSRMLS_D)
10285 +{
10286 + zend_extension dummy_ext;
10287 +#ifdef ZEND_ENGINE_2
10288 + APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext);
10289 + assert(APCG(reserved_offset) == dummy_ext.resource_number);
10290 + assert(APCG(reserved_offset) != -1);
10291 + assert(sizeof(apc_opflags_t) <= sizeof(void*));
10292 +#endif
10293 + if (!APCG(include_once)) {
10294 + /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
10295 + return;
10296 + }
10297 +
10298 + memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
10299 +
10300 + /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
10301 +#ifdef ZEND_ENGINE_2_1
10302 + apc_original_opcode_handlers = zend_opcode_handlers;
10303 + zend_opcode_handlers = apc_opcode_handlers;
10304 +#else
10305 + apc_original_opcode_handlers = apc_opcode_handlers;
10306 +#endif
10307 +
10308 + APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
10309 +}
10310 +
10311 +void apc_zend_shutdown(TSRMLS_D)
10312 +{
10313 + if (!APCG(include_once)) {
10314 + /* Nothing changed, nothing to restore */
10315 + return;
10316 + }
10317 +
10318 +#ifdef ZEND_ENGINE_2_1
10319 + zend_opcode_handlers = apc_original_opcode_handlers;
10320 +#else
10321 + memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
10322 +#endif
10323 +}
10324 +
10325 +#else /* Opcode Overrides unavailable */
10326 +
10327 +void apc_zend_init(TSRMLS_D) { }
10328 +void apc_zend_shutdown(TSRMLS_D) { }
10329 +
10330 +#endif /* APC_OPCODE_OVERRIDE */
10331 +
10332 +/*
10333 + * Local variables:
10334 + * tab-width: 4
10335 + * c-basic-offset: 4
10336 + * End:
10337 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10338 + * vim<600: expandtab sw=4 ts=4 sts=4
10339 + */
10340 Index: php-5.2.4/ext/apc/apc_zend.h
10341 ===================================================================
10342 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10343 +++ php-5.2.4/ext/apc/apc_zend.h 2007-09-02 12:24:46.000000000 +0200
10344 @@ -0,0 +1,53 @@
10345 +/*
10346 + +----------------------------------------------------------------------+
10347 + | APC |
10348 + +----------------------------------------------------------------------+
10349 + | Copyright (c) 2006 The PHP Group |
10350 + +----------------------------------------------------------------------+
10351 + | This source file is subject to version 3.01 of the PHP license, |
10352 + | that is bundled with this package in the file LICENSE, and is |
10353 + | available through the world-wide-web at the following url: |
10354 + | http://www.php.net/license/3_01.txt |
10355 + | If you did not receive a copy of the PHP license and are unable to |
10356 + | obtain it through the world-wide-web, please send a note to |
10357 + | license@php.net so we can mail you a copy immediately. |
10358 + +----------------------------------------------------------------------+
10359 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10360 + +----------------------------------------------------------------------+
10361 +
10362 + This software was contributed to PHP by Community Connect Inc. in 2002
10363 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10364 + Future revisions and derivatives of this source code must acknowledge
10365 + Community Connect Inc. as the original contributor of this module by
10366 + leaving this note intact in the source code.
10367 +
10368 + All other licensing and usage conditions are those of the PHP Group.
10369 +
10370 + */
10371 +
10372 +/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
10373 +
10374 +#ifndef APC_ZEND_H
10375 +#define APC_ZEND_H
10376 +
10377 +/* Utilities for interfacing with the zend engine */
10378 +
10379 +#include "apc.h"
10380 +#include "apc_php.h"
10381 +
10382 +extern void* apc_php_malloc(size_t n);
10383 +extern void apc_php_free(void* p);
10384 +
10385 +extern void apc_zend_init(TSRMLS_D);
10386 +extern void apc_zend_shutdown(TSRMLS_D);
10387 +
10388 +#endif
10389 +
10390 +/*
10391 + * Local variables:
10392 + * tab-width: 4
10393 + * c-basic-offset: 4
10394 + * End:
10395 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10396 + * vim<600: expandtab sw=4 ts=4 sts=4
10397 + */
10398 Index: php-5.2.4/ext/apc/CHANGELOG
10399 ===================================================================
10400 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10401 +++ php-5.2.4/ext/apc/CHANGELOG 2007-09-02 12:24:46.000000000 +0200
10402 @@ -0,0 +1,192 @@
10403 +3.0.14: 2007-03-21
10404 +- Build fix (Shire)
10405 +- Don't hook the upload hook if APC is disabled (Rasmus)
10406 +- Local shadow cache support (Gopal)
10407 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
10408 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
10409 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
10410 +- Allocator fixes to reduce fragmentation (Gopal)
10411 +
10412 +3.0.13: 2007-02-24
10413 +- File upload progress (Rasmus)
10414 +- Pthread mutex and spin locks (Shire)
10415 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
10416 +- apc.stat_ctime flag for ctime checks (Rasmus)
10417 +- Multiple key fetches with apc_fetch (Shire)
10418 +- Canary checks for shm memory deallocation (Gopal)
10419 +- Add hooks for external optimizer (Shire)
10420 +- Obsolete and remove apc optimizer (Gopal)
10421 +- APC info changes - cache insert rate, hit and miss rates (Shire)
10422 +- Fix apc_load_constants (Gopal)
10423 +- Rewrite dump opcode code to use vld (Gopal)
10424 +- Use apc_[ewn]print functions for error reporting (Shire)
10425 +- Auto global fixes and refactoring (Gopal, Shire)
10426 +- Fix memory leaks in object serialization (Ilia)
10427 +- Memory cleanup code for destructor order (Gopal)
10428 +- Win32 build fixes (Ilia, Wez)
10429 +- ZTS and Php 4 build fixes (Bjori)
10430 +- Add apc_add() function (Rasmus)
10431 +- Add optional limited flag to apc_sma_info() (Rasmus)
10432 +
10433 +3.0.12p2: 2006-09-05
10434 +- Package version up
10435 +
10436 +3.0,12p1: 2006-09-05
10437 +- PHP4 build fixes
10438 +
10439 +3.0.12: 2006-09-05
10440 +- PHP 5.2 compatibility (Gopal)
10441 +- TSRM fixes (Gopal)
10442 +- Add extra flags to op_array->reserved to improve op array
10443 + processing code (Gopal)
10444 +- Fix crashes in optimizer and cli mode (Ilia)
10445 +- Optimizer fixes for PHP5 (Ilia, Gopal)
10446 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
10447 +- Php 4 function table and properties fixes (Gopal)
10448 +- Fix memory leaks in apc_cache_info (Gopal)
10449 +
10450 +3.0.11: 2006-08-16
10451 +- Made --enable-apc-mmap the default compile option (for real this time)
10452 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
10453 + only fetch header information to make it useful when you have tens of
10454 + thousands of entries. (Brian Shire)
10455 +- 64-bit fixes (George)
10456 +- Don't mix Full Path and Inode keys (George)
10457 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
10458 + require_once() and include_once() statements. (Sara)
10459 +- Add a non-blocking write_lock for cache inserts. This is a better approach
10460 + to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
10461 +- A bit of work on the optimizer. (Sara)
10462 +- Various memory issues resolved. (Gopal)
10463 +
10464 +3.0.10: 2006-03-11
10465 +- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
10466 + includes will not be stat'ed for any changes. You will have to restart the server if you
10467 + change anything. This mode increases performance quite a bit, especially if you have a
10468 + lot of includes.
10469 +
10470 +- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
10471 + than it solves. I'll need to revisit locking and signal handling at some point soon.
10472 +
10473 +3.0.9: 2006-03-04
10474 +- Eliminate rand() call when slam_defense is not set (Rasmus)
10475 +- Fix for __isset problem (Gopal)
10476 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
10477 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
10478 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
10479 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
10480 +- Add automatic serialization of objects in apc_store() (Marcus)
10481 +- 64-bit .ini flag fix (Rasmus)
10482 +- Static members fix (Gopal)
10483 +- sma_cleanup() mem leak fix (Rasmus)
10484 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
10485 +- Fix autoglobals JIT bug (Gopal)
10486 +- Fix instance bug (Gopal)
10487 +- Add a lock cleanup safety net to request shutdown (Rasmus)
10488 +- Fix apc.slam_defense edge-case bug (Rasmus)
10489 +- User entry memory usage tracking support (Ilia)
10490 +- 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)
10491 +
10492 +3.0.8: 2005-08-24
10493 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
10494 +Cache corruption fix in cache-full cleanup code (Gopal)
10495 +
10496 +3.0.7: 2005-08-16
10497 +- Fix to apc.php to show final segment in frag chart. (Ilia)
10498 +- A couple of win32 fixes. (Frank)
10499 +- Add apc.enable_cli ini directive. (Rasmus)
10500 +- Add test cases. (Marcus)
10501 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
10502 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
10503 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
10504 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
10505 +
10506 +3.0.6: 2005-07-30
10507 +- Added apc.php to package.xml file.
10508 +- Track per-entry memory usage. (Val)
10509 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
10510 +- fcntl locking robustness fixes. (Rasmus)
10511 +- Shared read-locks where possible. (Rasmus)
10512 +- Added file_update_protection configuration parameter. (Rasmus)
10513 +- Windows ZTS fixes (Frank)
10514 +
10515 +3.0.5: 2005-07-27
10516 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
10517 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
10518 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
10519 +- Segfault in cache cleanup code (Ilia, Rasmus)
10520 +
10521 +3.0.4: 2005-07-18
10522 +- Add win32 support (Edin )
10523 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
10524 +- A couple of other minor fixes
10525 +
10526 +3.0.3: 2005-07-05
10527 +- Fix compile problem against PHP 5.0.x
10528 +
10529 +3.0.2: 2005-07-05
10530 +- Better shm error message
10531 +
10532 +3.0.1: 2005-07-05
10533 +- PHP4 build fix
10534 +
10535 +3.0: 2005-06-23
10536 +- PHP 5.1 support (Arun, Gopal, Rasmus)
10537 +- Major Inheritance bug fix (Arun, Gopal)
10538 +
10539 +2.0: 2003-02-10
10540 +- ground-up rewrite sharing none of the original source code (djc)
10541 +
10542 +1.0.10:
10543 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
10544 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
10545 + this parameter to your php.ini file to activate apc shm or mmap caching
10546 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
10547 + 2001-05-15]
10548 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
10549 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
10550 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
10551 +- fixed regex support [gws 2001-05-16]
10552 +- enhanced reader-writer lock support [rg 2001-05-07]
10553 +
10554 +1.0.9:
10555 +- fixed (?) memory alignment bug on 64 bit archiecures
10556 +- added many cache visibiliy functions
10557 +- added opional fcntl locks under shm version
10558 +- numerous bug fixes
10559 +
10560 +1.0.8:
10561 +- added ability to detect and decompile compiled files placed as 'source'
10562 + [gws,dw 2001-01-30]
10563 +- fixed apc_rstat bug [gws 2001-01-29]
10564 +- added hack to support included urls [gws 2001-01-30]
10565 +- fixed apc_cache_index [mb 2001-01-31]
10566 +- added multiple regex support [gs 2001-02-03]
10567 +- added apc_cache_info [mb,gs 2001-02-03]
10568 +
10569 +1.0.7:
10570 +- partially fixed for Solaris [gws 2001-01-29]
10571 +- fixed mtime support for relative includes [gws 2001-01-29]
10572 +- code cleanup [yg,ta,gws 2001-01-29]
10573 +
10574 +1.0.6:
10575 +- support for mtime in mmap [yg,gws 2001-01-27]
10576 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
10577 +
10578 +1.0.5:
10579 +- support for relative include paths [djc,gws 2001-01-19]
10580 +- class member array support fixed [djc 2001-01-18]
10581 +- added apc_cache_index [gws 2001-01-18]
10582 +
10583 +1.0.4:
10584 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
10585 +
10586 +1.0.3:
10587 +- fixed support for class inheritance [djc 2001-01-16]
10588 +
10589 +1.0.2:
10590 +- support for inherited classes [gws 2001-01-15]
10591 +- support for intialization of class variables and objects [gws 2001-01-13]
10592 +
10593 +1.0.1:
10594 +- added optional file modification time check [djc 2001-01-12]
10595 Index: php-5.2.4/ext/apc/config.m4
10596 ===================================================================
10597 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10598 +++ php-5.2.4/ext/apc/config.m4 2007-09-02 12:24:46.000000000 +0200
10599 @@ -0,0 +1,214 @@
10600 +dnl
10601 +dnl $Id: config.m4,v 3.25 2007/02/24 15:57:59 rasmus Exp $
10602 +dnl
10603 +
10604 +AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
10605 +AC_ARG_WITH(apxs,
10606 +[ --with-apxs[=FILE] Get compiler flags from apxs -q. Provide the
10607 + pathname to the Apache apxs tool; defaults to "apxs".],[
10608 + if test "$withval" != "no"; then
10609 + if test "$withval" = "yes"; then
10610 + APXS=apxs
10611 + $APXS -q CFLAGS >/dev/null 2>&1
10612 + if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
10613 + APXS=/usr/sbin/apxs
10614 + elif test -x /usr/bin/apxs2; then
10615 + APXS=/usr/bin/apxs2
10616 + elif test -x /usr/sbin/apxs2; then
10617 + APXS=/usr/sbin/apxs2
10618 + fi
10619 + else
10620 + PHP_EXPAND_PATH($withval, APXS)
10621 + fi
10622 +
10623 + $APXS -q CFLAGS >/dev/null 2>&1
10624 + if test "$?" != "0"; then
10625 + AC_MSG_RESULT()
10626 + AC_MSG_RESULT()
10627 + AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:])
10628 + AC_MSG_RESULT()
10629 + AC_MSG_RESULT([1. Perl is not installed;])
10630 + AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);])
10631 + AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs])
10632 + AC_MSG_RESULT([The output of $APXS follows])
10633 + $APXS -q CFLAGS
10634 + AC_MSG_ERROR([Aborting])
10635 + fi
10636 +
10637 + APC_CFLAGS=`$APXS -q CFLAGS`
10638 + AC_MSG_RESULT(yes)
10639 + else
10640 + AC_MSG_RESULT(no)
10641 + fi
10642 +],[
10643 + AC_MSG_RESULT(no)
10644 +])
10645 +
10646 +PHP_ARG_ENABLE(apc, whether to enable APC support,
10647 +[ --enable-apc Enable APC support])
10648 +
10649 +AC_MSG_CHECKING(Checking whether we should use mmap)
10650 +AC_ARG_ENABLE(apc-mmap,
10651 +[ --disable-apc-mmap
10652 + Disable mmap support and use IPC shm instead],
10653 +[
10654 + PHP_APC_MMAP=$enableval
10655 + AC_MSG_RESULT($enableval)
10656 +], [
10657 + PHP_APC_MMAP=yes
10658 + AC_MSG_RESULT(yes)
10659 +])
10660 +
10661 +AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
10662 +AC_ARG_ENABLE(apc-sem,
10663 +[ --enable-apc-sem
10664 + Enable semaphore locks instead of fcntl],
10665 +[
10666 + PHP_APC_SEM=$enableval
10667 + AC_MSG_RESULT($enableval)
10668 +], [
10669 + PHP_APC_SEM=no
10670 + AC_MSG_RESULT(no)
10671 +])
10672 +
10673 +AC_MSG_CHECKING(Checking whether we should use futex locking)
10674 +AC_ARG_ENABLE(apc-futex,
10675 +[ --enable-apc-futex
10676 + Enable linux futex based locks EXPERIMENTAL ],
10677 +[
10678 + PHP_APC_FUTEX=$enableval
10679 + AC_MSG_RESULT($enableval)
10680 +],
10681 +[
10682 + PHP_APC_FUTEX=no
10683 + AC_MSG_RESULT(no)
10684 +])
10685 +
10686 +if test "$PHP_APC_FUTEX" != "no"; then
10687 + 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.]); ] )
10688 +fi
10689 +
10690 +AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
10691 +AC_ARG_ENABLE(apc-pthreadmutex,
10692 +[ --enable-apc-pthreadmutex
10693 + Enable pthread mutex locking EXPERIMENTAL ],
10694 +[
10695 + PHP_APC_PTHREADMUTEX=$enableval
10696 + AC_MSG_RESULT($enableval)
10697 +],
10698 +[
10699 + PHP_APC_PTHREADMUTEX=no
10700 + AC_MSG_RESULT(no)
10701 +])
10702 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
10703 + orig_LIBS="$LIBS"
10704 + LIBS="$LIBS -lpthread"
10705 + AC_TRY_RUN(
10706 + [
10707 + #include <sys/types.h>
10708 + #include <pthread.h>
10709 + main() {
10710 + pthread_mutex_t mutex;
10711 + pthread_mutexattr_t attr;
10712 +
10713 + if(pthread_mutexattr_init(&attr)) {
10714 + puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
10715 + return -1;
10716 + }
10717 + if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
10718 + puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's which are required. (if you're using threads you should just use the built-in php thread locking).");
10719 + return -1;
10720 + }
10721 + if(pthread_mutex_init(&mutex, &attr)) {
10722 + puts("Unable to initialize the mutex (pthread_mutex_init).");
10723 + return -1;
10724 + }
10725 + if(pthread_mutexattr_destroy(&attr)) {
10726 + puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
10727 + return -1;
10728 + }
10729 + if(pthread_mutex_destroy(&mutex)) {
10730 + puts("Unable to destroy mutex (pthread_mutex_destroy).");
10731 + return -1;
10732 + }
10733 +
10734 + puts("pthread mutex's are supported!");
10735 + return 0;
10736 + }
10737 + ],
10738 + [ dnl -Success-
10739 + PHP_ADD_LIBRARY(pthread)
10740 + ],
10741 + [ dnl -Failure-
10742 + AC_MSG_ERROR([It doesn't appear that pthread mutex's are supported on your system, please try a different configuration])
10743 + ],
10744 + [
10745 + PHP_ADD_LIBRARY(pthread)
10746 + ]
10747 + )
10748 + LIBS="$orig_LIBS"
10749 +fi
10750 +
10751 +AC_MSG_CHECKING(Checking whether we should use spin locks)
10752 +AC_ARG_ENABLE(apc-spinlocks,
10753 +[ --enable-apc-spinlocks
10754 + Enable spin locks EXPERIMENTAL ],
10755 +[
10756 + PHP_APC_SPINLOCKS=$enableval
10757 + AC_MSG_RESULT($enableval)
10758 +],
10759 +[
10760 + PHP_APC_SPINLOCKS=no
10761 + AC_MSG_RESULT(no)
10762 +])
10763 +
10764 +if test "$PHP_APC" != "no"; then
10765 + test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
10766 + test "$PHP_APC_SEM" != "no" && AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
10767 + test "$PHP_APC_FUTEX" != "no" && AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
10768 + test "$PHP_APC_PTHREADMUTEX" != "no" && AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
10769 + test "$PHP_APC_SPINLOCKS" != "no" && AC_DEFINE(APC_SPIN_LOCKS, 1, [ ])
10770 +
10771 + AC_CACHE_CHECK(for union semun, php_cv_semun,
10772 + [
10773 + AC_TRY_COMPILE([
10774 +#include <sys/types.h>
10775 +#include <sys/ipc.h>
10776 +#include <sys/sem.h>
10777 + ], [union semun x;], [
10778 + php_cv_semun=yes
10779 + ],[
10780 + php_cv_semun=no
10781 + ])
10782 + ])
10783 + if test "$php_cv_semun" = "yes"; then
10784 + AC_DEFINE(HAVE_SEMUN, 1, [ ])
10785 + else
10786 + AC_DEFINE(HAVE_SEMUN, 0, [ ])
10787 + fi
10788 +
10789 + apc_sources="apc.c php_apc.c \
10790 + apc_cache.c \
10791 + apc_compile.c \
10792 + apc_debug.c \
10793 + apc_fcntl.c \
10794 + apc_main.c \
10795 + apc_mmap.c \
10796 + apc_sem.c \
10797 + apc_shm.c \
10798 + apc_futex.c \
10799 + apc_pthreadmutex.c \
10800 + apc_spin.c \
10801 + pgsql_s_lock.c \
10802 + apc_sma.c \
10803 + apc_stack.c \
10804 + apc_zend.c \
10805 + apc_rfc1867.c "
10806 +
10807 + PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
10808 + PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
10809 + PHP_SUBST(APC_SHARED_LIBADD)
10810 + PHP_SUBST(APC_CFLAGS)
10811 + AC_DEFINE(HAVE_APC, 1, [ ])
10812 +fi
10813 +
10814 Index: php-5.2.4/ext/apc/INSTALL
10815 ===================================================================
10816 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10817 +++ php-5.2.4/ext/apc/INSTALL 2007-09-02 12:24:46.000000000 +0200
10818 @@ -0,0 +1,405 @@
10819 +Installation Instructions for APC
10820 +---------------------------------
10821 +
10822 +This version of APC should work on PHP 4.3.0 - 4.4.x and
10823 +5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer
10824 +supported. Upgrade to PHP 5.1.x or 5.2.x and you will
10825 +notice all sorts of performance increases.
10826 +
10827 +CVS Instructions
10828 +----------------
10829 +Building from CVS can be done like this:
10830 +
10831 + cvs -d :pserver:cvsread@cvs.php.net:/repository login
10832 + Password: phpfi
10833 + cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
10834 + cd pecl/apc
10835 + phpize
10836 + ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10837 + make
10838 + make install
10839 +
10840 +Suggested Configuration (in your php.ini file)
10841 +----------------------------------------------
10842 + extension=apc.so
10843 + apc.enabled=1
10844 + apc.shm_segments=1
10845 + apc.shm_size=128
10846 + apc.ttl=7200
10847 + apc.user_ttl=7200
10848 + apc.num_files_hint=1024
10849 + apc.mmap_file_mask=/tmp/apc.XXXXXX
10850 + apc.enable_cli=1
10851 +
10852 +These are fully described at the bottom of this file.
10853 +
10854 +PHP 4 Optimization
10855 +------------------
10856 +If you are trying to get every little bit of speed out of PHP4+APC, you need
10857 +to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
10858 +your CPPFLAGS. (if you don't have httpd.h, install the apache_dev package
10859 +for your OS) and do:
10860 + export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
10861 + setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
10862 +and then re-run your configure script.
10863 +
10864 +This optimization saves a stat syscall on the main script file. In PHP5 this
10865 +optimization is automatic and doesn't need any special build flags.
10866 +
10867 +The second thing you are going to want to do to save another syscall is to
10868 +compile using the --with-apxs configure switch. This should work for both
10869 +Apache1 and Apache2. Point it directly at your apxs2 script for Apache2.
10870 +eg. --with-apxs=/usr/local/bin/apxs2
10871 +
10872 ++---------------------+
10873 +| QUICK INSTALL (DSO) |
10874 ++---------------------+
10875 +
10876 +These instructions assume your PHP installation is located in /usr/local/php and you
10877 +want Apache optimizations (--with-apxs).
10878 +
10879 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10880 +$ cd apc_x.y
10881 +$ /usr/local/php/bin/phpize
10882 +$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10883 +$ make
10884 +$ make install
10885 +
10886 +You will probably need to run the final command (make install) as root.
10887 +
10888 +The above sequence of commands will install a .so file in your PHP
10889 +installation extension directory. The output of make install should display
10890 +that path to the screen.
10891 +
10892 +Next you must edit your php.ini file, which is normally located in
10893 +/usr/local/php/lib/php.ini, and add the following line:
10894 +
10895 + extension="apc.so"
10896 +
10897 +Replace "/path/to/php/extensions" with whatever path was displayed when you
10898 +ran make install above.
10899 +
10900 +Then restart your web server and consult the output of phpinfo(). If there is
10901 +an informational section for APC, the installation was successful.
10902 +
10903 ++------------------------+
10904 +| QUICK INSTALL (Static) |
10905 ++------------------------+
10906 +
10907 +APC will not successfully compile on all systems as a DSO. If you run into
10908 +problems using the DSO quick install, you can try to compile it statically
10909 +into PHP. (The DSO install is recommended, though.)
10910 +
10911 +These instructions assume the current directory is the root of the PHP source
10912 +tree, and that you have already configured PHP by running its bundled
10913 +configure script.
10914 +
10915 +$ cd ext
10916 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10917 +$ cd ..
10918 +$ ./buildconf
10919 +$ ./config.nice
10920 +$ make
10921 +$ make install
10922 +
10923 +Once this is complete, simply restart your web server. You do not need to
10924 +modify your php.ini file to enable APC.
10925 +
10926 ++-----------------+
10927 +| VERBOSE INSTALL |
10928 ++-----------------+
10929 +
10930 +These instructions assume your PHP installation is located in /usr/local/php.
10931 +
10932 +1. Unpack your distribution file.
10933 +
10934 + You will have downloaded a file named something like apc_x.y.tar.gz.
10935 + Unzip this file with a command like
10936 +
10937 + gunzip apc_x.y.tar.gz
10938 +
10939 + Next you have to untar it with
10940 +
10941 + tar xvf apc_x.y.tar
10942 +
10943 + This will create an apc_x.y directory. cd into this new directory:
10944 +
10945 + cd apc_x.y
10946 +
10947 +2. Run phpize.
10948 +
10949 + phpize is a script that should have been installed with PHP, and is
10950 + normally located in /usr/local/php/bin assuming you installed PHP in
10951 + /usr/local/php. (If you do not have the phpize script, you must reinstall
10952 + PHP and be sure not to disable PEAR.)
10953 +
10954 + Run the phpize command:
10955 +
10956 + /usr/local/php/bin/phpize
10957 +
10958 + Its output should resemble this:
10959 +
10960 + autoheader: `config.h.in' is created
10961 + You should update your `aclocal.m4' by running aclocal.
10962 + Configuring for:
10963 + PHP Api Version: 20020918
10964 + Zend Module Api No: 20020429
10965 + Zend Extension Api No: 20021010
10966 +
10967 + phpize should create a configure script in the current directory. If you
10968 + get errors instead, you might be missing some required development tools,
10969 + such as autoconf or libtool. You can try downloading the latest versions
10970 + of those tools and running phpize again.
10971 +
10972 +3. Run the configure script.
10973 +
10974 + phpize creates a configure script. The only option you need to specify is
10975 + the location of your php-config script:
10976 +
10977 + ./configure --enable-apc
10978 +
10979 + php-config should be located in the same directory as phpize.
10980 +
10981 + If you prefer to use mmap instead of the default IPC shared memory support,
10982 + add --enable-apc-mmap to your configure line.
10983 +
10984 + If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
10985 + --enable-sem to your configure line. If you don't have a problem
10986 + with your server segaulting, or any other unnatural accumulation of
10987 + semaphores on your system, the semaphore based locking is slightly faster.
10988 +
10989 +4. Compile and install the files. Simply type: make install
10990 +
10991 + (You may need to be root in order to install)
10992 +
10993 + If you encounter errors from libtool or gcc during this step, please
10994 + contact the project maintainer (dcowgill@php.net).
10995 +
10996 +5. Edit your php.ini
10997 +
10998 + make install should have printed a line resembling the following:
10999 +
11000 + Installing shared extensions: /path/to/extension/
11001 +
11002 + Copy the path /path/to/extension/ and add the following line to your
11003 + php.ini file (normally located in /usr/local/php/lib/php.ini):
11004 +
11005 + extension="apc.so"
11006 +
11007 + If you don't have a php.ini file in that location, you can create it now.
11008 +
11009 +6. Restart the web server and test the installation.
11010 +
11011 + Restart your web server now (for apache, it's apachectl restart) and
11012 + create a small test PHP file in your document root. The file should
11013 + contain just the following line:
11014 +
11015 + <?php phpinfo() ?>
11016 +
11017 + Request that file in a web browser. If there is an entry for APC in the
11018 + list of installed modules, the installation was successful.
11019 +
11020 + If APC is not listed, consult your web server error log. If it contains an
11021 + error message saying that it can't load the APC extension, your system
11022 + might not be able to load shared libraries created with PHP's build
11023 + system. One alternative would be to compile APC statically into PHP. See
11024 + the Quick Install (Static) instructions above.
11025 +
11026 + You should consult your error log anyway to see if APC generated any
11027 + errors. On BSD-based platforms, it is typical for APC to be unable to
11028 + allocate the default-sized shared memory segment. See below for hints on
11029 + raising your system's shared memory limitations.
11030 +
11031 ++-----------------+
11032 +| CONFIGURING APC |
11033 ++-----------------+
11034 +
11035 +Although the default APC settings are fine for many installations, serious
11036 +users should consider tuning the following parameters:
11037 +
11038 + OPTION DESCRIPTION
11039 + ------------------ --------------------------------------------------
11040 + apc.enabled This can be set to 0 to disable APC. This is
11041 + primarily useful when APC is statically compiled
11042 + into PHP, since there is no other way to disable
11043 + it (when compiled as a DSO, the zend_extension
11044 + line can just be commented-out).
11045 + (Default: 1)
11046 +
11047 + apc.shm_segments The number of shared memory segments to allocate
11048 + for the compiler cache. If APC is running out of
11049 + shared memory but you have already set
11050 + apc.shm_size as high as your system allows, you
11051 + can try raising this value. Setting this to a
11052 + value other than 1 has no effect in mmap mode
11053 + since mmap'ed shm segments don't have size limits.
11054 + (Default: 1)
11055 +
11056 + apc.shm_size The size of each shared memory segment in MB.
11057 + By default, some systems (including most BSD
11058 + variants) have very low limits on the size of a
11059 + shared memory segment.
11060 + (Default: 30)
11061 +
11062 + apc.optimization This option has been deprecated.
11063 + (Default: 0)
11064 +
11065 + apc.num_files_hint A "hint" about the number of distinct source files
11066 + that will be included or requested on your web
11067 + server. Set to zero or omit if you're not sure;
11068 + this setting is mainly useful for sites that have
11069 + many thousands of source files.
11070 + (Default: 1000)
11071 +
11072 + apc.user_entries_hint Just like num_files_hint, a "hint" about the number
11073 + of distinct user cache variables to store.
11074 + Set to zero or omit if you're not sure;
11075 + (Default: 4096)
11076 +
11077 + apc.ttl The number of seconds a cache entry is allowed to
11078 + idle in a slot in case this cache entry slot is
11079 + needed by another entry. Leaving this at zero
11080 + means that your cache could potentially fill up
11081 + with stale entries while newer entries won't be
11082 + cached.
11083 + (Default: 0)
11084 +
11085 + apc.user_ttl The number of seconds a user cache entry is allowed
11086 + to idle in a slot in case this cache entry slot is
11087 + needed by another entry. Leaving this at zero
11088 + means that your cache could potentially fill up
11089 + with stale entries while newer entries won't be
11090 + cached.
11091 + (Default: 0)
11092 +
11093 +
11094 + apc.gc_ttl The number of seconds that a cache entry may
11095 + remain on the garbage-collection list. This value
11096 + provides a failsafe in the event that a server
11097 + process dies while executing a cached source file;
11098 + if that source file is modified, the memory
11099 + allocated for the old version will not be
11100 + reclaimed until this TTL reached. Set to zero to
11101 + disable this feature.
11102 + (Default: 3600)
11103 +
11104 + apc.cache_by_default On by default, but can be set to off and used in
11105 + conjunction with positive apc.filters so that files
11106 + are only cached if matched by a positive filter.
11107 + (Default: On)
11108 +
11109 + apc.filters A comma-separated list of POSIX extended regular
11110 + expressions. If any pattern matches the source
11111 + filename, the file will not be cached. Note that
11112 + the filename used for matching is the one passed
11113 + to include/require, not the absolute path. If the
11114 + first character of the expression is a + then the
11115 + expression will be additive in the sense that any
11116 + files matched by the expression will be cached, and
11117 + if the first character is a - then anything matched
11118 + will not be cached. The - case is the default, so
11119 + it can be left off.
11120 + (Default: "")
11121 +
11122 + apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap
11123 + this is the mktemp-style file_mask to pass to the
11124 + mmap module for determing whether your mmap'ed memory
11125 + region is going to be file-backed or shared memory
11126 + backed. For straight file-backed mmap, set it to
11127 + something like /tmp/apc.XXXXXX (exactly 6 X's).
11128 + To use POSIX-style shm_open/mmap put a ".shm"
11129 + somewhere in your mask. eg. "/apc.shm.XXXXXX"
11130 + You can also set it to "/dev/zero" to use your
11131 + kernel's /dev/zero interface to anonymous mmap'ed
11132 + memory. Leaving it undefined will force an
11133 + anonymous mmap.
11134 + (Default: "")
11135 +
11136 + apc.slam_defense ** DEPRECATED - Use apc.write_lock instead **
11137 + On very busy servers whenever you start the server or
11138 + modify files you can create a race of many processes
11139 + all trying to cache the same file at the same time.
11140 + This option sets the percentage of processes that will
11141 + skip trying to cache an uncached file. Or think of it
11142 + as the probability of a single process to skip caching.
11143 + For example, setting this to 75 would mean that there is
11144 + a 75% chance that the process will not cache an uncached
11145 + file. So the higher the setting the greater the defense
11146 + against cache slams. Setting this to 0 disables this
11147 + feature.
11148 + (Default: 0)
11149 +
11150 + apc.file_update_protection
11151 + When you modify a file on a live web server you really
11152 + should do so in an atomic manner. That is, write to a
11153 + temporary file and rename (mv) the file into its permanent
11154 + position when it is ready. Many text editors, cp, tar and
11155 + other such programs don't do this. This means that there
11156 + is a chance that a file is accessed (and cached) while it
11157 + is still being written to. This file_update_protection
11158 + setting puts a delay on caching brand new files. The
11159 + default is 2 seconds which means that if the modification
11160 + timestamp (mtime) on a file shows that it is less than 2
11161 + seconds old when it is accessed, it will not be cached.
11162 + The unfortunate person who accessed this half-written file
11163 + will still see weirdness, but at least it won't persist.
11164 + If you are certain you always atomically update your files
11165 + by using something like rsync which does this correctly, you
11166 + can turn this protection off by setting it to 0. If you
11167 + have a system that is flooded with io causing some update
11168 + procedure to take longer than 2 seconds, you may want to
11169 + increase this a bit.
11170 + (Default: 2)
11171 +
11172 + apc.enable_cli Mostly for testing and debugging. Setting this enables APC
11173 + for the CLI version of PHP. Normally you wouldn't want to
11174 + create, populate and tear down the APC cache on every CLI
11175 + request, but for various test scenarios it is handy to be
11176 + able to enable APC for the CLI version of APC easily.
11177 + (Default: 0)
11178 +
11179 + apc.max_file_size Prevents large files from being cached.
11180 + (Default: 1M)
11181 +
11182 + apc.stat Whether to stat the main script file and the fullpath
11183 + includes. If you turn this off you will need to restart
11184 + your server in order to update scripts.
11185 + (Default: 1)
11186 +
11187 + apc.write_lock On busy servers when you first start up the server, or when
11188 + many files are modified, you can end up with all your processes
11189 + trying to compile and cache the same files. With write_lock
11190 + enabled, only one process at a time will try to compile an
11191 + uncached script while the other processes will run uncached
11192 + instead of sitting around waiting on a lock.
11193 + (Default: 1)
11194 +
11195 + apc.report_autofilter Logs any scripts that were automatically excluded from being
11196 + cached due to early/late binding issues.
11197 + (Default: 0)
11198 +
11199 + apc.rfc1867 RFC1867 File Upload Progress hook handler is only available
11200 + if you compiled APC against PHP 5.2.0 or later. When enabled
11201 + any file uploads which includes a field called
11202 + APC_UPLOAD_PROGRESS before the file field in an upload form
11203 + will cause APC to automatically create an upload_<key>
11204 + user cache entry where <key> is the value of the
11205 + APC_UPLOAD_PROGRESS form entry.
11206 +
11207 + Note that the file upload tracking is not threadsafe at this
11208 + point, so new uploads that happen while a previous one is
11209 + still going will disable the tracking for the previous.
11210 + (Default: 0)
11211 +
11212 + apc.localcache This enables a lock-free local process shadow-cache which
11213 + reduces lock contention when the cache is being written to.
11214 + (Default: 0)
11215 +
11216 + apc.localcache.size The size of the local process shadow-cache, should be set to
11217 + a sufficently large value, approximately half of num_files_hint.
11218 + (Default: 512)
11219 +
11220 + apc.include_once_override
11221 + Optimize include_once and require_once calls and avoid the
11222 + expensive system calls used.
11223 + (Default: 0)
11224 Index: php-5.2.4/ext/apc/LICENSE
11225 ===================================================================
11226 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11227 +++ php-5.2.4/ext/apc/LICENSE 2007-09-02 12:24:46.000000000 +0200
11228 @@ -0,0 +1,68 @@
11229 +--------------------------------------------------------------------
11230 + The PHP License, version 3.01
11231 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
11232 +--------------------------------------------------------------------
11233 +
11234 +Redistribution and use in source and binary forms, with or without
11235 +modification, is permitted provided that the following conditions
11236 +are met:
11237 +
11238 + 1. Redistributions of source code must retain the above copyright
11239 + notice, this list of conditions and the following disclaimer.
11240 +
11241 + 2. Redistributions in binary form must reproduce the above copyright
11242 + notice, this list of conditions and the following disclaimer in
11243 + the documentation and/or other materials provided with the
11244 + distribution.
11245 +
11246 + 3. The name "PHP" must not be used to endorse or promote products
11247 + derived from this software without prior written permission. For
11248 + written permission, please contact group@php.net.
11249 +
11250 + 4. Products derived from this software may not be called "PHP", nor
11251 + may "PHP" appear in their name, without prior written permission
11252 + from group@php.net. You may indicate that your software works in
11253 + conjunction with PHP by saying "Foo for PHP" instead of calling
11254 + it "PHP Foo" or "phpfoo"
11255 +
11256 + 5. The PHP Group may publish revised and/or new versions of the
11257 + license from time to time. Each version will be given a
11258 + distinguishing version number.
11259 + Once covered code has been published under a particular version
11260 + of the license, you may always continue to use it under the terms
11261 + of that version. You may also choose to use such covered code
11262 + under the terms of any subsequent version of the license
11263 + published by the PHP Group. No one other than the PHP Group has
11264 + the right to modify the terms applicable to covered code created
11265 + under this License.
11266 +
11267 + 6. Redistributions of any form whatsoever must retain the following
11268 + acknowledgment:
11269 + "This product includes PHP software, freely available from
11270 + <http://www.php.net/software/>".
11271 +
11272 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
11273 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
11274 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11275 +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
11276 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
11277 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11278 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
11279 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11280 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
11281 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11282 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11283 +OF THE POSSIBILITY OF SUCH DAMAGE.
11284 +
11285 +--------------------------------------------------------------------
11286 +
11287 +This software consists of voluntary contributions made by many
11288 +individuals on behalf of the PHP Group.
11289 +
11290 +The PHP Group can be contacted via Email at group@php.net.
11291 +
11292 +For more information on the PHP Group and the PHP project,
11293 +please see <http://www.php.net>.
11294 +
11295 +PHP includes the Zend Engine, freely available at
11296 +<http://www.zend.com>.
11297 Index: php-5.2.4/ext/apc/NOTICE
11298 ===================================================================
11299 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11300 +++ php-5.2.4/ext/apc/NOTICE 2007-09-02 12:24:46.000000000 +0200
11301 @@ -0,0 +1,43 @@
11302 +This is the NOTICE file that holds acknowledgements and stuff.
11303 +
11304 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
11305 +This extension is being released under the PHP License for complete compliance
11306 +with PHP and to encourage wide-spread use. It is our intention that this
11307 +project be kept open source and that all commercial spin-offs contribute their
11308 +modifications back into the public source-tree.
11309 +
11310 +Creators:
11311 + Daniel Cowgill
11312 + George Schlossnagle
11313 +
11314 +PHP5 support and major features by:
11315 + Arun C. Murthy
11316 + Gopal Vijayaraghavan
11317 + Rasmus Lerdorf
11318 +
11319 +This software was contributed to PHP by Community Connect Inc. in 2002
11320 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11321 +Future revisions and derivatives of this source code must acknowledge
11322 +Community Connect Inc. as the original contributor of this module by
11323 +leaving this note intact in the source code.
11324 +
11325 +All other licensing and usage conditions are those of the PHP Group.
11326 +
11327 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting
11328 +this project and providing a challenging and stimulating environment in
11329 +which exciting projects can happen.
11330 +
11331 +Contributors:
11332 + Mike Bretz bug fixes, GUI, and lots of work
11333 + Ricardo Galli changed read-write locks to prefer readers
11334 + Yann Grossel bug fixes
11335 + Thies Arntzen bug fixes
11336 + Sara Golemon optimizer work
11337 +
11338 +Special Thanks:
11339 + Florian Baumert help debugging phplib problems
11340 + Thomas Duffey help debugging inheritance issues
11341 + Vibol Hou help debugging phplib problems
11342 + Angel Li diffs for ANSI comment compliance
11343 + Christian Rishøj help debugging phplib problems
11344 + Sascha Schumann memory error bug fix
11345 Index: php-5.2.4/ext/apc/pgsql_s_lock.c
11346 ===================================================================
11347 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11348 +++ php-5.2.4/ext/apc/pgsql_s_lock.c 2007-09-02 12:24:46.000000000 +0200
11349 @@ -0,0 +1,481 @@
11350 +/*
11351 + +----------------------------------------------------------------------+
11352 + | APC |
11353 + +----------------------------------------------------------------------+
11354 + | Copyright (c) 2007 The PHP Group |
11355 + +----------------------------------------------------------------------+
11356 + | This source file is subject to version 3.01 of the PHP license, |
11357 + | that is bundled with this package in the file LICENSE, and is |
11358 + | available through the world-wide-web at the following url: |
11359 + | http://www.php.net/license/3_01.txt |
11360 + | If you did not receive a copy of the PHP license and are unable to |
11361 + | obtain it through the world-wide-web, please send a note to |
11362 + | license@php.net so we can mail you a copy immediately. |
11363 + +----------------------------------------------------------------------+
11364 + | The following code was ported from the PostgreSQL project, please |
11365 + | see appropriate copyright notices that follow. |
11366 + | Initial conversion by Brian Shire <shire@php.net> |
11367 + +----------------------------------------------------------------------+
11368 +
11369 + */
11370 +
11371 +/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
11372 +
11373 +/*-------------------------------------------------------------------------
11374 + *
11375 + * s_lock.c
11376 + * Hardware-dependent implementation of spinlocks.
11377 + *
11378 + *
11379 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11380 + * Portions Copyright (c) 1994, Regents of the University of California
11381 + *
11382 + *
11383 + * IDENTIFICATION
11384 + * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
11385 + *
11386 + *-------------------------------------------------------------------------
11387 + */
11388 +/* #include "postgres.h" -- Removed for APC */
11389 +
11390 +/* -- Added for APC -- */
11391 +#include "apc.h"
11392 +#ifdef APC_SPIN_LOCKS
11393 +
11394 +#ifdef S_LOCK_TEST
11395 +#include <stdio.h>
11396 +#endif
11397 +#ifndef WIN32
11398 +#include <sys/select.h>
11399 +#endif
11400 +/* ---- */
11401 +
11402 +#include <time.h>
11403 +#include <unistd.h>
11404 +
11405 +/* #include "storage/s_lock.h" -- Removed for APC */
11406 +#include "pgsql_s_lock.h"
11407 +
11408 +static int spins_per_delay = DEFAULT_SPINS_PER_DELAY;
11409 +
11410 +
11411 +/* -- APC specific additions ------------------------------*/
11412 +/* The following dependencies have been copied from
11413 + * other pgsql source files. The original locations
11414 + * have been noted.
11415 + */
11416 +
11417 +/* -- from include/c.h -- */
11418 +#ifndef TRUE
11419 +#define TRUE 1
11420 +#endif
11421 +
11422 +#ifndef FALSE
11423 +#define FALSE 0
11424 +#endif
11425 +
11426 +/* -- from include/pg_config_manual.h -- */
11427 +#define MAX_RANDOM_VALUE (0x7FFFFFFF)
11428 +
11429 +/*
11430 + * Max
11431 + * Return the maximum of two numbers.
11432 + */
11433 +#define Max(x, y) ((x) > (y) ? (x) : (y))
11434 +
11435 +/* -- from include/c.h -- */
11436 +/*
11437 + * Min
11438 + * Return the minimum of two numbers.
11439 + */
11440 +#define Min(x, y) ((x) < (y) ? (x) : (y))
11441 +
11442 +
11443 +/* -- from backend/port/win32/signal.c -- */
11444 +/*
11445 + * pg_usleep --- delay the specified number of microseconds.
11446 + *
11447 + * NOTE: although the delay is specified in microseconds, the effective
11448 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
11449 + * the requested delay to be rounded up to the next resolution boundary.
11450 + *
11451 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
11452 + */
11453 +void
11454 +pg_usleep(long microsec)
11455 +{
11456 + if (microsec > 0)
11457 + {
11458 +#ifndef WIN32
11459 + struct timeval delay;
11460 +
11461 + delay.tv_sec = microsec / 1000000L;
11462 + delay.tv_usec = microsec % 1000000L;
11463 + (void) select(0, NULL, NULL, NULL, &delay);
11464 +#else
11465 + SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
11466 +#endif
11467 + }
11468 +}
11469 +
11470 +/* -- End APC specific additions ------------------------------*/
11471 +
11472 +
11473 +/*
11474 + * s_lock_stuck() - complain about a stuck spinlock
11475 + */
11476 +static void
11477 +s_lock_stuck(volatile slock_t *lock, const char *file, int line)
11478 +{
11479 +#if defined(S_LOCK_TEST)
11480 + fprintf(stderr,
11481 + "\nStuck spinlock (%p) detected at %s:%d.\n",
11482 + lock, file, line);
11483 + exit(1);
11484 +#else
11485 + /* -- Removed for APC
11486 + elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
11487 + lock, file, line);
11488 + */
11489 + apc_eprint("Stuck spinlock (%p) detected", lock);
11490 +#endif
11491 +}
11492 +
11493 +
11494 +/*
11495 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
11496 + */
11497 +void
11498 +s_lock(volatile slock_t *lock, const char *file, int line)
11499 +{
11500 + /*
11501 + * We loop tightly for awhile, then delay using pg_usleep() and try again.
11502 + * Preferably, "awhile" should be a small multiple of the maximum time we
11503 + * expect a spinlock to be held. 100 iterations seems about right as an
11504 + * initial guess. However, on a uniprocessor the loop is a waste of
11505 + * cycles, while in a multi-CPU scenario it's usually better to spin a bit
11506 + * longer than to call the kernel, so we try to adapt the spin loop count
11507 + * depending on whether we seem to be in a uniprocessor or multiprocessor.
11508 + *
11509 + * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
11510 + * be wrong; there are platforms where that can result in a "stuck
11511 + * spinlock" failure. This has been seen particularly on Alphas; it seems
11512 + * that the first TAS after returning from kernel space will always fail
11513 + * on that hardware.
11514 + *
11515 + * Once we do decide to block, we use randomly increasing pg_usleep()
11516 + * delays. The first delay is 1 msec, then the delay randomly increases to
11517 + * about one second, after which we reset to 1 msec and start again. The
11518 + * idea here is that in the presence of heavy contention we need to
11519 + * increase the delay, else the spinlock holder may never get to run and
11520 + * release the lock. (Consider situation where spinlock holder has been
11521 + * nice'd down in priority by the scheduler --- it will not get scheduled
11522 + * until all would-be acquirers are sleeping, so if we always use a 1-msec
11523 + * sleep, there is a real possibility of starvation.) But we can't just
11524 + * clamp the delay to an upper bound, else it would take a long time to
11525 + * make a reasonable number of tries.
11526 + *
11527 + * We time out and declare error after NUM_DELAYS delays (thus, exactly
11528 + * that many tries). With the given settings, this will usually take 2 or
11529 + * so minutes. It seems better to fix the total number of tries (and thus
11530 + * the probability of unintended failure) than to fix the total time
11531 + * spent.
11532 + *
11533 + * The pg_usleep() delays are measured in milliseconds because 1 msec is a
11534 + * common resolution limit at the OS level for newer platforms. On older
11535 + * platforms the resolution limit is usually 10 msec, in which case the
11536 + * total delay before timeout will be a bit more.
11537 + */
11538 +#define MIN_SPINS_PER_DELAY 10
11539 +#define MAX_SPINS_PER_DELAY 1000
11540 +#define NUM_DELAYS 1000
11541 +#define MIN_DELAY_MSEC 1
11542 +#define MAX_DELAY_MSEC 1000
11543 +
11544 + int spins = 0;
11545 + int delays = 0;
11546 + int cur_delay = 0;
11547 +
11548 + while (TAS(lock))
11549 + {
11550 + /* CPU-specific delay each time through the loop */
11551 + SPIN_DELAY();
11552 +
11553 + /* Block the process every spins_per_delay tries */
11554 + if (++spins >= spins_per_delay)
11555 + {
11556 + if (++delays > NUM_DELAYS)
11557 + s_lock_stuck(lock, file, line);
11558 +
11559 + if (cur_delay == 0) /* first time to delay? */
11560 + cur_delay = MIN_DELAY_MSEC;
11561 +
11562 + pg_usleep(cur_delay * 1000L);
11563 +
11564 +#if defined(S_LOCK_TEST)
11565 + fprintf(stdout, "*");
11566 + fflush(stdout);
11567 +#endif
11568 +
11569 + /* increase delay by a random fraction between 1X and 2X */
11570 + cur_delay += (int) (cur_delay *
11571 + ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
11572 + /* wrap back to minimum delay when max is exceeded */
11573 + if (cur_delay > MAX_DELAY_MSEC)
11574 + cur_delay = MIN_DELAY_MSEC;
11575 +
11576 + spins = 0;
11577 + }
11578 + }
11579 +
11580 + /*
11581 + * If we were able to acquire the lock without delaying, it's a good
11582 + * indication we are in a multiprocessor. If we had to delay, it's a sign
11583 + * (but not a sure thing) that we are in a uniprocessor. Hence, we
11584 + * decrement spins_per_delay slowly when we had to delay, and increase it
11585 + * rapidly when we didn't. It's expected that spins_per_delay will
11586 + * converge to the minimum value on a uniprocessor and to the maximum
11587 + * value on a multiprocessor.
11588 + *
11589 + * Note: spins_per_delay is local within our current process. We want to
11590 + * average these observations across multiple backends, since it's
11591 + * relatively rare for this function to even get entered, and so a single
11592 + * backend might not live long enough to converge on a good value. That
11593 + * is handled by the two routines below.
11594 + */
11595 + if (cur_delay == 0)
11596 + {
11597 + /* we never had to delay */
11598 + if (spins_per_delay < MAX_SPINS_PER_DELAY)
11599 + spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
11600 + }
11601 + else
11602 + {
11603 + if (spins_per_delay > MIN_SPINS_PER_DELAY)
11604 + spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
11605 + }
11606 +}
11607 +
11608 +
11609 +#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
11610 +/*
11611 + * Set local copy of spins_per_delay during backend startup.
11612 + *
11613 + * NB: this has to be pretty fast as it is called while holding a spinlock
11614 + */
11615 +void
11616 +set_spins_per_delay(int shared_spins_per_delay)
11617 +{
11618 + spins_per_delay = shared_spins_per_delay;
11619 +}
11620 +
11621 +/*
11622 + * Update shared estimate of spins_per_delay during backend exit.
11623 + *
11624 + * NB: this has to be pretty fast as it is called while holding a spinlock
11625 + */
11626 +int
11627 +update_spins_per_delay(int shared_spins_per_delay)
11628 +{
11629 + /*
11630 + * We use an exponential moving average with a relatively slow adaption
11631 + * rate, so that noise in any one backend's result won't affect the shared
11632 + * value too much. As long as both inputs are within the allowed range,
11633 + * the result must be too, so we need not worry about clamping the result.
11634 + *
11635 + * We deliberately truncate rather than rounding; this is so that single
11636 + * adjustments inside a backend can affect the shared estimate (see the
11637 + * asymmetric adjustment rules above).
11638 + */
11639 + return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
11640 +}
11641 +#endif
11642 +
11643 +/*
11644 + * Various TAS implementations that cannot live in s_lock.h as no inline
11645 + * definition exists (yet).
11646 + * In the future, get rid of tas.[cso] and fold it into this file.
11647 + *
11648 + * If you change something here, you will likely need to modify s_lock.h too,
11649 + * because the definitions for these are split between this file and s_lock.h.
11650 + */
11651 +
11652 +
11653 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
11654 +
11655 +
11656 +#if defined(__GNUC__)
11657 +
11658 +/*
11659 + * All the gcc flavors that are not inlined
11660 + */
11661 +
11662 +
11663 +/*
11664 + * Note: all the if-tests here probably ought to be testing gcc version
11665 + * rather than platform, but I don't have adequate info to know what to
11666 + * write. Ideally we'd flush all this in favor of the inline version.
11667 + */
11668 +#if defined(__m68k__) && !defined(__linux__)
11669 +/* really means: extern int tas(slock_t* **lock); */
11670 +static void
11671 +tas_dummy()
11672 +{
11673 + __asm__ __volatile__(
11674 +#if defined(__NetBSD__) && defined(__ELF__)
11675 +/* no underscore for label and % for registers */
11676 + "\
11677 +.global tas \n\
11678 +tas: \n\
11679 + movel %sp@(0x4),%a0 \n\
11680 + tas %a0@ \n\
11681 + beq _success \n\
11682 + moveq #-128,%d0 \n\
11683 + rts \n\
11684 +_success: \n\
11685 + moveq #0,%d0 \n\
11686 + rts \n"
11687 +#else
11688 + "\
11689 +.global _tas \n\
11690 +_tas: \n\
11691 + movel sp@(0x4),a0 \n\
11692 + tas a0@ \n\
11693 + beq _success \n\
11694 + moveq #-128,d0 \n\
11695 + rts \n\
11696 +_success: \n\
11697 + moveq #0,d0 \n\
11698 + rts \n"
11699 +#endif /* __NetBSD__ && __ELF__ */
11700 + );
11701 +}
11702 +#endif /* __m68k__ && !__linux__ */
11703 +#else /* not __GNUC__ */
11704 +
11705 +/*
11706 + * All non gcc
11707 + */
11708 +
11709 +
11710 +#if defined(sun3)
11711 +static void
11712 +tas_dummy() /* really means: extern int tas(slock_t
11713 + * *lock); */
11714 +{
11715 + asm("LLA0:");
11716 + asm(" .data");
11717 + asm(" .text");
11718 + asm("|#PROC# 04");
11719 + asm(" .globl _tas");
11720 + asm("_tas:");
11721 + asm("|#PROLOGUE# 1");
11722 + asm(" movel sp@(0x4),a0");
11723 + asm(" tas a0@");
11724 + asm(" beq LLA1");
11725 + asm(" moveq #-128,d0");
11726 + asm(" rts");
11727 + asm("LLA1:");
11728 + asm(" moveq #0,d0");
11729 + asm(" rts");
11730 + asm(" .data");
11731 +}
11732 +#endif /* sun3 */
11733 +#endif /* not __GNUC__ */
11734 +#endif /* HAVE_SPINLOCKS */
11735 +
11736 +
11737 +
11738 +/*****************************************************************************/
11739 +#if defined(S_LOCK_TEST)
11740 +
11741 +/*
11742 + * test program for verifying a port's spinlock support.
11743 + */
11744 +
11745 +struct test_lock_struct
11746 +{
11747 + char pad1;
11748 + slock_t lock;
11749 + char pad2;
11750 +};
11751 +
11752 +volatile struct test_lock_struct test_lock;
11753 +
11754 +int
11755 +main()
11756 +{
11757 + srandom((unsigned int) time(NULL));
11758 +
11759 + test_lock.pad1 = test_lock.pad2 = 0x44;
11760 +
11761 + S_INIT_LOCK(&test_lock.lock);
11762 +
11763 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11764 + {
11765 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11766 + return 1;
11767 + }
11768 +
11769 + if (!S_LOCK_FREE(&test_lock.lock))
11770 + {
11771 + printf("S_LOCK_TEST: failed, lock not initialized\n");
11772 + return 1;
11773 + }
11774 +
11775 + S_LOCK(&test_lock.lock);
11776 +
11777 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11778 + {
11779 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11780 + return 1;
11781 + }
11782 +
11783 + if (S_LOCK_FREE(&test_lock.lock))
11784 + {
11785 + printf("S_LOCK_TEST: failed, lock not locked\n");
11786 + return 1;
11787 + }
11788 +
11789 + S_UNLOCK(&test_lock.lock);
11790 +
11791 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11792 + {
11793 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11794 + return 1;
11795 + }
11796 +
11797 + if (!S_LOCK_FREE(&test_lock.lock))
11798 + {
11799 + printf("S_LOCK_TEST: failed, lock not unlocked\n");
11800 + return 1;
11801 + }
11802 +
11803 + S_LOCK(&test_lock.lock);
11804 +
11805 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11806 + {
11807 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11808 + return 1;
11809 + }
11810 +
11811 + if (S_LOCK_FREE(&test_lock.lock))
11812 + {
11813 + printf("S_LOCK_TEST: failed, lock not re-locked\n");
11814 + return 1;
11815 + }
11816 +
11817 + printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
11818 + printf(" exit with a 'stuck spinlock' message\n");
11819 + printf(" if S_LOCK() and TAS() are working.\n");
11820 + fflush(stdout);
11821 +
11822 + s_lock(&test_lock.lock, __FILE__, __LINE__);
11823 +
11824 + printf("S_LOCK_TEST: failed, lock not locked\n");
11825 + return 1;
11826 +}
11827 +
11828 +#endif /* S_LOCK_TEST */
11829 +
11830 +#endif /* APC_SPIN_LOCKS */
11831 Index: php-5.2.4/ext/apc/pgsql_s_lock.h
11832 ===================================================================
11833 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11834 +++ php-5.2.4/ext/apc/pgsql_s_lock.h 2007-09-02 12:24:46.000000000 +0200
11835 @@ -0,0 +1,928 @@
11836 +/*
11837 + +----------------------------------------------------------------------+
11838 + | APC |
11839 + +----------------------------------------------------------------------+
11840 + | Copyright (c) 2007 The PHP Group |
11841 + +----------------------------------------------------------------------+
11842 + | This source file is subject to version 3.01 of the PHP license, |
11843 + | that is bundled with this package in the file LICENSE, and is |
11844 + | available through the world-wide-web at the following url: |
11845 + | http://www.php.net/license/3_01.txt |
11846 + | If you did not receive a copy of the PHP license and are unable to |
11847 + | obtain it through the world-wide-web, please send a note to |
11848 + | license@php.net so we can mail you a copy immediately. |
11849 + +----------------------------------------------------------------------+
11850 + | The following code was ported from the PostgreSQL project, please |
11851 + | see appropriate copyright notices that follow. |
11852 + | Initial conversion by Brian Shire <shire@php.net> |
11853 + +----------------------------------------------------------------------+
11854 +
11855 + */
11856 +
11857 +/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
11858 +
11859 +/*-------------------------------------------------------------------------
11860 + *
11861 + * s_lock.h
11862 + * Hardware-dependent implementation of spinlocks.
11863 + *
11864 + * NOTE: none of the macros in this file are intended to be called directly.
11865 + * Call them through the hardware-independent macros in spin.h.
11866 + *
11867 + * The following hardware-dependent macros must be provided for each
11868 + * supported platform:
11869 + *
11870 + * void S_INIT_LOCK(slock_t *lock)
11871 + * Initialize a spinlock (to the unlocked state).
11872 + *
11873 + * void S_LOCK(slock_t *lock)
11874 + * Acquire a spinlock, waiting if necessary.
11875 + * Time out and abort() if unable to acquire the lock in a
11876 + * "reasonable" amount of time --- typically ~ 1 minute.
11877 + *
11878 + * void S_UNLOCK(slock_t *lock)
11879 + * Unlock a previously acquired lock.
11880 + *
11881 + * bool S_LOCK_FREE(slock_t *lock)
11882 + * Tests if the lock is free. Returns TRUE if free, FALSE if locked.
11883 + * This does *not* change the state of the lock.
11884 + *
11885 + * void SPIN_DELAY(void)
11886 + * Delay operation to occur inside spinlock wait loop.
11887 + *
11888 + * Note to implementors: there are default implementations for all these
11889 + * macros at the bottom of the file. Check if your platform can use
11890 + * these or needs to override them.
11891 + *
11892 + * Usually, S_LOCK() is implemented in terms of an even lower-level macro
11893 + * TAS():
11894 + *
11895 + * int TAS(slock_t *lock)
11896 + * Atomic test-and-set instruction. Attempt to acquire the lock,
11897 + * but do *not* wait. Returns 0 if successful, nonzero if unable
11898 + * to acquire the lock.
11899 + *
11900 + * TAS() is NOT part of the API, and should never be called directly.
11901 + *
11902 + * CAUTION: on some platforms TAS() may sometimes report failure to acquire
11903 + * a lock even when the lock is not locked. For example, on Alpha TAS()
11904 + * will "fail" if interrupted. Therefore TAS() should always be invoked
11905 + * in a retry loop, even if you are certain the lock is free.
11906 + *
11907 + * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
11908 + * points, ie, loads and stores of other values must not be moved across
11909 + * a lock or unlock. In most cases it suffices to make the operation be
11910 + * done through a "volatile" pointer.
11911 + *
11912 + * On most supported platforms, TAS() uses a tas() function written
11913 + * in assembly language to execute a hardware atomic-test-and-set
11914 + * instruction. Equivalent OS-supplied mutex routines could be used too.
11915 + *
11916 + * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
11917 + * defined), then we fall back on an emulation that uses SysV semaphores
11918 + * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
11919 + * implementation, because of the cost of a kernel call per lock or unlock.
11920 + * An old report is that Postgres spends around 40% of its time in semop(2)
11921 + * when using the SysV semaphore code.
11922 + *
11923 + *
11924 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11925 + * Portions Copyright (c) 1994, Regents of the University of California
11926 + *
11927 + * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
11928 + *
11929 + *-------------------------------------------------------------------------
11930 + */
11931 +#ifndef S_LOCK_H
11932 +#define S_LOCK_H
11933 +
11934 +/** APC namespace protection ************************************************/
11935 +/* hack to protect against any possible runtime namespace collisions...*/
11936 +#define pg_usleep apc_spin_pg_usleep
11937 +#define s_lock apc_spin_s_lock
11938 +#define spins_per_delay apc_spin_spins_per_delay
11939 +/****************************************************************************/
11940 +
11941 +
11942 +/* #include "storage/pg_sema.h" -- Removed for APC */
11943 +
11944 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
11945 +
11946 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
11947 +
11948 +
11949 +#if defined(__GNUC__) || defined(__ICC)
11950 +/*************************************************************************
11951 + * All the gcc inlines
11952 + * Gcc consistently defines the CPU as __cpu__.
11953 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
11954 + */
11955 +
11956 +/*----------
11957 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
11958 +
11959 + __asm__ __volatile__(
11960 + " instruction \n"
11961 + " instruction \n"
11962 + " instruction \n"
11963 +: "=r"(_res), "+m"(*lock) // return register, in/out lock value
11964 +: "r"(lock) // lock pointer, in input register
11965 +: "memory", "cc"); // show clobbered registers here
11966 +
11967 + * The output-operands list (after first colon) should always include
11968 + * "+m"(*lock), whether or not the asm code actually refers to this
11969 + * operand directly. This ensures that gcc believes the value in the
11970 + * lock variable is used and set by the asm code. Also, the clobbers
11971 + * list (after third colon) should always include "memory"; this prevents
11972 + * gcc from thinking it can cache the values of shared-memory fields
11973 + * across the asm code. Add "cc" if your asm code changes the condition
11974 + * code register, and also list any temp registers the code uses.
11975 + *----------
11976 + */
11977 +
11978 +
11979 +#ifdef __i386__ /* 32-bit i386 */
11980 +#define HAS_TEST_AND_SET
11981 +
11982 +typedef unsigned char slock_t;
11983 +
11984 +#define TAS(lock) tas(lock)
11985 +
11986 +static __inline__ int
11987 +tas(volatile slock_t *lock)
11988 +{
11989 + register slock_t _res = 1;
11990 +
11991 + /*
11992 + * Use a non-locking test before asserting the bus lock. Note that the
11993 + * extra test appears to be a small loss on some x86 platforms and a small
11994 + * win on others; it's by no means clear that we should keep it.
11995 + */
11996 + __asm__ __volatile__(
11997 + " cmpb $0,%1 \n"
11998 + " jne 1f \n"
11999 + " lock \n"
12000 + " xchgb %0,%1 \n"
12001 + "1: \n"
12002 +: "+q"(_res), "+m"(*lock)
12003 +:
12004 +: "memory", "cc");
12005 + return (int) _res;
12006 +}
12007 +
12008 +#define SPIN_DELAY() spin_delay()
12009 +
12010 +static __inline__ void
12011 +spin_delay(void)
12012 +{
12013 + /*
12014 + * This sequence is equivalent to the PAUSE instruction ("rep" is
12015 + * ignored by old IA32 processors if the following instruction is
12016 + * not a string operation); the IA-32 Architecture Software
12017 + * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
12018 + * PAUSE in the inner loop of a spin lock is necessary for good
12019 + * performance:
12020 + *
12021 + * The PAUSE instruction improves the performance of IA-32
12022 + * processors supporting Hyper-Threading Technology when
12023 + * executing spin-wait loops and other routines where one
12024 + * thread is accessing a shared lock or semaphore in a tight
12025 + * polling loop. When executing a spin-wait loop, the
12026 + * processor can suffer a severe performance penalty when
12027 + * exiting the loop because it detects a possible memory order
12028 + * violation and flushes the core processor's pipeline. The
12029 + * PAUSE instruction provides a hint to the processor that the
12030 + * code sequence is a spin-wait loop. The processor uses this
12031 + * hint to avoid the memory order violation and prevent the
12032 + * pipeline flush. In addition, the PAUSE instruction
12033 + * de-pipelines the spin-wait loop to prevent it from
12034 + * consuming execution resources excessively.
12035 + */
12036 + __asm__ __volatile__(
12037 + " rep; nop \n");
12038 +}
12039 +
12040 +#endif /* __i386__ */
12041 +
12042 +
12043 +#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
12044 +#define HAS_TEST_AND_SET
12045 +
12046 +typedef unsigned char slock_t;
12047 +
12048 +#define TAS(lock) tas(lock)
12049 +
12050 +static __inline__ int
12051 +tas(volatile slock_t *lock)
12052 +{
12053 + register slock_t _res = 1;
12054 +
12055 + /*
12056 + * On Opteron, using a non-locking test before the locking instruction
12057 + * is a huge loss. On EM64T, it appears to be a wash or small loss,
12058 + * so we needn't bother to try to distinguish the sub-architectures.
12059 + */
12060 + __asm__ __volatile__(
12061 + " lock \n"
12062 + " xchgb %0,%1 \n"
12063 +: "+q"(_res), "+m"(*lock)
12064 +:
12065 +: "memory", "cc");
12066 + return (int) _res;
12067 +}
12068 +
12069 +#define SPIN_DELAY() spin_delay()
12070 +
12071 +static __inline__ void
12072 +spin_delay(void)
12073 +{
12074 + /*
12075 + * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
12076 + * Opteron, but it may be of some use on EM64T, so we keep it.
12077 + */
12078 + __asm__ __volatile__(
12079 + " rep; nop \n");
12080 +}
12081 +
12082 +#endif /* __x86_64__ */
12083 +
12084 +
12085 +#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */
12086 +#define HAS_TEST_AND_SET
12087 +
12088 +typedef unsigned int slock_t;
12089 +
12090 +#define TAS(lock) tas(lock)
12091 +
12092 +#ifndef __INTEL_COMPILER
12093 +
12094 +static __inline__ int
12095 +tas(volatile slock_t *lock)
12096 +{
12097 + long int ret;
12098 +
12099 + __asm__ __volatile__(
12100 + " xchg4 %0=%1,%2 \n"
12101 +: "=r"(ret), "+m"(*lock)
12102 +: "r"(1)
12103 +: "memory");
12104 + return (int) ret;
12105 +}
12106 +
12107 +#else /* __INTEL_COMPILER */
12108 +
12109 +static __inline__ int
12110 +tas(volatile slock_t *lock)
12111 +{
12112 + int ret;
12113 +
12114 + ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
12115 +
12116 + return ret;
12117 +}
12118 +
12119 +#endif /* __INTEL_COMPILER */
12120 +#endif /* __ia64__ || __ia64 */
12121 +
12122 +
12123 +#if defined(__arm__) || defined(__arm)
12124 +#define HAS_TEST_AND_SET
12125 +
12126 +typedef unsigned char slock_t;
12127 +
12128 +#define TAS(lock) tas(lock)
12129 +
12130 +static __inline__ int
12131 +tas(volatile slock_t *lock)
12132 +{
12133 + register slock_t _res = 1;
12134 +
12135 + __asm__ __volatile__(
12136 + " swpb %0, %0, [%2] \n"
12137 +: "+r"(_res), "+m"(*lock)
12138 +: "r"(lock)
12139 +: "memory");
12140 + return (int) _res;
12141 +}
12142 +
12143 +#endif /* __arm__ */
12144 +
12145 +
12146 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
12147 +#if defined(__s390__) || defined(__s390x__)
12148 +#define HAS_TEST_AND_SET
12149 +
12150 +typedef unsigned int slock_t;
12151 +
12152 +#define TAS(lock) tas(lock)
12153 +
12154 +static __inline__ int
12155 +tas(volatile slock_t *lock)
12156 +{
12157 + int _res = 0;
12158 +
12159 + __asm__ __volatile__(
12160 + " cs %0,%3,0(%2) \n"
12161 +: "+d"(_res), "+m"(*lock)
12162 +: "a"(lock), "d"(1)
12163 +: "memory", "cc");
12164 + return _res;
12165 +}
12166 +
12167 +#endif /* __s390__ || __s390x__ */
12168 +
12169 +
12170 +#if defined(__sparc__) /* Sparc */
12171 +#define HAS_TEST_AND_SET
12172 +
12173 +typedef unsigned char slock_t;
12174 +
12175 +#define TAS(lock) tas(lock)
12176 +
12177 +static __inline__ int
12178 +tas(volatile slock_t *lock)
12179 +{
12180 + register slock_t _res;
12181 +
12182 + /*
12183 + * See comment in /pg/backend/port/tas/solaris_sparc.s for why this
12184 + * uses "ldstub", and that file uses "cas". gcc currently generates
12185 + * sparcv7-targeted binaries, so "cas" use isn't possible.
12186 + */
12187 + __asm__ __volatile__(
12188 + " ldstub [%2], %0 \n"
12189 +: "=r"(_res), "+m"(*lock)
12190 +: "r"(lock)
12191 +: "memory");
12192 + return (int) _res;
12193 +}
12194 +
12195 +#endif /* __sparc__ */
12196 +
12197 +
12198 +/* PowerPC */
12199 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
12200 +#define HAS_TEST_AND_SET
12201 +
12202 +#if defined(__ppc64__) || defined(__powerpc64__)
12203 +typedef unsigned long slock_t;
12204 +#else
12205 +typedef unsigned int slock_t;
12206 +#endif
12207 +
12208 +#define TAS(lock) tas(lock)
12209 +/*
12210 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
12211 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
12212 + */
12213 +static __inline__ int
12214 +tas(volatile slock_t *lock)
12215 +{
12216 + slock_t _t;
12217 + int _res;
12218 +
12219 + __asm__ __volatile__(
12220 +" lwarx %0,0,%3 \n"
12221 +" cmpwi %0,0 \n"
12222 +" bne 1f \n"
12223 +" addi %0,%0,1 \n"
12224 +" stwcx. %0,0,%3 \n"
12225 +" beq 2f \n"
12226 +"1: li %1,1 \n"
12227 +" b 3f \n"
12228 +"2: \n"
12229 +" isync \n"
12230 +" li %1,0 \n"
12231 +"3: \n"
12232 +
12233 +: "=&r"(_t), "=r"(_res), "+m"(*lock)
12234 +: "r"(lock)
12235 +: "memory", "cc");
12236 + return _res;
12237 +}
12238 +
12239 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
12240 +#define S_UNLOCK(lock) \
12241 +do \
12242 +{ \
12243 + __asm__ __volatile__ (" sync \n"); \
12244 + *((volatile slock_t *) (lock)) = 0; \
12245 +} while (0)
12246 +
12247 +#endif /* powerpc */
12248 +
12249 +
12250 +/* Linux Motorola 68k */
12251 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
12252 +#define HAS_TEST_AND_SET
12253 +
12254 +typedef unsigned char slock_t;
12255 +
12256 +#define TAS(lock) tas(lock)
12257 +
12258 +static __inline__ int
12259 +tas(volatile slock_t *lock)
12260 +{
12261 + register int rv;
12262 +
12263 + __asm__ __volatile__(
12264 + " clrl %0 \n"
12265 + " tas %1 \n"
12266 + " sne %0 \n"
12267 +: "=d"(rv), "+m"(*lock)
12268 +:
12269 +: "memory", "cc");
12270 + return rv;
12271 +}
12272 +
12273 +#endif /* (__mc68000__ || __m68k__) && __linux__ */
12274 +
12275 +
12276 +/*
12277 + * VAXen -- even multiprocessor ones
12278 + * (thanks to Tom Ivar Helbekkmo)
12279 + */
12280 +#if defined(__vax__)
12281 +#define HAS_TEST_AND_SET
12282 +
12283 +typedef unsigned char slock_t;
12284 +
12285 +#define TAS(lock) tas(lock)
12286 +
12287 +static __inline__ int
12288 +tas(volatile slock_t *lock)
12289 +{
12290 + register int _res;
12291 +
12292 + __asm__ __volatile__(
12293 + " movl $1, %0 \n"
12294 + " bbssi $0, (%2), 1f \n"
12295 + " clrl %0 \n"
12296 + "1: \n"
12297 +: "=&r"(_res), "+m"(*lock)
12298 +: "r"(lock)
12299 +: "memory");
12300 + return _res;
12301 +}
12302 +
12303 +#endif /* __vax__ */
12304 +
12305 +
12306 +#if defined(__ns32k__) /* National Semiconductor 32K */
12307 +#define HAS_TEST_AND_SET
12308 +
12309 +typedef unsigned char slock_t;
12310 +
12311 +#define TAS(lock) tas(lock)
12312 +
12313 +static __inline__ int
12314 +tas(volatile slock_t *lock)
12315 +{
12316 + register int _res;
12317 +
12318 + __asm__ __volatile__(
12319 + " sbitb 0, %1 \n"
12320 + " sfsd %0 \n"
12321 +: "=r"(_res), "+m"(*lock)
12322 +:
12323 +: "memory");
12324 + return _res;
12325 +}
12326 +
12327 +#endif /* __ns32k__ */
12328 +
12329 +
12330 +#if defined(__alpha) || defined(__alpha__) /* Alpha */
12331 +/*
12332 + * Correct multi-processor locking methods are explained in section 5.5.3
12333 + * of the Alpha AXP Architecture Handbook, which at this writing can be
12334 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
12335 + * For gcc we implement the handbook's code directly with inline assembler.
12336 + */
12337 +#define HAS_TEST_AND_SET
12338 +
12339 +typedef unsigned long slock_t;
12340 +
12341 +#define TAS(lock) tas(lock)
12342 +
12343 +static __inline__ int
12344 +tas(volatile slock_t *lock)
12345 +{
12346 + register slock_t _res;
12347 +
12348 + __asm__ __volatile__(
12349 + " ldq $0, %1 \n"
12350 + " bne $0, 2f \n"
12351 + " ldq_l %0, %1 \n"
12352 + " bne %0, 2f \n"
12353 + " mov 1, $0 \n"
12354 + " stq_c $0, %1 \n"
12355 + " beq $0, 2f \n"
12356 + " mb \n"
12357 + " br 3f \n"
12358 + "2: mov 1, %0 \n"
12359 + "3: \n"
12360 +: "=&r"(_res), "+m"(*lock)
12361 +:
12362 +: "memory", "0");
12363 + return (int) _res;
12364 +}
12365 +
12366 +#define S_UNLOCK(lock) \
12367 +do \
12368 +{\
12369 + __asm__ __volatile__ (" mb \n"); \
12370 + *((volatile slock_t *) (lock)) = 0; \
12371 +} while (0)
12372 +
12373 +#endif /* __alpha || __alpha__ */
12374 +
12375 +
12376 +#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
12377 +/* Note: on SGI we use the OS' mutex ABI, see below */
12378 +/* Note: R10000 processors require a separate SYNC */
12379 +#define HAS_TEST_AND_SET
12380 +
12381 +typedef unsigned int slock_t;
12382 +
12383 +#define TAS(lock) tas(lock)
12384 +
12385 +static __inline__ int
12386 +tas(volatile slock_t *lock)
12387 +{
12388 + register volatile slock_t *_l = lock;
12389 + register int _res;
12390 + register int _tmp;
12391 +
12392 + __asm__ __volatile__(
12393 + " .set push \n"
12394 + " .set mips2 \n"
12395 + " .set noreorder \n"
12396 + " .set nomacro \n"
12397 + " ll %0, %2 \n"
12398 + " or %1, %0, 1 \n"
12399 + " sc %1, %2 \n"
12400 + " xori %1, 1 \n"
12401 + " or %0, %0, %1 \n"
12402 + " sync \n"
12403 + " .set pop "
12404 +: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
12405 +:
12406 +: "memory");
12407 + return _res;
12408 +}
12409 +
12410 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
12411 +#define S_UNLOCK(lock) \
12412 +do \
12413 +{ \
12414 + __asm__ __volatile__( \
12415 + " .set push \n" \
12416 + " .set mips2 \n" \
12417 + " .set noreorder \n" \
12418 + " .set nomacro \n" \
12419 + " sync \n" \
12420 + " .set pop "); \
12421 + *((volatile slock_t *) (lock)) = 0; \
12422 +} while (0)
12423 +
12424 +#endif /* __mips__ && !__sgi */
12425 +
12426 +
12427 +/* These live in s_lock.c, but only for gcc */
12428 +
12429 +
12430 +#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
12431 +#define HAS_TEST_AND_SET
12432 +
12433 +typedef unsigned char slock_t;
12434 +#endif
12435 +
12436 +
12437 +#endif /* __GNUC__ */
12438 +
12439 +
12440 +
12441 +/*
12442 + * ---------------------------------------------------------------------
12443 + * Platforms that use non-gcc inline assembly:
12444 + * ---------------------------------------------------------------------
12445 + */
12446 +
12447 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
12448 +
12449 +
12450 +#if defined(USE_UNIVEL_CC) /* Unixware compiler */
12451 +#define HAS_TEST_AND_SET
12452 +
12453 +typedef unsigned char slock_t;
12454 +
12455 +#define TAS(lock) tas(lock)
12456 +
12457 +asm int
12458 +tas(volatile slock_t *s_lock)
12459 +{
12460 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
12461 +%mem s_lock
12462 + pushl %ebx
12463 + movl s_lock, %ebx
12464 + movl $255, %eax
12465 + lock
12466 + xchgb %al, (%ebx)
12467 + popl %ebx
12468 +}
12469 +
12470 +#endif /* defined(USE_UNIVEL_CC) */
12471 +
12472 +
12473 +#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */
12474 +/*
12475 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
12476 + * have some builtin functions that accomplish much the same results.
12477 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
12478 + * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only
12479 + * operate on an int (ie, longword), but that's OK as long as we define
12480 + * S_INIT_LOCK to zero out the whole quadword.
12481 + */
12482 +#define HAS_TEST_AND_SET
12483 +
12484 +typedef unsigned long slock_t;
12485 +
12486 +#include <alpha/builtins.h>
12487 +#define S_INIT_LOCK(lock) (*(lock) = 0)
12488 +#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
12489 +#define S_UNLOCK(lock) __UNLOCK_LONG(lock)
12490 +
12491 +#endif /* __alpha || __alpha__ */
12492 +
12493 +
12494 +#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
12495 +/*
12496 + * HP's PA-RISC
12497 + *
12498 + * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
12499 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
12500 + * struct. The active word in the struct is whichever has the aligned address;
12501 + * the other three words just sit at -1.
12502 + *
12503 + * When using gcc, we can inline the required assembly code.
12504 + */
12505 +#define HAS_TEST_AND_SET
12506 +
12507 +typedef struct
12508 +{
12509 + int sema[4];
12510 +} slock_t;
12511 +
12512 +#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
12513 +
12514 +#if defined(__GNUC__)
12515 +
12516 +static __inline__ int
12517 +tas(volatile slock_t *lock)
12518 +{
12519 + volatile int *lockword = TAS_ACTIVE_WORD(lock);
12520 + register int lockval;
12521 +
12522 + __asm__ __volatile__(
12523 + " ldcwx 0(0,%2),%0 \n"
12524 +: "=r"(lockval), "+m"(*lockword)
12525 +: "r"(lockword)
12526 +: "memory");
12527 + return (lockval == 0);
12528 +}
12529 +
12530 +#endif /* __GNUC__ */
12531 +
12532 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
12533 +
12534 +#define S_INIT_LOCK(lock) \
12535 + do { \
12536 + volatile slock_t *lock_ = (lock); \
12537 + lock_->sema[0] = -1; \
12538 + lock_->sema[1] = -1; \
12539 + lock_->sema[2] = -1; \
12540 + lock_->sema[3] = -1; \
12541 + } while (0)
12542 +
12543 +#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
12544 +
12545 +#endif /* __hppa || __hppa__ */
12546 +
12547 +
12548 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
12549 +
12550 +#define HAS_TEST_AND_SET
12551 +
12552 +typedef unsigned int slock_t;
12553 +
12554 +#include <ia64/sys/inline.h>
12555 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
12556 +
12557 +#endif /* HPUX on IA64, non gcc */
12558 +
12559 +
12560 +#if defined(__sgi) /* SGI compiler */
12561 +/*
12562 + * SGI IRIX 5
12563 + * slock_t is defined as a unsigned long. We use the standard SGI
12564 + * mutex API.
12565 + *
12566 + * The following comment is left for historical reasons, but is probably
12567 + * not a good idea since the mutex ABI is supported.
12568 + *
12569 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
12570 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
12571 + * for the R3000 chips out there.
12572 + */
12573 +#define HAS_TEST_AND_SET
12574 +
12575 +typedef unsigned long slock_t;
12576 +
12577 +#include "mutex.h"
12578 +#define TAS(lock) (test_and_set(lock,1))
12579 +#define S_UNLOCK(lock) (test_then_and(lock,0))
12580 +#define S_INIT_LOCK(lock) (test_then_and(lock,0))
12581 +#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
12582 +#endif /* __sgi */
12583 +
12584 +
12585 +#if defined(sinix) /* Sinix */
12586 +/*
12587 + * SINIX / Reliant UNIX
12588 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
12589 + * member. (Basically same as SGI)
12590 + */
12591 +#define HAS_TEST_AND_SET
12592 +
12593 +#include "abi_mutex.h"
12594 +typedef abilock_t slock_t;
12595 +
12596 +#define TAS(lock) (!acquire_lock(lock))
12597 +#define S_UNLOCK(lock) release_lock(lock)
12598 +#define S_INIT_LOCK(lock) init_lock(lock)
12599 +#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
12600 +#endif /* sinix */
12601 +
12602 +
12603 +#if defined(_AIX) /* AIX */
12604 +/*
12605 + * AIX (POWER)
12606 + */
12607 +#define HAS_TEST_AND_SET
12608 +
12609 +typedef unsigned int slock_t;
12610 +
12611 +#define TAS(lock) _check_lock(lock, 0, 1)
12612 +#define S_UNLOCK(lock) _clear_lock(lock, 0)
12613 +#endif /* _AIX */
12614 +
12615 +
12616 +#if defined (nextstep) /* Nextstep */
12617 +#define HAS_TEST_AND_SET
12618 +
12619 +typedef struct mutex slock_t;
12620 +
12621 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */
12622 +
12623 +#define S_LOCK(lock) mutex_lock(lock)
12624 +#define S_UNLOCK(lock) mutex_unlock(lock)
12625 +#define S_INIT_LOCK(lock) mutex_init(lock)
12626 +/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
12627 +#define S_LOCK_FREE(alock) ((alock)->lock == 0)
12628 +#endif /* nextstep */
12629 +
12630 +
12631 +/* These are in s_lock.c */
12632 +
12633 +
12634 +#if defined(sun3) /* Sun3 */
12635 +#define HAS_TEST_AND_SET
12636 +
12637 +typedef unsigned char slock_t;
12638 +#endif
12639 +
12640 +
12641 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
12642 +#define HAS_TEST_AND_SET
12643 +
12644 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
12645 +typedef unsigned int slock_t;
12646 +#else
12647 +typedef unsigned char slock_t;
12648 +#endif
12649 +
12650 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
12651 + slock_t cmp);
12652 +
12653 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
12654 +#endif
12655 +
12656 +
12657 +#ifdef WIN32_ONLY_COMPILER
12658 +typedef LONG slock_t;
12659 +
12660 +#define HAS_TEST_AND_SET
12661 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
12662 +
12663 +#define SPIN_DELAY() spin_delay()
12664 +
12665 +static __forceinline void
12666 +spin_delay(void)
12667 +{
12668 + /* See comment for gcc code. Same code, MASM syntax */
12669 + __asm rep nop;
12670 +}
12671 +
12672 +#endif
12673 +
12674 +
12675 +#endif /* !defined(HAS_TEST_AND_SET) */
12676 +
12677 +
12678 +/* Blow up if we didn't have any way to do spinlocks */
12679 +#ifndef HAS_TEST_AND_SET
12680 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
12681 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
12682 +/* #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. */
12683 +#endif
12684 +
12685 +
12686 +#else /* !HAVE_SPINLOCKS */
12687 +
12688 +
12689 +/*
12690 + * Fake spinlock implementation using semaphores --- slow and prone
12691 + * to fall foul of kernel limits on number of semaphores, so don't use this
12692 + * unless you must! The subroutines appear in spin.c.
12693 + */
12694 +
12695 +/* -- Removed for APC
12696 +typedef PGSemaphoreData slock_t;
12697 +
12698 +extern bool s_lock_free_sema(volatile slock_t *lock);
12699 +extern void s_unlock_sema(volatile slock_t *lock);
12700 +extern void s_init_lock_sema(volatile slock_t *lock);
12701 +extern int tas_sema(volatile slock_t *lock);
12702 +
12703 +#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
12704 +#define S_UNLOCK(lock) s_unlock_sema(lock)
12705 +#define S_INIT_LOCK(lock) s_init_lock_sema(lock)
12706 +#define TAS(lock) tas_sema(lock)
12707 +*/
12708 +
12709 +#endif /* HAVE_SPINLOCKS */
12710 +
12711 +
12712 +/*
12713 + * Default Definitions - override these above as needed.
12714 + */
12715 +
12716 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
12717 +
12718 +#if !defined(S_LOCK)
12719 +#define S_LOCK(lock) \
12720 + do { \
12721 + if (TAS(lock)) \
12722 + s_lock((lock), __FILE__, __LINE__); \
12723 + } while (0)
12724 +#endif /* S_LOCK */
12725 +
12726 +#if !defined(S_LOCK_FREE)
12727 +#define S_LOCK_FREE(lock) (*(lock) == 0)
12728 +#endif /* S_LOCK_FREE */
12729 +
12730 +#if !defined(S_UNLOCK)
12731 +#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
12732 +#endif /* S_UNLOCK */
12733 +
12734 +#if !defined(S_INIT_LOCK)
12735 +#define S_INIT_LOCK(lock) S_UNLOCK(lock)
12736 +#endif /* S_INIT_LOCK */
12737 +
12738 +#if !defined(SPIN_DELAY)
12739 +#define SPIN_DELAY() ((void) 0)
12740 +#endif /* SPIN_DELAY */
12741 +
12742 +#if !defined(TAS)
12743 +extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
12744 + * s_lock.c */
12745 +
12746 +#define TAS(lock) tas(lock)
12747 +#endif /* TAS */
12748 +
12749 +
12750 +/*
12751 + * Platform-independent out-of-line support routines
12752 + */
12753 +extern void s_lock(volatile slock_t *lock, const char *file, int line);
12754 +
12755 +/* Support for dynamic adjustment of spins_per_delay */
12756 +#define DEFAULT_SPINS_PER_DELAY 100
12757 +
12758 +#if 0 /* -- Removed from APC use -- */
12759 +extern void set_spins_per_delay(int shared_spins_per_delay);
12760 +extern int update_spins_per_delay(int shared_spins_per_delay);
12761 +#endif
12762 +
12763 +#endif /* S_LOCK_H */
12764 Index: php-5.2.4/ext/apc/php_apc.c
12765 ===================================================================
12766 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
12767 +++ php-5.2.4/ext/apc/php_apc.c 2007-09-02 12:24:46.000000000 +0200
12768 @@ -0,0 +1,957 @@
12769 +/*
12770 + +----------------------------------------------------------------------+
12771 + | APC |
12772 + +----------------------------------------------------------------------+
12773 + | Copyright (c) 2006 The PHP Group |
12774 + +----------------------------------------------------------------------+
12775 + | This source file is subject to version 3.01 of the PHP license, |
12776 + | that is bundled with this package in the file LICENSE, and is |
12777 + | available through the world-wide-web at the following url: |
12778 + | http://www.php.net/license/3_01.txt |
12779 + | If you did not receive a copy of the PHP license and are unable to |
12780 + | obtain it through the world-wide-web, please send a note to |
12781 + | license@php.net so we can mail you a copy immediately. |
12782 + +----------------------------------------------------------------------+
12783 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
12784 + | Rasmus Lerdorf <rasmus@php.net> |
12785 + +----------------------------------------------------------------------+
12786 +
12787 + This software was contributed to PHP by Community Connect Inc. in 2002
12788 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12789 + Future revisions and derivatives of this source code must acknowledge
12790 + Community Connect Inc. as the original contributor of this module by
12791 + leaving this note intact in the source code.
12792 +
12793 + All other licensing and usage conditions are those of the PHP Group.
12794 +
12795 + */
12796 +
12797 +/* $Id: php_apc.c,v 3.140 2007/03/28 07:14:54 gopalv Exp $ */
12798 +
12799 +#include "apc_zend.h"
12800 +#include "apc_cache.h"
12801 +#include "apc_main.h"
12802 +#include "apc_sma.h"
12803 +#include "apc_lock.h"
12804 +#include "php_globals.h"
12805 +#include "php_ini.h"
12806 +#include "ext/standard/info.h"
12807 +#include "SAPI.h"
12808 +#include "rfc1867.h"
12809 +#include "php_apc.h"
12810 +#if PHP_API_VERSION <= 20020918
12811 +#if HAVE_APACHE
12812 +#ifdef APC_PHP4_STAT
12813 +#undef XtOffsetOf
12814 +#include "httpd.h"
12815 +#endif
12816 +#endif
12817 +#endif
12818 +
12819 +/* {{{ PHP_FUNCTION declarations */
12820 +PHP_FUNCTION(apc_cache_info);
12821 +PHP_FUNCTION(apc_clear_cache);
12822 +PHP_FUNCTION(apc_sma_info);
12823 +PHP_FUNCTION(apc_store);
12824 +PHP_FUNCTION(apc_fetch);
12825 +PHP_FUNCTION(apc_delete);
12826 +PHP_FUNCTION(apc_compile_file);
12827 +PHP_FUNCTION(apc_define_constants);
12828 +PHP_FUNCTION(apc_load_constants);
12829 +PHP_FUNCTION(apc_add);
12830 +/* }}} */
12831 +
12832 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
12833 +ZEND_DECLARE_MODULE_GLOBALS(apc)
12834 +
12835 +/* True globals */
12836 +apc_cache_t* apc_cache = NULL;
12837 +apc_cache_t* apc_user_cache = NULL;
12838 +void* apc_compiled_filters = NULL;
12839 +
12840 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12841 +{
12842 + apc_globals->filters = NULL;
12843 + apc_globals->initialized = 0;
12844 + apc_globals->cache_stack = apc_stack_create(0);
12845 + apc_globals->cache_by_default = 1;
12846 + apc_globals->slam_defense = 0;
12847 + apc_globals->mem_size_ptr = NULL;
12848 + apc_globals->fpstat = 1;
12849 + apc_globals->stat_ctime = 0;
12850 + apc_globals->write_lock = 1;
12851 + apc_globals->report_autofilter = 0;
12852 + apc_globals->apc_optimize_function = NULL;
12853 +#ifdef MULTIPART_EVENT_FORMDATA
12854 + apc_globals->rfc1867 = 0;
12855 +#endif
12856 + apc_globals->copied_zvals = NULL;
12857 +#ifdef ZEND_ENGINE_2
12858 + apc_globals->reserved_offset = -1;
12859 +#endif
12860 + apc_globals->localcache = 0;
12861 + apc_globals->localcache_size = 0;
12862 + apc_globals->lcache = NULL;
12863 +}
12864 +
12865 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12866 +{
12867 + /* deallocate the ignore patterns */
12868 + if (apc_globals->filters != NULL) {
12869 + int i;
12870 + for (i=0; apc_globals->filters[i] != NULL; i++) {
12871 + apc_efree(apc_globals->filters[i]);
12872 + }
12873 + apc_efree(apc_globals->filters);
12874 + }
12875 +
12876 + /* the stack should be empty */
12877 + assert(apc_stack_size(apc_globals->cache_stack) == 0);
12878 +
12879 + /* apc cleanup */
12880 + apc_stack_destroy(apc_globals->cache_stack);
12881 +
12882 + /* the rest of the globals are cleaned up in apc_module_shutdown() */
12883 +}
12884 +
12885 +/* }}} */
12886 +
12887 +/* {{{ PHP_INI */
12888 +
12889 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
12890 +{
12891 + APCG(filters) = apc_tokenize(new_value, ',');
12892 + return SUCCESS;
12893 +}
12894 +/* }}} */
12895 +
12896 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
12897 +{
12898 +#if APC_MMAP
12899 + if(atoi(new_value)!=1) {
12900 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
12901 + }
12902 + APCG(shm_segments) = 1;
12903 +#else
12904 + APCG(shm_segments) = atoi(new_value);
12905 +#endif
12906 + return SUCCESS;
12907 +}
12908 +/* }}} */
12909 +
12910 +
12911 +#ifdef ZEND_ENGINE_2
12912 +#define OnUpdateInt OnUpdateLong
12913 +#endif
12914 +
12915 +PHP_INI_BEGIN()
12916 +STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
12917 +STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
12918 +STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
12919 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
12920 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
12921 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
12922 +STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
12923 +STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
12924 +STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
12925 +#if APC_MMAP
12926 +STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
12927 +#endif
12928 +PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
12929 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
12930 +STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
12931 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
12932 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
12933 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
12934 +STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
12935 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
12936 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
12937 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
12938 +#ifdef MULTIPART_EVENT_FORMDATA
12939 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
12940 +#endif
12941 +STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
12942 +STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size, zend_apc_globals, apc_globals)
12943 +PHP_INI_END()
12944 +
12945 +/* }}} */
12946 +
12947 +/* {{{ PHP_MINFO_FUNCTION(apc) */
12948 +static PHP_MINFO_FUNCTION(apc)
12949 +{
12950 + php_info_print_table_start();
12951 + php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
12952 + php_info_print_table_row(2, "Version", APC_VERSION);
12953 +#if APC_MMAP
12954 + php_info_print_table_row(2, "MMAP Support", "Enabled");
12955 + php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
12956 +#else
12957 + php_info_print_table_row(2, "MMAP Support", "Disabled");
12958 +#endif
12959 +#if APC_SEM_LOCKS
12960 + php_info_print_table_row(2, "Locking type", "IPC Semaphore");
12961 +#elif APC_FUTEX_LOCKS
12962 + php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
12963 +#elif APC_PTHREADMUTEX_LOCKS
12964 + php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
12965 +#elif APC_SPIN_LOCKS
12966 + php_info_print_table_row(2, "Locking type", "spin Locks");
12967 +#else
12968 + php_info_print_table_row(2, "Locking type", "File Locks");
12969 +#endif
12970 + php_info_print_table_row(2, "Revision", "$Revision: 3.140 $");
12971 + php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
12972 + php_info_print_table_end();
12973 + DISPLAY_INI_ENTRIES();
12974 +}
12975 +/* }}} */
12976 +
12977 +#ifdef MULTIPART_EVENT_FORMDATA
12978 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
12979 +#endif
12980 +
12981 +/* {{{ PHP_MINIT_FUNCTION(apc) */
12982 +static PHP_MINIT_FUNCTION(apc)
12983 +{
12984 + ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
12985 +
12986 + REGISTER_INI_ENTRIES();
12987 +
12988 + /* Disable APC in cli mode unless overridden by apc.enable_cli */
12989 + if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
12990 + APCG(enabled) = 0;
12991 + }
12992 +
12993 + if (APCG(enabled)) {
12994 + if(APCG(initialized)) {
12995 + apc_process_init(module_number TSRMLS_CC);
12996 + } else {
12997 + apc_module_init(module_number TSRMLS_CC);
12998 + apc_zend_init(TSRMLS_C);
12999 + apc_process_init(module_number TSRMLS_CC);
13000 +#ifdef MULTIPART_EVENT_FORMDATA
13001 + /* File upload progress tracking */
13002 + if(APCG(rfc1867)) {
13003 + php_rfc1867_callback = apc_rfc1867_progress;
13004 + }
13005 +#endif
13006 + }
13007 + }
13008 +
13009 + return SUCCESS;
13010 +}
13011 +/* }}} */
13012 +
13013 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
13014 +static PHP_MSHUTDOWN_FUNCTION(apc)
13015 +{
13016 + if(APCG(enabled)) {
13017 + apc_process_shutdown(TSRMLS_C);
13018 + apc_zend_shutdown(TSRMLS_C);
13019 + apc_module_shutdown(TSRMLS_C);
13020 +#ifndef ZTS
13021 + php_apc_shutdown_globals(&apc_globals);
13022 +#endif
13023 + }
13024 +#ifdef ZTS
13025 + ts_free_id(apc_globals_id);
13026 +#endif
13027 + UNREGISTER_INI_ENTRIES();
13028 + return SUCCESS;
13029 +}
13030 +/* }}} */
13031 +
13032 +/* {{{ PHP_RINIT_FUNCTION(apc) */
13033 +static PHP_RINIT_FUNCTION(apc)
13034 +{
13035 + if(APCG(enabled)) {
13036 + apc_request_init(TSRMLS_C);
13037 + }
13038 + return SUCCESS;
13039 +}
13040 +/* }}} */
13041 +
13042 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
13043 +static PHP_RSHUTDOWN_FUNCTION(apc)
13044 +{
13045 + if(APCG(enabled)) {
13046 + apc_request_shutdown(TSRMLS_C);
13047 + }
13048 + return SUCCESS;
13049 +}
13050 +/* }}} */
13051 +
13052 +/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
13053 +PHP_FUNCTION(apc_cache_info)
13054 +{
13055 + apc_cache_info_t* info;
13056 + apc_cache_link_t* p;
13057 + zval* list;
13058 + char *cache_type;
13059 + int ct_len;
13060 + zend_bool limited=0;
13061 +
13062 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
13063 + return;
13064 + }
13065 +
13066 + if(ZEND_NUM_ARGS()) {
13067 + if(!strcasecmp(cache_type,"user")) {
13068 + info = apc_cache_info(apc_user_cache, limited);
13069 + } else {
13070 + info = apc_cache_info(apc_cache, limited);
13071 + }
13072 + } else info = apc_cache_info(apc_cache, limited);
13073 +
13074 + if(!info) {
13075 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
13076 + RETURN_FALSE;
13077 + }
13078 +
13079 + array_init(return_value);
13080 + add_assoc_long(return_value, "num_slots", info->num_slots);
13081 + add_assoc_long(return_value, "ttl", info->ttl);
13082 + add_assoc_long(return_value, "num_hits", info->num_hits);
13083 + add_assoc_long(return_value, "num_misses", info->num_misses);
13084 + add_assoc_long(return_value, "start_time", info->start_time);
13085 + add_assoc_long(return_value, "expunges", info->expunges);
13086 + add_assoc_long(return_value, "mem_size", info->mem_size);
13087 + add_assoc_long(return_value, "num_entries", info->num_entries);
13088 + add_assoc_long(return_value, "num_inserts", info->num_inserts);
13089 +#ifdef MULTIPART_EVENT_FORMDATA
13090 + add_assoc_long(return_value, "file_upload_progress", 1);
13091 +#else
13092 + add_assoc_long(return_value, "file_upload_progress", 0);
13093 +#endif
13094 +#if APC_MMAP
13095 + add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
13096 +#else
13097 + add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
13098 +#endif
13099 +#if APC_SEM_LOCKS
13100 + add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
13101 +#elif APC_FUTEX_LOCKS
13102 + add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
13103 +#elif APC_PTHREADMUTEX_LOCKS
13104 + add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
13105 +#elif APC_SPIN_LOCKS
13106 + add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
13107 +#else
13108 + add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
13109 +#endif
13110 + if(limited) {
13111 + apc_cache_free_info(info);
13112 + return;
13113 + }
13114 +
13115 + ALLOC_INIT_ZVAL(list);
13116 + array_init(list);
13117 +
13118 + for (p = info->list; p != NULL; p = p->next) {
13119 + zval* link;
13120 +
13121 + ALLOC_INIT_ZVAL(link);
13122 + array_init(link);
13123 +
13124 + if(p->type == APC_CACHE_ENTRY_FILE) {
13125 + add_assoc_string(link, "filename", p->data.file.filename, 1);
13126 + add_assoc_long(link, "device", p->data.file.device);
13127 + add_assoc_long(link, "inode", p->data.file.inode);
13128 + add_assoc_string(link, "type", "file", 1);
13129 + } else if(p->type == APC_CACHE_ENTRY_USER) {
13130 + add_assoc_string(link, "info", p->data.user.info, 1);
13131 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13132 + add_assoc_string(link, "type", "user", 1);
13133 + }
13134 + add_assoc_long(link, "num_hits", p->num_hits);
13135 + add_assoc_long(link, "mtime", p->mtime);
13136 + add_assoc_long(link, "creation_time", p->creation_time);
13137 + add_assoc_long(link, "deletion_time", p->deletion_time);
13138 + add_assoc_long(link, "access_time", p->access_time);
13139 + add_assoc_long(link, "ref_count", p->ref_count);
13140 + add_assoc_long(link, "mem_size", p->mem_size);
13141 + add_next_index_zval(list, link);
13142 + }
13143 + add_assoc_zval(return_value, "cache_list", list);
13144 +
13145 + ALLOC_INIT_ZVAL(list);
13146 + array_init(list);
13147 +
13148 + for (p = info->deleted_list; p != NULL; p = p->next) {
13149 + zval* link;
13150 +
13151 + ALLOC_INIT_ZVAL(link);
13152 + array_init(link);
13153 +
13154 + if(p->type == APC_CACHE_ENTRY_FILE) {
13155 + add_assoc_string(link, "filename", p->data.file.filename, 1);
13156 + add_assoc_long(link, "device", p->data.file.device);
13157 + add_assoc_long(link, "inode", p->data.file.inode);
13158 + add_assoc_string(link, "type", "file", 1);
13159 + } else if(p->type == APC_CACHE_ENTRY_USER) {
13160 + add_assoc_string(link, "info", p->data.user.info, 1);
13161 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13162 + add_assoc_string(link, "type", "user", 1);
13163 + }
13164 + add_assoc_long(link, "num_hits", p->num_hits);
13165 + add_assoc_long(link, "mtime", p->mtime);
13166 + add_assoc_long(link, "creation_time", p->creation_time);
13167 + add_assoc_long(link, "deletion_time", p->deletion_time);
13168 + add_assoc_long(link, "access_time", p->access_time);
13169 + add_assoc_long(link, "ref_count", p->ref_count);
13170 + add_assoc_long(link, "mem_size", p->mem_size);
13171 + add_next_index_zval(list, link);
13172 + }
13173 + add_assoc_zval(return_value, "deleted_list", list);
13174 +
13175 + apc_cache_free_info(info);
13176 +}
13177 +/* }}} */
13178 +
13179 +/* {{{ proto void apc_clear_cache() */
13180 +PHP_FUNCTION(apc_clear_cache)
13181 +{
13182 + char *cache_type;
13183 + int ct_len;
13184 +
13185 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
13186 + return;
13187 + }
13188 +
13189 + if(ZEND_NUM_ARGS()) {
13190 + if(!strcasecmp(cache_type,"user")) {
13191 + apc_cache_clear(apc_user_cache);
13192 + RETURN_TRUE;
13193 + }
13194 + }
13195 + apc_cache_clear(apc_cache);
13196 +}
13197 +/* }}} */
13198 +
13199 +/* {{{ proto array apc_sma_info([bool limited]) */
13200 +PHP_FUNCTION(apc_sma_info)
13201 +{
13202 + apc_sma_info_t* info;
13203 + zval* block_lists;
13204 + int i;
13205 + zend_bool limited = 0;
13206 +
13207 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
13208 + return;
13209 + }
13210 +
13211 + info = apc_sma_info(limited);
13212 +
13213 + if(!info) {
13214 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
13215 + RETURN_FALSE;
13216 + }
13217 +
13218 + array_init(return_value);
13219 + add_assoc_long(return_value, "num_seg", info->num_seg);
13220 + add_assoc_long(return_value, "seg_size", info->seg_size);
13221 + add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
13222 +
13223 + if(limited) {
13224 + apc_sma_free_info(info);
13225 + return;
13226 + }
13227 +
13228 +#if ALLOC_DISTRIBUTION
13229 + {
13230 + size_t *adist = apc_sma_get_alloc_distribution();
13231 + zval* list;
13232 + ALLOC_INIT_ZVAL(list);
13233 + array_init(list);
13234 + for(i=0; i<30; i++) {
13235 + add_next_index_long(list, adist[i]);
13236 + }
13237 + add_assoc_zval(return_value, "adist", list);
13238 + }
13239 +#endif
13240 + ALLOC_INIT_ZVAL(block_lists);
13241 + array_init(block_lists);
13242 +
13243 + for (i = 0; i < info->num_seg; i++) {
13244 + apc_sma_link_t* p;
13245 + zval* list;
13246 +
13247 + ALLOC_INIT_ZVAL(list);
13248 + array_init(list);
13249 +
13250 + for (p = info->list[i]; p != NULL; p = p->next) {
13251 + zval* link;
13252 +
13253 + ALLOC_INIT_ZVAL(link);
13254 + array_init(link);
13255 +
13256 + add_assoc_long(link, "size", p->size);
13257 + add_assoc_long(link, "offset", p->offset);
13258 + add_next_index_zval(list, link);
13259 + }
13260 + add_next_index_zval(block_lists, list);
13261 + }
13262 + add_assoc_zval(return_value, "block_lists", block_lists);
13263 + apc_sma_free_info(info);
13264 +}
13265 +/* }}} */
13266 +
13267 +/* {{{ _apc_store */
13268 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
13269 + apc_cache_entry_t *entry;
13270 + apc_cache_key_t key;
13271 + time_t t;
13272 + size_t mem_size = 0;
13273 +
13274 +#if PHP_API_VERSION <= 20041225
13275 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13276 + t = ((request_rec *)SG(server_context))->request_time;
13277 +#else
13278 + t = time(0);
13279 +#endif
13280 +#else
13281 + t = sapi_get_request_time(TSRMLS_C);
13282 +#endif
13283 +
13284 + if(!APCG(enabled)) return 0;
13285 +
13286 + HANDLE_BLOCK_INTERRUPTIONS();
13287 +
13288 + APCG(mem_size_ptr) = &mem_size;
13289 + if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
13290 + APCG(mem_size_ptr) = NULL;
13291 + apc_cache_expunge(apc_cache,t);
13292 + apc_cache_expunge(apc_user_cache,t);
13293 + HANDLE_UNBLOCK_INTERRUPTIONS();
13294 + return 0;
13295 + }
13296 +
13297 + if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
13298 + APCG(mem_size_ptr) = NULL;
13299 + apc_cache_free_entry(entry);
13300 + apc_cache_expunge(apc_cache,t);
13301 + apc_cache_expunge(apc_user_cache,t);
13302 + HANDLE_UNBLOCK_INTERRUPTIONS();
13303 + return 0;
13304 + }
13305 +
13306 + if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
13307 + APCG(mem_size_ptr) = NULL;
13308 + apc_cache_free_entry(entry);
13309 + apc_cache_expunge(apc_cache,t);
13310 + apc_cache_expunge(apc_user_cache,t);
13311 + HANDLE_UNBLOCK_INTERRUPTIONS();
13312 + return 0;
13313 + }
13314 +
13315 + APCG(mem_size_ptr) = NULL;
13316 +
13317 + HANDLE_UNBLOCK_INTERRUPTIONS();
13318 +
13319 + return 1;
13320 +}
13321 +/* }}} */
13322 +
13323 +/* {{{ proto int apc_store(string key, zval var [, ttl ])
13324 + */
13325 +PHP_FUNCTION(apc_store) {
13326 + zval *val;
13327 + char *strkey;
13328 + int strkey_len;
13329 + long ttl = 0L;
13330 +
13331 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13332 + return;
13333 + }
13334 +
13335 + if(!strkey_len) RETURN_FALSE;
13336 +
13337 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
13338 + RETURN_FALSE;
13339 +}
13340 +/* }}} */
13341 +
13342 +/* {{{ proto int apc_add(string key, zval var [, ttl ])
13343 + */
13344 +PHP_FUNCTION(apc_add) {
13345 + zval *val;
13346 + char *strkey;
13347 + int strkey_len;
13348 + long ttl = 0L;
13349 +
13350 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13351 + return;
13352 + }
13353 +
13354 + if(!strkey_len) RETURN_FALSE;
13355 +
13356 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
13357 + RETURN_FALSE;
13358 +}
13359 +/* }}} */
13360 +
13361 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
13362 + return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
13363 +}
13364 +
13365 +/* {{{ RETURN_ZVAL for php4 */
13366 +#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
13367 +#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
13368 +#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
13369 +#define ZVAL_ZVAL(z, zv, copy, dtor) { \
13370 + int is_ref, refcount; \
13371 + is_ref = (z)->is_ref; \
13372 + refcount = (z)->refcount; \
13373 + *(z) = *(zv); \
13374 + if (copy) { \
13375 + zval_copy_ctor(z); \
13376 + } \
13377 + if (dtor) { \
13378 + if (!copy) { \
13379 + ZVAL_NULL(zv); \
13380 + } \
13381 + zval_ptr_dtor(&zv); \
13382 + } \
13383 + (z)->is_ref = is_ref; \
13384 + (z)->refcount = refcount; \
13385 + }
13386 +#endif
13387 +/* }}} */
13388 +
13389 +/* {{{ proto mixed apc_fetch(mixed key)
13390 + */
13391 +PHP_FUNCTION(apc_fetch) {
13392 + zval *key;
13393 + HashTable *hash;
13394 + HashPosition hpos;
13395 + zval **hentry;
13396 + zval *result;
13397 + zval *result_entry;
13398 + char *strkey;
13399 + int strkey_len;
13400 + apc_cache_entry_t* entry;
13401 + time_t t;
13402 +
13403 + if(!APCG(enabled)) RETURN_FALSE;
13404 +
13405 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
13406 + return;
13407 + }
13408 +
13409 +#if PHP_API_VERSION <= 20041225
13410 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13411 + t = ((request_rec *)SG(server_context))->request_time;
13412 +#else
13413 + t = time(0);
13414 +#endif
13415 +#else
13416 + t = sapi_get_request_time(TSRMLS_C);
13417 +#endif
13418 +
13419 + if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
13420 + convert_to_string(key);
13421 + }
13422 +
13423 + if(Z_TYPE_P(key) == IS_STRING) {
13424 + strkey = Z_STRVAL_P(key);
13425 + strkey_len = Z_STRLEN_P(key);
13426 + if(!strkey_len) RETURN_FALSE;
13427 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13428 + if(entry) {
13429 + /* deep-copy returned shm zval to emalloc'ed return_value */
13430 + apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
13431 + apc_cache_release(apc_user_cache, entry);
13432 + } else {
13433 + RETURN_FALSE;
13434 + }
13435 + } else if(Z_TYPE_P(key) == IS_ARRAY) {
13436 + hash = Z_ARRVAL_P(key);
13437 + MAKE_STD_ZVAL(result);
13438 + array_init(result);
13439 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
13440 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
13441 + if(Z_TYPE_PP(hentry) != IS_STRING) {
13442 + apc_wprint("apc_fetch() expects a string or array of strings.");
13443 + RETURN_FALSE;
13444 + }
13445 + entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
13446 + if(entry) {
13447 + /* deep-copy returned shm zval to emalloc'ed return_value */
13448 + MAKE_STD_ZVAL(result_entry);
13449 + apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
13450 + apc_cache_release(apc_user_cache, entry);
13451 + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
13452 + } /* don't set values we didn't find */
13453 + zend_hash_move_forward_ex(hash, &hpos);
13454 + }
13455 + RETURN_ZVAL(result, 0, 1);
13456 + } else {
13457 + apc_wprint("apc_fetch() expects a string or array of strings.");
13458 + RETURN_FALSE;
13459 + }
13460 +
13461 + return;
13462 +}
13463 +/* }}} */
13464 +
13465 +/* {{{ proto mixed apc_delete(string key)
13466 + */
13467 +PHP_FUNCTION(apc_delete) {
13468 + char *strkey;
13469 + int strkey_len;
13470 +
13471 + if(!APCG(enabled)) RETURN_FALSE;
13472 +
13473 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
13474 + return;
13475 + }
13476 +
13477 + if(!strkey_len) RETURN_FALSE;
13478 +
13479 + if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
13480 + RETURN_TRUE;
13481 + } else {
13482 + RETURN_FALSE;
13483 + }
13484 +}
13485 +/* }}} */
13486 +
13487 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
13488 + char *const_key;
13489 + unsigned int const_key_len;
13490 + zval **entry;
13491 + HashPosition pos;
13492 +
13493 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
13494 + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
13495 + zend_constant c;
13496 + int key_type;
13497 + ulong num_key;
13498 +
13499 + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
13500 + if(key_type != HASH_KEY_IS_STRING) {
13501 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13502 + continue;
13503 + }
13504 + switch(Z_TYPE_PP(entry)) {
13505 + case IS_LONG:
13506 + case IS_DOUBLE:
13507 + case IS_STRING:
13508 + case IS_BOOL:
13509 + case IS_RESOURCE:
13510 + case IS_NULL:
13511 + break;
13512 + default:
13513 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13514 + continue;
13515 + }
13516 + c.value = **entry;
13517 + zval_copy_ctor(&c.value);
13518 + c.flags = case_sensitive;
13519 + c.name = zend_strndup(const_key, const_key_len);
13520 + c.name_len = const_key_len;
13521 +#ifdef ZEND_ENGINE_2
13522 + c.module_number = PHP_USER_CONSTANT;
13523 +#endif
13524 + zend_register_constant(&c TSRMLS_CC);
13525 +
13526 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13527 + }
13528 +}
13529 +
13530 +/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
13531 + */
13532 +PHP_FUNCTION(apc_define_constants) {
13533 + char *strkey;
13534 + int strkey_len;
13535 + zval *constants = NULL;
13536 + zend_bool case_sensitive = 1;
13537 + int argc = ZEND_NUM_ARGS();
13538 +
13539 + if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
13540 + return;
13541 + }
13542 +
13543 + if(!strkey_len) RETURN_FALSE;
13544 +
13545 + _apc_define_constants(constants, case_sensitive TSRMLS_CC);
13546 + if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
13547 + RETURN_FALSE;
13548 +} /* }}} */
13549 +
13550 +/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
13551 + */
13552 +PHP_FUNCTION(apc_load_constants) {
13553 + char *strkey;
13554 + int strkey_len;
13555 + apc_cache_entry_t* entry;
13556 + time_t t;
13557 + zend_bool case_sensitive = 1;
13558 +
13559 + if(!APCG(enabled)) RETURN_FALSE;
13560 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
13561 + return;
13562 + }
13563 +
13564 + if(!strkey_len) RETURN_FALSE;
13565 +
13566 +#if PHP_API_VERSION <= 20041225
13567 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13568 + t = ((request_rec *)SG(server_context))->request_time;
13569 +#else
13570 + t = time(0);
13571 +#endif
13572 +#else
13573 + t = sapi_get_request_time(TSRMLS_C);
13574 +#endif
13575 +
13576 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13577 +
13578 + if(entry) {
13579 + _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
13580 + apc_cache_release(apc_user_cache, entry);
13581 + RETURN_TRUE;
13582 + } else {
13583 + RETURN_FALSE;
13584 + }
13585 +}
13586 +/* }}} */
13587 +
13588 +/* {{{ proto boolean apc_compile_file(string filename)
13589 + */
13590 +PHP_FUNCTION(apc_compile_file) {
13591 + char *filename;
13592 + int filename_len;
13593 + zend_file_handle file_handle;
13594 + zend_op_array *op_array;
13595 + long slam_defense = 0;
13596 + char** filters = NULL;
13597 + zend_bool cache_by_default = 1;
13598 + HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
13599 + HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
13600 +
13601 + if(!APCG(enabled)) RETURN_FALSE;
13602 +
13603 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
13604 + return;
13605 + }
13606 +
13607 + if(!filename) RETURN_FALSE;
13608 +
13609 + /* If slam defense is active, temporarily disable */
13610 + if(APCG(slam_defense)) {
13611 + slam_defense = APCG(slam_defense);
13612 + APCG(slam_defense) = 0;
13613 + }
13614 +
13615 + /* If filter is active, temporarily disable */
13616 + if(APCG(filters) != NULL) {
13617 + filters = APCG(filters);
13618 + APCG(filters) = NULL;
13619 + }
13620 +
13621 + /* If cache_by_default is off, temporarily enable */
13622 + if(!APCG(cache_by_default)) {
13623 + cache_by_default = APCG(cache_by_default);
13624 + APCG(cache_by_default) = 1;
13625 + }
13626 +
13627 + /* Replace function/class tables to avoid namespace conflicts */
13628 + zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13629 + cg_orig_function_table = CG(function_table);
13630 + CG(function_table) = &cg_function_table;
13631 + zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13632 + cg_orig_class_table = CG(class_table);
13633 + CG(class_table) = &cg_class_table;
13634 + zend_hash_init_ex(&eg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13635 + eg_orig_function_table = EG(function_table);
13636 + EG(function_table) = &eg_function_table;
13637 + zend_hash_init_ex(&eg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13638 + eg_orig_class_table = EG(class_table);
13639 + EG(class_table) = &eg_class_table;
13640 +
13641 + /* Compile the file, loading it into the cache */
13642 + file_handle.type = ZEND_HANDLE_FILENAME;
13643 + file_handle.filename = filename;
13644 + file_handle.free_filename = 0;
13645 + file_handle.opened_path = NULL;
13646 + zend_try {
13647 + op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
13648 + } zend_catch {
13649 + apc_eprint("Error compiling %s in apc_compile_file.", filename);
13650 + op_array = NULL;
13651 + } zend_end_try();
13652 +
13653 + /* Return class/function tables to previous states, destroy temp tables */
13654 + CG(function_table) = cg_orig_function_table;
13655 + zend_hash_destroy(&cg_function_table);
13656 + CG(class_table) = cg_orig_class_table;
13657 + zend_hash_destroy(&cg_class_table);
13658 + EG(function_table) = eg_orig_function_table;
13659 + zend_hash_destroy(&eg_function_table);
13660 + EG(class_table) = eg_orig_class_table;
13661 + zend_hash_destroy(&eg_class_table);
13662 +
13663 + /* Restore global settings */
13664 + APCG(slam_defense) = slam_defense;
13665 + APCG(filters) = filters;
13666 + APCG(cache_by_default) = cache_by_default;
13667 +
13668 + if(op_array == NULL) { RETURN_FALSE; }
13669 +
13670 + /* Free up everything */
13671 + zend_destroy_file_handle(&file_handle TSRMLS_CC);
13672 +#ifdef ZEND_ENGINE_2
13673 + destroy_op_array(op_array TSRMLS_CC);
13674 +#else
13675 + destroy_op_array(op_array);
13676 +#endif
13677 + efree(op_array);
13678 +
13679 + RETURN_TRUE;
13680 +}
13681 +/* }}} */
13682 +
13683 +/* {{{ apc_functions[] */
13684 +function_entry apc_functions[] = {
13685 + PHP_FE(apc_cache_info, NULL)
13686 + PHP_FE(apc_clear_cache, NULL)
13687 + PHP_FE(apc_sma_info, NULL)
13688 + PHP_FE(apc_store, NULL)
13689 + PHP_FE(apc_fetch, NULL)
13690 + PHP_FE(apc_delete, NULL)
13691 + PHP_FE(apc_define_constants, NULL)
13692 + PHP_FE(apc_load_constants, NULL)
13693 + PHP_FE(apc_compile_file, NULL)
13694 + {NULL, NULL, NULL}
13695 +};
13696 +/* }}} */
13697 +
13698 +/* {{{ module definition structure */
13699 +
13700 +zend_module_entry apc_module_entry = {
13701 + STANDARD_MODULE_HEADER,
13702 + "apc",
13703 + apc_functions,
13704 + PHP_MINIT(apc),
13705 + PHP_MSHUTDOWN(apc),
13706 + PHP_RINIT(apc),
13707 + PHP_RSHUTDOWN(apc),
13708 + PHP_MINFO(apc),
13709 + APC_VERSION,
13710 + STANDARD_MODULE_PROPERTIES
13711 +};
13712 +
13713 +#ifdef COMPILE_DL_APC
13714 +ZEND_GET_MODULE(apc)
13715 +#endif
13716 +/* }}} */
13717 +
13718 +/*
13719 + * Local variables:
13720 + * tab-width: 4
13721 + * c-basic-offset: 4
13722 + * End:
13723 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13724 + * vim<600: expandtab sw=4 ts=4 sts=4
13725 + */
13726 Index: php-5.2.4/ext/apc/php_apc.h
13727 ===================================================================
13728 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13729 +++ php-5.2.4/ext/apc/php_apc.h 2007-09-02 12:24:46.000000000 +0200
13730 @@ -0,0 +1,52 @@
13731 +/*
13732 + +----------------------------------------------------------------------+
13733 + | APC |
13734 + +----------------------------------------------------------------------+
13735 + | Copyright (c) 2006 The PHP Group |
13736 + +----------------------------------------------------------------------+
13737 + | This source file is subject to version 3.01 of the PHP license, |
13738 + | that is bundled with this package in the file LICENSE, and is |
13739 + | available through the world-wide-web at the following url: |
13740 + | http://www.php.net/license/3_01.txt |
13741 + | If you did not receive a copy of the PHP license and are unable to |
13742 + | obtain it through the world-wide-web, please send a note to |
13743 + | license@php.net so we can mail you a copy immediately. |
13744 + +----------------------------------------------------------------------+
13745 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13746 + | George Schlossnagle <george@omniti.com> |
13747 + | Rasmus Lerdorf <rasmus@php.net> |
13748 + +----------------------------------------------------------------------+
13749 +
13750 + This software was contributed to PHP by Community Connect Inc. in 2002
13751 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13752 + Future revisions and derivatives of this source code must acknowledge
13753 + Community Connect Inc. as the original contributor of this module by
13754 + leaving this note intact in the source code.
13755 +
13756 + All other licensing and usage conditions are those of the PHP Group.
13757 +
13758 + */
13759 +
13760 +/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
13761 +
13762 +#ifndef PHP_APC_H
13763 +#define PHP_APC_H
13764 +
13765 +#include "apc_php.h"
13766 +#include "apc_globals.h"
13767 +
13768 +extern zend_module_entry apc_module_entry;
13769 +#define apc_module_ptr &apc_module_entry
13770 +
13771 +#define phpext_apc_ptr apc_module_ptr
13772 +
13773 +#endif /* PHP_APC_H */
13774 +
13775 +/*
13776 + * Local variables:
13777 + * tab-width: 4
13778 + * c-basic-offset: 4
13779 + * End:
13780 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13781 + * vim<600: expandtab sw=4 ts=4 sts=4
13782 + */
13783 Index: php-5.2.4/ext/apc/TECHNOTES.txt
13784 ===================================================================
13785 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13786 +++ php-5.2.4/ext/apc/TECHNOTES.txt 2007-09-02 12:24:46.000000000 +0200
13787 @@ -0,0 +1,357 @@
13788 +APC Quick-Start Braindump
13789 +
13790 +This is a rapidly written braindump of how APC currently works in the
13791 +form of a quick-start guide to start hacking on APC.
13792 +
13793 +1. Install and use APC a bit so you know what it does from the end-user's
13794 + perspective.
13795 + user-space functions are all explained here:
13796 +
13797 +2. Grab the current APC code from CVS:
13798 +
13799 + cvs -d:pserver:cvsread@cvs.php.net:/repository login
13800 + Password: phpfi
13801 + cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
13802 +
13803 + apc/php_apc.c has most of the code for the user-visible stuff. It is
13804 + also a regular PHP extension in the sense that there are MINIT, MINFO,
13805 + MSHUTDOWN, RSHUTDOWN, etc. functions.
13806 +
13807 +3. Build it.
13808 +
13809 + cd pecl/apc
13810 + phpize
13811 + ./configure --enable-apc --enable-mmap
13812 + make
13813 + cp modules/apc.so /usr/local/lib/php
13814 + apachectl restart
13815 +
13816 +4. Debugging Hints
13817 +
13818 + apachectl stop
13819 + gdb /usr/bin/httpd
13820 + break ??
13821 + run -X
13822 +
13823 + Grab the .gdbinit from the PHP source tree and have a look at the macros.
13824 +
13825 +5. Look through apc/apc_sma.c
13826 + It is a pretty standard memory allocator.
13827 +
13828 + apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
13829 + caller just like malloc, realloc, strdup and free
13830 +
13831 + On server startup the MINIT hook in php_apc.c calls apc_module_init() in
13832 + apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into
13833 + apc_mmap.c to mmap the specified sized segment (I tend to just use a single
13834 + segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and
13835 + then unlinks that file right after the mmap to provide automatic shared memory
13836 + cleanup in case the process dies.
13837 +
13838 + Once the region has been initialized we stick a header_t at the beginning
13839 + of the region. It contains the total size in header->segsize and the number
13840 + of bytes available in header->avail.
13841 +
13842 + After the header comes a bit of a hack. A zero-sized block is inserted just
13843 + to make things easier later on. And then a huge block that is basically
13844 + the size of the entire segment minus the two (for the 0-sized block, and this one)
13845 + block headers.
13846 +
13847 + The code for this is:
13848 +
13849 + header = (header_t*) shmaddr;
13850 + header->segsize = sma_segsize;
13851 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
13852 + memset(&header->lock,0,sizeof(header->lock));
13853 + sma_lock = &header->lock;
13854 + block = BLOCKAT(sizeof(header_t));
13855 + block->size = 0;
13856 + block->next = sizeof(header_t) + sizeof(block_t);
13857 + block = BLOCKAT(block->next);
13858 + block->size = header->avail;
13859 + block->next = 0;
13860 +
13861 + So the shared memory looks like this:
13862 +
13863 + +--------+-------+---------------------------------+
13864 + | header | block | block |
13865 + +--------+-------+---------------------------------+
13866 +
13867 + sma_shmaddrs[0] gives you the address of header
13868 +
13869 + The blocks are just a simple offset-based linked list (so no pointers):
13870 +
13871 + typedef struct block_t block_t;
13872 + struct block_t {
13873 + int size; /* size of this block */
13874 + int next; /* offset in segment of next free block */
13875 + };
13876 +
13877 + The BLOCKAT macro turns an offset into an actual address for you:
13878 +
13879 + #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
13880 +
13881 + where shmaddr = sma_shaddrs[0]
13882 +
13883 + And the OFFSET macro goes the other way:
13884 +
13885 + #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
13886 +
13887 + Allocating a block with a call to apc_sma_allocate() walks through the
13888 + linked list of blocks until it finds one that is >= to the requested size.
13889 + The first call to apc_sma_allocate() will hit the second block. We then
13890 + chop up that block so it looks like this:
13891 +
13892 + +--------+-------+-------+-------------------------+
13893 + | header | block | block | block |
13894 + +--------+-------+-------+-------------------------+
13895 +
13896 + Then we unlink that block from the linked list so it won't show up
13897 + as an available block on the next allocate. So we actually have:
13898 +
13899 + +--------+-------+ +-------------------------+
13900 + | header | block |------>| block |
13901 + +--------+-------+ +-------------------------+
13902 +
13903 + And header->avail along with block->size of the remaining large
13904 + block are updated accordingly. The arrow there representing the
13905 + link which now points to a block with an offset further along in
13906 + the segment.
13907 +
13908 + When the block is freed using apc_sma_deallocate() the steps are
13909 + basically just reversed. The block is put back and then the deallocate
13910 + code looks at the block before and after to see if the block immediately
13911 + before and after are free and if so the blocks are combined. So you never
13912 + have 2 free blocks next to each other, apart from at the front with that
13913 + 0-sized dummy block. This mostly prevents fragmentation. I have been
13914 + toying with the idea of always allocating block at 2^n boundaries to make
13915 + it more likely that they will be re-used to cut down on fragmentation further.
13916 + That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
13917 +
13918 + Of course, anytime we fiddle with our shared memory segment we lock using
13919 + the locking macros, LOCK() and UNLOCK().
13920 +
13921 + That should mostly take care of the low-level shared memory handling.
13922 +
13923 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
13924 + cache logic.
13925 +
13926 + The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
13927 + and apc_cache.c for actual cache manipulation.
13928 +
13929 + After the shared memory segment is created and the caches are initialized,
13930 + apc_module_init() installs the my_compile_file() function overriding Zend's
13931 + version. I'll talk about my_compile_file() and the rest of apc_compile.c
13932 + in the next section. For now I will stick with apc_main.c and apc_cache.c
13933 + and talk about the actual caches. A cache consists of a block of shared
13934 + memory returned by apc_sma_allocate() via apc_sma_malloc(). You will
13935 + notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper
13936 + around PHP's own emalloc() function which allocates per-process memory from
13937 + PHP's pool-based memory allocator. Don't confuse apc_emalloc() and
13938 + apc_sma_malloc() as the first is per-process and the second is shared memory.
13939 +
13940 + The cache is stored in/described by this struct allocated locally using
13941 + emalloc():
13942 +
13943 + struct apc_cache_t {
13944 + void* shmaddr; /* process (local) address of shared cache */
13945 + header_t* header; /* cache header (stored in SHM) */
13946 + slot_t** slots; /* array of cache slots (stored in SHM) */
13947 + int num_slots; /* number of slots in cache */
13948 + int gc_ttl; /* maximum time on GC list for a slot */
13949 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
13950 + };
13951 +
13952 + Whenever you see functions that take a 'cache' argument, this is what they
13953 + take. And apc_cache_create() returns a pointer to this populated struct.
13954 +
13955 + At the beginning of the cache we have a header. Remember, we are down a level now
13956 + from the sma stuff. The sma stuff is the low-level shared-memory allocator which
13957 + has its own header which is completely separate and invisible to apc_cache.c.
13958 + As far as apc_cache.c is concerned the block of memory it is working with could
13959 + have come from a call to malloc().
13960 +
13961 + The header looks like this:
13962 +
13963 + typedef struct header_t header_t;
13964 + struct header_t {
13965 + int num_hits; /* total successful hits in cache */
13966 + int num_misses; /* total unsuccessful hits in cache */
13967 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
13968 + };
13969 +
13970 + Since this is at the start of the shared memory segment, these values are accessible
13971 + across all the yapache processes and hence access to them has to be locked.
13972 +
13973 + After the header we have an array of slots. The number of slots is user-defined
13974 + through the apc.num_slots ini hint. Each slot is described by:
13975 +
13976 + typedef struct slot_t slot_t;
13977 + struct slot_t {
13978 + apc_cache_key_t key; /* slot key */
13979 + apc_cache_entry_t* value; /* slot value */
13980 + slot_t* next; /* next slot in linked list */
13981 + int num_hits; /* number of hits to this bucket */
13982 + time_t creation_time; /* time slot was initialized */
13983 + time_t deletion_time; /* time slot was removed from cache */
13984 + time_t access_time; /* time slot was last accessed */
13985 + };
13986 +
13987 + The slot_t *next there is a linked list to other slots that happened to hash to the
13988 + same array position.
13989 +
13990 + apc_cache_insert() shows what happens on a new cache insert.
13991 +
13992 + slot = &cache->slots[hash(key) % cache->num_slots];
13993 +
13994 + cache->slots is our array of slots in the segment. hash() is simply:
13995 +
13996 + static unsigned int hash(apc_cache_key_t key)
13997 + {
13998 + return key.data.file.device + key.data.file.inode;
13999 + }
14000 +
14001 + That is, we use the file's device and inode to uniquely identify it. Initially
14002 + we had used the file's full path, but getting that requires a realpath() call which
14003 + is amazingly expensive since it has to stat each component of the path to resolve
14004 + symlinks and get rid of relative path components. By using the device+inode we
14005 + can uniquely identify a file with a single stat.
14006 +
14007 + So, on an insert we find the array position in the slots array by hasing the device+inode.
14008 + If there are currently no other slots there, we just create the slot and stick it into
14009 + the array:
14010 +
14011 + *slot = make_slot(key, value, *slot, t)
14012 +
14013 + If there are other slots already at this position we walk the link list to get to
14014 + the end. Here is the loop:
14015 +
14016 + while (*slot) {
14017 + if (key_equals((*slot)->key.data.file, key.data.file)) {
14018 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
14019 + if ((*slot)->key.mtime != key.mtime) {
14020 + remove_slot(cache, slot);
14021 + break;
14022 + }
14023 + UNLOCK(cache);
14024 + return 0;
14025 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
14026 + remove_slot(cache, slot);
14027 + continue;
14028 + }
14029 + slot = &(*slot)->next;
14030 + }
14031 +
14032 + That first key_equals() check sees if we have an exact match meaning the file
14033 + is already in the cache. Since we try to find the file in the cache before doing
14034 + an insert, this will generally only happen if another process managed to beat us
14035 + to inserting it. If we have a newer version of the file at this point we remove
14036 + it an insert the new version. If our version is not newer we just return without
14037 + doing anything.
14038 +
14039 + While walking the linked list we also check to see if the cache has a TTL defined.
14040 + If while walking the linked list we see a slot that has expired, we remove it
14041 + since we are right there looking at it. This is the only place we remove stale
14042 + entries unless the shared memory segment fills up and we force a full expunge via
14043 + apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks
14044 + down every linked list removing stale slots to free up room. This is obviously
14045 + slow and thus only happens when we have run out of room.
14046 +
14047 + apc_cache_find() simply hashes and returns the entry if it is there. If it is there
14048 + but older than the mtime in the entry we are looking for, we delete the one that is
14049 + there and return indicating we didn't find it.
14050 +
14051 + Next we need to understand what an actual cache entry looks like. Have a look at
14052 + apc_cache.h for the structs. I sort of glossed over the key part earlier saying
14053 + that we just used the device+inode to find a hash slot. It is actually a bit more
14054 + complex than that because we have two kinds of caches. We have the standard file
14055 + cache containing opcode arrays, but we also have a user-controlled cache that the
14056 + user can insert whatever they want into via apc_store(). For the user cache we
14057 + obviously don't have a device+inode. The actual identifier is provided by the user
14058 + as a char *. So the key is actually a union that looks like this:
14059 +
14060 + typedef union _apc_cache_key_data_t {
14061 + struct {
14062 + int device; /* the filesystem device */
14063 + int inode; /* the filesystem inode */
14064 + } file;
14065 + struct {
14066 + char *identifier;
14067 + } user;
14068 + } apc_cache_key_data_t;
14069 +
14070 + struct apc_cache_key_t {
14071 + apc_cache_key_data_t data;
14072 + int mtime; /* the mtime of this cached entry */
14073 + };
14074 +
14075 + And we have two sets of functions to do inserts and finds. apc_cache_user_find()
14076 + and apc_cache_user_insert() operate on the user cache.
14077 +
14078 + Ok, on to the actual cache entry. Again, because we have two kinds of caches, we
14079 + also have the corresponding two kinds of cache entries described by this union:
14080 +
14081 + typedef union _apc_cache_entry_value_t {
14082 + struct {
14083 + char *filename; /* absolute path to source file */
14084 + zend_op_array* op_array; /* op_array allocated in shared memory */
14085 + apc_function_t* functions; /* array of apc_function_t's */
14086 + apc_class_t* classes; /* array of apc_class_t's */
14087 + } file;
14088 + struct {
14089 + char *info;
14090 + zval *val;
14091 + unsigned int ttl;
14092 + } user;
14093 + } apc_cache_entry_value_t;
14094 +
14095 + And then the actual cache entry:
14096 +
14097 + struct apc_cache_entry_t {
14098 + apc_cache_entry_value_t data;
14099 + unsigned char type;
14100 + int ref_count;
14101 + };
14102 +
14103 + The user entry is pretty simple and not all that important for now. I will
14104 + concentrate on the file entries since that is what holds the actual compiled
14105 + opcode arrays along with the functions and classes required by the executor.
14106 +
14107 + apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
14108 + The main thing to understand here is that we need more than just the opcode
14109 + array, we also need the functions and classes created by the compiler when it
14110 + created the opcode array. As far as the executor is concerned, it doesn't know
14111 + that it isn't operating in normal mode being called right after the parse/compile
14112 + phase, so we need to recreate everything so it looks exactly like it would at
14113 + that point.
14114 +
14115 +7. my_compile_file() and apc_compile.c
14116 +
14117 + my_compile_file() in apc_main.c controls where we get the opcodes from. If
14118 + the user-specified filters exclude the file from being cached, then we just
14119 + call the original compile function and return. Otherwise we fetch the request
14120 + time from Apache to avoid an extra syscall, create the key so we can look up
14121 + the file in the cache. If we find it we stick it on a local stack which we
14122 + use at cleanup time to make sure we return everything back to normal after a
14123 + request and call cached_compile() which installs the functions and classes
14124 + associated with the op_array in this entry and then copy the op_array down
14125 + into our memory space for execution.
14126 +
14127 + If we didn't find the file in the cache, we need to compile it and insert it.
14128 + To compile it we simply call the original compile function:
14129 +
14130 + op_array = old_compile_file(h, type TSRMLS_CC);
14131 +
14132 + To do the insert we need to copy the functions, classes and the opcode array
14133 + the compile phase created into shared memory. This all happens in apc_compile.c
14134 + in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
14135 + functions. Then we make the file entry and do the insert. Both of these
14136 + operations were described in the previous section.
14137 +
14138 +8. The Optimizer
14139 +
14140 + The optimizer has been deprecated.
14141 +
14142 +If you made it to the end of this, you should have a pretty good idea of where things are in
14143 +the code. I skimmed over a lot of things, so plan on spending some time reading through the code.
14144 +
14145 Index: php-5.2.4/ext/apc/tests/apc_001.phpt
14146 ===================================================================
14147 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14148 +++ php-5.2.4/ext/apc/tests/apc_001.phpt 2007-09-02 12:24:46.000000000 +0200
14149 @@ -0,0 +1,27 @@
14150 +--TEST--
14151 +APC: apc_store/fetch with strings
14152 +--SKIPIF--
14153 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14154 +--INI--
14155 +apc.enabled=1
14156 +apc.enable_cli=1
14157 +apc.file_update_protection=0
14158 +--FILE--
14159 +<?php
14160 +
14161 +$foo = 'hello world';
14162 +var_dump($foo);
14163 +apc_store('foo',$foo);
14164 +$bar = apc_fetch('foo');
14165 +var_dump($bar);
14166 +$bar = 'nice';
14167 +var_dump($bar);
14168 +
14169 +?>
14170 +===DONE===
14171 +<?php exit(0); ?>
14172 +--EXPECTF--
14173 +string(11) "hello world"
14174 +string(11) "hello world"
14175 +string(4) "nice"
14176 +===DONE===
14177 Index: php-5.2.4/ext/apc/tests/apc_002.phpt
14178 ===================================================================
14179 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14180 +++ php-5.2.4/ext/apc/tests/apc_002.phpt 2007-09-02 12:24:46.000000000 +0200
14181 @@ -0,0 +1,34 @@
14182 +--TEST--
14183 +APC: apc_store/fetch with objects
14184 +--SKIPIF--
14185 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14186 +--INI--
14187 +apc.enabled=1
14188 +apc.enable_cli=1
14189 +apc.file_update_protection=0
14190 +--FILE--
14191 +<?php
14192 +
14193 +class foo { }
14194 +$foo = new foo;
14195 +var_dump($foo);
14196 +apc_store('foo',$foo);
14197 +unset($foo);
14198 +$bar = apc_fetch('foo');
14199 +var_dump($bar);
14200 +$bar->a = true;
14201 +var_dump($bar);
14202 +
14203 +?>
14204 +===DONE===
14205 +<?php exit(0); ?>
14206 +--EXPECTF--
14207 +object(foo)#%d (0) {
14208 +}
14209 +object(foo)#%d (0) {
14210 +}
14211 +object(foo)#%d (1) {
14212 + ["a"]=>
14213 + bool(true)
14214 +}
14215 +===DONE===
14216 Index: php-5.2.4/ext/apc/tests/apc_003.phpt
14217 ===================================================================
14218 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14219 +++ php-5.2.4/ext/apc/tests/apc_003.phpt 2007-09-02 12:24:46.000000000 +0200
14220 @@ -0,0 +1,112 @@
14221 +--TEST--
14222 +APC: apc_store/fetch with objects
14223 +--SKIPIF--
14224 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14225 +--INI--
14226 +apc.enabled=1
14227 +apc.enable_cli=1
14228 +apc.file_update_protection=0
14229 +--FILE--
14230 +<?php
14231 +
14232 +class foo { }
14233 +$foo = new foo;
14234 +var_dump($foo);
14235 +apc_store('foo',$foo);
14236 +unset($foo);
14237 +$bar = apc_fetch('foo');
14238 +var_dump($bar);
14239 +$bar->a = true;
14240 +var_dump($bar);
14241 +
14242 +class bar extends foo
14243 +{
14244 + public $pub = 'bar';
14245 + protected $pro = 'bar';
14246 + private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
14247 +
14248 + function __construct()
14249 + {
14250 + $this->bar = true;
14251 + }
14252 +
14253 + function change()
14254 + {
14255 + $this->pri = 'mod';
14256 + }
14257 +}
14258 +
14259 +class baz extends bar
14260 +{
14261 + private $pri = 'baz';
14262 +
14263 + function __construct()
14264 + {
14265 + parent::__construct();
14266 + $this->baz = true;
14267 + }
14268 +}
14269 +
14270 +$baz = new baz;
14271 +var_dump($baz);
14272 +$baz->change();
14273 +var_dump($baz);
14274 +apc_store('baz', $baz);
14275 +unset($baz);
14276 +var_dump(apc_fetch('baz'));
14277 +
14278 +?>
14279 +===DONE===
14280 +<?php exit(0); ?>
14281 +--EXPECTF--
14282 +object(foo)#%d (0) {
14283 +}
14284 +object(foo)#%d (0) {
14285 +}
14286 +object(foo)#%d (1) {
14287 + ["a"]=>
14288 + bool(true)
14289 +}
14290 +object(baz)#%d (6) {
14291 + ["pri:private"]=>
14292 + string(3) "baz"
14293 + ["pub"]=>
14294 + string(3) "bar"
14295 + ["pro:protected"]=>
14296 + string(3) "bar"
14297 + ["pri:private"]=>
14298 + string(3) "bar"
14299 + ["bar"]=>
14300 + bool(true)
14301 + ["baz"]=>
14302 + bool(true)
14303 +}
14304 +object(baz)#%d (6) {
14305 + ["pri:private"]=>
14306 + string(3) "baz"
14307 + ["pub"]=>
14308 + string(3) "bar"
14309 + ["pro:protected"]=>
14310 + string(3) "bar"
14311 + ["pri:private"]=>
14312 + string(3) "mod"
14313 + ["bar"]=>
14314 + bool(true)
14315 + ["baz"]=>
14316 + bool(true)
14317 +}
14318 +object(baz)#%d (6) {
14319 + ["pri:private"]=>
14320 + string(3) "baz"
14321 + ["pub"]=>
14322 + string(3) "bar"
14323 + ["pro:protected"]=>
14324 + string(3) "bar"
14325 + ["pri:private"]=>
14326 + string(3) "mod"
14327 + ["bar"]=>
14328 + bool(true)
14329 + ["baz"]=>
14330 + bool(true)
14331 +}
14332 +===DONE===
14333 Index: php-5.2.4/ext/apc/tests/skipif.inc
14334 ===================================================================
14335 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14336 +++ php-5.2.4/ext/apc/tests/skipif.inc 2007-09-02 12:24:46.000000000 +0200
14337 @@ -0,0 +1,6 @@
14338 +<?php
14339 +
14340 +if (!extension_loaded("apc")) die("skip");
14341 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
14342 +
14343 +?>
14344 Index: php-5.2.4/ext/apc/TODO
14345 ===================================================================
14346 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14347 +++ php-5.2.4/ext/apc/TODO 2007-09-02 12:24:46.000000000 +0200
14348 @@ -0,0 +1,30 @@
14349 +Known Bugs
14350 +
14351 +1. Gallery2 doesn't work with PHP5+APC. There is something wrong
14352 + with the way methods are restored in some edge case I haven't
14353 + been able to figure out yet.
14354 + To reproduce install gallery2 and click down to an individual photo.
14355 +
14356 +2. apc_store() probably needs some checks to skip trying to store
14357 + internal classes. Something along the lines of:
14358 +
14359 + if(Z_TYPE_P(val) == IS_OBJECT) {
14360 + zend_class_entry *ce = Z_OBJCE_P(val);
14361 + if(ce->type == ZEND_INTERNAL_CLASS) {
14362 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
14363 + RETURN_FALSE;
14364 + }
14365 + }
14366 +
14367 + in the apc_store() function in php_apc.c but I am wondering if it needs to do more
14368 + than that.
14369 +
14370 +Enhancements
14371 +
14372 +1. Some faster platform-specific locking mechanisms wouldd be nice. futex support
14373 + for the 2.6 Linux kernels, and/or x86-specific spinlock support.
14374 +
14375 +2. The optimizer needs a lot of work.
14376 +
14377 +3. Assert() elimination in the optimizer when some debug flag somewhere isn't set.
14378 +