2f35c6369e
git-svn-id: svn://svn.openwrt.org/openwrt/packages@10213 3c298f89-4303-0410-b956-a3cf2f4a3e73
15501 lines
525 KiB
Diff
15501 lines
525 KiB
Diff
diff -ubrN php-5.2.5-orig/ext/apc/apc.c php-5.2.5/ext/apc/apc.c
|
||
--- php-5.2.5-orig/ext/apc/apc.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,554 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc.c,v 3.18 2007/11/29 22:15:53 shire Exp $ */
|
||
+
|
||
+#include "apc.h"
|
||
+#include <regex.h> /* for POSIX regular expressions */
|
||
+#include "php.h"
|
||
+
|
||
+#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
|
||
+
|
||
+/* {{{ memory allocation wrappers */
|
||
+
|
||
+void* apc_emalloc(size_t n)
|
||
+{
|
||
+ void* p = malloc(n);
|
||
+ if (p == NULL) {
|
||
+ apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
|
||
+ }
|
||
+ return p;
|
||
+}
|
||
+
|
||
+void* apc_erealloc(void* p, size_t n)
|
||
+{
|
||
+ p = realloc(p, n);
|
||
+ if (p == NULL) {
|
||
+ apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
|
||
+ }
|
||
+ return p;
|
||
+}
|
||
+
|
||
+void apc_efree(void* p)
|
||
+{
|
||
+ if (p == NULL) {
|
||
+ apc_eprint("apc_efree: attempt to free null pointer");
|
||
+ }
|
||
+ free(p);
|
||
+}
|
||
+
|
||
+char* apc_estrdup(const char* s)
|
||
+{
|
||
+ int len;
|
||
+ char* dup;
|
||
+
|
||
+ if (s == NULL) {
|
||
+ return NULL;
|
||
+ }
|
||
+ len = strlen(s);
|
||
+ dup = (char*) malloc(len+1);
|
||
+ if (dup == NULL) {
|
||
+ apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
|
||
+ }
|
||
+ memcpy(dup, s, len);
|
||
+ dup[len] = '\0';
|
||
+ return dup;
|
||
+}
|
||
+
|
||
+void* apc_xstrdup(const char* s, apc_malloc_t f)
|
||
+{
|
||
+ return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
|
||
+}
|
||
+
|
||
+void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
|
||
+{
|
||
+ void* q;
|
||
+
|
||
+ if (p != NULL && (q = f(n)) != NULL) {
|
||
+ memcpy(q, p, n);
|
||
+ return q;
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ console display functions */
|
||
+
|
||
+static void my_log(int level, const char* fmt, va_list args)
|
||
+{
|
||
+ static const char* level_strings[] = {
|
||
+ "apc-debug",
|
||
+ "apc-notice",
|
||
+ "apc-warning",
|
||
+ "apc-error"
|
||
+ };
|
||
+ static const int num_levels = NELEMS(level_strings);
|
||
+
|
||
+ time_t now;
|
||
+ char* buf; /* for ctime */
|
||
+
|
||
+ fflush(stdout);
|
||
+
|
||
+ if (level < 0)
|
||
+ level = 0;
|
||
+ else if (level >= num_levels)
|
||
+ level = num_levels-1;
|
||
+
|
||
+ now = time(0);
|
||
+ buf = ctime(&now); /* TODO: replace with reentrant impl */
|
||
+ buf[24] = '\0';
|
||
+
|
||
+ fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
|
||
+ vfprintf(stderr, fmt, args);
|
||
+
|
||
+ if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
|
||
+ fprintf(stderr, " %s", strerror(errno));
|
||
+ }
|
||
+ fprintf(stderr, "\n");
|
||
+
|
||
+ if (level == APC_ERROR) {
|
||
+ exit(2);
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_log(int level, const char* fmt, ...)
|
||
+{
|
||
+ va_list args;
|
||
+ va_start(args, fmt);
|
||
+ my_log(level, fmt, args);
|
||
+ va_end(args);
|
||
+}
|
||
+
|
||
+void apc_eprint(const char* fmt, ...)
|
||
+{
|
||
+ va_list args;
|
||
+ va_start(args, fmt);
|
||
+ my_log(APC_ERROR, fmt, args);
|
||
+ va_end(args);
|
||
+}
|
||
+
|
||
+void apc_wprint(const char* fmt, ...)
|
||
+{
|
||
+ va_list args;
|
||
+ va_start(args, fmt);
|
||
+ my_log(APC_WARNING, fmt, args);
|
||
+ va_end(args);
|
||
+}
|
||
+
|
||
+void apc_nprint(const char* fmt, ...)
|
||
+{
|
||
+ va_list args;
|
||
+ va_start(args, fmt);
|
||
+ my_log(APC_NOTICE, fmt, args);
|
||
+ va_end(args);
|
||
+}
|
||
+
|
||
+void apc_dprint(const char* fmt, ...)
|
||
+{
|
||
+#ifdef APC_DEBUG
|
||
+ va_list args;
|
||
+ va_start(args, fmt);
|
||
+ my_log(APC_DBG, fmt, args);
|
||
+ va_end(args);
|
||
+#endif
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ string and text manipulation */
|
||
+
|
||
+char* apc_append(const char* s, const char* t)
|
||
+{
|
||
+ int slen;
|
||
+ int tlen;
|
||
+ char* p;
|
||
+
|
||
+ slen = strlen(s);
|
||
+ tlen = strlen(t);
|
||
+
|
||
+ p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
|
||
+ memcpy(p, s, slen);
|
||
+ memcpy(p + slen, t, tlen + 1);
|
||
+
|
||
+ return p;
|
||
+}
|
||
+
|
||
+char* apc_substr(const char* s, int start, int length)
|
||
+{
|
||
+ char* substr;
|
||
+ int src_len = strlen(s);
|
||
+
|
||
+ /* bring start into range */
|
||
+ if (start < 0) {
|
||
+ start = 0;
|
||
+ }
|
||
+ else if (start >= src_len) {
|
||
+ start = src_len - 1;
|
||
+ }
|
||
+
|
||
+ /* bring length into range */
|
||
+ if (length < 0 || src_len - start < length) {
|
||
+ length = src_len - start;
|
||
+ }
|
||
+
|
||
+ /* create the substring */
|
||
+ substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
|
||
+ substr[length] = '\0';
|
||
+ return substr;
|
||
+}
|
||
+
|
||
+char** apc_tokenize(const char* s, char delim)
|
||
+{
|
||
+ char** tokens; /* array of tokens, NULL terminated */
|
||
+ int size; /* size of tokens array */
|
||
+ int n; /* index of next token in tokens array */
|
||
+ int cur; /* current position in input string */
|
||
+ int end; /* final legal position in input string */
|
||
+ int next; /* position of next delimiter in input */
|
||
+
|
||
+ if (!s) {
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ size = 2;
|
||
+ n = 0;
|
||
+ cur = 0;
|
||
+ end = strlen(s) - 1;
|
||
+
|
||
+ tokens = (char**) apc_emalloc(size * sizeof(char*));
|
||
+ tokens[n] = NULL;
|
||
+
|
||
+ while (cur <= end) {
|
||
+ /* search for the next delimiter */
|
||
+ char* p = strchr(s + cur, delim);
|
||
+ next = p ? p-s : end+1;
|
||
+
|
||
+ /* resize token array if necessary */
|
||
+ if (n == size-1) {
|
||
+ size *= 2;
|
||
+ tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
|
||
+ }
|
||
+
|
||
+ /* save the current token */
|
||
+ tokens[n] = apc_substr(s, cur, next-cur);
|
||
+
|
||
+ tokens[++n] = NULL;
|
||
+ cur = next + 1;
|
||
+ }
|
||
+
|
||
+ return tokens;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ filesystem functions */
|
||
+
|
||
+#ifdef PHP_WIN32
|
||
+int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
|
||
+{
|
||
+ char rpath[MAXPATHLEN];
|
||
+ BY_HANDLE_FILE_INFORMATION fi;
|
||
+ HANDLE f;
|
||
+
|
||
+ if (VCWD_STAT(path, buf)) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ VCWD_REALPATH(path, rpath);
|
||
+ f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
|
||
+ GetFileInformationByHandle(f, &fi);
|
||
+ buf->st_ino = (ino_t)fi.nFileIndexLow;
|
||
+ CloseHandle (f);
|
||
+ return 0;
|
||
+}
|
||
+#endif
|
||
+
|
||
+int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
|
||
+{
|
||
+ char** paths;
|
||
+ char *exec_fname;
|
||
+ int exec_fname_length;
|
||
+ int found = 0;
|
||
+ int i;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ assert(filename && fileinfo);
|
||
+
|
||
+ if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
|
||
+ strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
|
||
+ if (!paths)
|
||
+ return -1;
|
||
+
|
||
+ /* for each directory in paths, look for filename inside */
|
||
+ for (i = 0; paths[i]; i++) {
|
||
+ snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
|
||
+ if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
|
||
+ found = 1;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* check in path of the calling scripts' current working directory */
|
||
+ /* modified from main/streams/plain_wrapper.c */
|
||
+ if(!found && zend_is_executing(TSRMLS_C)) {
|
||
+ exec_fname = zend_get_executed_filename(TSRMLS_C);
|
||
+ exec_fname_length = strlen(exec_fname);
|
||
+ while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
|
||
+ if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
|
||
+ /* not: [no active file] or no path */
|
||
+ memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
|
||
+ fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
|
||
+ strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
|
||
+ /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
|
||
+ if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
|
||
+ found = 1;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* free the value returned by apc_tokenize */
|
||
+ for (i = 0; paths[i]; i++) {
|
||
+ apc_efree(paths[i]);
|
||
+ }
|
||
+ apc_efree(paths);
|
||
+
|
||
+ return found ? 0 : -1;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ regular expression wrapper functions */
|
||
+
|
||
+typedef struct {
|
||
+ regex_t *reg;
|
||
+ unsigned char type;
|
||
+} apc_regex;
|
||
+
|
||
+void* apc_regex_compile_array(char* patterns[])
|
||
+{
|
||
+ apc_regex** regs;
|
||
+ int npat;
|
||
+ int i;
|
||
+
|
||
+ if (!patterns)
|
||
+ return NULL;
|
||
+
|
||
+ /* count the number of patterns in patterns */
|
||
+ for (npat = 0; patterns[npat] != NULL; npat++) {}
|
||
+
|
||
+ if (npat == 0)
|
||
+ return NULL;
|
||
+
|
||
+ /* allocate the array of compiled expressions */
|
||
+ regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
|
||
+ for (i = 0; i <= npat; i++) {
|
||
+ regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
|
||
+ regs[i]->reg = NULL;
|
||
+ regs[i]->type = APC_NEGATIVE_MATCH;
|
||
+ }
|
||
+
|
||
+ /* compile the expressions */
|
||
+ for (i = 0; i < npat; i++) {
|
||
+ char *pattern = patterns[i];
|
||
+ if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
|
||
+ else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
|
||
+
|
||
+ regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
|
||
+
|
||
+ if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
|
||
+ apc_wprint("apc_regex_compile_array: invalid expression '%s'",
|
||
+ pattern);
|
||
+
|
||
+ apc_regex_destroy_array(regs);
|
||
+
|
||
+ return NULL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return (void*) regs;
|
||
+}
|
||
+
|
||
+void apc_regex_destroy_array(void* p)
|
||
+{
|
||
+ if (p != NULL) {
|
||
+ apc_regex** regs = (apc_regex**) p;
|
||
+ int i;
|
||
+
|
||
+ for (i = 0; regs[i]->reg != NULL; i++) {
|
||
+ regfree(regs[i]->reg);
|
||
+ apc_efree(regs[i]->reg);
|
||
+ apc_efree(regs[i]);
|
||
+ }
|
||
+ apc_efree(regs);
|
||
+ }
|
||
+}
|
||
+
|
||
+int apc_regex_match_array(void* p, const char* input)
|
||
+{
|
||
+ apc_regex** regs;
|
||
+ int i;
|
||
+
|
||
+ if (!p)
|
||
+ return 0;
|
||
+
|
||
+ regs = (apc_regex**) p;
|
||
+ for (i = 0; regs[i]->reg != NULL; i++)
|
||
+ if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
|
||
+ return (int)(regs[i]->type);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ crc32 implementation */
|
||
+
|
||
+/* this table was generated by crc32gen() */
|
||
+static unsigned int crc32tab[] = {
|
||
+ /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
|
||
+ /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
|
||
+ /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
|
||
+ /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
|
||
+ /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
|
||
+ /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
|
||
+ /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
|
||
+ /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
|
||
+ /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
|
||
+ /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
|
||
+ /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
|
||
+ /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
|
||
+ /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
|
||
+ /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
|
||
+ /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
|
||
+ /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
|
||
+ /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
|
||
+ /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
|
||
+ /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
|
||
+ /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
|
||
+ /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
|
||
+ /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
|
||
+ /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
|
||
+ /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
|
||
+ /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
|
||
+ /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
|
||
+ /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
|
||
+ /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
|
||
+ /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
|
||
+ /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
|
||
+ /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
|
||
+ /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
|
||
+ /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
|
||
+ /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
|
||
+ /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
|
||
+ /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
|
||
+ /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
|
||
+ /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
|
||
+ /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
|
||
+ /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
|
||
+ /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
|
||
+ /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
|
||
+ /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
|
||
+ /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
|
||
+ /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
|
||
+ /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
|
||
+ /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
|
||
+ /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
|
||
+ /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
|
||
+ /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
|
||
+ /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
|
||
+ /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
|
||
+ /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
|
||
+ /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
|
||
+ /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
|
||
+ /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
|
||
+ /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
|
||
+ /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
|
||
+ /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
|
||
+ /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
|
||
+ /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
|
||
+ /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
|
||
+ /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
|
||
+ /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
|
||
+};
|
||
+
|
||
+unsigned int apc_crc32(const char* buf, int len)
|
||
+{
|
||
+ int i;
|
||
+ int k;
|
||
+ unsigned int crc;
|
||
+
|
||
+ /* preconditioning */
|
||
+ crc = 0xFFFFFFFF;
|
||
+
|
||
+ for (i = 0; i < len; i++) {
|
||
+ k = (crc ^ buf[i]) & 0x000000FF;
|
||
+ crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
|
||
+ }
|
||
+
|
||
+ /* postconditioning */
|
||
+ return ~crc;
|
||
+}
|
||
+
|
||
+/* crc32gen: generate the nth (0..255) crc32 table value */
|
||
+#if 0
|
||
+static unsigned long crc32gen(int n)
|
||
+{
|
||
+ int i;
|
||
+ unsigned long crc;
|
||
+
|
||
+ crc = n;
|
||
+ for (i = 8; i >= 0; i--) {
|
||
+ if (crc & 1) {
|
||
+ crc = (crc >> 1) ^ 0xEDB88320;
|
||
+ }
|
||
+ else {
|
||
+ crc >>= 1;
|
||
+ }
|
||
+ }
|
||
+ return crc;
|
||
+}
|
||
+#endif
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.c php-5.2.5/ext/apc/apc_cache.c
|
||
--- php-5.2.5-orig/ext/apc/apc_cache.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_cache.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,1343 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_cache.c,v 3.145 2007/10/05 23:06:56 gopalv Exp $ */
|
||
+
|
||
+#include "apc_cache.h"
|
||
+#include "apc_lock.h"
|
||
+#include "apc_sma.h"
|
||
+#include "apc_globals.h"
|
||
+#include "SAPI.h"
|
||
+#include "ext/standard/php_var.h"
|
||
+#include "ext/standard/php_smart_str.h"
|
||
+
|
||
+/* TODO: rehash when load factor exceeds threshold */
|
||
+
|
||
+#define CHECK(p) { if ((p) == NULL) return NULL; }
|
||
+
|
||
+/* {{{ locking macros */
|
||
+#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock)
|
||
+#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
|
||
+#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
|
||
+#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
|
||
+#define UNLOCK(c) { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: slot_t */
|
||
+typedef struct slot_t slot_t;
|
||
+struct slot_t {
|
||
+ apc_cache_key_t key; /* slot key */
|
||
+ apc_cache_entry_t* value; /* slot value */
|
||
+ slot_t* next; /* next slot in linked list */
|
||
+ int num_hits; /* number of hits to this bucket */
|
||
+ time_t creation_time; /* time slot was initialized */
|
||
+ time_t deletion_time; /* time slot was removed from cache */
|
||
+ time_t access_time; /* time slot was last accessed */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: header_t
|
||
+ Any values that must be shared among processes should go in here. */
|
||
+typedef struct header_t header_t;
|
||
+struct header_t {
|
||
+ apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */
|
||
+ apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */
|
||
+ int num_hits; /* total successful hits in cache */
|
||
+ int num_misses; /* total unsuccessful hits in cache */
|
||
+ int num_inserts; /* total successful inserts in cache */
|
||
+ slot_t* deleted_list; /* linked list of to-be-deleted slots */
|
||
+ time_t start_time; /* time the above counters were reset */
|
||
+ int expunges; /* total number of expunges */
|
||
+ zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */
|
||
+ int num_entries; /* Statistic on the number of entries */
|
||
+ size_t mem_size; /* Statistic on the memory size used by this cache */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_cache_t */
|
||
+struct apc_cache_t {
|
||
+ void* shmaddr; /* process (local) address of shared cache */
|
||
+ header_t* header; /* cache header (stored in SHM) */
|
||
+ slot_t** slots; /* array of cache slots (stored in SHM) */
|
||
+ int num_slots; /* number of slots in cache */
|
||
+ int gc_ttl; /* maximum time on GC list for a slot */
|
||
+ int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition local_slot_t */
|
||
+typedef struct local_slot_t local_slot_t;
|
||
+struct local_slot_t {
|
||
+ slot_t *original; /* the original slot in shm */
|
||
+ int num_hits; /* number of hits */
|
||
+ time_t creation_time; /* creation time */
|
||
+ apc_cache_entry_t *value; /* shallow copy of slot->value */
|
||
+ local_slot_t *next; /* only for dead list */
|
||
+};
|
||
+/* }}} */
|
||
+/* {{{ struct definition apc_local_cache_t */
|
||
+struct apc_local_cache_t {
|
||
+ apc_cache_t* shmcache; /* the real cache in shm */
|
||
+ local_slot_t* slots; /* process (local) cache of objects */
|
||
+ local_slot_t* dead_list; /* list of objects pending removal */
|
||
+ int num_slots; /* number of slots in cache */
|
||
+ int ttl; /* time to live */
|
||
+ int num_hits; /* number of hits */
|
||
+ int generation; /* every generation lives between expunges */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ key_equals */
|
||
+#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ hash */
|
||
+static unsigned int hash(apc_cache_key_t key)
|
||
+{
|
||
+ return key.data.file.device + key.data.file.inode;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ string_nhash_8 */
|
||
+static unsigned int string_nhash_8(const char *s, size_t len)
|
||
+{
|
||
+ register const unsigned int *iv = (const unsigned int *)s;
|
||
+ register unsigned int h = 0;
|
||
+ register const unsigned int *e = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
|
||
+
|
||
+ for(;iv<e;iv++) {
|
||
+ h += *iv;
|
||
+ h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
|
||
+ }
|
||
+ s = (const char *)iv;
|
||
+ for(len %= sizeof(unsigned int);len;len--) {
|
||
+ h += *(s++);
|
||
+ }
|
||
+ h ^= (h >> 13);
|
||
+ h ^= (h >> 7);
|
||
+ return h;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ make_slot */
|
||
+slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
|
||
+{
|
||
+ slot_t* p = apc_sma_malloc(sizeof(slot_t));
|
||
+ if (!p) return NULL;
|
||
+
|
||
+ if(value->type == APC_CACHE_ENTRY_USER) {
|
||
+ char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
|
||
+ if (!identifier) {
|
||
+ apc_sma_free(p);
|
||
+ return NULL;
|
||
+ }
|
||
+ key.data.user.identifier = identifier;
|
||
+ } else if(key.type == APC_CACHE_KEY_FPFILE) {
|
||
+ char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
|
||
+ if (!fullpath) {
|
||
+ apc_sma_free(p);
|
||
+ return NULL;
|
||
+ }
|
||
+ key.data.fpfile.fullpath = fullpath;
|
||
+ }
|
||
+ p->key = key;
|
||
+ p->value = value;
|
||
+ p->next = next;
|
||
+ p->num_hits = 0;
|
||
+ p->creation_time = t;
|
||
+ p->access_time = t;
|
||
+ p->deletion_time = 0;
|
||
+ return p;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ free_slot */
|
||
+static void free_slot(slot_t* slot)
|
||
+{
|
||
+ if(slot->value->type == APC_CACHE_ENTRY_USER) {
|
||
+ apc_sma_free((char *)slot->key.data.user.identifier);
|
||
+ } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
|
||
+ apc_sma_free((char *)slot->key.data.fpfile.fullpath);
|
||
+ }
|
||
+ apc_cache_free_entry(slot->value);
|
||
+ apc_sma_free(slot);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ remove_slot */
|
||
+static void remove_slot(apc_cache_t* cache, slot_t** slot)
|
||
+{
|
||
+ slot_t* dead = *slot;
|
||
+ *slot = (*slot)->next;
|
||
+
|
||
+ cache->header->mem_size -= dead->value->mem_size;
|
||
+ cache->header->num_entries--;
|
||
+ if (dead->value->ref_count <= 0) {
|
||
+ free_slot(dead);
|
||
+ }
|
||
+ else {
|
||
+ dead->next = cache->header->deleted_list;
|
||
+ dead->deletion_time = time(0);
|
||
+ cache->header->deleted_list = dead;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ process_pending_removals */
|
||
+static void process_pending_removals(apc_cache_t* cache)
|
||
+{
|
||
+ slot_t** slot;
|
||
+ time_t now;
|
||
+
|
||
+ /* This function scans the list of removed cache entries and deletes any
|
||
+ * entry whose reference count is zero (indicating that it is no longer
|
||
+ * being executed) or that has been on the pending list for more than
|
||
+ * cache->gc_ttl seconds (we issue a warning in the latter case).
|
||
+ */
|
||
+
|
||
+ if (!cache->header->deleted_list)
|
||
+ return;
|
||
+
|
||
+ slot = &cache->header->deleted_list;
|
||
+ now = time(0);
|
||
+
|
||
+ while (*slot != NULL) {
|
||
+ int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
|
||
+
|
||
+ if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
|
||
+ slot_t* dead = *slot;
|
||
+
|
||
+ if (dead->value->ref_count > 0) {
|
||
+ switch(dead->value->type) {
|
||
+ case APC_CACHE_ENTRY_FILE:
|
||
+ apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
|
||
+ "was on gc-list for %d seconds", dead->value->data.file.filename,
|
||
+ dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
|
||
+ break;
|
||
+ case APC_CACHE_ENTRY_USER:
|
||
+ apc_log(APC_WARNING, "GC cache entry '%s' "
|
||
+ "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ *slot = dead->next;
|
||
+ free_slot(dead);
|
||
+ }
|
||
+ else {
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ prevent_garbage_collection */
|
||
+static void prevent_garbage_collection(apc_cache_entry_t* entry)
|
||
+{
|
||
+ /* set reference counts on zend objects to an arbitrarily high value to
|
||
+ * prevent garbage collection after execution */
|
||
+
|
||
+ enum { BIG_VALUE = 1000 };
|
||
+
|
||
+ if(entry->data.file.op_array) {
|
||
+ entry->data.file.op_array->refcount[0] = BIG_VALUE;
|
||
+ }
|
||
+ if (entry->data.file.functions) {
|
||
+ int i;
|
||
+ apc_function_t* fns = entry->data.file.functions;
|
||
+ for (i=0; fns[i].function != NULL; i++) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ *(fns[i].function->op_array.refcount) = BIG_VALUE;
|
||
+#else
|
||
+ fns[i].function->op_array.refcount[0] = BIG_VALUE;
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+ if (entry->data.file.classes) {
|
||
+ int i;
|
||
+ apc_class_t* classes = entry->data.file.classes;
|
||
+ for (i=0; classes[i].class_entry != NULL; i++) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ classes[i].class_entry->refcount = BIG_VALUE;
|
||
+#else
|
||
+ classes[i].class_entry->refcount[0] = BIG_VALUE;
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_create */
|
||
+apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
|
||
+{
|
||
+ apc_cache_t* cache;
|
||
+ int cache_size;
|
||
+ int num_slots;
|
||
+ int i;
|
||
+
|
||
+ num_slots = size_hint > 0 ? size_hint*2 : 2000;
|
||
+
|
||
+ cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
|
||
+ cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
|
||
+
|
||
+ cache->shmaddr = apc_sma_malloc(cache_size);
|
||
+ if(!cache->shmaddr) {
|
||
+ apc_eprint("Unable to allocate shared memory for cache structures. (Perhaps your shared memory size isn't large enough?). ");
|
||
+ }
|
||
+ memset(cache->shmaddr, 0, cache_size);
|
||
+
|
||
+ cache->header = (header_t*) cache->shmaddr;
|
||
+ cache->header->num_hits = 0;
|
||
+ cache->header->num_misses = 0;
|
||
+ cache->header->deleted_list = NULL;
|
||
+ cache->header->start_time = time(NULL);
|
||
+ cache->header->expunges = 0;
|
||
+ cache->header->busy = 0;
|
||
+
|
||
+ cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
|
||
+ cache->num_slots = num_slots;
|
||
+ cache->gc_ttl = gc_ttl;
|
||
+ cache->ttl = ttl;
|
||
+ CREATE_LOCK(cache->header->lock);
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ CREATE_LOCK(cache->header->wrlock);
|
||
+#endif
|
||
+ for (i = 0; i < num_slots; i++) {
|
||
+ cache->slots[i] = NULL;
|
||
+ }
|
||
+
|
||
+ return cache;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_destroy */
|
||
+void apc_cache_destroy(apc_cache_t* cache)
|
||
+{
|
||
+ DESTROY_LOCK(cache);
|
||
+ apc_efree(cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_clear */
|
||
+void apc_cache_clear(apc_cache_t* cache)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ if(!cache) return;
|
||
+
|
||
+ LOCK(cache);
|
||
+ cache->header->busy = 1;
|
||
+ cache->header->num_hits = 0;
|
||
+ cache->header->num_misses = 0;
|
||
+ cache->header->start_time = time(NULL);
|
||
+ cache->header->expunges = 0;
|
||
+
|
||
+ for (i = 0; i < cache->num_slots; i++) {
|
||
+ slot_t* p = cache->slots[i];
|
||
+ while (p) {
|
||
+ remove_slot(cache, &p);
|
||
+ }
|
||
+ cache->slots[i] = NULL;
|
||
+ }
|
||
+
|
||
+ cache->header->busy = 0;
|
||
+ UNLOCK(cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_expunge */
|
||
+void apc_cache_expunge(apc_cache_t* cache, time_t t)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ if(!cache) return;
|
||
+
|
||
+ if(!cache->ttl) {
|
||
+ /*
|
||
+ * If cache->ttl is not set, we wipe out the entire cache when
|
||
+ * we run out of space.
|
||
+ */
|
||
+ LOCK(cache);
|
||
+ cache->header->busy = 1;
|
||
+ cache->header->expunges++;
|
||
+ for (i = 0; i < cache->num_slots; i++) {
|
||
+ slot_t* p = cache->slots[i];
|
||
+ while (p) {
|
||
+ remove_slot(cache, &p);
|
||
+ }
|
||
+ cache->slots[i] = NULL;
|
||
+ }
|
||
+ cache->header->busy = 0;
|
||
+ UNLOCK(cache);
|
||
+ } else {
|
||
+ slot_t **p;
|
||
+
|
||
+ /*
|
||
+ * If the ttl for the cache is set we walk through and delete stale
|
||
+ * entries. For the user cache that is slightly confusing since
|
||
+ * we have the individual entry ttl's we can look at, but that would be
|
||
+ * too much work. So if you want the user cache expunged, set a high
|
||
+ * default apc.user_ttl and still provide a specific ttl for each entry
|
||
+ * on insert
|
||
+ */
|
||
+
|
||
+ LOCK(cache);
|
||
+ cache->header->busy = 1;
|
||
+ cache->header->expunges++;
|
||
+ for (i = 0; i < cache->num_slots; i++) {
|
||
+ p = &cache->slots[i];
|
||
+ while(*p) {
|
||
+ /*
|
||
+ * For the user cache we look at the individual entry ttl values
|
||
+ * and if not set fall back to the default ttl for the user cache
|
||
+ */
|
||
+ if((*p)->value->type == APC_CACHE_ENTRY_USER) {
|
||
+ if((*p)->value->data.user.ttl) {
|
||
+ if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
|
||
+ remove_slot(cache, p);
|
||
+ continue;
|
||
+ }
|
||
+ } else if(cache->ttl) {
|
||
+ if((*p)->creation_time + cache->ttl < t) {
|
||
+ remove_slot(cache, p);
|
||
+ continue;
|
||
+ }
|
||
+ }
|
||
+ } else if((*p)->access_time < (t - cache->ttl)) {
|
||
+ remove_slot(cache, p);
|
||
+ continue;
|
||
+ }
|
||
+ p = &(*p)->next;
|
||
+ }
|
||
+ }
|
||
+ cache->header->busy = 0;
|
||
+ UNLOCK(cache);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_insert */
|
||
+int apc_cache_insert(apc_cache_t* cache,
|
||
+ apc_cache_key_t key,
|
||
+ apc_cache_entry_t* value,
|
||
+ time_t t)
|
||
+{
|
||
+ slot_t** slot;
|
||
+
|
||
+ if (!value) {
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
|
||
+#endif
|
||
+
|
||
+ LOCK(cache);
|
||
+ process_pending_removals(cache);
|
||
+
|
||
+ if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
|
||
+ else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
|
||
+
|
||
+ while(*slot) {
|
||
+ if(key.type == (*slot)->key.type) {
|
||
+ if(key.type == APC_CACHE_KEY_FILE) {
|
||
+ if(key_equals((*slot)->key.data.file, key.data.file)) {
|
||
+ /* If existing slot for the same device+inode is different, remove it and insert the new version */
|
||
+ if ((*slot)->key.mtime != key.mtime) {
|
||
+ remove_slot(cache, slot);
|
||
+ break;
|
||
+ }
|
||
+ UNLOCK(cache);
|
||
+ return 0;
|
||
+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
|
||
+ remove_slot(cache, slot);
|
||
+ continue;
|
||
+ }
|
||
+ } else { /* APC_CACHE_KEY_FPFILE */
|
||
+ if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
|
||
+ /* Hrm.. it's already here, remove it and insert new one */
|
||
+ remove_slot(cache, slot);
|
||
+ break;
|
||
+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
|
||
+ remove_slot(cache, slot);
|
||
+ continue;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+
|
||
+ if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
|
||
+ UNLOCK(cache);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ cache->header->mem_size += value->mem_size;
|
||
+ cache->header->num_entries++;
|
||
+ cache->header->num_inserts++;
|
||
+
|
||
+ UNLOCK(cache);
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_user_insert */
|
||
+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)
|
||
+{
|
||
+ slot_t** slot;
|
||
+ size_t* mem_size_ptr = NULL;
|
||
+
|
||
+ if (!value) {
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ LOCK(cache);
|
||
+ process_pending_removals(cache);
|
||
+
|
||
+ slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
|
||
+
|
||
+ if (APCG(mem_size_ptr) != NULL) {
|
||
+ mem_size_ptr = APCG(mem_size_ptr);
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+ }
|
||
+
|
||
+ while (*slot) {
|
||
+ if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
|
||
+ /*
|
||
+ * At this point we have found the user cache entry. If we are doing
|
||
+ * an exclusive insert (apc_add) we are going to bail right away if
|
||
+ * the user entry already exists and it has no ttl, or
|
||
+ * there is a ttl and the entry has not timed out yet.
|
||
+ */
|
||
+ if(exclusive && ( !(*slot)->value->data.user.ttl ||
|
||
+ ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t )
|
||
+ ) ) {
|
||
+ UNLOCK(cache);
|
||
+ return 0;
|
||
+ }
|
||
+ remove_slot(cache, slot);
|
||
+ break;
|
||
+ } else
|
||
+ /*
|
||
+ * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of
|
||
+ * slot entries so we don't always have to skip past a bunch of stale entries. We check
|
||
+ * for staleness here and get rid of them by first checking to see if the cache has a global
|
||
+ * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
|
||
+ * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
|
||
+ */
|
||
+ if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) ||
|
||
+ ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
|
||
+ remove_slot(cache, slot);
|
||
+ continue;
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+
|
||
+ if (mem_size_ptr != NULL) {
|
||
+ APCG(mem_size_ptr) = mem_size_ptr;
|
||
+ }
|
||
+
|
||
+ if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
|
||
+ UNLOCK(cache);
|
||
+ return 0;
|
||
+ }
|
||
+ if (APCG(mem_size_ptr) != NULL) {
|
||
+ value->mem_size = *APCG(mem_size_ptr);
|
||
+ cache->header->mem_size += *APCG(mem_size_ptr);
|
||
+ }
|
||
+ cache->header->num_entries++;
|
||
+ cache->header->num_inserts++;
|
||
+
|
||
+ UNLOCK(cache);
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_find_slot */
|
||
+slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
|
||
+{
|
||
+ slot_t** slot;
|
||
+ volatile slot_t* retval = NULL;
|
||
+
|
||
+ LOCK(cache);
|
||
+ if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
|
||
+ else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
|
||
+
|
||
+ while (*slot) {
|
||
+ if(key.type == (*slot)->key.type) {
|
||
+ if(key.type == APC_CACHE_KEY_FILE) {
|
||
+ if(key_equals((*slot)->key.data.file, key.data.file)) {
|
||
+ if((*slot)->key.mtime != key.mtime) {
|
||
+ remove_slot(cache, slot);
|
||
+ cache->header->num_misses++;
|
||
+ UNLOCK(cache);
|
||
+ return NULL;
|
||
+ }
|
||
+ (*slot)->num_hits++;
|
||
+ (*slot)->value->ref_count++;
|
||
+ (*slot)->access_time = t;
|
||
+ prevent_garbage_collection((*slot)->value);
|
||
+ cache->header->num_hits++;
|
||
+ retval = *slot;
|
||
+ UNLOCK(cache);
|
||
+ return (slot_t*)retval;
|
||
+ }
|
||
+ } else { /* APC_CACHE_KEY_FPFILE */
|
||
+ if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
|
||
+ /* TTL Check ? */
|
||
+ (*slot)->num_hits++;
|
||
+ (*slot)->value->ref_count++;
|
||
+ (*slot)->access_time = t;
|
||
+ prevent_garbage_collection((*slot)->value);
|
||
+ cache->header->num_hits++;
|
||
+ retval = *slot;
|
||
+ UNLOCK(cache);
|
||
+ return (slot_t*)retval;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+ cache->header->num_misses++;
|
||
+ UNLOCK(cache);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_find */
|
||
+apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
|
||
+{
|
||
+ slot_t * slot = apc_cache_find_slot(cache, key, t);
|
||
+ return (slot) ? slot->value : NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_user_find */
|
||
+apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
|
||
+{
|
||
+ slot_t** slot;
|
||
+ volatile apc_cache_entry_t* value = NULL;
|
||
+
|
||
+ LOCK(cache);
|
||
+
|
||
+ slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
|
||
+
|
||
+ while (*slot) {
|
||
+ if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
|
||
+ /* Check to make sure this entry isn't expired by a hard TTL */
|
||
+ if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
|
||
+ remove_slot(cache, slot);
|
||
+ UNLOCK(cache);
|
||
+ return NULL;
|
||
+ }
|
||
+ /* Otherwise we are fine, increase counters and return the cache entry */
|
||
+ (*slot)->num_hits++;
|
||
+ (*slot)->value->ref_count++;
|
||
+ (*slot)->access_time = t;
|
||
+
|
||
+ cache->header->num_hits++;
|
||
+ value = (*slot)->value;
|
||
+ UNLOCK(cache);
|
||
+ return (apc_cache_entry_t*)value;
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+
|
||
+ UNLOCK(cache);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_user_delete */
|
||
+int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
|
||
+{
|
||
+ slot_t** slot;
|
||
+
|
||
+ LOCK(cache);
|
||
+
|
||
+ slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
|
||
+
|
||
+ while (*slot) {
|
||
+ if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
|
||
+ remove_slot(cache, slot);
|
||
+ UNLOCK(cache);
|
||
+ return 1;
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+
|
||
+ UNLOCK(cache);
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_release */
|
||
+void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
|
||
+{
|
||
+ /* local cache refcount-- is done in apc_local_cache_cleanup */
|
||
+ if(entry->local) return;
|
||
+
|
||
+ LOCK(cache);
|
||
+ entry->ref_count--;
|
||
+ UNLOCK(cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_make_file_key */
|
||
+int apc_cache_make_file_key(apc_cache_key_t* key,
|
||
+ const char* filename,
|
||
+ const char* include_path,
|
||
+ time_t t
|
||
+ TSRMLS_DC)
|
||
+{
|
||
+ struct stat *tmp_buf=NULL;
|
||
+ struct apc_fileinfo_t fileinfo = { {0}, };
|
||
+ int len;
|
||
+
|
||
+ assert(key != NULL);
|
||
+
|
||
+ if (!filename || !SG(request_info).path_translated) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"No filename and no path_translated - bailing\n");
|
||
+#endif
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ len = strlen(filename);
|
||
+ if(APCG(fpstat)==0) {
|
||
+ if(IS_ABSOLUTE_PATH(filename,len)) {
|
||
+ key->data.fpfile.fullpath = filename;
|
||
+ key->data.fpfile.fullpath_len = len;
|
||
+ key->mtime = t;
|
||
+ key->type = APC_CACHE_KEY_FPFILE;
|
||
+ } else {
|
||
+ if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
|
||
+ apc_wprint("apc failed to locate %s - bailing", filename);
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if(!realpath(fileinfo.fullpath, APCG(canon_path))) {
|
||
+ apc_wprint("realpath failed to canonicalize %s - bailing", filename);
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ key->data.fpfile.fullpath = APCG(canon_path);
|
||
+ key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
|
||
+ key->mtime = t;
|
||
+ key->type = APC_CACHE_KEY_FPFILE;
|
||
+ }
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if(!strcmp(SG(request_info).path_translated, filename)) {
|
||
+ tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
|
||
+ }
|
||
+ if(tmp_buf) {
|
||
+ fileinfo.st_buf = *tmp_buf;
|
||
+ } else {
|
||
+ if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
|
||
+#endif
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
|
||
+#endif
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * This is a bit of a hack.
|
||
+ *
|
||
+ * Here I am checking to see if the file is at least 2 seconds old.
|
||
+ * The idea is that if the file is currently being written to then its
|
||
+ * mtime is going to match or at most be 1 second off of the current
|
||
+ * request time and we want to avoid caching files that have not been
|
||
+ * completely written. Of course, people should be using atomic
|
||
+ * mechanisms to push files onto live web servers, but adding this
|
||
+ * tiny safety is easier than educating the world. This is now
|
||
+ * configurable, but the default is still 2 seconds.
|
||
+ */
|
||
+ if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
|
||
+#endif
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ key->data.file.device = fileinfo.st_buf.st_dev;
|
||
+ key->data.file.inode = fileinfo.st_buf.st_ino;
|
||
+ /*
|
||
+ * If working with content management systems that like to munge the mtime,
|
||
+ * it might be appropriate to key off of the ctime to be immune to systems
|
||
+ * that try to backdate a template. If the mtime is set to something older
|
||
+ * than the previous mtime of a template we will obviously never see this
|
||
+ * "older" template. At some point the Smarty templating system did this.
|
||
+ * I generally disagree with using the ctime here because you lose the
|
||
+ * ability to warm up new content by saving it to a temporary file, hitting
|
||
+ * it once to cache it and then renaming it into its permanent location so
|
||
+ * set the apc.stat_ctime=true to enable this check.
|
||
+ */
|
||
+ if(APCG(stat_ctime)) {
|
||
+ key->mtime = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime;
|
||
+ } else {
|
||
+ key->mtime = fileinfo.st_buf.st_mtime;
|
||
+ }
|
||
+ key->type = APC_CACHE_KEY_FILE;
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_make_user_key */
|
||
+int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
|
||
+{
|
||
+ assert(key != NULL);
|
||
+
|
||
+ if (!identifier)
|
||
+ return 0;
|
||
+
|
||
+ key->data.user.identifier = identifier;
|
||
+ key->data.user.identifier_len = identifier_len;
|
||
+ key->mtime = t;
|
||
+ key->type = APC_CACHE_KEY_USER;
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_make_file_entry */
|
||
+apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
|
||
+ zend_op_array* op_array,
|
||
+ apc_function_t* functions,
|
||
+ apc_class_t* classes)
|
||
+{
|
||
+ apc_cache_entry_t* entry;
|
||
+
|
||
+ entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
|
||
+ if (!entry) return NULL;
|
||
+
|
||
+ entry->data.file.filename = apc_xstrdup(filename, apc_sma_malloc);
|
||
+ if(!entry->data.file.filename) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
|
||
+#endif
|
||
+ apc_sma_free(entry);
|
||
+ return NULL;
|
||
+ }
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
|
||
+#endif
|
||
+ entry->data.file.op_array = op_array;
|
||
+ entry->data.file.functions = functions;
|
||
+ entry->data.file.classes = classes;
|
||
+ entry->type = APC_CACHE_ENTRY_FILE;
|
||
+ entry->ref_count = 0;
|
||
+ entry->mem_size = 0;
|
||
+ entry->local = 0;
|
||
+ return entry;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_store_zval */
|
||
+zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ smart_str buf = {0};
|
||
+ php_serialize_data_t var_hash;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
|
||
+ if(!dst) {
|
||
+ CHECK(dst = (zval*) allocate(sizeof(zval)));
|
||
+ }
|
||
+
|
||
+ PHP_VAR_SERIALIZE_INIT(var_hash);
|
||
+ php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
|
||
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
|
||
+
|
||
+ dst->type = IS_NULL; /* in case we fail */
|
||
+ if(buf.c) {
|
||
+ dst->type = src->type & ~IS_CONSTANT_INDEX;
|
||
+ dst->value.str.len = buf.len;
|
||
+ CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
|
||
+ dst->type = src->type;
|
||
+ smart_str_free(&buf);
|
||
+ }
|
||
+ return dst;
|
||
+ } else {
|
||
+
|
||
+ /* Maintain a list of zvals we've copied to properly handle recursive structures */
|
||
+ HashTable *old = APCG(copied_zvals);
|
||
+ APCG(copied_zvals) = emalloc(sizeof(HashTable));
|
||
+ zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
|
||
+
|
||
+ dst = apc_copy_zval(dst, src, allocate, deallocate);
|
||
+
|
||
+ if(APCG(copied_zvals)) {
|
||
+ zend_hash_destroy(APCG(copied_zvals));
|
||
+ efree(APCG(copied_zvals));
|
||
+ }
|
||
+
|
||
+ APCG(copied_zvals) = old;
|
||
+
|
||
+ return dst;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_fetch_zval */
|
||
+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ TSRMLS_FETCH();
|
||
+ if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
|
||
+ php_unserialize_data_t var_hash;
|
||
+ const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
|
||
+
|
||
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
|
||
+ if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
|
||
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||
+ zval_dtor(dst);
|
||
+ 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));
|
||
+ dst->type = IS_NULL;
|
||
+ }
|
||
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||
+ return dst;
|
||
+ } else {
|
||
+
|
||
+ /* Maintain a list of zvals we've copied to properly handle recursive structures */
|
||
+ HashTable *old = APCG(copied_zvals);
|
||
+ APCG(copied_zvals) = emalloc(sizeof(HashTable));
|
||
+ zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
|
||
+
|
||
+ dst = apc_copy_zval(dst, src, allocate, deallocate);
|
||
+
|
||
+ if(APCG(copied_zvals)) {
|
||
+ zend_hash_destroy(APCG(copied_zvals));
|
||
+ efree(APCG(copied_zvals));
|
||
+ }
|
||
+
|
||
+ APCG(copied_zvals) = old;
|
||
+
|
||
+ return dst;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_free_zval */
|
||
+void apc_cache_free_zval(zval* src, apc_free_t deallocate)
|
||
+{
|
||
+ TSRMLS_FETCH();
|
||
+ if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
|
||
+ if (src->value.str.val) {
|
||
+ deallocate(src->value.str.val);
|
||
+ }
|
||
+ deallocate(src);
|
||
+ } else {
|
||
+ /* Maintain a list of zvals we've copied to properly handle recursive structures */
|
||
+ HashTable *old = APCG(copied_zvals);
|
||
+ APCG(copied_zvals) = emalloc(sizeof(HashTable));
|
||
+ zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
|
||
+
|
||
+ apc_free_zval(src, deallocate);
|
||
+
|
||
+ if(APCG(copied_zvals)) {
|
||
+ zend_hash_destroy(APCG(copied_zvals));
|
||
+ efree(APCG(copied_zvals));
|
||
+ }
|
||
+
|
||
+ APCG(copied_zvals) = old;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_make_user_entry */
|
||
+apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
|
||
+{
|
||
+ apc_cache_entry_t* entry;
|
||
+
|
||
+ entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
|
||
+ if (!entry) return NULL;
|
||
+
|
||
+ entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
|
||
+ entry->data.user.info_len = info_len;
|
||
+ if(!entry->data.user.info) {
|
||
+ apc_sma_free(entry);
|
||
+ return NULL;
|
||
+ }
|
||
+ entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
|
||
+ if(!entry->data.user.val) {
|
||
+ apc_sma_free(entry->data.user.info);
|
||
+ apc_sma_free(entry);
|
||
+ return NULL;
|
||
+ }
|
||
+ INIT_PZVAL(entry->data.user.val);
|
||
+ entry->data.user.ttl = ttl;
|
||
+ entry->type = APC_CACHE_ENTRY_USER;
|
||
+ entry->ref_count = 0;
|
||
+ entry->mem_size = 0;
|
||
+ entry->local = 0;
|
||
+ return entry;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_free_entry */
|
||
+void apc_cache_free_entry(apc_cache_entry_t* entry)
|
||
+{
|
||
+ if (entry != NULL) {
|
||
+ assert(entry->ref_count == 0);
|
||
+ switch(entry->type) {
|
||
+ case APC_CACHE_ENTRY_FILE:
|
||
+ apc_sma_free(entry->data.file.filename);
|
||
+ apc_free_op_array(entry->data.file.op_array, apc_sma_free);
|
||
+ apc_free_functions(entry->data.file.functions, apc_sma_free);
|
||
+ apc_free_classes(entry->data.file.classes, apc_sma_free);
|
||
+ break;
|
||
+ case APC_CACHE_ENTRY_USER:
|
||
+ apc_sma_free(entry->data.user.info);
|
||
+ apc_cache_free_zval(entry->data.user.val, apc_sma_free);
|
||
+ break;
|
||
+ }
|
||
+ apc_sma_free(entry);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_info */
|
||
+apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
|
||
+{
|
||
+ apc_cache_info_t* info;
|
||
+ slot_t* p;
|
||
+ int i;
|
||
+
|
||
+ if(!cache) return NULL;
|
||
+
|
||
+ LOCK(cache);
|
||
+
|
||
+ info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
|
||
+ if(!info) {
|
||
+ UNLOCK(cache);
|
||
+ return NULL;
|
||
+ }
|
||
+ info->num_slots = cache->num_slots;
|
||
+ info->ttl = cache->ttl;
|
||
+ info->num_hits = cache->header->num_hits;
|
||
+ info->num_misses = cache->header->num_misses;
|
||
+ info->list = NULL;
|
||
+ info->deleted_list = NULL;
|
||
+ info->start_time = cache->header->start_time;
|
||
+ info->expunges = cache->header->expunges;
|
||
+ info->mem_size = cache->header->mem_size;
|
||
+ info->num_entries = cache->header->num_entries;
|
||
+ info->num_inserts = cache->header->num_inserts;
|
||
+
|
||
+ if(!limited) {
|
||
+ /* For each hashtable slot */
|
||
+ for (i = 0; i < info->num_slots; i++) {
|
||
+ p = cache->slots[i];
|
||
+ for (; p != NULL; p = p->next) {
|
||
+ apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
|
||
+
|
||
+ if(p->value->type == APC_CACHE_ENTRY_FILE) {
|
||
+ link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
|
||
+ link->data.file.device = p->key.data.file.device;
|
||
+ link->data.file.inode = p->key.data.file.inode;
|
||
+ link->type = APC_CACHE_ENTRY_FILE;
|
||
+ } else if(p->value->type == APC_CACHE_ENTRY_USER) {
|
||
+ link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
|
||
+ link->data.user.ttl = p->value->data.user.ttl;
|
||
+ link->type = APC_CACHE_ENTRY_USER;
|
||
+ }
|
||
+ link->num_hits = p->num_hits;
|
||
+ link->mtime = p->key.mtime;
|
||
+ link->creation_time = p->creation_time;
|
||
+ link->deletion_time = p->deletion_time;
|
||
+ link->access_time = p->access_time;
|
||
+ link->ref_count = p->value->ref_count;
|
||
+ link->mem_size = p->value->mem_size;
|
||
+ link->next = info->list;
|
||
+ info->list = link;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* For each slot pending deletion */
|
||
+ for (p = cache->header->deleted_list; p != NULL; p = p->next) {
|
||
+ apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
|
||
+
|
||
+ if(p->value->type == APC_CACHE_ENTRY_FILE) {
|
||
+ link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
|
||
+ if(p->key.type == APC_CACHE_KEY_FILE) {
|
||
+ link->data.file.device = p->key.data.file.device;
|
||
+ link->data.file.inode = p->key.data.file.inode;
|
||
+ } else { /* This is a no-stat fullpath file entry */
|
||
+ link->data.file.device = 0;
|
||
+ link->data.file.inode = 0;
|
||
+ }
|
||
+ link->type = APC_CACHE_ENTRY_FILE;
|
||
+ } else if(p->value->type == APC_CACHE_ENTRY_USER) {
|
||
+ link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
|
||
+ link->data.user.ttl = p->value->data.user.ttl;
|
||
+ link->type = APC_CACHE_ENTRY_USER;
|
||
+ }
|
||
+ link->num_hits = p->num_hits;
|
||
+ link->mtime = p->key.mtime;
|
||
+ link->creation_time = p->creation_time;
|
||
+ link->deletion_time = p->deletion_time;
|
||
+ link->access_time = p->access_time;
|
||
+ link->ref_count = p->value->ref_count;
|
||
+ link->mem_size = p->value->mem_size;
|
||
+ link->next = info->deleted_list;
|
||
+ info->deleted_list = link;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ UNLOCK(cache);
|
||
+ return info;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_free_info */
|
||
+void apc_cache_free_info(apc_cache_info_t* info)
|
||
+{
|
||
+ apc_cache_link_t* p = info->list;
|
||
+ apc_cache_link_t* q = NULL;
|
||
+ while (p != NULL) {
|
||
+ q = p;
|
||
+ p = p->next;
|
||
+ if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
|
||
+ else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
|
||
+ apc_efree(q);
|
||
+ }
|
||
+ p = info->deleted_list;
|
||
+ while (p != NULL) {
|
||
+ q = p;
|
||
+ p = p->next;
|
||
+ if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
|
||
+ else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
|
||
+ apc_efree(q);
|
||
+ }
|
||
+ apc_efree(info);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_unlock */
|
||
+void apc_cache_unlock(apc_cache_t* cache)
|
||
+{
|
||
+ UNLOCK(cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_busy */
|
||
+zend_bool apc_cache_busy(apc_cache_t* cache)
|
||
+{
|
||
+ return cache->header->busy;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+/* {{{ apc_cache_write_lock */
|
||
+zend_bool apc_cache_write_lock(apc_cache_t* cache)
|
||
+{
|
||
+ return apc_lck_nb_lock(cache->header->wrlock);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_cache_write_unlock */
|
||
+void apc_cache_write_unlock(apc_cache_t* cache)
|
||
+{
|
||
+ apc_lck_unlock(cache->header->wrlock);
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ make_local_slot */
|
||
+static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot, time_t t)
|
||
+{
|
||
+ apc_cache_entry_t* value;
|
||
+
|
||
+ value = apc_emalloc(sizeof(apc_cache_entry_t));
|
||
+ memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
|
||
+ value->local = 1;
|
||
+
|
||
+ lslot->original = slot;
|
||
+ lslot->value = value;
|
||
+ lslot->num_hits = 0;
|
||
+ lslot->creation_time = t;
|
||
+
|
||
+ return lslot; /* for what joy ? ... consistency */
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ free_local_slot */
|
||
+static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot)
|
||
+{
|
||
+ local_slot_t * dead = NULL;
|
||
+ if(!lslot->original) return;
|
||
+
|
||
+ /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
|
||
+ dead = apc_emalloc(sizeof(local_slot_t));
|
||
+ memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
|
||
+
|
||
+ lslot->original = NULL;
|
||
+ lslot->value = NULL;
|
||
+
|
||
+ dead->next = cache->dead_list;
|
||
+ cache->dead_list = dead;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_local_cache_create */
|
||
+apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
|
||
+{
|
||
+ apc_local_cache_t* cache = NULL;
|
||
+
|
||
+ cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
|
||
+
|
||
+ cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
|
||
+ memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
|
||
+
|
||
+ cache->shmcache = shmcache;
|
||
+ cache->num_slots = num_slots;
|
||
+ cache->ttl = ttl;
|
||
+ cache->num_hits = 0;
|
||
+ cache->generation = shmcache->header->expunges;
|
||
+ cache->dead_list = NULL;
|
||
+
|
||
+ return cache;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_local_cache_cleanup */
|
||
+void apc_local_cache_cleanup(apc_local_cache_t* cache) {
|
||
+ local_slot_t * lslot;
|
||
+ time_t t = time(0);
|
||
+
|
||
+ int i;
|
||
+ for(i = 0; i < cache->num_slots; i++) {
|
||
+ lslot = &cache->slots[i];
|
||
+ /* every slot lives for exactly TTL seconds */
|
||
+ if((lslot->original && lslot->creation_time < (t - cache->ttl)) ||
|
||
+ cache->generation != cache->shmcache->header->expunges) {
|
||
+ free_local_slot(cache, lslot);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ LOCK(cache->shmcache);
|
||
+ for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
|
||
+ lslot->original->num_hits += lslot->num_hits;
|
||
+ lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
|
||
+ apc_efree(lslot->value);
|
||
+ }
|
||
+ UNLOCK(cache->shmcache);
|
||
+
|
||
+ cache->dead_list = NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_local_cache_destroy */
|
||
+void apc_local_cache_destroy(apc_local_cache_t* cache)
|
||
+{
|
||
+ int i;
|
||
+ for(i = 0; i < cache->num_slots; i++) {
|
||
+ free_local_slot(cache, &cache->slots[i]);
|
||
+ }
|
||
+
|
||
+ apc_local_cache_cleanup(cache);
|
||
+
|
||
+ LOCK(cache->shmcache);
|
||
+ cache->shmcache->header->num_hits += cache->num_hits;
|
||
+ UNLOCK(cache->shmcache);
|
||
+
|
||
+ apc_efree(cache->slots);
|
||
+ apc_efree(cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_local_cache_find */
|
||
+apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
|
||
+{
|
||
+ slot_t* slot;
|
||
+ local_slot_t* lslot;
|
||
+
|
||
+ if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
|
||
+ else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
|
||
+
|
||
+ slot = lslot->original;
|
||
+
|
||
+ if(slot && key.type == slot->key.type) {
|
||
+ if(slot->access_time < (t - cache->ttl)) {
|
||
+ goto not_found;
|
||
+ }
|
||
+ if(key.type == APC_CACHE_KEY_FILE &&
|
||
+ key_equals(slot->key.data.file, key.data.file)) {
|
||
+ if(slot->key.mtime != key.mtime) {
|
||
+ free_local_slot(cache, lslot);
|
||
+ goto not_found;
|
||
+ }
|
||
+ cache->num_hits++;
|
||
+ lslot->num_hits++;
|
||
+ lslot->original->access_time = t; /* unlocked write, but last write wins */
|
||
+ return lslot->value;
|
||
+ } else if(key.type == APC_CACHE_KEY_FPFILE) {
|
||
+ if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
|
||
+ cache->num_hits++;
|
||
+ lslot->num_hits++;
|
||
+ lslot->original->access_time = t; /* unlocked write, but last write wins */
|
||
+ return lslot->value;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+not_found:
|
||
+ if(apc_cache_busy(cache->shmcache)) {
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ slot = apc_cache_find_slot(cache->shmcache, key, t);
|
||
+
|
||
+ if(!slot) return NULL;
|
||
+
|
||
+ /* i.e maintain a sort of top list */
|
||
+ if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits) < slot->num_hits) {
|
||
+ free_local_slot(cache, lslot);
|
||
+ make_local_slot(cache, lslot, slot, t);
|
||
+ return lslot->value;
|
||
+ }
|
||
+ return slot->value;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.h php-5.2.5/ext/apc/apc_cache.h
|
||
--- php-5.2.5-orig/ext/apc/apc_cache.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_cache.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,312 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt. |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_cache.h,v 3.46 2007/10/05 23:06:56 gopalv Exp $ */
|
||
+
|
||
+#ifndef APC_CACHE_H
|
||
+#define APC_CACHE_H
|
||
+
|
||
+/*
|
||
+ * This module defines the shared memory file cache. Basically all of the
|
||
+ * logic for storing and retrieving cache entries lives here.
|
||
+ */
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_compile.h"
|
||
+
|
||
+#define APC_CACHE_ENTRY_FILE 1
|
||
+#define APC_CACHE_ENTRY_USER 2
|
||
+
|
||
+#define APC_CACHE_KEY_FILE 1
|
||
+#define APC_CACHE_KEY_USER 2
|
||
+#define APC_CACHE_KEY_FPFILE 3
|
||
+
|
||
+/* {{{ struct definition: apc_cache_key_t */
|
||
+#define T apc_cache_t*
|
||
+typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
|
||
+
|
||
+typedef union _apc_cache_key_data_t {
|
||
+ struct {
|
||
+ dev_t device; /* the filesystem device */
|
||
+ ino_t inode; /* the filesystem inode */
|
||
+ } file;
|
||
+ struct {
|
||
+ const char *identifier;
|
||
+ int identifier_len;
|
||
+ } user;
|
||
+ struct {
|
||
+ const char *fullpath;
|
||
+ int fullpath_len;
|
||
+ } fpfile;
|
||
+} apc_cache_key_data_t;
|
||
+
|
||
+typedef struct apc_cache_key_t apc_cache_key_t;
|
||
+struct apc_cache_key_t {
|
||
+ apc_cache_key_data_t data;
|
||
+ time_t mtime; /* the mtime of this cached entry */
|
||
+ unsigned char type;
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_cache_entry_t */
|
||
+typedef union _apc_cache_entry_value_t {
|
||
+ struct {
|
||
+ char *filename; /* absolute path to source file */
|
||
+ zend_op_array* op_array; /* op_array allocated in shared memory */
|
||
+ apc_function_t* functions; /* array of apc_function_t's */
|
||
+ apc_class_t* classes; /* array of apc_class_t's */
|
||
+ } file;
|
||
+ struct {
|
||
+ char *info;
|
||
+ int info_len;
|
||
+ zval *val;
|
||
+ unsigned int ttl;
|
||
+ } user;
|
||
+} apc_cache_entry_value_t;
|
||
+
|
||
+typedef struct apc_cache_entry_t apc_cache_entry_t;
|
||
+struct apc_cache_entry_t {
|
||
+ apc_cache_entry_value_t data;
|
||
+ unsigned char type;
|
||
+ unsigned char local;
|
||
+ int ref_count;
|
||
+ size_t mem_size;
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * apc_cache_create creates the shared memory compiler cache. This function
|
||
+ * should be called just once (ideally in the web server parent process, e.g.
|
||
+ * in apache), otherwise you will end up with multiple caches (which won't
|
||
+ * necessarily break anything). Returns a pointer to the cache object.
|
||
+ *
|
||
+ * size_hint is a "hint" at the total number of source files that will be
|
||
+ * cached. It determines the physical size of the hash table. Passing 0 for
|
||
+ * this argument will use a reasonable default value.
|
||
+ *
|
||
+ * gc_ttl is the maximum time a cache entry may speed on the garbage
|
||
+ * collection list. This is basically a work around for the inherent
|
||
+ * unreliability of our reference counting mechanism (see apc_cache_release).
|
||
+ *
|
||
+ * ttl is the maximum time a cache entry can idle in a slot in case the slot
|
||
+ * is needed. This helps in cleaning up the cache and ensuring that entries
|
||
+ * hit frequently stay cached and ones not hit very often eventually disappear.
|
||
+ */
|
||
+extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
|
||
+
|
||
+/*
|
||
+ * apc_cache_destroy releases any OS resources associated with a cache object.
|
||
+ * Under apache, this function can be safely called by the child processes
|
||
+ * when they exit.
|
||
+ */
|
||
+extern void apc_cache_destroy(T cache);
|
||
+
|
||
+/*
|
||
+ * apc_cache_clear empties a cache. This can safely be called at any time,
|
||
+ * even while other server processes are executing cached source files.
|
||
+ */
|
||
+extern void apc_cache_clear(T cache);
|
||
+
|
||
+/*
|
||
+ * apc_cache_insert adds an entry to the cache, using a filename as a key.
|
||
+ * Internally, the filename is translated to a canonical representation, so
|
||
+ * that relative and absolute filenames will map to a single key. Returns
|
||
+ * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
|
||
+ * returned, the caller must free the cache entry by calling
|
||
+ * apc_cache_free_entry (see below).
|
||
+ *
|
||
+ * key is the value created by apc_cache_make_file_key for file keys.
|
||
+ *
|
||
+ * value is a cache entry returned by apc_cache_make_entry (see below).
|
||
+ */
|
||
+extern int apc_cache_insert(T cache, apc_cache_key_t key,
|
||
+ apc_cache_entry_t* value, time_t t);
|
||
+
|
||
+extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
|
||
+ apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
|
||
+
|
||
+/*
|
||
+ * apc_cache_find searches for a cache entry by filename, and returns a
|
||
+ * pointer to the entry if found, NULL otherwise.
|
||
+ *
|
||
+ * key is a value created by apc_cache_make_file_key for file keys.
|
||
+ */
|
||
+extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
|
||
+
|
||
+/*
|
||
+ * apc_cache_user_find searches for a cache entry by its hashed identifier,
|
||
+ * and returns a pointer to the entry if found, NULL otherwise.
|
||
+ *
|
||
+ */
|
||
+extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
|
||
+
|
||
+/*
|
||
+ * apc_cache_user_delete finds an entry in the user cache and deletes it.
|
||
+ */
|
||
+extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
|
||
+
|
||
+/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
|
||
+ * zval from it.
|
||
+ *
|
||
+ */
|
||
+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
|
||
+
|
||
+/*
|
||
+ * apc_cache_release decrements the reference count associated with a cache
|
||
+ * entry. Calling apc_cache_find automatically increments the reference count,
|
||
+ * and this function must be called post-execution to return the count to its
|
||
+ * original value. Failing to do so will prevent the entry from being
|
||
+ * garbage-collected.
|
||
+ *
|
||
+ * entry is the cache entry whose ref count you want to decrement.
|
||
+ */
|
||
+extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
|
||
+
|
||
+/*
|
||
+ * apc_cache_make_file_key creates a key object given a relative or absolute
|
||
+ * filename and an optional list of auxillary paths to search. include_path is
|
||
+ * searched if the filename cannot be found relative to the current working
|
||
+ * directory.
|
||
+ *
|
||
+ * key points to caller-allocated storage (must not be null).
|
||
+ *
|
||
+ * filename is the path to the source file.
|
||
+ *
|
||
+ * include_path is a colon-separated list of directories to search.
|
||
+ *
|
||
+ * and finally we pass in the current request time so we can avoid
|
||
+ * caching files with a current mtime which tends to indicate that
|
||
+ * they are still being written to.
|
||
+ */
|
||
+extern int apc_cache_make_file_key(apc_cache_key_t* key,
|
||
+ const char* filename,
|
||
+ const char* include_path,
|
||
+ time_t t
|
||
+ TSRMLS_DC);
|
||
+
|
||
+/*
|
||
+ * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
|
||
+ * and the compilation results returned by the PHP compiler.
|
||
+ */
|
||
+extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
|
||
+ zend_op_array* op_array,
|
||
+ apc_function_t* functions,
|
||
+ apc_class_t* classes);
|
||
+/*
|
||
+ * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
|
||
+ * and the zval to be stored.
|
||
+ */
|
||
+extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
|
||
+
|
||
+extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
|
||
+
|
||
+/*
|
||
+ * Frees all memory associated with an object returned by apc_cache_make_entry
|
||
+ * (see above).
|
||
+ */
|
||
+extern void apc_cache_free_entry(apc_cache_entry_t* entry);
|
||
+
|
||
+/* {{{ struct definition: apc_cache_link_data_t */
|
||
+typedef union _apc_cache_link_data_t {
|
||
+ struct {
|
||
+ char *filename;
|
||
+ dev_t device;
|
||
+ ino_t inode;
|
||
+ } file;
|
||
+ struct {
|
||
+ char *info;
|
||
+ unsigned int ttl;
|
||
+ } user;
|
||
+} apc_cache_link_data_t;
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_cache_link_t */
|
||
+typedef struct apc_cache_link_t apc_cache_link_t;
|
||
+struct apc_cache_link_t {
|
||
+ apc_cache_link_data_t data;
|
||
+ unsigned char type;
|
||
+ int num_hits;
|
||
+ time_t mtime;
|
||
+ time_t creation_time;
|
||
+ time_t deletion_time;
|
||
+ time_t access_time;
|
||
+ int ref_count;
|
||
+ size_t mem_size;
|
||
+ apc_cache_link_t* next;
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_cache_info_t */
|
||
+typedef struct apc_cache_info_t apc_cache_info_t;
|
||
+struct apc_cache_info_t {
|
||
+ int num_slots;
|
||
+ int num_hits;
|
||
+ int num_misses;
|
||
+ int ttl;
|
||
+ apc_cache_link_t* list;
|
||
+ apc_cache_link_t* deleted_list;
|
||
+ time_t start_time;
|
||
+ int expunges;
|
||
+ int num_entries;
|
||
+ int num_inserts;
|
||
+ size_t mem_size;
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
|
||
+extern void apc_cache_free_info(apc_cache_info_t* info);
|
||
+extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
|
||
+extern void apc_cache_unlock(apc_cache_t* cache);
|
||
+extern zend_bool apc_cache_busy(apc_cache_t* cache);
|
||
+extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
|
||
+extern void apc_cache_write_unlock(apc_cache_t* cache);
|
||
+
|
||
+/*
|
||
+ * Process local cache, which keeps a refcount hungry version of the slots
|
||
+ * for quick access without a lock - as long as the entry exists in local
|
||
+ * cache, the refcount of the shm version will be +1 more than required.
|
||
+ * It holds no data, only a shallow copy of apc_cache_entry.
|
||
+ */
|
||
+typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */
|
||
+
|
||
+extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
|
||
+extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
|
||
+extern void apc_local_cache_destroy(apc_local_cache_t* cache);
|
||
+extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
|
||
+
|
||
+#undef T
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.c php-5.2.5/ext/apc/apc_compile.c
|
||
--- php-5.2.5-orig/ext/apc/apc_compile.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_compile.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,2529 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt. |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_compile.c,v 3.87 2007/08/25 13:09:13 gopalv Exp $ */
|
||
+
|
||
+#include "apc_compile.h"
|
||
+#include "apc_globals.h"
|
||
+#include "apc_zend.h"
|
||
+
|
||
+typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
|
||
+typedef void (*ht_free_fun_t)(void*, apc_free_t);
|
||
+typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
|
||
+#endif
|
||
+
|
||
+#define CHECK(p) { if ((p) == NULL) return NULL; }
|
||
+
|
||
+/* {{{ internal function declarations */
|
||
+
|
||
+static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
|
||
+
|
||
+static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
|
||
+
|
||
+/*
|
||
+ * The "copy" functions perform deep-copies on a particular data structure
|
||
+ * (passed as the second argument). They also optionally allocate space for
|
||
+ * the destination data structure if the first argument is null.
|
||
+ */
|
||
+static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
|
||
+static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
|
||
+static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
|
||
+static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
|
||
+static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
|
||
+static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
|
||
+static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
|
||
+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, ...);
|
||
+#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
|
||
+ my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
|
||
+static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
|
||
+static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
|
||
+static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
|
||
+#endif
|
||
+/*
|
||
+ * The "destroy" functions free the memory associated with a particular data
|
||
+ * structure but do not free the pointer to the data structure.
|
||
+ *
|
||
+ * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
|
||
+ * the zval* has other references elsewhere
|
||
+ */
|
||
+static int my_destroy_zval(zval*, apc_free_t);
|
||
+static void my_destroy_zval_ptr(zval**, apc_free_t);
|
||
+static void my_destroy_zend_op(zend_op*, apc_free_t);
|
||
+static void my_destroy_znode(znode*, apc_free_t);
|
||
+static void my_destroy_function(zend_function*, apc_free_t);
|
||
+static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
|
||
+static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
|
||
+static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
|
||
+static void my_destroy_op_array(zend_op_array*, apc_free_t);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static void my_destroy_property_info(zend_property_info*, apc_free_t);
|
||
+static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
|
||
+static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * The "free" functions work exactly like their "destroy" counterparts (see
|
||
+ * above) but also free the pointer to the data structure.
|
||
+ */
|
||
+static void my_free_zval_ptr(zval**, apc_free_t);
|
||
+static void my_free_function(zend_function*, apc_free_t);
|
||
+static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static void my_free_property_info(zend_property_info* src, apc_free_t);
|
||
+static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
|
||
+static void my_free_arg_info(zend_arg_info*, apc_free_t);
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * The "fixup" functions need for ZEND_ENGINE_2
|
||
+ */
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
|
||
+static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
|
||
+/* my_fixup_function_for_execution is the same as my_fixup_function
|
||
+ * but named differently for clarity
|
||
+ */
|
||
+#define my_fixup_function_for_execution my_fixup_function
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
|
||
+#define my_fixup_property_info_for_execution my_fixup_property_info
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * These functions return "1" if the member/function is
|
||
+ * defined/overridden in the 'current' class and not inherited.
|
||
+ */
|
||
+static int my_check_copy_function(Bucket* src, va_list args);
|
||
+static int my_check_copy_default_property(Bucket* p, va_list args);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static int my_check_copy_property_info(Bucket* src, va_list args);
|
||
+static int my_check_copy_static_member(Bucket* src, va_list args);
|
||
+#endif
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ check_op_array_integrity */
|
||
+#if 0
|
||
+static void check_op_array_integrity(zend_op_array* src)
|
||
+{
|
||
+ int i, j;
|
||
+
|
||
+ /* These sorts of checks really aren't particularly effective, but they
|
||
+ * can provide a welcome sanity check when debugging. Just don't enable
|
||
+ * for production use! */
|
||
+
|
||
+ assert(src->refcount != NULL);
|
||
+ assert(src->opcodes != NULL);
|
||
+ assert(src->last > 0);
|
||
+
|
||
+ for (i = 0; i < src->last; i++) {
|
||
+ zend_op* op = &src->opcodes[i];
|
||
+ znode* nodes[] = { &op->result, &op->op1, &op->op2 };
|
||
+ for (j = 0; j < 3; j++) {
|
||
+ assert(nodes[j]->op_type == IS_CONST ||
|
||
+ nodes[j]->op_type == IS_VAR ||
|
||
+ nodes[j]->op_type == IS_TMP_VAR ||
|
||
+ nodes[j]->op_type == IS_UNUSED);
|
||
+
|
||
+ if (nodes[j]->op_type == IS_CONST) {
|
||
+ int type = nodes[j]->u.constant.type;
|
||
+ assert(type == IS_RESOURCE ||
|
||
+ type == IS_BOOL ||
|
||
+ type == IS_LONG ||
|
||
+ type == IS_DOUBLE ||
|
||
+ type == IS_NULL ||
|
||
+ type == IS_CONSTANT ||
|
||
+ type == IS_STRING ||
|
||
+ type == FLAG_IS_BC ||
|
||
+ type == IS_ARRAY ||
|
||
+ type == IS_CONSTANT_ARRAY ||
|
||
+ type == IS_OBJECT);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ is_derived_class */
|
||
+static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ /*
|
||
+ * Scan the op_array for execution-time class declarations of derived
|
||
+ * classes. If we find one whose key matches our current class key, we
|
||
+ * know the current class is a derived class.
|
||
+ *
|
||
+ * This check is exceedingly inefficient (fortunately it only has to occur
|
||
+ * once, when the source file is first compiled and cached), but the
|
||
+ * compiler should save this information for us -- definitely a candidate
|
||
+ * for a Zend Engine patch.
|
||
+ *
|
||
+ * XXX checking for derived classes provides a minimal (albeit measurable)
|
||
+ * speed up. It may not be worth the added complexity -- considere
|
||
+ * removing this optimization.
|
||
+ */
|
||
+
|
||
+ for (i = 0; i < op_array->last; i++) {
|
||
+ zend_op* op = &op_array->opcodes[i];
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (op->opcode == ZEND_DECLARE_CLASS &&
|
||
+ op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
|
||
+#else
|
||
+ if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
|
||
+ op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
|
||
+#endif
|
||
+ {
|
||
+ if (op->op1.u.constant.value.str.len == key_size &&
|
||
+ !memcmp(op->op1.u.constant.value.str.val, key, key_size))
|
||
+ {
|
||
+ return 1;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_bitwise_copy_function */
|
||
+static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
|
||
+ }
|
||
+
|
||
+ /* We only need to do a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_zval_ptr */
|
||
+static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ zval* dst_new;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zval**) allocate(sizeof(zval*)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+ }
|
||
+ dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
|
||
+ if(dst_new != *dst) {
|
||
+ deallocate(*dst);
|
||
+ *dst = dst_new;
|
||
+ }
|
||
+
|
||
+ (*dst)->refcount = (*src)->refcount;
|
||
+ (*dst)->is_ref = (*src)->is_ref;
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_zval */
|
||
+static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ zval **tmp;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ assert(dst != NULL);
|
||
+ assert(src != NULL);
|
||
+
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ switch (src->type & ~IS_CONSTANT_INDEX) {
|
||
+ case IS_RESOURCE:
|
||
+ case IS_BOOL:
|
||
+ case IS_LONG:
|
||
+ case IS_DOUBLE:
|
||
+ case IS_NULL:
|
||
+ break;
|
||
+
|
||
+ case IS_CONSTANT:
|
||
+ case IS_STRING:
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ case FLAG_IS_BC:
|
||
+#endif
|
||
+ if (src->value.str.val) {
|
||
+ CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
|
||
+ src->value.str.len+1,
|
||
+ allocate));
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case IS_ARRAY:
|
||
+
|
||
+ if(APCG(copied_zvals)) {
|
||
+ if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
|
||
+ (*tmp)->refcount++;
|
||
+ return *tmp;
|
||
+ }
|
||
+
|
||
+ zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
|
||
+ }
|
||
+ /* fall through */
|
||
+
|
||
+ case IS_CONSTANT_ARRAY:
|
||
+
|
||
+ CHECK(dst->value.ht =
|
||
+ my_copy_hashtable(NULL,
|
||
+ src->value.ht,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate));
|
||
+ break;
|
||
+
|
||
+ case IS_OBJECT:
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ CHECK(dst->value.obj.ce =
|
||
+ my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
|
||
+
|
||
+ if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
|
||
+ src->value.obj.properties,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate))) {
|
||
+ my_destroy_class_entry(dst->value.obj.ce, deallocate);
|
||
+ return NULL;
|
||
+ }
|
||
+ break;
|
||
+#else
|
||
+ dst->type = IS_NULL;
|
||
+#endif
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ assert(0);
|
||
+ }
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_znode */
|
||
+static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ assert(dst != NULL);
|
||
+ assert(src != NULL);
|
||
+
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+#ifdef IS_CV
|
||
+ assert(dst ->op_type == IS_CONST ||
|
||
+ dst ->op_type == IS_VAR ||
|
||
+ dst ->op_type == IS_CV ||
|
||
+ dst ->op_type == IS_TMP_VAR ||
|
||
+ dst ->op_type == IS_UNUSED);
|
||
+#else
|
||
+ assert(dst ->op_type == IS_CONST ||
|
||
+ dst ->op_type == IS_VAR ||
|
||
+ dst ->op_type == IS_TMP_VAR ||
|
||
+ dst ->op_type == IS_UNUSED);
|
||
+#endif
|
||
+
|
||
+ if (src->op_type == IS_CONST) {
|
||
+ if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_zend_op */
|
||
+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ assert(dst != NULL);
|
||
+ assert(src != NULL);
|
||
+
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL
|
||
+ || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
|
||
+ || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
|
||
+ {
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_function */
|
||
+static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if(!dst) local_dst_alloc = 1;
|
||
+ CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
|
||
+
|
||
+ switch (src->type) {
|
||
+ case ZEND_INTERNAL_FUNCTION:
|
||
+ case ZEND_OVERLOADED_FUNCTION:
|
||
+ /* shallow copy because op_array is internal */
|
||
+ dst->op_array = src->op_array;
|
||
+ break;
|
||
+
|
||
+ case ZEND_USER_FUNCTION:
|
||
+ case ZEND_EVAL_CODE:
|
||
+ if(!apc_copy_op_array(&dst->op_array,
|
||
+ &src->op_array,
|
||
+ allocate, deallocate TSRMLS_CC)) {
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ assert(0);
|
||
+ }
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ /*
|
||
+ * op_array bitwise copying overwrites what ever you modified
|
||
+ * before apc_copy_op_array - which is why this code is outside
|
||
+ * my_bitwise_copy_function.
|
||
+ */
|
||
+
|
||
+ /* zend_do_inheritance will re-look this up, because the pointers
|
||
+ * in prototype are from a function table of another class. It just
|
||
+ * helps if that one is from EG(class_table).
|
||
+ */
|
||
+ dst->common.prototype = NULL;
|
||
+
|
||
+ /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
|
||
+ * have to carry around a prototype. Thankfully zend_do_inheritance
|
||
+ * sets this properly as well
|
||
+ */
|
||
+ dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
|
||
+#endif
|
||
+
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_function_entry */
|
||
+static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* Start with a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ dst->fname = NULL;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ dst->arg_info = NULL;
|
||
+#else
|
||
+ dst->func_arg_types = NULL;
|
||
+#endif
|
||
+
|
||
+ if (src->fname) {
|
||
+ if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->arg_info) {
|
||
+ if(!(dst->arg_info = my_copy_arg_info_array(NULL,
|
||
+ src->arg_info,
|
||
+ src->num_args,
|
||
+ allocate,
|
||
+ deallocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#else
|
||
+ if (src->func_arg_types) {
|
||
+ if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
|
||
+ src->func_arg_types[0]+1,
|
||
+ allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ return dst;
|
||
+
|
||
+cleanup:
|
||
+ if(dst->fname) deallocate(dst->fname);
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+/* {{{ my_copy_property_info */
|
||
+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* Start with a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(*src));
|
||
+
|
||
+ dst->name = NULL;
|
||
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
|
||
+ dst->doc_comment = NULL;
|
||
+#endif
|
||
+
|
||
+ if (src->name) {
|
||
+ /* private members are stored inside property_info as a mangled
|
||
+ * string of the form:
|
||
+ * \0<classname>\0<membername>\0
|
||
+ */
|
||
+ if(!(dst->name =
|
||
+ apc_xmemcpy(src->name, src->name_length+1, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
|
||
+ if (src->doc_comment) {
|
||
+ if( !(dst->doc_comment =
|
||
+ apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ return dst;
|
||
+
|
||
+cleanup:
|
||
+ if(dst->name) deallocate(dst->name);
|
||
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
|
||
+ if(dst->doc_comment) deallocate(dst->doc_comment);
|
||
+#endif
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_property_info_for_execution */
|
||
+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)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* We need only a shallow copy */
|
||
+ memcpy(dst, src, sizeof(*src));
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_arg_info_array */
|
||
+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)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ int i = 0;
|
||
+
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* Start with a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(*src)*num_args);
|
||
+
|
||
+ for(i=0; i < num_args; i++) {
|
||
+ if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {
|
||
+ if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_arg_info */
|
||
+static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* Start with a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(*src));
|
||
+
|
||
+ dst->name = NULL;
|
||
+ dst->class_name = NULL;
|
||
+
|
||
+ if (src->name) {
|
||
+ if(!(dst->name =
|
||
+ apc_xmemcpy(src->name, src->name_len+1, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (src->class_name) {
|
||
+ if(!(dst->class_name =
|
||
+ apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return dst;
|
||
+
|
||
+cleanup:
|
||
+ if(dst->name) deallocate(dst->name);
|
||
+ if(dst->class_name) deallocate(dst->name);
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ my_copy_class_entry */
|
||
+static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ int i = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ /* Start with a bitwise copy */
|
||
+ memcpy(dst, src, sizeof(*src));
|
||
+
|
||
+ dst->name = NULL;
|
||
+ dst->builtin_functions = NULL;
|
||
+ memset(&dst->function_table, 0, sizeof(dst->function_table));
|
||
+ memset(&dst->default_properties, 0, sizeof(dst->default_properties));
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ dst->refcount = NULL;
|
||
+#else
|
||
+ dst->static_members = NULL;
|
||
+ dst->doc_comment = NULL;
|
||
+ dst->filename = NULL;
|
||
+ memset(&dst->properties_info, 0, sizeof(dst->properties_info));
|
||
+ memset(&dst->constants_table, 0, sizeof(dst->constants_table));
|
||
+ memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
|
||
+#endif
|
||
+
|
||
+ if (src->name) {
|
||
+ if(!(dst->name = apc_xstrdup(src->name, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ if(!(dst->refcount = apc_xmemcpy(src->refcount,
|
||
+ sizeof(src->refcount[0]),
|
||
+ allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if(!(my_copy_hashtable_ex(&dst->function_table,
|
||
+ &src->function_table,
|
||
+ (ht_copy_fun_t) my_copy_function,
|
||
+ (ht_free_fun_t) my_free_function,
|
||
+ 0,
|
||
+ allocate, deallocate,
|
||
+ (ht_check_copy_fun_t) my_check_copy_function,
|
||
+ src))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+ /* the interfaces are populated at runtime using ADD_INTERFACE */
|
||
+ dst->interfaces = NULL;
|
||
+
|
||
+ /* the current count includes inherited interfaces as well,
|
||
+ the real dynamic ones are the first <n> which are zero'd
|
||
+ out in zend_do_end_class_declaration */
|
||
+ for(i = 0 ; i < src->num_interfaces ; i++) {
|
||
+ if(src->interfaces[i])
|
||
+ {
|
||
+ dst->num_interfaces = i;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* these will either be set inside my_fixup_hashtable or
|
||
+ * they will be copied out from parent inside zend_do_inheritance
|
||
+ */
|
||
+ dst->constructor = NULL;
|
||
+ dst->destructor = NULL;
|
||
+ dst->clone = NULL;
|
||
+ dst->__get = NULL;
|
||
+ dst->__set = NULL;
|
||
+ dst->__unset = NULL;
|
||
+ dst->__isset = NULL;
|
||
+ dst->__call = NULL;
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ dst->__tostring = NULL;
|
||
+#endif
|
||
+
|
||
+ /* unset function proxies */
|
||
+ dst->serialize_func = NULL;
|
||
+ dst->unserialize_func = NULL;
|
||
+
|
||
+ my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
|
||
+#endif
|
||
+
|
||
+ if(!(my_copy_hashtable_ex(&dst->default_properties,
|
||
+ &src->default_properties,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate,deallocate,
|
||
+ (ht_check_copy_fun_t) my_check_copy_default_property,
|
||
+ src))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+ if(!(my_copy_hashtable_ex(&dst->properties_info,
|
||
+ &src->properties_info,
|
||
+ (ht_copy_fun_t) my_copy_property_info,
|
||
+ (ht_free_fun_t) my_free_property_info,
|
||
+ 0,
|
||
+ allocate, deallocate,
|
||
+ (ht_check_copy_fun_t) my_check_copy_property_info,
|
||
+ src))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ /* php5.2 introduced a scope attribute for property info */
|
||
+ my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
|
||
+#endif
|
||
+
|
||
+ if(!my_copy_hashtable_ex(&dst->default_static_members,
|
||
+ &src->default_static_members,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate,
|
||
+ (ht_check_copy_fun_t) my_check_copy_static_member,
|
||
+ src,
|
||
+ &src->default_static_members)) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ if(src->static_members != &src->default_static_members)
|
||
+ {
|
||
+ if(!(dst->static_members = my_copy_hashtable_ex(NULL,
|
||
+ src->static_members,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate,
|
||
+ (ht_check_copy_fun_t) my_check_copy_static_member,
|
||
+ src,
|
||
+ src->static_members))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ dst->static_members = &dst->default_static_members;
|
||
+ }
|
||
+
|
||
+ if(!(my_copy_hashtable(&dst->constants_table,
|
||
+ &src->constants_table,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ if (src->doc_comment) {
|
||
+ if(!(dst->doc_comment =
|
||
+ apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (src->builtin_functions) {
|
||
+ int i, n;
|
||
+
|
||
+ for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
|
||
+
|
||
+ if(!(dst->builtin_functions =
|
||
+ (zend_function_entry*)
|
||
+ allocate((n + 1) * sizeof(zend_function_entry)))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+
|
||
+ for (i = 0; i < n; i++) {
|
||
+ if(!my_copy_function_entry(&dst->builtin_functions[i],
|
||
+ &src->builtin_functions[i],
|
||
+ allocate, deallocate)) {
|
||
+ int ii;
|
||
+
|
||
+ for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+ dst->builtin_functions[n].fname = NULL;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->filename) {
|
||
+ if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ return dst;
|
||
+
|
||
+
|
||
+cleanup:
|
||
+ if(dst->name) deallocate(dst->name);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(dst->doc_comment) deallocate(dst->doc_comment);
|
||
+ if(dst->filename) deallocate(dst->filename);
|
||
+#else
|
||
+ if(dst->refcount) deallocate(dst->refcount);
|
||
+#endif
|
||
+
|
||
+ if(dst->builtin_functions) deallocate(dst->builtin_functions);
|
||
+ if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
|
||
+ if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
|
||
+ if(dst->default_static_members.arBuckets)
|
||
+ {
|
||
+ my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
|
||
+ }
|
||
+ if(dst->static_members && dst->static_members != &(dst->default_static_members))
|
||
+ {
|
||
+ my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
|
||
+ deallocate(dst->static_members);
|
||
+ }
|
||
+ if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
|
||
+#endif
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_hashtable */
|
||
+static HashTable* my_copy_hashtable_ex(HashTable* dst,
|
||
+ HashTable* src,
|
||
+ ht_copy_fun_t copy_fn,
|
||
+ ht_free_fun_t free_fn,
|
||
+ int holds_ptrs,
|
||
+ apc_malloc_t allocate,
|
||
+ apc_free_t deallocate,
|
||
+ ht_check_copy_fun_t check_fn,
|
||
+ ...)
|
||
+{
|
||
+ Bucket* curr = NULL;
|
||
+ Bucket* prev = NULL;
|
||
+ Bucket* newp = NULL;
|
||
+ int first = 1;
|
||
+ int local_dst_alloc = 0;
|
||
+ int index = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ /* allocate buckets for the new hashtable */
|
||
+ if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
|
||
+ dst->pInternalPointer = NULL;
|
||
+ dst->pListHead = NULL;
|
||
+
|
||
+ for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
|
||
+ int n = curr->h % dst->nTableSize;
|
||
+
|
||
+ if(check_fn) {
|
||
+ va_list args;
|
||
+ va_start(args, check_fn);
|
||
+
|
||
+ /* Call the check_fn to see if the current bucket
|
||
+ * needs to be copied out
|
||
+ */
|
||
+ if(!check_fn(curr, args)) {
|
||
+ dst->nNumOfElements--;
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ va_end(args);
|
||
+ }
|
||
+
|
||
+ /* create a copy of the bucket 'curr' */
|
||
+ if(!(newp =
|
||
+ (Bucket*) apc_xmemcpy(curr,
|
||
+ sizeof(Bucket) + curr->nKeyLength - 1,
|
||
+ allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ /* insert 'newp' into the linked list at its hashed index */
|
||
+ if (dst->arBuckets[n]) {
|
||
+ newp->pNext = dst->arBuckets[n];
|
||
+ newp->pLast = NULL;
|
||
+ newp->pNext->pLast = newp;
|
||
+ }
|
||
+ else {
|
||
+ newp->pNext = newp->pLast = NULL;
|
||
+ }
|
||
+
|
||
+ dst->arBuckets[n] = newp;
|
||
+
|
||
+ /* copy the bucket data using our 'copy_fn' callback function */
|
||
+ if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ if (holds_ptrs) {
|
||
+ memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
|
||
+ }
|
||
+ else {
|
||
+ newp->pDataPtr = NULL;
|
||
+ }
|
||
+
|
||
+ /* insert 'newp' into the table-thread linked list */
|
||
+ newp->pListLast = prev;
|
||
+ newp->pListNext = NULL;
|
||
+
|
||
+ if (prev) {
|
||
+ prev->pListNext = newp;
|
||
+ }
|
||
+
|
||
+ if (first) {
|
||
+ dst->pListHead = newp;
|
||
+ first = 0;
|
||
+ }
|
||
+
|
||
+ prev = newp;
|
||
+ }
|
||
+
|
||
+ dst->pListTail = newp;
|
||
+
|
||
+ return dst;
|
||
+
|
||
+ cleanup:
|
||
+ for(index = 0; index < dst->nTableSize; index++)
|
||
+ {
|
||
+ curr = dst->arBuckets[index];
|
||
+ while(curr != NULL)
|
||
+ {
|
||
+ Bucket * tmp = curr;
|
||
+ if(curr->pData && free_fn)
|
||
+ {
|
||
+ free_fn(curr->pData, deallocate);
|
||
+ }
|
||
+ curr = curr->pNext;
|
||
+ deallocate(tmp);
|
||
+ }
|
||
+ }
|
||
+ deallocate(dst->arBuckets);
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ else dst->arBuckets = NULL;
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_copy_static_variables */
|
||
+static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ if (src->static_variables == NULL) {
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ return my_copy_hashtable(NULL,
|
||
+ src->static_variables,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ allocate, deallocate);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_zval */
|
||
+zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ int local_dst_alloc = 0;
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zval*) allocate(sizeof(zval)));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ dst = my_copy_zval(dst, src, allocate, deallocate);
|
||
+ if(!dst) {
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+ }
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+/* {{{ apc_fixup_op_array_jumps */
|
||
+static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ for (i=0; i < dst->last; ++i) {
|
||
+ zend_op *zo = &(dst->opcodes[i]);
|
||
+ /*convert opline number to jump address*/
|
||
+ switch (zo->opcode) {
|
||
+ case ZEND_JMP:
|
||
+ /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
|
||
+ zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
|
||
+ break;
|
||
+ case ZEND_JMPZ:
|
||
+ case ZEND_JMPNZ:
|
||
+ case ZEND_JMPZ_EX:
|
||
+ case ZEND_JMPNZ_EX:
|
||
+ zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ apc_copy_op_array */
|
||
+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)
|
||
+{
|
||
+ int i;
|
||
+ int local_dst_alloc = 0;
|
||
+ apc_fileinfo_t fileinfo;
|
||
+ char canon_path[MAXPATHLEN];
|
||
+ char *fullpath = NULL;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ apc_opflags_t * flags = NULL;
|
||
+#endif
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ if (!dst) {
|
||
+ CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
|
||
+ local_dst_alloc = 1;
|
||
+ }
|
||
+
|
||
+ if(APCG(apc_optimize_function)) {
|
||
+ APCG(apc_optimize_function)(src TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* start with a bitwise copy of the array */
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+ dst->function_name = NULL;
|
||
+ dst->filename = NULL;
|
||
+ dst->refcount = NULL;
|
||
+ dst->opcodes = NULL;
|
||
+ dst->brk_cont_array = NULL;
|
||
+ dst->static_variables = NULL;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ dst->try_catch_array = NULL;
|
||
+ dst->arg_info = NULL;
|
||
+ dst->doc_comment = NULL;
|
||
+#else
|
||
+ dst->arg_types = NULL;
|
||
+#endif
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ dst->vars = NULL;
|
||
+#endif
|
||
+
|
||
+ /* copy the arg types array (if set) */
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->arg_info) {
|
||
+ if(!(dst->arg_info = my_copy_arg_info_array(NULL,
|
||
+ src->arg_info,
|
||
+ src->num_args,
|
||
+ allocate,
|
||
+ deallocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#else
|
||
+ if (src->arg_types) {
|
||
+ if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
|
||
+ sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
|
||
+ allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (src->function_name) {
|
||
+ if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+ if (src->filename) {
|
||
+ if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if(!(dst->refcount = apc_xmemcpy(src->refcount,
|
||
+ sizeof(src->refcount[0]),
|
||
+ allocate))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ /* deep-copy the opcodes */
|
||
+ if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(APCG(reserved_offset) != -1) {
|
||
+ /* Insanity alert: the void* pointer is cast into an apc_opflags_t
|
||
+ * struct. apc_zend_init() checks to ensure that it fits in a void* */
|
||
+ flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
|
||
+ memset(flags, 0, sizeof(apc_opflags_t));
|
||
+ /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ for (i = 0; i < src->last; i++) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_op *zo = &(src->opcodes[i]);
|
||
+ /* a lot of files are merely constant arrays with no jumps */
|
||
+ switch (zo->opcode) {
|
||
+ case ZEND_JMP:
|
||
+ case ZEND_JMPZ:
|
||
+ case ZEND_JMPNZ:
|
||
+ case ZEND_JMPZ_EX:
|
||
+ case ZEND_JMPNZ_EX:
|
||
+ if(flags != NULL) {
|
||
+ flags->has_jumps = 1;
|
||
+ }
|
||
+ break;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ /* auto_globals_jit was not in php-4.3.* */
|
||
+ case ZEND_FETCH_R:
|
||
+ case ZEND_FETCH_W:
|
||
+ case ZEND_FETCH_IS:
|
||
+ case ZEND_FETCH_FUNC_ARG:
|
||
+ if(PG(auto_globals_jit) && flags != NULL)
|
||
+ {
|
||
+ /* The fetch is only required if auto_globals_jit=1 */
|
||
+ if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
|
||
+ zo->op1.op_type == IS_CONST &&
|
||
+ zo->op1.u.constant.type == IS_STRING) {
|
||
+ znode * varname = &zo->op1;
|
||
+ if (varname->u.constant.value.str.val[0] == '_') {
|
||
+#define SET_IF_AUTOGLOBAL(member) \
|
||
+ if(!strcmp(varname->u.constant.value.str.val, #member)) \
|
||
+ flags->member = 1 /* no ';' here */
|
||
+ SET_IF_AUTOGLOBAL(_GET);
|
||
+ else SET_IF_AUTOGLOBAL(_POST);
|
||
+ else SET_IF_AUTOGLOBAL(_COOKIE);
|
||
+ else SET_IF_AUTOGLOBAL(_SERVER);
|
||
+ else SET_IF_AUTOGLOBAL(_ENV);
|
||
+ else SET_IF_AUTOGLOBAL(_FILES);
|
||
+ else SET_IF_AUTOGLOBAL(_REQUEST);
|
||
+ else if(zend_is_auto_global(
|
||
+ varname->u.constant.value.str.val,
|
||
+ varname->u.constant.value.str.len
|
||
+ TSRMLS_CC))
|
||
+ {
|
||
+ flags->unknown_global = 1;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+#endif
|
||
+ case ZEND_RECV_INIT:
|
||
+ if(zo->op2.op_type == IS_CONST &&
|
||
+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
|
||
+ if(flags != NULL) {
|
||
+ flags->deep_copy = 1;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ if((zo->op1.op_type == IS_CONST &&
|
||
+ zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
|
||
+ (zo->op2.op_type == IS_CONST &&
|
||
+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
|
||
+ if(flags != NULL) {
|
||
+ flags->deep_copy = 1;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+#endif
|
||
+ if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
|
||
+ int ii;
|
||
+ for(ii = i-1; ii>=0; ii--) {
|
||
+ my_destroy_zend_op(dst->opcodes+ii, deallocate);
|
||
+ }
|
||
+ goto cleanup;
|
||
+ }
|
||
+#ifdef ZEND_ENGINE_2
|
||
+/* This code breaks apc's rule#1 - cache what you compile */
|
||
+ if(APCG(fpstat)==0) {
|
||
+ if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
|
||
+ (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
|
||
+ /* constant includes */
|
||
+ if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) {
|
||
+ if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
|
||
+ if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
|
||
+ /* everything has to go through a realpath() */
|
||
+ zend_op *dzo = &(dst->opcodes[i]);
|
||
+ deallocate(dzo->op1.u.constant.value.str.val);
|
||
+ dzo->op1.u.constant.value.str.len = strlen(fullpath);
|
||
+ dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(flags == NULL || flags->has_jumps) {
|
||
+ apc_fixup_op_array_jumps(dst,src);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* copy the break-continue array */
|
||
+ if (src->brk_cont_array) {
|
||
+ if(!(dst->brk_cont_array =
|
||
+ apc_xmemcpy(src->brk_cont_array,
|
||
+ sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
|
||
+ allocate))) {
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* copy the table of static variables */
|
||
+ if (src->static_variables) {
|
||
+ if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->try_catch_array) {
|
||
+ if(!(dst->try_catch_array =
|
||
+ apc_xmemcpy(src->try_catch_array,
|
||
+ sizeof(src->try_catch_array[0]) * src->last_try_catch,
|
||
+ allocate))) {
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
|
||
+ if (src->vars) {
|
||
+ if(!(dst->vars = apc_xmemcpy(src->vars,
|
||
+ sizeof(src->vars[0]) * src->last_var,
|
||
+ allocate))) {
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+
|
||
+ for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
|
||
+
|
||
+ for(i = 0; i < src->last_var; i++) {
|
||
+ if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
|
||
+ src->vars[i].name_len + 1,
|
||
+ allocate))) {
|
||
+ dst->last_var = i;
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->doc_comment) {
|
||
+ if (!(dst->doc_comment
|
||
+ = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
|
||
+ goto cleanup_opcodes;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ return dst;
|
||
+
|
||
+cleanup_opcodes:
|
||
+ if(dst->opcodes) {
|
||
+ for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
|
||
+ }
|
||
+cleanup:
|
||
+ if(dst->function_name) deallocate(dst->function_name);
|
||
+ if(dst->refcount) deallocate(dst->refcount);
|
||
+ if(dst->filename) deallocate(dst->filename);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
|
||
+ if(dst->try_catch_array) deallocate(dst->try_catch_array);
|
||
+ if(dst->doc_comment) deallocate(dst->doc_comment);
|
||
+#else
|
||
+ if(dst->arg_types) deallocate(dst->arg_types);
|
||
+#endif
|
||
+ if(dst->opcodes) deallocate(dst->opcodes);
|
||
+ if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
|
||
+ if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ if (dst->vars) {
|
||
+ for(i=0; i < dst->last_var; i++) {
|
||
+ if(dst->vars[i].name) deallocate(dst->vars[i].name);
|
||
+ }
|
||
+ deallocate(dst->vars);
|
||
+ }
|
||
+#endif
|
||
+ if(local_dst_alloc) deallocate(dst);
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_new_functions */
|
||
+apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
|
||
+{
|
||
+ apc_function_t* array;
|
||
+ int new_count; /* number of new functions in table */
|
||
+ int i;
|
||
+
|
||
+ new_count = zend_hash_num_elements(CG(function_table)) - old_count;
|
||
+ assert(new_count >= 0);
|
||
+
|
||
+ CHECK(array =
|
||
+ (apc_function_t*)
|
||
+ allocate(sizeof(apc_function_t) * (new_count+1)));
|
||
+
|
||
+ if (new_count == 0) {
|
||
+ array[0].function = NULL;
|
||
+ return array;
|
||
+ }
|
||
+
|
||
+ /* Skip the first `old_count` functions in the table */
|
||
+ zend_hash_internal_pointer_reset(CG(function_table));
|
||
+ for (i = 0; i < old_count; i++) {
|
||
+ zend_hash_move_forward(CG(function_table));
|
||
+ }
|
||
+
|
||
+ /* Add the next `new_count` functions to our array */
|
||
+ for (i = 0; i < new_count; i++) {
|
||
+ char* key;
|
||
+ uint key_size;
|
||
+ zend_function* fun;
|
||
+
|
||
+ zend_hash_get_current_key_ex(CG(function_table),
|
||
+ &key,
|
||
+ &key_size,
|
||
+ NULL,
|
||
+ 0,
|
||
+ NULL);
|
||
+
|
||
+ zend_hash_get_current_data(CG(function_table), (void**) &fun);
|
||
+
|
||
+ if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
|
||
+ int ii;
|
||
+ for(ii=i-1; ii>=0; ii--) {
|
||
+ deallocate(array[ii].name);
|
||
+ my_free_function(array[ii].function, deallocate);
|
||
+ }
|
||
+ deallocate(array);
|
||
+ return NULL;
|
||
+ }
|
||
+ array[i].name_len = (int) key_size-1;
|
||
+ if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
|
||
+ int ii;
|
||
+ deallocate(array[i].name);
|
||
+ for(ii=i-1; ii>=0; ii--) {
|
||
+ deallocate(array[ii].name);
|
||
+ my_free_function(array[ii].function, deallocate);
|
||
+ }
|
||
+ deallocate(array);
|
||
+ return NULL;
|
||
+ }
|
||
+ zend_hash_move_forward(CG(function_table));
|
||
+ }
|
||
+
|
||
+ array[i].function = NULL;
|
||
+ return array;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_new_classes */
|
||
+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)
|
||
+{
|
||
+ apc_class_t* array;
|
||
+ int new_count; /* number of new classes in table */
|
||
+ int i;
|
||
+
|
||
+ new_count = zend_hash_num_elements(CG(class_table)) - old_count;
|
||
+ assert(new_count >= 0);
|
||
+
|
||
+ CHECK(array =
|
||
+ (apc_class_t*)
|
||
+ allocate(sizeof(apc_class_t)*(new_count+1)));
|
||
+
|
||
+ if (new_count == 0) {
|
||
+ array[0].class_entry = NULL;
|
||
+ return array;
|
||
+ }
|
||
+
|
||
+ /* Skip the first `old_count` classes in the table */
|
||
+ zend_hash_internal_pointer_reset(CG(class_table));
|
||
+ for (i = 0; i < old_count; i++) {
|
||
+ zend_hash_move_forward(CG(class_table));
|
||
+ }
|
||
+
|
||
+ /* Add the next `new_count` classes to our array */
|
||
+ for (i = 0; i < new_count; i++) {
|
||
+ char* key;
|
||
+ uint key_size;
|
||
+ zend_class_entry* elem = NULL;
|
||
+
|
||
+ array[i].class_entry = NULL;
|
||
+
|
||
+ zend_hash_get_current_key_ex(CG(class_table),
|
||
+ &key,
|
||
+ &key_size,
|
||
+ NULL,
|
||
+ 0,
|
||
+ NULL);
|
||
+
|
||
+ zend_hash_get_current_data(CG(class_table), (void**) &elem);
|
||
+
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ elem = *((zend_class_entry**)elem);
|
||
+#endif
|
||
+
|
||
+ if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
|
||
+ int ii;
|
||
+
|
||
+ for(ii=i-1; ii>=0; ii--) {
|
||
+ deallocate(array[ii].name);
|
||
+ my_destroy_class_entry(array[ii].class_entry, deallocate);
|
||
+ deallocate(array[ii].class_entry);
|
||
+ }
|
||
+ deallocate(array);
|
||
+ return NULL;
|
||
+ }
|
||
+ array[i].name_len = (int) key_size-1;
|
||
+ if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
|
||
+ int ii;
|
||
+
|
||
+ deallocate(array[i].name);
|
||
+ for(ii=i-1; ii>=0; ii--) {
|
||
+ deallocate(array[ii].name);
|
||
+ my_destroy_class_entry(array[ii].class_entry, deallocate);
|
||
+ deallocate(array[ii].class_entry);
|
||
+ }
|
||
+ deallocate(array);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * If the class has a pointer to its parent class, save the parent
|
||
+ * name so that we can enable compile-time inheritance when we reload
|
||
+ * the child class; otherwise, set the parent name to null and scan
|
||
+ * the op_array to determine if this class inherits from some base
|
||
+ * class at execution-time.
|
||
+ */
|
||
+
|
||
+ if (elem->parent) {
|
||
+ if(!(array[i].parent_name =
|
||
+ apc_xstrdup(elem->parent->name, allocate))) {
|
||
+ int ii;
|
||
+
|
||
+ for(ii=i; ii>=0; ii--) {
|
||
+ deallocate(array[ii].name);
|
||
+ my_destroy_class_entry(array[ii].class_entry, deallocate);
|
||
+ deallocate(array[ii].class_entry);
|
||
+ if(ii==i) continue;
|
||
+ if(array[ii].parent_name) deallocate(array[ii].parent_name);
|
||
+ }
|
||
+ deallocate(array);
|
||
+ return NULL;
|
||
+ }
|
||
+ array[i].is_derived = 1;
|
||
+ }
|
||
+ else {
|
||
+ array[i].parent_name = NULL;
|
||
+ array[i].is_derived = is_derived_class(op_array, key, key_size);
|
||
+ }
|
||
+
|
||
+ zend_hash_move_forward(CG(class_table));
|
||
+ }
|
||
+
|
||
+ array[i].class_entry = NULL;
|
||
+ return array;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_zval_ptr */
|
||
+static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+ if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
|
||
+ deallocate(src[0]);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_zval */
|
||
+static int my_destroy_zval(zval* src, apc_free_t deallocate)
|
||
+{
|
||
+ zval **tmp;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ switch (src->type & ~IS_CONSTANT_INDEX) {
|
||
+ case IS_RESOURCE:
|
||
+ case IS_BOOL:
|
||
+ case IS_LONG:
|
||
+ case IS_DOUBLE:
|
||
+ case IS_NULL:
|
||
+ break;
|
||
+
|
||
+ case IS_CONSTANT:
|
||
+ case IS_STRING:
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ case FLAG_IS_BC:
|
||
+#endif
|
||
+ deallocate(src->value.str.val);
|
||
+ break;
|
||
+
|
||
+ case IS_ARRAY:
|
||
+
|
||
+ /* Maintain a list of zvals we've copied to properly handle recursive structures */
|
||
+ if(APCG(copied_zvals)) {
|
||
+ if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
|
||
+ (*tmp)->refcount--;
|
||
+ return FAILURE;
|
||
+ }
|
||
+ zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
|
||
+ }
|
||
+ /* fall through */
|
||
+
|
||
+ case IS_CONSTANT_ARRAY:
|
||
+ my_free_hashtable(src->value.ht,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+ break;
|
||
+
|
||
+ case IS_OBJECT:
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ my_destroy_class_entry(src->value.obj.ce, deallocate);
|
||
+ deallocate(src->value.obj.ce);
|
||
+ my_free_hashtable(src->value.obj.properties,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+#endif
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ assert(0);
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_znode */
|
||
+static void my_destroy_znode(znode* src, apc_free_t deallocate)
|
||
+{
|
||
+ if (src->op_type == IS_CONST) {
|
||
+ my_destroy_zval(&src->u.constant, deallocate);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_zend_op */
|
||
+static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_znode(&src->result, deallocate);
|
||
+ my_destroy_znode(&src->op1, deallocate);
|
||
+ my_destroy_znode(&src->op2, deallocate);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_function */
|
||
+static void my_destroy_function(zend_function* src, apc_free_t deallocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+
|
||
+ switch (src->type) {
|
||
+ case ZEND_INTERNAL_FUNCTION:
|
||
+ case ZEND_OVERLOADED_FUNCTION:
|
||
+ break;
|
||
+
|
||
+ case ZEND_USER_FUNCTION:
|
||
+ case ZEND_EVAL_CODE:
|
||
+ my_destroy_op_array(&src->op_array, deallocate);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ assert(0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_function_entry */
|
||
+static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+
|
||
+ deallocate(src->fname);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->arg_info) {
|
||
+ my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
|
||
+ }
|
||
+#else
|
||
+ if (src->func_arg_types) {
|
||
+ deallocate(src->func_arg_types);
|
||
+ }
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+/* {{{ my_destroy_property_info*/
|
||
+static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+
|
||
+ deallocate(src->name);
|
||
+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
|
||
+ if(src->doc_comment) deallocate(src->doc_comment);
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_arg_info_array */
|
||
+static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
|
||
+{
|
||
+ int i = 0;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ for(i=0; i < num_args; i++) {
|
||
+ my_destroy_arg_info(&src[i], deallocate);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_arg_info */
|
||
+static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
|
||
+{
|
||
+ assert(src != NULL);
|
||
+
|
||
+ deallocate(src->name);
|
||
+ deallocate(src->class_name);
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ my_destroy_class_entry */
|
||
+static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
|
||
+{
|
||
+ uint i;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ deallocate(src->name);
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ deallocate(src->refcount);
|
||
+#else
|
||
+ if(src->doc_comment) deallocate(src->doc_comment);
|
||
+ if(src->filename) deallocate(src->filename);
|
||
+#endif
|
||
+
|
||
+ my_destroy_hashtable(&src->function_table,
|
||
+ (ht_free_fun_t) my_free_function,
|
||
+ deallocate);
|
||
+
|
||
+ my_destroy_hashtable(&src->default_properties,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ my_destroy_hashtable(&src->properties_info,
|
||
+ (ht_free_fun_t) my_free_property_info,
|
||
+ deallocate);
|
||
+ if(src->static_members)
|
||
+ {
|
||
+ my_destroy_hashtable(src->static_members,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+ if(src->static_members != &(src->default_static_members))
|
||
+ {
|
||
+ deallocate(src->static_members);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ my_destroy_hashtable(&src->constants_table,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+#endif
|
||
+
|
||
+ if (src->builtin_functions) {
|
||
+ for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
|
||
+ my_destroy_function_entry(&src->builtin_functions[i], deallocate);
|
||
+ }
|
||
+ deallocate(src->builtin_functions);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_hashtable */
|
||
+static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+ for (i = 0; i < src->nTableSize; i++) {
|
||
+ Bucket* p = src->arBuckets[i];
|
||
+ while (p != NULL) {
|
||
+ Bucket* q = p;
|
||
+ p = p->pNext;
|
||
+ free_fn(q->pData, deallocate);
|
||
+ deallocate(q);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ deallocate(src->arBuckets);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_destroy_op_array */
|
||
+static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ assert(src != NULL);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (src->arg_info) {
|
||
+ my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
|
||
+ }
|
||
+#else
|
||
+ if (src->arg_types) {
|
||
+ deallocate(src->arg_types);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ deallocate(src->function_name);
|
||
+ deallocate(src->filename);
|
||
+ deallocate(src->refcount);
|
||
+
|
||
+ for (i = 0; i < src->last; i++) {
|
||
+ my_destroy_zend_op(src->opcodes + i, deallocate);
|
||
+ }
|
||
+ deallocate(src->opcodes);
|
||
+
|
||
+ if (src->brk_cont_array) {
|
||
+ deallocate(src->brk_cont_array);
|
||
+ }
|
||
+
|
||
+ if (src->static_variables) {
|
||
+ my_free_hashtable(src->static_variables,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ deallocate);
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ if (src->vars) {
|
||
+ for(i=0; i < src->last_var; i++) {
|
||
+ if(src->vars[i].name) deallocate(src->vars[i].name);
|
||
+ }
|
||
+ deallocate(src->vars);
|
||
+ }
|
||
+#endif
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(src->try_catch_array) {
|
||
+ deallocate(src->try_catch_array);
|
||
+ }
|
||
+ if (src->doc_comment) {
|
||
+ deallocate(src->doc_comment);
|
||
+ }
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_free_zval_ptr */
|
||
+static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_zval_ptr(src, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+/* {{{ my_free_property_info */
|
||
+static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_property_info(src, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_free_arg_info_array */
|
||
+static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_arg_info_array(src, num_args, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_free_arg_info */
|
||
+static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_arg_info(src, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ my_free_function */
|
||
+static void my_free_function(zend_function* src, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_function(src, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_free_hashtable */
|
||
+static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
|
||
+{
|
||
+ my_destroy_hashtable(src, free_fn, deallocate);
|
||
+ deallocate(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_free_op_array */
|
||
+void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
|
||
+{
|
||
+ if (src != NULL) {
|
||
+ my_destroy_op_array(src, deallocate);
|
||
+ deallocate(src);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_free_functions */
|
||
+void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ if (src != NULL) {
|
||
+ for (i = 0; src[i].function != NULL; i++) {
|
||
+ deallocate(src[i].name);
|
||
+ my_destroy_function(src[i].function, deallocate);
|
||
+ deallocate(src[i].function);
|
||
+ }
|
||
+ deallocate(src);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_free_classes */
|
||
+void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ if (src != NULL) {
|
||
+ for (i = 0; src[i].class_entry != NULL; i++) {
|
||
+ deallocate(src[i].name);
|
||
+ deallocate(src[i].parent_name);
|
||
+ my_destroy_class_entry(src[i].class_entry, deallocate);
|
||
+ deallocate(src[i].class_entry);
|
||
+ }
|
||
+ deallocate(src);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_free_zval */
|
||
+void apc_free_zval(zval* src, apc_free_t deallocate)
|
||
+{
|
||
+ if (src != NULL) {
|
||
+ if(my_destroy_zval(src, deallocate) == SUCCESS) {
|
||
+ deallocate(src);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+
|
||
+/* Used only by my_prepare_op_array_for_execution */
|
||
+#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
|
||
+ /* The fetch is only required if auto_globals_jit=1 */ \
|
||
+ if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
|
||
+ zo->op1.op_type == IS_CONST && \
|
||
+ zo->op1.u.constant.type == IS_STRING && \
|
||
+ zo->op1.u.constant.value.str.val[0] == '_') { \
|
||
+ \
|
||
+ znode* varname = &zo->op1; \
|
||
+ (void)zend_is_auto_global(varname->u.constant.value.str.val, \
|
||
+ varname->u.constant.value.str.len \
|
||
+ TSRMLS_CC); \
|
||
+ } \
|
||
+
|
||
+/* {{{ my_prepare_op_array_for_execution */
|
||
+static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
|
||
+{
|
||
+ /* combine my_fetch_global_vars and my_copy_data_exceptions.
|
||
+ * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
|
||
+ * - If the opcode stream contain mutable data, ensure a copy.
|
||
+ * - Fixup array jumps in the same loop.
|
||
+ */
|
||
+ int i=src->last;
|
||
+ zend_op *zo;
|
||
+ zend_op *dzo;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ apc_opflags_t * flags = APCG(reserved_offset) != -1 ?
|
||
+ (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
|
||
+ int needcopy = flags ? flags->deep_copy : 1;
|
||
+ /* auto_globals_jit was not in php4 */
|
||
+ int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
|
||
+
|
||
+#define FETCH_AUTOGLOBAL(member) do { \
|
||
+ if(flags && flags->member == 1) { \
|
||
+ zend_is_auto_global(#member,\
|
||
+ (sizeof(#member) - 1)\
|
||
+ TSRMLS_CC);\
|
||
+ } \
|
||
+}while(0);
|
||
+
|
||
+ FETCH_AUTOGLOBAL(_GET);
|
||
+ FETCH_AUTOGLOBAL(_POST);
|
||
+ FETCH_AUTOGLOBAL(_COOKIE);
|
||
+ FETCH_AUTOGLOBAL(_SERVER);
|
||
+ FETCH_AUTOGLOBAL(_ENV);
|
||
+ FETCH_AUTOGLOBAL(_FILES);
|
||
+ FETCH_AUTOGLOBAL(_REQUEST);
|
||
+
|
||
+#else
|
||
+ int needcopy = 0;
|
||
+ int do_prepare_fetch_global = 0;
|
||
+ int j = 0;
|
||
+
|
||
+ for(j = 0; j < src->last; j++) {
|
||
+ zo = &src->opcodes[j];
|
||
+
|
||
+ if( ((zo->op1.op_type == IS_CONST &&
|
||
+ zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
|
||
+ ((zo->op2.op_type == IS_CONST &&
|
||
+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
|
||
+ needcopy = 1;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if(needcopy) {
|
||
+
|
||
+ dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
|
||
+ sizeof(zend_op) * src->last,
|
||
+ apc_php_malloc);
|
||
+ zo = src->opcodes;
|
||
+ dzo = dst->opcodes;
|
||
+ while(i > 0) {
|
||
+
|
||
+ if( ((zo->op1.op_type == IS_CONST &&
|
||
+ zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
|
||
+ ((zo->op2.op_type == IS_CONST &&
|
||
+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
|
||
+
|
||
+ if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
|
||
+ assert(0); /* emalloc failed or a bad constant array */
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ switch(zo->opcode) {
|
||
+ case ZEND_JMP:
|
||
+ dzo->op1.u.jmp_addr = dst->opcodes +
|
||
+ (zo->op1.u.jmp_addr - src->opcodes);
|
||
+ break;
|
||
+ case ZEND_JMPZ:
|
||
+ case ZEND_JMPNZ:
|
||
+ case ZEND_JMPZ_EX:
|
||
+ case ZEND_JMPNZ_EX:
|
||
+ dzo->op2.u.jmp_addr = dst->opcodes +
|
||
+ (zo->op2.u.jmp_addr - src->opcodes);
|
||
+ break;
|
||
+ case ZEND_FETCH_R:
|
||
+ case ZEND_FETCH_W:
|
||
+ case ZEND_FETCH_IS:
|
||
+ case ZEND_FETCH_FUNC_ARG:
|
||
+ if(do_prepare_fetch_global)
|
||
+ {
|
||
+ APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+#endif
|
||
+ i--;
|
||
+ zo++;
|
||
+ dzo++;
|
||
+ }
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ } else { /* !needcopy */
|
||
+ /* The fetch is only required if auto_globals_jit=1 */
|
||
+ if(do_prepare_fetch_global)
|
||
+ {
|
||
+ zo = src->opcodes;
|
||
+ while(i > 0) {
|
||
+
|
||
+ if(zo->opcode == ZEND_FETCH_R ||
|
||
+ zo->opcode == ZEND_FETCH_W ||
|
||
+ zo->opcode == ZEND_FETCH_IS ||
|
||
+ zo->opcode == ZEND_FETCH_FUNC_ARG
|
||
+ ) {
|
||
+ APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
|
||
+ }
|
||
+
|
||
+ i--;
|
||
+ zo++;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_op_array_for_execution */
|
||
+zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
|
||
+{
|
||
+ if(dst == NULL) {
|
||
+ dst = (zend_op_array*) emalloc(sizeof(src[0]));
|
||
+ }
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+ dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
|
||
+
|
||
+ dst->refcount = apc_xmemcpy(src->refcount,
|
||
+ sizeof(src->refcount[0]),
|
||
+ apc_php_malloc);
|
||
+
|
||
+ my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_function_for_execution */
|
||
+zend_function* apc_copy_function_for_execution(zend_function* src)
|
||
+{
|
||
+ zend_function* dst;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ dst = (zend_function*) emalloc(sizeof(src[0]));
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+ apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_function_for_execution_ex */
|
||
+zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
|
||
+{
|
||
+ if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
|
||
+ return apc_copy_function_for_execution(src);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_copy_class_entry_for_execution */
|
||
+zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
|
||
+{
|
||
+ zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
|
||
+ memcpy(dst, src, sizeof(src[0]));
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(src->num_interfaces)
|
||
+ {
|
||
+ /* These are slots to be populated later by ADD_INTERFACE insns */
|
||
+ dst->interfaces = apc_php_malloc(
|
||
+ sizeof(zend_class_entry*) * src->num_interfaces);
|
||
+ memset(dst->interfaces, 0,
|
||
+ sizeof(zend_class_entry*) * src->num_interfaces);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* assert(dst->interfaces == NULL); */
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ dst->refcount = apc_xmemcpy(src->refcount,
|
||
+ sizeof(src->refcount[0]),
|
||
+ apc_php_malloc);
|
||
+#endif
|
||
+
|
||
+ /* Deep-copy the class properties, because they will be modified */
|
||
+
|
||
+ my_copy_hashtable(&dst->default_properties,
|
||
+ &src->default_properties,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+
|
||
+ /* For derived classes, we must also copy the function hashtable (although
|
||
+ * we can merely bitwise copy the functions it contains) */
|
||
+
|
||
+ my_copy_hashtable(&dst->function_table,
|
||
+ &src->function_table,
|
||
+ (ht_copy_fun_t) apc_copy_function_for_execution_ex,
|
||
+ NULL,
|
||
+ 0,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
|
||
+
|
||
+ /* zend_do_inheritance merges properties_info.
|
||
+ * Need only shallow copying as it doesn't hold the pointers.
|
||
+ */
|
||
+ my_copy_hashtable(&dst->properties_info,
|
||
+ &src->properties_info,
|
||
+ (ht_copy_fun_t) my_copy_property_info_for_execution,
|
||
+ NULL,
|
||
+ 0,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ /* php5.2 introduced a scope attribute for property info */
|
||
+ my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
|
||
+#endif
|
||
+
|
||
+ /* if inheritance results in a hash_del, it might result in
|
||
+ * a pefree() of the pointers here. Deep copying required.
|
||
+ */
|
||
+
|
||
+ my_copy_hashtable(&dst->constants_table,
|
||
+ &src->constants_table,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ NULL,
|
||
+ 1,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+
|
||
+ my_copy_hashtable(&dst->default_static_members,
|
||
+ &src->default_static_members,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+
|
||
+ if(src->static_members != &(src->default_static_members))
|
||
+ {
|
||
+ dst->static_members = my_copy_hashtable(NULL,
|
||
+ src->static_members,
|
||
+ (ht_copy_fun_t) my_copy_zval_ptr,
|
||
+ (ht_free_fun_t) my_free_zval_ptr,
|
||
+ 1,
|
||
+ apc_php_malloc, apc_php_free);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ dst->static_members = &(dst->default_static_members);
|
||
+ }
|
||
+
|
||
+#endif
|
||
+
|
||
+ return dst;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_free_class_entry_after_execution */
|
||
+void apc_free_class_entry_after_execution(zend_class_entry* src)
|
||
+{
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(src->num_interfaces > 0 && src->interfaces) {
|
||
+ apc_php_free(src->interfaces);
|
||
+ src->interfaces = NULL;
|
||
+ src->num_interfaces = 0;
|
||
+ }
|
||
+ /* my_destroy_hashtable() does not play nice with refcounts */
|
||
+
|
||
+ zend_hash_clean(&src->default_static_members);
|
||
+ if(src->static_members != &(src->default_static_members))
|
||
+ {
|
||
+ zend_hash_destroy(src->static_members);
|
||
+ apc_php_free(src->static_members);
|
||
+ src->static_members = NULL;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ src->static_members = NULL;
|
||
+ }
|
||
+ zend_hash_clean(&src->default_properties);
|
||
+ zend_hash_clean(&src->constants_table);
|
||
+#endif
|
||
+
|
||
+ /* TODO: more cleanup */
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+/* {{{ my_fixup_function */
|
||
+static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
|
||
+{
|
||
+ zend_function* zf = p->pData;
|
||
+
|
||
+ #define SET_IF_SAME_NAME(member) \
|
||
+ do { \
|
||
+ if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
|
||
+ dst->member = zf; \
|
||
+ } \
|
||
+ } \
|
||
+ while(0)
|
||
+
|
||
+ if(zf->common.scope == src)
|
||
+ {
|
||
+
|
||
+ /* Fixing up the default functions for objects here since
|
||
+ * we need to compare with the newly allocated functions
|
||
+ *
|
||
+ * caveat: a sub-class method can have the same name as the
|
||
+ * parent's constructor and create problems.
|
||
+ */
|
||
+
|
||
+ if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
|
||
+ else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
|
||
+ else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
|
||
+ else
|
||
+ {
|
||
+ SET_IF_SAME_NAME(__get);
|
||
+ SET_IF_SAME_NAME(__set);
|
||
+ SET_IF_SAME_NAME(__unset);
|
||
+ SET_IF_SAME_NAME(__isset);
|
||
+ SET_IF_SAME_NAME(__call);
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ SET_IF_SAME_NAME(__tostring);
|
||
+#endif
|
||
+ }
|
||
+ zf->common.scope = dst;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* no other function should reach here */
|
||
+ assert(0);
|
||
+ }
|
||
+
|
||
+ #undef SET_IF_SAME_NAME
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+/* {{{ my_fixup_property_info */
|
||
+static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
|
||
+{
|
||
+ zend_property_info* property_info = (zend_property_info*)p->pData;
|
||
+
|
||
+ if(property_info->ce == src)
|
||
+ {
|
||
+ property_info->ce = dst;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ assert(0); /* should never happen */
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ my_fixup_hashtable */
|
||
+static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
|
||
+{
|
||
+ Bucket *p;
|
||
+
|
||
+ uint i;
|
||
+
|
||
+ for (i = 0; i < ht->nTableSize; i++) {
|
||
+ if(!ht->arBuckets) break;
|
||
+ p = ht->arBuckets[i];
|
||
+ while (p != NULL) {
|
||
+ fixup(p, src, dst);
|
||
+ p = p->pNext;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif
|
||
+
|
||
+/* {{{ my_check_copy_function */
|
||
+static int my_check_copy_function(Bucket* p, va_list args)
|
||
+{
|
||
+ zend_class_entry* src = va_arg(args, zend_class_entry*);
|
||
+ zend_function* zf = (zend_function*)p->pData;
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ zend_class_entry* parent = src->parent;
|
||
+ zend_function* parent_fn = NULL;
|
||
+#endif
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ return (zf->common.scope == src);
|
||
+#else
|
||
+ if (parent &&
|
||
+ zend_hash_quick_find(&parent->function_table, p->arKey,
|
||
+ p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
|
||
+
|
||
+ if((parent_fn && zf) &&
|
||
+ (parent_fn->op_array.refcount == zf->op_array.refcount))
|
||
+ {
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+ return 1;
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_check_copy_default_property */
|
||
+static int my_check_copy_default_property(Bucket* p, va_list args)
|
||
+{
|
||
+ zend_class_entry* src = va_arg(args, zend_class_entry*);
|
||
+ zend_class_entry* parent = src->parent;
|
||
+ zval ** child_prop = (zval**)p->pData;
|
||
+ zval ** parent_prop = NULL;
|
||
+
|
||
+ if (parent &&
|
||
+ zend_hash_quick_find(&parent->default_properties, p->arKey,
|
||
+ p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
|
||
+
|
||
+ if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
|
||
+ {
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* possibly not in the parent */
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+/* {{{ my_check_copy_property_info */
|
||
+static int my_check_copy_property_info(Bucket* p, va_list args)
|
||
+{
|
||
+ zend_class_entry* src = va_arg(args, zend_class_entry*);
|
||
+ zend_class_entry* parent = src->parent;
|
||
+ zend_property_info* child_info = (zend_property_info*)p->pData;
|
||
+ zend_property_info* parent_info = NULL;
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ /* so much easier */
|
||
+ return (child_info->ce == src);
|
||
+#endif
|
||
+
|
||
+ if (parent &&
|
||
+ zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
|
||
+ p->h, (void **) &parent_info)==SUCCESS) {
|
||
+ if(parent_info->flags & ZEND_ACC_PRIVATE)
|
||
+ {
|
||
+ return 1;
|
||
+ }
|
||
+ if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
|
||
+ (child_info->flags & ZEND_ACC_PPP_MASK))
|
||
+ {
|
||
+ /* TODO: figure out whether ACC_CHANGED is more appropriate
|
||
+ * here */
|
||
+ return 1;
|
||
+ }
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ /* property doesn't exist in parent, copy into cached child */
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_check_copy_static_member */
|
||
+static int my_check_copy_static_member(Bucket* p, va_list args)
|
||
+{
|
||
+ zend_class_entry* src = va_arg(args, zend_class_entry*);
|
||
+ HashTable * ht = va_arg(args, HashTable*);
|
||
+ zend_class_entry* parent = src->parent;
|
||
+ HashTable * parent_ht = NULL;
|
||
+ char * member_name;
|
||
+ char * class_name = NULL;
|
||
+
|
||
+ zend_property_info *parent_info = NULL;
|
||
+ zend_property_info *child_info = NULL;
|
||
+ zval ** parent_prop = NULL;
|
||
+ zval ** child_prop = (zval**)(p->pData);
|
||
+
|
||
+ if(!parent) {
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ /* these do not need free'ing */
|
||
+#ifdef ZEND_ENGINE_2_2
|
||
+ zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
|
||
+#else
|
||
+ zend_unmangle_property_name(p->arKey, &class_name, &member_name);
|
||
+#endif
|
||
+
|
||
+ /* please refer do_inherit_property_access_check in zend_compile.c
|
||
+ * to understand why we lookup in properties_info.
|
||
+ */
|
||
+ if((zend_hash_find(&parent->properties_info, member_name,
|
||
+ strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
|
||
+ &&
|
||
+ (zend_hash_find(&src->properties_info, member_name,
|
||
+ strlen(member_name)+1, (void**)&child_info) == SUCCESS))
|
||
+ {
|
||
+ if(child_info->flags & ZEND_ACC_STATIC &&
|
||
+ (parent_info->flags & ZEND_ACC_PROTECTED &&
|
||
+ child_info->flags & ZEND_ACC_PUBLIC))
|
||
+ {
|
||
+ /* Do not copy into static_members. zend_do_inheritance
|
||
+ * will automatically insert a NULL value.
|
||
+ * TODO: decrement refcount or fixup when copying out for exec ?
|
||
+ */
|
||
+ return 0;
|
||
+ }
|
||
+ if(ht == &(src->default_static_members))
|
||
+ {
|
||
+ parent_ht = &parent->default_static_members;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ parent_ht = parent->static_members;
|
||
+ }
|
||
+
|
||
+ if(zend_hash_quick_find(parent_ht, p->arKey,
|
||
+ p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
|
||
+ {
|
||
+ /* they point to the same zval */
|
||
+ if(*parent_prop == *child_prop)
|
||
+ {
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
|
||
+ * register a optimizer callback function, returns the previous callback
|
||
+ */
|
||
+apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
|
||
+ apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
|
||
+ APCG(apc_optimize_function) = optimizer;
|
||
+ return old_optimizer;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.h php-5.2.5/ext/apc/apc_compile.h
|
||
--- php-5.2.5-orig/ext/apc/apc_compile.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_compile.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,134 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
|
||
+
|
||
+#ifndef APC_COMPILE_H
|
||
+#define APC_COMPILE_H
|
||
+
|
||
+/*
|
||
+ * This module encapsulates most of the complexity involved in deep-copying
|
||
+ * the Zend compiler data structures. The routines are allocator-agnostic, so
|
||
+ * the same function can be used for copying to and from shared memory.
|
||
+ */
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_php.h"
|
||
+
|
||
+/* {{{ struct definition: apc_function_t */
|
||
+typedef struct apc_function_t apc_function_t;
|
||
+struct apc_function_t {
|
||
+ char* name; /* the function name */
|
||
+ int name_len; /* length of name */
|
||
+ zend_function* function; /* the zend function data structure */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_class_t */
|
||
+typedef struct apc_class_t apc_class_t;
|
||
+struct apc_class_t {
|
||
+ char* name; /* the class name */
|
||
+ int name_len; /* length of name */
|
||
+ int is_derived; /* true if this is a derived class */
|
||
+ char* parent_name; /* the parent class name */
|
||
+ zend_class_entry* class_entry; /* the zend class data structure */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_opflags_t */
|
||
+typedef struct apc_opflags_t apc_opflags_t;
|
||
+struct apc_opflags_t {
|
||
+ unsigned int has_jumps : 1; /* has jump offsets */
|
||
+ unsigned int deep_copy : 1; /* needs deep copy */
|
||
+
|
||
+ /* autoglobal bits */
|
||
+ unsigned int _POST : 1;
|
||
+ unsigned int _GET : 1;
|
||
+ unsigned int _COOKIE : 1;
|
||
+ unsigned int _SERVER : 1;
|
||
+ unsigned int _ENV : 1;
|
||
+ unsigned int _FILES : 1;
|
||
+ unsigned int _REQUEST : 1;
|
||
+ unsigned int unknown_global : 1;
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * These are the top-level copy functions.
|
||
+ */
|
||
+
|
||
+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);
|
||
+extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
|
||
+extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
|
||
+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);
|
||
+extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
|
||
+
|
||
+/*
|
||
+ * Deallocation functions corresponding to the copy functions above.
|
||
+ */
|
||
+
|
||
+extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
|
||
+extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
|
||
+extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
|
||
+extern void apc_free_zval(zval* src, apc_free_t deallocate);
|
||
+
|
||
+/*
|
||
+ * These "copy-for-execution" functions must be called after retrieving an
|
||
+ * object from the shared cache. They do the minimal amount of work necessary
|
||
+ * to allow multiple processes to concurrently execute the same VM data
|
||
+ * structures.
|
||
+ */
|
||
+
|
||
+extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
|
||
+extern zend_function* apc_copy_function_for_execution(zend_function* src);
|
||
+extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
|
||
+
|
||
+/*
|
||
+ * The "free-after-execution" function performs a cursory clean up of the class data
|
||
+ * This is required to minimize memory leak warnings and to ensure correct destructor
|
||
+ * ordering of some variables.
|
||
+ */
|
||
+extern void apc_free_class_entry_after_execution(zend_class_entry* src);
|
||
+
|
||
+/*
|
||
+ * Optimization callback definition and registration function.
|
||
+ */
|
||
+typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
|
||
+extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.c php-5.2.5/ext/apc/apc_debug.c
|
||
--- php-5.2.5-orig/ext/apc/apc_debug.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_debug.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,57 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+*/
|
||
+
|
||
+/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
|
||
+#include "apc.h"
|
||
+#include <stdio.h>
|
||
+#include "zend_compile.h"
|
||
+
|
||
+#ifdef __DEBUG_APC__
|
||
+
|
||
+#include <dlfcn.h>
|
||
+
|
||
+/* keep track of vld_dump_oparray() signature */
|
||
+typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+void dump(zend_op_array *op_array TSRMLS_DC)
|
||
+{
|
||
+#ifdef __DEBUG_APC__
|
||
+ vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
|
||
+
|
||
+ if(dump_op_array)
|
||
+ {
|
||
+ dump_op_array(op_array TSRMLS_CC);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ apc_wprint("vld is not installed or something even worse.");
|
||
+ }
|
||
+#endif
|
||
+}
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.h php-5.2.5/ext/apc/apc_debug.h
|
||
--- php-5.2.5-orig/ext/apc/apc_debug.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_debug.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1 @@
|
||
+void dump(zend_op_array * TSRMLS_DC);
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc.dsp php-5.2.5/ext/apc/apc.dsp
|
||
--- php-5.2.5-orig/ext/apc/apc.dsp 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc.dsp 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,207 @@
|
||
+# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
|
||
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||
+# ** DO NOT EDIT **
|
||
+
|
||
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||
+
|
||
+CFG=apc - Win32 Debug_TS
|
||
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||
+!MESSAGE use the Export Makefile command and run
|
||
+!MESSAGE
|
||
+!MESSAGE NMAKE /f "apc.mak".
|
||
+!MESSAGE
|
||
+!MESSAGE You can specify a configuration when running NMAKE
|
||
+!MESSAGE by defining the macro CFG on the command line. For example:
|
||
+!MESSAGE
|
||
+!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
|
||
+!MESSAGE
|
||
+!MESSAGE Possible choices for configuration are:
|
||
+!MESSAGE
|
||
+!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
|
||
+!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
|
||
+!MESSAGE
|
||
+
|
||
+# Begin Project
|
||
+# PROP AllowPerConfigDependencies 0
|
||
+# PROP Scc_ProjName ""
|
||
+# PROP Scc_LocalPath ""
|
||
+CPP=cl.exe
|
||
+MTL=midl.exe
|
||
+RSC=rc.exe
|
||
+
|
||
+!IF "$(CFG)" == "apc - Win32 Debug_TS"
|
||
+
|
||
+# PROP BASE Use_MFC 0
|
||
+# PROP BASE Use_Debug_Libraries 1
|
||
+# PROP BASE Output_Dir "Debug_TS"
|
||
+# PROP BASE Intermediate_Dir "Debug_TS"
|
||
+# PROP BASE Target_Dir ""
|
||
+# PROP Use_MFC 0
|
||
+# PROP Use_Debug_Libraries 1
|
||
+# PROP Output_Dir "Debug_TS"
|
||
+# PROP Intermediate_Dir "Debug_TS"
|
||
+# PROP Ignore_Export_Lib 0
|
||
+# PROP Target_Dir ""
|
||
+# 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
|
||
+# 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
|
||
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||
+# ADD RSC /l 0x409 /d "_DEBUG"
|
||
+BSC32=bscmake.exe
|
||
+# ADD BASE BSC32 /nologo
|
||
+# ADD BSC32 /nologo
|
||
+LINK32=link.exe
|
||
+# 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
|
||
+# 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"
|
||
+
|
||
+!ELSEIF "$(CFG)" == "apc - Win32 Release_TS"
|
||
+
|
||
+# PROP BASE Use_MFC 0
|
||
+# PROP BASE Use_Debug_Libraries 0
|
||
+# PROP BASE Output_Dir "Release_TS"
|
||
+# PROP BASE Intermediate_Dir "Release_TS"
|
||
+# PROP BASE Target_Dir ""
|
||
+# PROP Use_MFC 0
|
||
+# PROP Use_Debug_Libraries 0
|
||
+# PROP Output_Dir "Release_TS"
|
||
+# PROP Intermediate_Dir "Release_TS"
|
||
+# PROP Ignore_Export_Lib 0
|
||
+# PROP Target_Dir ""
|
||
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
|
||
+# 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
|
||
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||
+# ADD RSC /l 0x409 /d "NDEBUG"
|
||
+BSC32=bscmake.exe
|
||
+# ADD BASE BSC32 /nologo
|
||
+# ADD BSC32 /nologo
|
||
+LINK32=link.exe
|
||
+# 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
|
||
+# 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"
|
||
+
|
||
+!ENDIF
|
||
+
|
||
+# Begin Target
|
||
+
|
||
+# Name "apc - Win32 Debug_TS"
|
||
+# Name "apc - Win32 Release_TS"
|
||
+# Begin Group "Source Files"
|
||
+
|
||
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_cache.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_compile.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_debug.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_fcntl_win32.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_main.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_rfc1867.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_shm.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_sma.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_stack.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_zend.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_apc.c
|
||
+# End Source File
|
||
+# End Group
|
||
+# Begin Group "Header Files"
|
||
+
|
||
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_cache.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_compile.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_debug.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_fcntl.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_globals.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_lock.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_main.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_php.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_shm.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_sma.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_stack.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\apc_zend.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_apc.h
|
||
+# End Source File
|
||
+# End Group
|
||
+# Begin Group "Resource Files"
|
||
+
|
||
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||
+# End Group
|
||
+# End Target
|
||
+# End Project
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.c php-5.2.5/ext/apc/apc_fcntl.c
|
||
--- php-5.2.5-orig/ext/apc/apc_fcntl.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_fcntl.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,118 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
|
||
+
|
||
+#include "apc_fcntl.h"
|
||
+#include "apc.h"
|
||
+#include <unistd.h>
|
||
+#include <fcntl.h>
|
||
+
|
||
+int apc_fcntl_create(const char* pathname)
|
||
+{
|
||
+ int fd;
|
||
+ if(pathname == NULL) {
|
||
+ char lock_path[] = "/tmp/.apc.XXXXXX";
|
||
+ mktemp(lock_path);
|
||
+ fd = open(lock_path, O_RDWR|O_CREAT, 0666);
|
||
+ if(fd > 0 ) {
|
||
+ unlink(lock_path);
|
||
+ return fd;
|
||
+ } else {
|
||
+ apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
|
||
+ return -1;
|
||
+ }
|
||
+ }
|
||
+ fd = open(pathname, O_RDWR|O_CREAT, 0666);
|
||
+ if(fd > 0 ) {
|
||
+ unlink(pathname);
|
||
+ return fd;
|
||
+ }
|
||
+ apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+void apc_fcntl_destroy(int fd)
|
||
+{
|
||
+ close(fd);
|
||
+}
|
||
+
|
||
+static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
|
||
+{
|
||
+ int ret;
|
||
+ struct flock lock;
|
||
+
|
||
+ lock.l_type = type;
|
||
+ lock.l_start = offset;
|
||
+ lock.l_whence = whence;
|
||
+ lock.l_len = len;
|
||
+ lock.l_pid = 0;
|
||
+
|
||
+ do { ret = fcntl(fd, cmd, &lock) ; }
|
||
+ while(ret < 0 && errno == EINTR);
|
||
+ return(ret);
|
||
+}
|
||
+
|
||
+void apc_fcntl_lock(int fd)
|
||
+{
|
||
+ if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
|
||
+ apc_eprint("apc_fcntl_lock failed:");
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_fcntl_rdlock(int fd)
|
||
+{
|
||
+ if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
|
||
+ apc_eprint("apc_fcntl_rdlock failed:");
|
||
+ }
|
||
+}
|
||
+
|
||
+zend_bool apc_fcntl_nonblocking_lock(int fd)
|
||
+{
|
||
+ if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
|
||
+ if(errno==EACCES||errno==EAGAIN) return 0;
|
||
+ else apc_eprint("apc_fcntl_lock failed:");
|
||
+ }
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+void apc_fcntl_unlock(int fd)
|
||
+{
|
||
+ if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
|
||
+ apc_eprint("apc_fcntl_unlock failed:");
|
||
+ }
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.h php-5.2.5/ext/apc/apc_fcntl.h
|
||
--- php-5.2.5-orig/ext/apc/apc_fcntl.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_fcntl.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,50 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt. |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
|
||
+
|
||
+#ifndef APC_FCNTL_H
|
||
+#define APC_FCNTL_H
|
||
+
|
||
+
|
||
+extern int apc_fcntl_create(const char* pathname);
|
||
+extern void apc_fcntl_destroy(int fd);
|
||
+extern void apc_fcntl_lock(int fd);
|
||
+extern void apc_fcntl_rdlock(int fd);
|
||
+extern void apc_fcntl_unlock(int fd);
|
||
+extern unsigned char apc_fcntl_nonblocking_lock(int fd);
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl_win32.c php-5.2.5/ext/apc/apc_fcntl_win32.c
|
||
--- php-5.2.5-orig/ext/apc/apc_fcntl_win32.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_fcntl_win32.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,117 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: George Schlossnagle <george@omniti.com> |
|
||
+ | Edin Kadribasic <edink@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#include "apc_fcntl.h"
|
||
+#include "apc.h"
|
||
+#include <php.h>
|
||
+#include <win32/flock.h>
|
||
+#include <io.h>
|
||
+#include <fcntl.h>
|
||
+#include <sys/types.h>
|
||
+#include <sys/stat.h>
|
||
+
|
||
+int apc_fcntl_create(const char* pathname)
|
||
+{
|
||
+ char *lock_file = emalloc(MAXPATHLEN);
|
||
+ HANDLE fd;
|
||
+ DWORD tmplen;
|
||
+ static int i=0;
|
||
+
|
||
+ tmplen = GetTempPath(MAXPATHLEN, lock_file);
|
||
+ if (!tmplen) {
|
||
+ efree(lock_file);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
|
||
+
|
||
+ fd = CreateFile(lock_file,
|
||
+ GENERIC_READ | GENERIC_WRITE,
|
||
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
+ NULL,
|
||
+ OPEN_ALWAYS,
|
||
+ FILE_ATTRIBUTE_NORMAL,
|
||
+ NULL);
|
||
+
|
||
+
|
||
+ if (fd == INVALID_HANDLE_VALUE) {
|
||
+ apc_eprint("apc_fcntl_create: could not open %s", lock_file);
|
||
+ efree(lock_file);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ efree(lock_file);
|
||
+ return (int)fd;
|
||
+}
|
||
+
|
||
+void apc_fcntl_destroy(int fd)
|
||
+{
|
||
+ CloseHandle((HANDLE)fd);
|
||
+}
|
||
+
|
||
+void apc_fcntl_lock(int fd)
|
||
+{
|
||
+ OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||
+
|
||
+ if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
|
||
+ apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_fcntl_rdlock(int fd)
|
||
+{
|
||
+ OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||
+
|
||
+ if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
|
||
+ apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_fcntl_unlock(int fd)
|
||
+{
|
||
+ OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||
+
|
||
+ if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
|
||
+ DWORD error_code = GetLastError();
|
||
+ /* Ignore already unlocked error */
|
||
+ if (error_code != ERROR_NOT_LOCKED) {
|
||
+ apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
|
||
--- php-5.2.5-orig/ext/apc/apc_futex.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_futex.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,116 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
|
||
+
|
||
+/***************************************************************************
|
||
+* Futex (Fast Userspace Mutex) support for APC
|
||
+*
|
||
+* Futex support provides user space locking with system calls only
|
||
+* for the contended cases. Some required reading for this functionality is:
|
||
+*
|
||
+* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux'
|
||
+* by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
|
||
+* http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
|
||
+*
|
||
+* 'Futexes are Tricky' by Ulrich Drepper
|
||
+* http://people.redhat.com/drepper/futex.pdf
|
||
+*
|
||
+*
|
||
+* This implementation is optimized and designed for the i386 and x86_64
|
||
+* architectures. Other architectures may require additional design
|
||
+* to efficiently and safely implement this functionality.
|
||
+*
|
||
+* Lock values are:
|
||
+* 0 = Unlocked
|
||
+* 1 = Locked without any waiting processes
|
||
+* 2 = Locked with an unknown number of waiting processes
|
||
+*
|
||
+***************************************************************************/
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_futex.h"
|
||
+
|
||
+#ifdef APC_FUTEX_LOCKS
|
||
+
|
||
+
|
||
+inline int apc_futex_create()
|
||
+{
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+inline void apc_futex_destroy(volatile int* lock)
|
||
+{
|
||
+ return;
|
||
+}
|
||
+
|
||
+void apc_futex_lock(volatile int* lock)
|
||
+{
|
||
+ int c;
|
||
+
|
||
+ /* Attempt to obtain a lock if not currently locked. If the previous
|
||
+ * value was not 0 then we did not obtain the lock, and must wait.
|
||
+ * If the previous value was 1 (has no waiting processes) then we
|
||
+ * set the lock to 2 before blocking on the futex wait operation.
|
||
+ * This implementation suffers from the possible difficulty of
|
||
+ * efficently implementing the atomic xchg operation on some
|
||
+ * architectures, and could also cause unecessary wake operations by
|
||
+ * setting the lock to 2 when there are no additional waiters.
|
||
+ */
|
||
+ if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
|
||
+ if(c != 2) {
|
||
+ c = apc_xchg(lock, 2);
|
||
+ }
|
||
+ while(c != 0) {
|
||
+ apc_futex_wait(lock, 2);
|
||
+ c = apc_xchg(lock, 2);
|
||
+ }
|
||
+ }
|
||
+
|
||
+}
|
||
+
|
||
+/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
|
||
+inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
|
||
+{
|
||
+ return apc_cmpxchg(lock, 0, 1) == 0;
|
||
+}
|
||
+
|
||
+
|
||
+inline void apc_futex_unlock(volatile int* lock)
|
||
+{
|
||
+ /* set the lock to 0, if it's previous values was not 1 (no waiters)
|
||
+ * then perform a wake operation on one process letting it know the lock
|
||
+ * is available. This is an optimization to save wake calls if there
|
||
+ * are no waiting processes for the lock
|
||
+ */
|
||
+ if(apc_xchg(lock,0) != 1) {
|
||
+ apc_futex_wake(lock, 1);
|
||
+ }
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.h php-5.2.5/ext/apc/apc_futex.h
|
||
--- php-5.2.5-orig/ext/apc/apc_futex.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_futex.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,55 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
|
||
+
|
||
+#ifndef APC_FUTEX_H
|
||
+#define APC_FUTEX_H
|
||
+
|
||
+#include "apc.h"
|
||
+
|
||
+#ifdef APC_FUTEX_LOCKS
|
||
+
|
||
+#include <asm/types.h>
|
||
+#include <unistd.h>
|
||
+#include <linux/futex.h>
|
||
+
|
||
+#include "arch/atomic.h"
|
||
+
|
||
+#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
|
||
+#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
|
||
+#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
|
||
+
|
||
+int apc_futex_create();
|
||
+void apc_futex_destroy(volatile int* lock);
|
||
+void apc_futex_lock(volatile int* lock);
|
||
+void apc_futex_unlock(volatile int* lock);
|
||
+
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_globals.h php-5.2.5/ext/apc/apc_globals.h
|
||
--- php-5.2.5-orig/ext/apc/apc_globals.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_globals.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,119 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt. |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_globals.h,v 3.70 2007/12/26 22:46:33 rasmus Exp $ */
|
||
+
|
||
+#ifndef APC_GLOBALS_H
|
||
+#define APC_GLOBALS_H
|
||
+
|
||
+#define APC_VERSION "3.0.16"
|
||
+
|
||
+#include "apc_cache.h"
|
||
+#include "apc_stack.h"
|
||
+#include "apc_php.h"
|
||
+
|
||
+ZEND_BEGIN_MODULE_GLOBALS(apc)
|
||
+ /* configuration parameters */
|
||
+ zend_bool enabled; /* if true, apc is enabled (defaults to true) */
|
||
+ long shm_segments; /* number of shared memory segments to use */
|
||
+ long shm_size; /* size of each shared memory segment (in MB) */
|
||
+ long num_files_hint; /* parameter to apc_cache_create */
|
||
+ long user_entries_hint;
|
||
+ long gc_ttl; /* parameter to apc_cache_create */
|
||
+ long ttl; /* parameter to apc_cache_create */
|
||
+ long user_ttl;
|
||
+#if APC_MMAP
|
||
+ char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */
|
||
+#endif
|
||
+ char** filters; /* array of regex filters that prevent caching */
|
||
+
|
||
+ /* module variables */
|
||
+ zend_bool initialized; /* true if module was initialized */
|
||
+ apc_stack_t* cache_stack; /* the stack of cached executable code */
|
||
+ zend_bool cache_by_default; /* true if files should be cached unless filtered out */
|
||
+ /* false if files should only be cached if filtered in */
|
||
+ long slam_defense; /* Probability of a process not caching an uncached file */
|
||
+ size_t* mem_size_ptr; /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
|
||
+ long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
|
||
+ zend_bool enable_cli; /* Flag to override turning APC off for CLI */
|
||
+ long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */
|
||
+ long slam_rand; /* A place to store the slam rand value for the request */
|
||
+ zend_bool fpstat; /* true if fullpath includes should be stat'ed */
|
||
+ zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */
|
||
+ zend_bool write_lock; /* true for a global write lock */
|
||
+ zend_bool report_autofilter; /* true for auto-filter warnings */
|
||
+ zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
|
||
+ apc_optimize_function_t apc_optimize_function; /* optimizer function callback */
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+ zend_bool rfc1867; /* Flag to enable rfc1867 handler */
|
||
+ char* rfc1867_prefix; /* Key prefix */
|
||
+ char* rfc1867_name; /* Name of hidden field to activate upload progress/key suffix */
|
||
+ double rfc1867_freq; /* Update frequency as percentage or bytes */
|
||
+#endif
|
||
+ HashTable *copied_zvals; /* my_copy recursion detection list */
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ int reserved_offset; /* offset for apc info in op_array->reserved[] */
|
||
+#endif
|
||
+ zend_bool localcache; /* enable local cache */
|
||
+ long localcache_size; /* size of fast cache */
|
||
+ apc_local_cache_t* lcache; /* unlocked local cache */
|
||
+ zend_bool force_file_update; /* force files to be updated during apc_compile_file */
|
||
+ char canon_path[MAXPATHLEN]; /* canonical path for key data */
|
||
+#if APC_FILEHITS
|
||
+ zval *filehits; /* Files that came from the cache for this request */
|
||
+#endif
|
||
+ zend_bool coredump_unmap; /* Trap signals that coredump and unmap shared memory */
|
||
+ZEND_END_MODULE_GLOBALS(apc)
|
||
+
|
||
+/* (the following declaration is defined in php_apc.c) */
|
||
+ZEND_EXTERN_MODULE_GLOBALS(apc)
|
||
+
|
||
+#ifdef ZTS
|
||
+# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
|
||
+#else
|
||
+# define APCG(v) (apc_globals.v)
|
||
+#endif
|
||
+
|
||
+/* True globals */
|
||
+extern apc_cache_t* apc_cache; /* the global compiler cache */
|
||
+extern apc_cache_t* apc_user_cache; /* the global user content cache */
|
||
+extern void* apc_compiled_filters; /* compiled filters */
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc.h php-5.2.5/ext/apc/apc.h
|
||
--- php-5.2.5-orig/ext/apc/apc.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,126 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
|
||
+
|
||
+#ifndef APC_H
|
||
+#define APC_H
|
||
+
|
||
+/*
|
||
+ * This module defines utilities and helper functions used elsewhere in APC.
|
||
+ */
|
||
+
|
||
+/* Commonly needed C library headers. */
|
||
+#include <assert.h>
|
||
+#include <errno.h>
|
||
+#include <stdarg.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <time.h>
|
||
+
|
||
+/* UNIX headers (needed for struct stat) */
|
||
+#include <sys/types.h>
|
||
+#include <sys/stat.h>
|
||
+#ifndef PHP_WIN32
|
||
+#include <unistd.h>
|
||
+#endif
|
||
+
|
||
+#ifdef HAVE_CONFIG_H
|
||
+#include <config.h>
|
||
+#endif
|
||
+
|
||
+#include "php.h"
|
||
+
|
||
+/* log levels constants (see apc_log) */
|
||
+enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
|
||
+
|
||
+/* typedefs for extensible memory allocators */
|
||
+typedef void* (*apc_malloc_t)(size_t);
|
||
+typedef void (*apc_free_t) (void*);
|
||
+
|
||
+/* wrappers for memory allocation routines */
|
||
+extern void* apc_emalloc(size_t n);
|
||
+extern void* apc_erealloc(void* p, size_t n);
|
||
+extern void apc_efree(void* p);
|
||
+extern char* apc_estrdup(const char* s);
|
||
+extern void* apc_xstrdup(const char* s, apc_malloc_t f);
|
||
+extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
|
||
+
|
||
+/* console display functions */
|
||
+extern void apc_log(int level, const char* fmt, ...);
|
||
+extern void apc_eprint(const char* fmt, ...);
|
||
+extern void apc_wprint(const char* fmt, ...);
|
||
+extern void apc_dprint(const char* fmt, ...);
|
||
+extern void apc_nprint(const char* fmt, ...);
|
||
+
|
||
+/* string and text manipulation */
|
||
+extern char* apc_append(const char* s, const char* t);
|
||
+extern char* apc_substr(const char* s, int start, int length);
|
||
+extern char** apc_tokenize(const char* s, char delim);
|
||
+
|
||
+/* filesystem functions */
|
||
+
|
||
+typedef struct apc_fileinfo_t
|
||
+{
|
||
+ char fullpath[MAXPATHLEN+1];
|
||
+ struct stat st_buf;
|
||
+} apc_fileinfo_t;
|
||
+
|
||
+#ifndef PHP_WIN32
|
||
+#define apc_stat(f, b) stat(f, b)
|
||
+#else
|
||
+#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
|
||
+extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
|
||
+#endif
|
||
+extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
|
||
+
|
||
+/* regular expression wrapper functions */
|
||
+extern void* apc_regex_compile_array(char* patterns[]);
|
||
+extern void apc_regex_destroy_array(void* p);
|
||
+extern int apc_regex_match_array(void* p, const char* input);
|
||
+
|
||
+/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
|
||
+extern unsigned int apc_crc32(const char* buf, int len);
|
||
+
|
||
+#define APC_NEGATIVE_MATCH 1
|
||
+#define APC_POSITIVE_MATCH 2
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_lock.h php-5.2.5/ext/apc/apc_lock.h
|
||
--- php-5.2.5-orig/ext/apc/apc_lock.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_lock.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,105 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
|
||
+
|
||
+#ifndef APC_LOCK
|
||
+#define APC_LOCK
|
||
+
|
||
+#include "apc_sem.h"
|
||
+#include "apc_fcntl.h"
|
||
+#include "apc_pthreadmutex.h"
|
||
+#include "apc_futex.h"
|
||
+#include "apc_spin.h"
|
||
+#ifdef HAVE_CONFIG_H
|
||
+#include <config.h>
|
||
+#endif
|
||
+
|
||
+#ifdef TSRM_LOCKS
|
||
+#define RDLOCK_AVAILABLE 0
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 0
|
||
+/* quick & dirty: use TSRM mutex locks for now */
|
||
+#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
|
||
+#define apc_lck_destroy(a) tsrm_mutex_free((MUTEX_T)a)
|
||
+#define apc_lck_lock(a) tsrm_mutex_lock((MUTEX_T)a)
|
||
+#define apc_lck_rdlock(a) tsrm_mutex_lock((MUTEX_T)a)
|
||
+#define apc_lck_unlock(a) tsrm_mutex_unlock((MUTEX_T)a)
|
||
+#elif defined(APC_SEM_LOCKS)
|
||
+#define RDLOCK_AVAILABLE 0
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 0
|
||
+#define apc_lck_t int
|
||
+#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
|
||
+#define apc_lck_destroy(a) apc_sem_destroy(a)
|
||
+#define apc_lck_lock(a) apc_sem_lock(a)
|
||
+#define apc_lck_rdlock(a) apc_sem_lock(a)
|
||
+#define apc_lck_unlock(a) apc_sem_unlock(a)
|
||
+#elif defined(APC_PTHREADMUTEX_LOCKS)
|
||
+#define RDLOCK_AVAILABLE 0
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 1
|
||
+#define apc_lck_t pthread_mutex_t
|
||
+#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
|
||
+#define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a)
|
||
+#define apc_lck_lock(a) apc_pthreadmutex_lock(&a)
|
||
+#define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a)
|
||
+#define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a)
|
||
+#define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a)
|
||
+#elif defined(APC_FUTEX_LOCKS)
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 1
|
||
+#define apc_lck_t int
|
||
+#define apc_lck_create(a,b,c,d) d=apc_futex_create()
|
||
+#define apc_lck_destroy(a) apc_futex_destroy(&a)
|
||
+#define apc_lck_lock(a) apc_futex_lock(&a)
|
||
+#define apc_lck_nb_lock(a) apc_futex_nonblocking_lock(&a)
|
||
+#define apc_lck_rdlock(a) apc_futex_lock(&a)
|
||
+#define apc_lck_unlock(a) apc_futex_unlock(&a)
|
||
+#elif defined(APC_SPIN_LOCKS)
|
||
+#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
|
||
+#define apc_lck_t slock_t
|
||
+#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
|
||
+#define apc_lck_destroy(a) apc_slock_destroy(&a)
|
||
+#define apc_lck_lock(a) apc_slock_lock(&a)
|
||
+#define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a)
|
||
+#define apc_lck_rdlock(a) apc_slock_lock(&a)
|
||
+#define apc_lck_unlock(a) apc_slock_unlock(&a)
|
||
+#else
|
||
+#define RDLOCK_AVAILABLE 1
|
||
+#ifdef PHP_WIN32
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 0
|
||
+#else
|
||
+#define NONBLOCKING_LOCK_AVAILABLE 1
|
||
+#endif
|
||
+#define apc_lck_t int
|
||
+#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
|
||
+#define apc_lck_destroy(a) apc_fcntl_destroy(a)
|
||
+#define apc_lck_lock(a) apc_fcntl_lock(a)
|
||
+#define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a)
|
||
+#define apc_lck_rdlock(a) apc_fcntl_rdlock(a)
|
||
+#define apc_lck_unlock(a) apc_fcntl_unlock(a)
|
||
+#endif
|
||
+
|
||
+#endif
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
|
||
--- php-5.2.5-orig/ext/apc/apc_main.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_main.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,701 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_main.c,v 3.103 2007/11/14 19:46:46 shire Exp $ */
|
||
+
|
||
+#include "apc_php.h"
|
||
+#include "apc_main.h"
|
||
+#include "apc.h"
|
||
+#include "apc_lock.h"
|
||
+#include "apc_cache.h"
|
||
+#include "apc_compile.h"
|
||
+#include "apc_globals.h"
|
||
+#include "apc_sma.h"
|
||
+#include "apc_stack.h"
|
||
+#include "apc_zend.h"
|
||
+#include "SAPI.h"
|
||
+#if PHP_API_VERSION <= 20020918
|
||
+#if HAVE_APACHE
|
||
+#ifdef APC_PHP4_STAT
|
||
+#undef XtOffsetOf
|
||
+#include "httpd.h"
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/* {{{ module variables */
|
||
+
|
||
+/* pointer to the original Zend engine compile_file function */
|
||
+typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
|
||
+static zend_compile_t *old_compile_file;
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
|
||
+static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
|
||
+{
|
||
+ zend_compile_t *retval = old_compile_file;
|
||
+
|
||
+ if (ptr != NULL) old_compile_file = ptr;
|
||
+ return retval;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ install_function */
|
||
+static int install_function(apc_function_t fn TSRMLS_DC)
|
||
+{
|
||
+ int status =
|
||
+ zend_hash_add(EG(function_table),
|
||
+ fn.name,
|
||
+ fn.name_len+1,
|
||
+ apc_copy_function_for_execution(fn.function),
|
||
+ sizeof(fn.function[0]),
|
||
+ NULL);
|
||
+
|
||
+ if (status == FAILURE) {
|
||
+ /* apc_eprint("Cannot redeclare %s()", fn.name); */
|
||
+ }
|
||
+
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ install_class */
|
||
+static int install_class(apc_class_t cl TSRMLS_DC)
|
||
+{
|
||
+ zend_class_entry* class_entry = cl.class_entry;
|
||
+ zend_class_entry* parent = NULL;
|
||
+ int status;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_class_entry** allocated_ce = NULL;
|
||
+#endif
|
||
+
|
||
+
|
||
+ /* Special case for mangled names. Mangled names are unique to a file.
|
||
+ * There is no way two classes with the same mangled name will occur,
|
||
+ * unless a file is included twice. And if in case, a file is included
|
||
+ * twice, all mangled name conflicts can be ignored and the class redeclaration
|
||
+ * error may be deferred till runtime of the corresponding DECLARE_CLASS
|
||
+ * calls.
|
||
+ */
|
||
+
|
||
+ if(cl.name_len != 0 && cl.name[0] == '\0') {
|
||
+ if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ /*
|
||
+ * XXX: We need to free this somewhere...
|
||
+ */
|
||
+ allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
|
||
+
|
||
+ if(!allocated_ce) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ *allocated_ce =
|
||
+#endif
|
||
+ class_entry =
|
||
+ apc_copy_class_entry_for_execution(cl.class_entry,
|
||
+ cl.is_derived);
|
||
+
|
||
+
|
||
+ /* restore parent class pointer for compile-time inheritance */
|
||
+ if (cl.parent_name != NULL) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_class_entry** parent_ptr = NULL;
|
||
+ /*
|
||
+ * zend_lookup_class has to be due to presence of __autoload,
|
||
+ * just looking up the EG(class_table) is not enough in php5!
|
||
+ * Even more dangerously, thanks to __autoload and people using
|
||
+ * class names as filepaths for inclusion, this has to be case
|
||
+ * sensitive. zend_lookup_class automatically does a case_fold
|
||
+ * internally, but passes the case preserved version to __autoload.
|
||
+ * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
|
||
+ * zend_lookup_class does it internally anyway!
|
||
+ */
|
||
+ status = zend_lookup_class(cl.parent_name,
|
||
+ strlen(cl.parent_name),
|
||
+ &parent_ptr TSRMLS_CC);
|
||
+#else
|
||
+ status = zend_hash_find(EG(class_table),
|
||
+ cl.parent_name,
|
||
+ strlen(cl.parent_name)+1,
|
||
+ (void**) &parent);
|
||
+#endif
|
||
+ if (status == FAILURE) {
|
||
+ if(APCG(report_autofilter)) {
|
||
+ apc_wprint("Dynamic inheritance detected for class %s", cl.name);
|
||
+ }
|
||
+ class_entry->parent = NULL;
|
||
+ return status;
|
||
+ }
|
||
+ else {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ parent = *parent_ptr;
|
||
+#endif
|
||
+ class_entry->parent = parent;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_do_inheritance(class_entry, parent TSRMLS_CC);
|
||
+#else
|
||
+ zend_do_inheritance(class_entry, parent);
|
||
+#endif
|
||
+ }
|
||
+
|
||
+
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ status = zend_hash_add(EG(class_table),
|
||
+ cl.name,
|
||
+ cl.name_len+1,
|
||
+ allocated_ce,
|
||
+ sizeof(zend_class_entry*),
|
||
+ NULL);
|
||
+#else
|
||
+ status = zend_hash_add(EG(class_table),
|
||
+ cl.name,
|
||
+ cl.name_len+1,
|
||
+ class_entry,
|
||
+ sizeof(zend_class_entry),
|
||
+ NULL);
|
||
+#endif
|
||
+
|
||
+ if (status == FAILURE) {
|
||
+ apc_eprint("Cannot redeclare class %s", cl.name);
|
||
+ }
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ uninstall_class */
|
||
+static int uninstall_class(apc_class_t cl TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ status = zend_hash_del(EG(class_table),
|
||
+ cl.name,
|
||
+ cl.name_len+1);
|
||
+#else
|
||
+ status = zend_hash_del(EG(class_table),
|
||
+ cl.name,
|
||
+ cl.name_len+1);
|
||
+#endif
|
||
+ if (status == FAILURE) {
|
||
+ apc_eprint("Cannot delete class %s", cl.name);
|
||
+ }
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ compare_file_handles */
|
||
+static int compare_file_handles(void* a, void* b)
|
||
+{
|
||
+ zend_file_handle* fh1 = (zend_file_handle*)a;
|
||
+ zend_file_handle* fh2 = (zend_file_handle*)b;
|
||
+ return (fh1->type == fh2->type &&
|
||
+ fh1->filename == fh2->filename &&
|
||
+ fh1->opened_path == fh2->opened_path);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ cached_compile */
|
||
+static zend_op_array* cached_compile(zend_file_handle* h,
|
||
+ int type TSRMLS_DC)
|
||
+{
|
||
+ apc_cache_entry_t* cache_entry;
|
||
+ int i, ii;
|
||
+
|
||
+ cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
|
||
+ assert(cache_entry != NULL);
|
||
+
|
||
+ if (cache_entry->data.file.classes) {
|
||
+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
|
||
+ if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
|
||
+ goto default_compile;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (cache_entry->data.file.functions) {
|
||
+ for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
|
||
+ install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+
|
||
+ return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
|
||
+
|
||
+default_compile:
|
||
+
|
||
+ if(APCG(report_autofilter)) {
|
||
+ apc_wprint("Autofiltering %s", h->opened_path);
|
||
+ }
|
||
+
|
||
+ if(cache_entry->data.file.classes) {
|
||
+ for(ii = 0; ii < i ; ii++) {
|
||
+ uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
|
||
+
|
||
+ apc_cache_release(apc_cache, cache_entry);
|
||
+
|
||
+ /* cannot free up cache data yet, it maybe in use */
|
||
+
|
||
+ zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
|
||
+
|
||
+ h->type = ZEND_HANDLE_FILENAME;
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ my_compile_file
|
||
+ Overrides zend_compile_file */
|
||
+static zend_op_array* my_compile_file(zend_file_handle* h,
|
||
+ int type TSRMLS_DC)
|
||
+{
|
||
+ apc_cache_key_t key;
|
||
+ apc_cache_entry_t* cache_entry;
|
||
+ zend_op_array* op_array;
|
||
+ int num_functions, num_classes, ret;
|
||
+ zend_op_array* alloc_op_array;
|
||
+ apc_function_t* alloc_functions;
|
||
+ apc_class_t* alloc_classes;
|
||
+ time_t t;
|
||
+ char *path;
|
||
+ size_t mem_size;
|
||
+
|
||
+ if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
|
||
+ return old_compile_file(h, type TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* check our regular expression filters */
|
||
+ if (APCG(filters) && apc_compiled_filters) {
|
||
+ int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
|
||
+ if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
|
||
+ return old_compile_file(h, type TSRMLS_CC);
|
||
+ }
|
||
+ } else if(!APCG(cache_by_default)) {
|
||
+ return old_compile_file(h, type TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+#if PHP_API_VERSION < 20041225
|
||
+#if HAVE_APACHE && defined(APC_PHP4_STAT)
|
||
+ t = ((request_rec *)SG(server_context))->request_time;
|
||
+#else
|
||
+ t = time(0);
|
||
+#endif
|
||
+#else
|
||
+ t = sapi_get_request_time(TSRMLS_C);
|
||
+#endif
|
||
+
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
|
||
+#endif
|
||
+
|
||
+ /* try to create a cache key; if we fail, give up on caching */
|
||
+ if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
|
||
+ return old_compile_file(h, type TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+
|
||
+ if(!APCG(force_file_update)) {
|
||
+ if(APCG(localcache)) {
|
||
+ /* search for the file in the local cache */
|
||
+ cache_entry = apc_local_cache_find(APCG(lcache), key, t);
|
||
+ } else {
|
||
+ /* search for the file in the cache */
|
||
+ cache_entry = apc_cache_find(apc_cache, key, t);
|
||
+ }
|
||
+ } else {
|
||
+ cache_entry = NULL;
|
||
+ }
|
||
+
|
||
+ if (cache_entry != NULL) {
|
||
+ int dummy = 1;
|
||
+ if (h->opened_path == NULL) {
|
||
+ h->opened_path = estrdup(cache_entry->data.file.filename);
|
||
+ }
|
||
+ zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
|
||
+ zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
|
||
+ apc_stack_push(APCG(cache_stack), cache_entry);
|
||
+ op_array = cached_compile(h, type TSRMLS_CC);
|
||
+ if(op_array) {
|
||
+#ifdef APC_FILEHITS
|
||
+ /* If the file comes from the cache, add it to the global request file list */
|
||
+ add_next_index_string(APCG(filehits), h->filename, 1);
|
||
+#endif
|
||
+ return op_array;
|
||
+ }
|
||
+ if(APCG(report_autofilter)) {
|
||
+ apc_wprint("Recompiling %s", h->opened_path);
|
||
+ }
|
||
+ /* TODO: check what happens with EG(included_files) */
|
||
+ }
|
||
+
|
||
+ if(apc_cache_busy(apc_cache) && APCG(localcache)) {
|
||
+ /* possibly local cache returned NULL because cache is busy */
|
||
+ return old_compile_file(h, type TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* remember how many functions and classes existed before compilation */
|
||
+ num_functions = zend_hash_num_elements(CG(function_table));
|
||
+ num_classes = zend_hash_num_elements(CG(class_table));
|
||
+
|
||
+ /* compile the file using the default compile function */
|
||
+ op_array = old_compile_file(h, type TSRMLS_CC);
|
||
+ if (op_array == NULL) {
|
||
+ return NULL;
|
||
+ }
|
||
+ /*
|
||
+ * Basically this will cause a file only to be cached on a percentage
|
||
+ * of the attempts. This is to avoid cache slams when starting up a
|
||
+ * very busy server or when modifying files on a very busy live server.
|
||
+ * There is no point having many processes all trying to cache the same
|
||
+ * file at the same time. By introducing a chance of being cached
|
||
+ * we theoretically cut the cache slam problem by the given percentage.
|
||
+ * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
|
||
+ * to cache an uncached file will be ignored.
|
||
+ */
|
||
+ if(APCG(slam_defense)) {
|
||
+ if(APCG(slam_rand)==-1) {
|
||
+ APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
|
||
+ }
|
||
+ if(APCG(slam_rand) < APCG(slam_defense)) {
|
||
+ return op_array;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
|
||
+ if(key.type == APC_CACHE_KEY_FPFILE) {
|
||
+ apc_fileinfo_t fileinfo;
|
||
+ struct stat *tmp_buf = NULL;
|
||
+ if(!strcmp(SG(request_info).path_translated, h->filename)) {
|
||
+ tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
|
||
+ }
|
||
+ if(tmp_buf) {
|
||
+ fileinfo.st_buf = *tmp_buf;
|
||
+ } else {
|
||
+ if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
|
||
+#endif
|
||
+ return op_array;
|
||
+ }
|
||
+ }
|
||
+ key.mtime = fileinfo.st_buf.st_mtime;
|
||
+ }
|
||
+
|
||
+ HANDLE_BLOCK_INTERRUPTIONS();
|
||
+
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ if(!apc_cache_write_lock(apc_cache)) {
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return op_array;
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ mem_size = 0;
|
||
+ APCG(mem_size_ptr) = &mem_size;
|
||
+ if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ apc_cache_write_unlock(apc_cache);
|
||
+ }
|
||
+#endif
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return op_array;
|
||
+ }
|
||
+
|
||
+ if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
|
||
+ apc_free_op_array(alloc_op_array, apc_sma_free);
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ apc_cache_write_unlock(apc_cache);
|
||
+ }
|
||
+#endif
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return op_array;
|
||
+ }
|
||
+ if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
|
||
+ apc_free_op_array(alloc_op_array, apc_sma_free);
|
||
+ apc_free_functions(alloc_functions, apc_sma_free);
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ apc_cache_write_unlock(apc_cache);
|
||
+ }
|
||
+#endif
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return op_array;
|
||
+ }
|
||
+
|
||
+ path = h->opened_path;
|
||
+ if(!path) path=h->filename;
|
||
+
|
||
+#ifdef __DEBUG_APC__
|
||
+ fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
|
||
+#endif
|
||
+
|
||
+ if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
|
||
+ apc_free_op_array(alloc_op_array, apc_sma_free);
|
||
+ apc_free_functions(alloc_functions, apc_sma_free);
|
||
+ apc_free_classes(alloc_classes, apc_sma_free);
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ apc_cache_write_unlock(apc_cache);
|
||
+ }
|
||
+#endif
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return op_array;
|
||
+ }
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+ cache_entry->mem_size = mem_size;
|
||
+
|
||
+ if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
|
||
+ apc_cache_free_entry(cache_entry);
|
||
+ if(ret==-1) {
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ }
|
||
+ }
|
||
+
|
||
+#if NONBLOCKING_LOCK_AVAILABLE
|
||
+ if(APCG(write_lock)) {
|
||
+ apc_cache_write_unlock(apc_cache);
|
||
+ }
|
||
+#endif
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+
|
||
+ return op_array;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ module init and shutdown */
|
||
+
|
||
+int apc_module_init(int module_number TSRMLS_DC)
|
||
+{
|
||
+ /* apc initialization */
|
||
+#if APC_MMAP
|
||
+ apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
|
||
+#else
|
||
+ apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
|
||
+#endif
|
||
+ apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
|
||
+ apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
|
||
+
|
||
+ apc_compiled_filters = apc_regex_compile_array(APCG(filters));
|
||
+
|
||
+ /* override compilation */
|
||
+ old_compile_file = zend_compile_file;
|
||
+ zend_compile_file = my_compile_file;
|
||
+ REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
|
||
+
|
||
+ APCG(initialized) = 1;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+int apc_module_shutdown(TSRMLS_D)
|
||
+{
|
||
+ if (!APCG(initialized))
|
||
+ return 0;
|
||
+
|
||
+ /* restore compilation */
|
||
+ zend_compile_file = old_compile_file;
|
||
+
|
||
+ /*
|
||
+ * In case we got interrupted by a SIGTERM or something else during execution
|
||
+ * we may have cache entries left on the stack that we need to check to make
|
||
+ * sure that any functions or classes these may have added to the global function
|
||
+ * and class tables are removed before we blow away the memory that hold them.
|
||
+ *
|
||
+ * This is merely to remove memory leak warnings - as the process is terminated
|
||
+ * immediately after shutdown. The following while loop can be removed without
|
||
+ * affecting anything else.
|
||
+ */
|
||
+ while (apc_stack_size(APCG(cache_stack)) > 0) {
|
||
+ int i;
|
||
+ apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
|
||
+ if (cache_entry->data.file.functions) {
|
||
+ for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
|
||
+ zend_hash_del(EG(function_table),
|
||
+ cache_entry->data.file.functions[i].name,
|
||
+ cache_entry->data.file.functions[i].name_len+1);
|
||
+ }
|
||
+ }
|
||
+ if (cache_entry->data.file.classes) {
|
||
+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
|
||
+ zend_hash_del(EG(class_table),
|
||
+ cache_entry->data.file.classes[i].name,
|
||
+ cache_entry->data.file.classes[i].name_len+1);
|
||
+ }
|
||
+ }
|
||
+ apc_cache_release(apc_cache, cache_entry);
|
||
+ }
|
||
+
|
||
+ apc_cache_destroy(apc_cache);
|
||
+ apc_cache_destroy(apc_user_cache);
|
||
+ apc_sma_cleanup();
|
||
+
|
||
+ APCG(initialized) = 0;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ process init and shutdown */
|
||
+int apc_process_init(int module_number TSRMLS_DC)
|
||
+{
|
||
+ int minttl = (APCG(gc_ttl) > APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
|
||
+ int size = APCG(localcache_size);
|
||
+ if(APCG(initialized) && APCG(localcache)) {
|
||
+ /* TTL is 2 mins by default */
|
||
+ APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+int apc_process_shutdown(TSRMLS_D)
|
||
+{
|
||
+ if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
|
||
+ apc_local_cache_destroy(APCG(lcache));
|
||
+ APCG(lcache) = NULL;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ request init and shutdown */
|
||
+
|
||
+int apc_request_init(TSRMLS_D)
|
||
+{
|
||
+ apc_stack_clear(APCG(cache_stack));
|
||
+ APCG(slam_rand) = -1;
|
||
+ APCG(copied_zvals) = NULL;
|
||
+
|
||
+#ifdef APC_FILEHITS
|
||
+ ALLOC_INIT_ZVAL(APCG(filehits));
|
||
+ array_init(APCG(filehits));
|
||
+#endif
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+int apc_request_shutdown(TSRMLS_D)
|
||
+{
|
||
+ apc_deactivate(TSRMLS_C);
|
||
+
|
||
+#ifdef APC_FILEHITS
|
||
+ zval_ptr_dtor(&APCG(filehits));
|
||
+#endif
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_deactivate */
|
||
+void apc_deactivate(TSRMLS_D)
|
||
+{
|
||
+ /* The execution stack was unwound, which prevented us from decrementing
|
||
+ * the reference counts on active cache entries in `my_execute`.
|
||
+ */
|
||
+ while (apc_stack_size(APCG(cache_stack)) > 0) {
|
||
+ int i;
|
||
+ zend_class_entry* zce = NULL;
|
||
+ void ** centry = (void*)(&zce);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_class_entry** pzce = NULL;
|
||
+#endif
|
||
+
|
||
+ apc_cache_entry_t* cache_entry =
|
||
+ (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
|
||
+
|
||
+ if (cache_entry->data.file.classes) {
|
||
+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
|
||
+#endif
|
||
+ if(zend_hash_find(EG(class_table),
|
||
+ cache_entry->data.file.classes[i].name,
|
||
+ cache_entry->data.file.classes[i].name_len+1,
|
||
+ (void**)centry) == FAILURE)
|
||
+ {
|
||
+ /* double inclusion of conditional classes ends up failing
|
||
+ * this lookup the second time around.
|
||
+ */
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zce = *pzce;
|
||
+#endif
|
||
+ zend_hash_del(EG(class_table),
|
||
+ cache_entry->data.file.classes[i].name,
|
||
+ cache_entry->data.file.classes[i].name_len+1);
|
||
+
|
||
+ apc_free_class_entry_after_execution(zce);
|
||
+ }
|
||
+ }
|
||
+ apc_cache_release(apc_cache, cache_entry);
|
||
+ }
|
||
+ if(APCG(localcache)) {
|
||
+ apc_local_cache_cleanup(APCG(lcache));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
|
||
--- php-5.2.5-orig/ext/apc/apc_main.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_main.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,67 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
|
||
+
|
||
+#ifndef APC_MAIN_H
|
||
+#define APC_MAIN_H
|
||
+
|
||
+/*
|
||
+ * This module provides the primary interface between PHP and APC.
|
||
+ */
|
||
+
|
||
+extern int apc_module_init(int module_number TSRMLS_DC);
|
||
+extern int apc_module_shutdown(TSRMLS_D);
|
||
+extern int apc_process_init(int module_number TSRMLS_DC);
|
||
+extern int apc_process_shutdown(TSRMLS_D);
|
||
+extern int apc_request_init(TSRMLS_D);
|
||
+extern int apc_request_shutdown(TSRMLS_D);
|
||
+
|
||
+/*
|
||
+ * apc_deactivate is called by the PHP interpreter when an "exception" is
|
||
+ * raised (e.g., a call to the exit function) that unwinds the execution
|
||
+ * stack.
|
||
+ */
|
||
+extern void apc_deactivate();
|
||
+
|
||
+
|
||
+extern const char* apc_version();
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
|
||
--- php-5.2.5-orig/ext/apc/apc_mmap.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_mmap.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,139 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_mmap.c,v 3.7 2007/12/20 23:00:51 shire Exp $ */
|
||
+
|
||
+#include "apc.h"
|
||
+
|
||
+#if APC_MMAP
|
||
+
|
||
+#include <fcntl.h>
|
||
+#include <sys/types.h>
|
||
+#include <sys/mman.h>
|
||
+
|
||
+/*
|
||
+ * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
|
||
+ * tells whatever update daemons might be running to not flush dirty
|
||
+ * vm pages to disk unless absolutely necessary. My guess is that
|
||
+ * most systems that don't have this probably default to only synching
|
||
+ * to disk when absolutely necessary.
|
||
+ */
|
||
+#ifndef MAP_NOSYNC
|
||
+#define MAP_NOSYNC 0
|
||
+#endif
|
||
+
|
||
+void *apc_mmap(char *file_mask, size_t size)
|
||
+{
|
||
+ void* shmaddr; /* the shared memory address */
|
||
+
|
||
+ /* If no filename was provided, do an anonymous mmap */
|
||
+ if(!file_mask || (file_mask && !strlen(file_mask))) {
|
||
+ shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||
+ } else {
|
||
+ int fd;
|
||
+
|
||
+ /*
|
||
+ * If the filemask contains .shm we try to do a POSIX-compliant shared memory
|
||
+ * backed mmap which should avoid synchs on some platforms. At least on
|
||
+ * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
|
||
+ * a file in a mounted shmfs. For this to work on Linux you need to make sure
|
||
+ * you actually have shmfs mounted. Also on Linux, make sure the file_mask you
|
||
+ * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX
|
||
+ * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
|
||
+ * path you want here.
|
||
+ */
|
||
+ if(strstr(file_mask,".shm")) {
|
||
+ mktemp(file_mask);
|
||
+ fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
|
||
+ if(fd == -1) {
|
||
+ apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
|
||
+ return (void *)-1;
|
||
+ }
|
||
+ if (ftruncate(fd, size) < 0) {
|
||
+ close(fd);
|
||
+ shm_unlink(file_mask);
|
||
+ apc_eprint("apc_mmap: ftruncate failed:");
|
||
+ return (void *)-1;
|
||
+ }
|
||
+ shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||
+ shm_unlink(file_mask);
|
||
+ close(fd);
|
||
+ }
|
||
+ /*
|
||
+ * Support anonymous mmap through the /dev/zero interface as well
|
||
+ */
|
||
+ else if(!strcmp(file_mask,"/dev/zero")) {
|
||
+ fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
|
||
+ if(fd == -1) {
|
||
+ apc_eprint("apc_mmap: open on /dev/zero failed:");
|
||
+ return (void *)-1;
|
||
+ }
|
||
+ shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||
+ close(fd);
|
||
+ }
|
||
+ /*
|
||
+ * Otherwise we do a normal filesystem mmap
|
||
+ */
|
||
+ else {
|
||
+ fd = mkstemp(file_mask);
|
||
+ if(fd == -1) {
|
||
+ apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
|
||
+ return (void *)-1;
|
||
+ }
|
||
+ if (ftruncate(fd, size) < 0) {
|
||
+ close(fd);
|
||
+ unlink(file_mask);
|
||
+ apc_eprint("apc_mmap: ftruncate failed:");
|
||
+ }
|
||
+ shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
|
||
+ close(fd);
|
||
+ unlink(file_mask);
|
||
+ }
|
||
+ }
|
||
+ if((int)shmaddr == -1) {
|
||
+ apc_eprint("apc_mmap: mmap failed:");
|
||
+ }
|
||
+ return shmaddr;
|
||
+}
|
||
+
|
||
+void apc_unmap(void* shmaddr, size_t size)
|
||
+{
|
||
+ if (munmap(shmaddr, size) < 0) {
|
||
+ apc_wprint("apc_unmap: munmap failed:");
|
||
+ }
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc.php php-5.2.5/ext/apc/apc.php
|
||
--- php-5.2.5-orig/ext/apc/apc.php 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc.php 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,1326 @@
|
||
+<?php
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Ralf Becker <beckerr@php.net> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Ilia Alshanetsky <ilia@prohost.org> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+$VERSION='$Id: apc.php,v 3.68 2007/07/22 00:25:48 gopalv Exp $';
|
||
+
|
||
+////////// READ OPTIONAL CONFIGURATION FILE ////////////
|
||
+if (file_exists("apc.conf.php")) include("apc.conf.php");
|
||
+////////////////////////////////////////////////////////
|
||
+
|
||
+////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
|
||
+
|
||
+defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if
|
||
+ // no other authentication is available
|
||
+ // If set to 0:
|
||
+ // There will be no further authentication. You
|
||
+ // will have to handle this by yourself!
|
||
+ // If set to 1:
|
||
+ // You need to change ADMIN_PASSWORD to make
|
||
+ // this work!
|
||
+defaults('ADMIN_USERNAME','apc'); // Admin Username
|
||
+defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!!
|
||
+
|
||
+// (beckerr) I'm using a clear text password here, because I've no good idea how to let
|
||
+// users generate a md5 or crypt password in a easy way to fill it in above
|
||
+
|
||
+//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German
|
||
+defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
|
||
+
|
||
+defaults('GRAPH_SIZE',200); // Image size
|
||
+
|
||
+////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
|
||
+
|
||
+
|
||
+// "define if not defined"
|
||
+function defaults($d,$v) {
|
||
+ if (!defined($d)) define($d,$v); // or just @define(...)
|
||
+}
|
||
+
|
||
+// rewrite $PHP_SELF to block XSS attacks
|
||
+//
|
||
+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES) : '';
|
||
+$time = time();
|
||
+$host = getenv('HOSTNAME');
|
||
+if($host) { $host = '('.$host.')'; }
|
||
+
|
||
+// operation constants
|
||
+define('OB_HOST_STATS',1);
|
||
+define('OB_SYS_CACHE',2);
|
||
+define('OB_USER_CACHE',3);
|
||
+define('OB_SYS_CACHE_DIR',4);
|
||
+define('OB_VERSION_CHECK',9);
|
||
+
|
||
+// check validity of input variables
|
||
+$vardom=array(
|
||
+ 'OB' => '/^\d+$/', // operational mode switch
|
||
+ 'CC' => '/^[01]$/', // clear cache requested
|
||
+ 'DU' => '/^.*$/', // Delete User Key
|
||
+ 'SH' => '/^[a-z0-9]+$/', // shared object description
|
||
+
|
||
+ 'IMG' => '/^[123]$/', // image to generate
|
||
+ 'LO' => '/^1$/', // login requested
|
||
+
|
||
+ 'COUNT' => '/^\d+$/', // number of line displayed in list
|
||
+ 'SCOPE' => '/^[AD]$/', // list view scope
|
||
+ 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key
|
||
+ 'SORT2' => '/^[DA]$/', // second sort key
|
||
+ 'AGGR' => '/^\d+$/', // aggregation by dir level
|
||
+ 'SEARCH' => '~^[a-zA-Z0-1/_.-]*$~' // aggregation by dir level
|
||
+);
|
||
+
|
||
+// default cache mode
|
||
+$cache_mode='opcode';
|
||
+
|
||
+// cache scope
|
||
+$scope_list=array(
|
||
+ 'A' => 'cache_list',
|
||
+ 'D' => 'deleted_list'
|
||
+);
|
||
+
|
||
+// handle POST and GET requests
|
||
+if (empty($_REQUEST)) {
|
||
+ if (!empty($_GET) && !empty($_POST)) {
|
||
+ $_REQUEST = array_merge($_GET, $_POST);
|
||
+ } else if (!empty($_GET)) {
|
||
+ $_REQUEST = $_GET;
|
||
+ } else if (!empty($_POST)) {
|
||
+ $_REQUEST = $_POST;
|
||
+ } else {
|
||
+ $_REQUEST = array();
|
||
+ }
|
||
+}
|
||
+
|
||
+// check parameter syntax
|
||
+foreach($vardom as $var => $dom) {
|
||
+ if (!isset($_REQUEST[$var])) {
|
||
+ $MYREQUEST[$var]=NULL;
|
||
+ } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
|
||
+ $MYREQUEST[$var]=$_REQUEST[$var];
|
||
+ } else {
|
||
+ $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+// check parameter sematics
|
||
+if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
|
||
+if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
|
||
+if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
|
||
+if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS;
|
||
+if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
|
||
+if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
|
||
+
|
||
+$MY_SELF=
|
||
+ "$PHP_SELF".
|
||
+ "?SCOPE=".$MYREQUEST['SCOPE'].
|
||
+ "&SORT1=".$MYREQUEST['SORT1'].
|
||
+ "&SORT2=".$MYREQUEST['SORT2'].
|
||
+ "&COUNT=".$MYREQUEST['COUNT'];
|
||
+$MY_SELF_WO_SORT=
|
||
+ "$PHP_SELF".
|
||
+ "?SCOPE=".$MYREQUEST['SCOPE'].
|
||
+ "&COUNT=".$MYREQUEST['COUNT'];
|
||
+
|
||
+// authentication needed?
|
||
+//
|
||
+if (!USE_AUTHENTICATION) {
|
||
+ $AUTHENTICATED=1;
|
||
+} else {
|
||
+ $AUTHENTICATED=0;
|
||
+ if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
|
||
+
|
||
+ if (!isset($_SERVER['PHP_AUTH_USER']) ||
|
||
+ !isset($_SERVER['PHP_AUTH_PW']) ||
|
||
+ $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
|
||
+ $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
|
||
+ Header("WWW-Authenticate: Basic realm=\"APC Login\"");
|
||
+ Header("HTTP/1.0 401 Unauthorized");
|
||
+
|
||
+ echo <<<EOB
|
||
+ <html><body>
|
||
+ <h1>Rejected!</h1>
|
||
+ <big>Wrong Username or Password!</big><br/> <br/>
|
||
+ <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
|
||
+ </body></html>
|
||
+EOB;
|
||
+ exit;
|
||
+
|
||
+ } else {
|
||
+ $AUTHENTICATED=1;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+// select cache mode
|
||
+if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
|
||
+ $cache_mode='user';
|
||
+}
|
||
+// clear cache
|
||
+if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
|
||
+ apc_clear_cache($cache_mode);
|
||
+}
|
||
+
|
||
+if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
|
||
+ apc_delete($MYREQUEST['DU']);
|
||
+}
|
||
+
|
||
+if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
|
||
+ echo "No cache info available. APC does not appear to be running.";
|
||
+ exit;
|
||
+}
|
||
+
|
||
+$cache_user = apc_cache_info('user', 1);
|
||
+$mem=apc_sma_info();
|
||
+if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear
|
||
+
|
||
+// don't cache this page
|
||
+//
|
||
+header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
|
||
+header("Cache-Control: post-check=0, pre-check=0", false);
|
||
+header("Pragma: no-cache"); // HTTP/1.0
|
||
+
|
||
+function duration($ts) {
|
||
+ global $time;
|
||
+ $years = (int)((($time - $ts)/(7*86400))/52.177457);
|
||
+ $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
|
||
+ $weeks = (int)(($rem)/(7*86400));
|
||
+ $days = (int)(($rem)/86400) - $weeks*7;
|
||
+ $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
|
||
+ $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
|
||
+ $str = '';
|
||
+ if($years==1) $str .= "$years year, ";
|
||
+ if($years>1) $str .= "$years years, ";
|
||
+ if($weeks==1) $str .= "$weeks week, ";
|
||
+ if($weeks>1) $str .= "$weeks weeks, ";
|
||
+ if($days==1) $str .= "$days day,";
|
||
+ if($days>1) $str .= "$days days,";
|
||
+ if($hours == 1) $str .= " $hours hour and";
|
||
+ if($hours>1) $str .= " $hours hours and";
|
||
+ if($mins == 1) $str .= " 1 minute";
|
||
+ else $str .= " $mins minutes";
|
||
+ return $str;
|
||
+}
|
||
+
|
||
+// create graphics
|
||
+//
|
||
+function graphics_avail() {
|
||
+ return extension_loaded('gd');
|
||
+}
|
||
+if (isset($MYREQUEST['IMG']))
|
||
+{
|
||
+ if (!graphics_avail()) {
|
||
+ exit(0);
|
||
+ }
|
||
+
|
||
+ function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
|
||
+ $r=$diameter/2;
|
||
+ $w=deg2rad((360+$start+($end-$start)/2)%360);
|
||
+
|
||
+
|
||
+ if (function_exists("imagefilledarc")) {
|
||
+ // exists only if GD 2.0.1 is avaliable
|
||
+ imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
|
||
+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
|
||
+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
|
||
+ } else {
|
||
+ imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
|
||
+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
|
||
+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
|
||
+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
|
||
+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
|
||
+ imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
|
||
+ }
|
||
+ if ($text) {
|
||
+ if ($placeindex>0) {
|
||
+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
|
||
+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
|
||
+
|
||
+ } else {
|
||
+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
|
||
+ $r=$diameter/2;
|
||
+ $w=deg2rad((360+$start+($end-$start)/2)%360);
|
||
+
|
||
+ if ($placeindex>0) {
|
||
+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
|
||
+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
|
||
+
|
||
+ } else {
|
||
+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
|
||
+ global $col_black;
|
||
+ $x1=$x+$w-1;
|
||
+ $y1=$y+$h-1;
|
||
+
|
||
+ imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
|
||
+ if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
|
||
+ else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
|
||
+ imagerectangle($im, $x, $y1, $x1, $y, $color1);
|
||
+ if ($text) {
|
||
+ if ($placeindex>0) {
|
||
+
|
||
+ if ($placeindex<16)
|
||
+ {
|
||
+ $px=5;
|
||
+ $py=$placeindex*12+6;
|
||
+ imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
|
||
+ imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
|
||
+ imagestring($im,2,$px,$py-6,$text,$color1);
|
||
+
|
||
+ } else {
|
||
+ if ($placeindex<31) {
|
||
+ $px=$x+40*2;
|
||
+ $py=($placeindex-15)*12+6;
|
||
+ } else {
|
||
+ $px=$x+40*2+100*intval(($placeindex-15)/15);
|
||
+ $py=($placeindex%15)*12+6;
|
||
+ }
|
||
+ imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
|
||
+ imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
|
||
+ imagestring($im,2,$px+2,$py-6,$text,$color1);
|
||
+ }
|
||
+ } else {
|
||
+ imagestring($im,4,$x+5,$y1-16,$text,$color1);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+
|
||
+ $size = GRAPH_SIZE; // image size
|
||
+ if ($MYREQUEST['IMG']==3)
|
||
+ $image = imagecreate(2*$size+150, $size+10);
|
||
+ else
|
||
+ $image = imagecreate($size+50, $size+10);
|
||
+
|
||
+ $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
|
||
+ $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
|
||
+ $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
|
||
+ $col_black = imagecolorallocate($image, 0, 0, 0);
|
||
+ imagecolortransparent($image,$col_white);
|
||
+
|
||
+ switch ($MYREQUEST['IMG']) {
|
||
+
|
||
+ case 1:
|
||
+ $s=$mem['num_seg']*$mem['seg_size'];
|
||
+ $a=$mem['avail_mem'];
|
||
+ $x=$y=$size/2;
|
||
+ $fuzz = 0.000001;
|
||
+
|
||
+ // This block of code creates the pie chart. It is a lot more complex than you
|
||
+ // would expect because we try to visualize any memory fragmentation as well.
|
||
+ $angle_from = 0;
|
||
+ $string_placement=array();
|
||
+ for($i=0; $i<$mem['num_seg']; $i++) {
|
||
+ $ptr = 0;
|
||
+ $free = $mem['block_lists'][$i];
|
||
+ foreach($free as $block) {
|
||
+ if($block['offset']!=$ptr) { // Used block
|
||
+ $angle_to = $angle_from+($block['offset']-$ptr)/$s;
|
||
+ if(($angle_to+$fuzz)>1) $angle_to = 1;
|
||
+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
|
||
+ if (($angle_to-$angle_from)>0.05) {
|
||
+ array_push($string_placement, array($angle_from,$angle_to));
|
||
+ }
|
||
+ $angle_from = $angle_to;
|
||
+ }
|
||
+ $angle_to = $angle_from+($block['size'])/$s;
|
||
+ if(($angle_to+$fuzz)>1) $angle_to = 1;
|
||
+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
|
||
+ if (($angle_to-$angle_from)>0.05) {
|
||
+ array_push($string_placement, array($angle_from,$angle_to));
|
||
+ }
|
||
+ $angle_from = $angle_to;
|
||
+ $ptr = $block['offset']+$block['size'];
|
||
+ }
|
||
+ if ($ptr < $mem['seg_size']) { // memory at the end
|
||
+ $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
|
||
+ if(($angle_to+$fuzz)>1) $angle_to = 1;
|
||
+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
|
||
+ if (($angle_to-$angle_from)>0.05) {
|
||
+ array_push($string_placement, array($angle_from,$angle_to));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ foreach ($string_placement as $angle) {
|
||
+ text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case 2:
|
||
+ $s=$cache['num_hits']+$cache['num_misses'];
|
||
+ $a=$cache['num_hits'];
|
||
+
|
||
+ fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
|
||
+ fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
|
||
+ break;
|
||
+
|
||
+ case 3:
|
||
+ $s=$mem['num_seg']*$mem['seg_size'];
|
||
+ $a=$mem['avail_mem'];
|
||
+ $x=130;
|
||
+ $y=1;
|
||
+ $j=1;
|
||
+
|
||
+ // This block of code creates the bar chart. It is a lot more complex than you
|
||
+ // would expect because we try to visualize any memory fragmentation as well.
|
||
+ for($i=0; $i<$mem['num_seg']; $i++) {
|
||
+ $ptr = 0;
|
||
+ $free = $mem['block_lists'][$i];
|
||
+ foreach($free as $block) {
|
||
+ if($block['offset']!=$ptr) { // Used block
|
||
+ $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
|
||
+ if ($h>0) {
|
||
+ $j++;
|
||
+ if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
|
||
+ else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
|
||
+ }
|
||
+ $y+=$h;
|
||
+ }
|
||
+ $h=(GRAPH_SIZE-5)*($block['size'])/$s;
|
||
+ if ($h>0) {
|
||
+ $j++;
|
||
+ if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
|
||
+ else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
|
||
+ }
|
||
+ $y+=$h;
|
||
+ $ptr = $block['offset']+$block['size'];
|
||
+ }
|
||
+ if ($ptr < $mem['seg_size']) { // memory at the end
|
||
+ $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
|
||
+ if ($h > 0) {
|
||
+ fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ case 4:
|
||
+ $s=$cache['num_hits']+$cache['num_misses'];
|
||
+ $a=$cache['num_hits'];
|
||
+
|
||
+ fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
|
||
+ fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
|
||
+ break;
|
||
+
|
||
+ }
|
||
+ header("Content-type: image/png");
|
||
+ imagepng($image);
|
||
+ exit;
|
||
+}
|
||
+
|
||
+// pretty printer for byte values
|
||
+//
|
||
+function bsize($s) {
|
||
+ foreach (array('','K','M','G') as $i => $k) {
|
||
+ if ($s < 1024) break;
|
||
+ $s/=1024;
|
||
+ }
|
||
+ return sprintf("%5.1f %sBytes",$s,$k);
|
||
+}
|
||
+
|
||
+// sortable table header in "scripts for this host" view
|
||
+function sortheader($key,$name,$extra='') {
|
||
+ global $MYREQUEST, $MY_SELF_WO_SORT;
|
||
+
|
||
+ if ($MYREQUEST['SORT1']==$key) {
|
||
+ $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
|
||
+ }
|
||
+ return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
|
||
+
|
||
+}
|
||
+
|
||
+// create menu entry
|
||
+function menu_entry($ob,$title) {
|
||
+ global $MYREQUEST,$MY_SELF;
|
||
+ if ($MYREQUEST['OB']!=$ob) {
|
||
+ return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
|
||
+ } else if (empty($MYREQUEST['SH'])) {
|
||
+ return "<li><span class=active>$title</span></li>";
|
||
+ } else {
|
||
+ return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";
|
||
+ }
|
||
+}
|
||
+
|
||
+function put_login_link($s="Login")
|
||
+{
|
||
+ global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
|
||
+ // needs ADMIN_PASSWORD to be changed!
|
||
+ //
|
||
+ if (!USE_AUTHENTICATION) {
|
||
+ return;
|
||
+ } else if (ADMIN_PASSWORD=='password')
|
||
+ {
|
||
+ print <<<EOB
|
||
+ <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>
|
||
+EOB;
|
||
+ } else if ($AUTHENTICATED) {
|
||
+ print <<<EOB
|
||
+ '{$_SERVER['PHP_AUTH_USER']}' logged in!
|
||
+EOB;
|
||
+ } else{
|
||
+ print <<<EOB
|
||
+ <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
|
||
+EOB;
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+?>
|
||
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||
+<html>
|
||
+<head><title>APC INFO <?php echo $host ?></title>
|
||
+<style><!--
|
||
+body { background:white; font-size:100.01%; margin:0; padding:0; }
|
||
+body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
|
||
+* html body {font-size:0.8em}
|
||
+* html p {font-size:0.8em}
|
||
+* html td {font-size:0.8em}
|
||
+* html th {font-size:0.8em}
|
||
+* html input {font-size:0.8em}
|
||
+* html submit {font-size:0.8em}
|
||
+td { vertical-align:top }
|
||
+a { color:black; font-weight:none; text-decoration:none; }
|
||
+a:hover { text-decoration:underline; }
|
||
+div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
|
||
+
|
||
+
|
||
+div.head div.login {
|
||
+ position:absolute;
|
||
+ right: 1em;
|
||
+ top: 1.2em;
|
||
+ color:white;
|
||
+ width:6em;
|
||
+ }
|
||
+div.head div.login a {
|
||
+ position:absolute;
|
||
+ right: 0em;
|
||
+ background:rgb(119,123,180);
|
||
+ border:solid rgb(102,102,153) 2px;
|
||
+ color:white;
|
||
+ font-weight:bold;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ text-decoration:none;
|
||
+ }
|
||
+div.head div.login a:hover {
|
||
+ background:rgb(193,193,244);
|
||
+ }
|
||
+
|
||
+h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
|
||
+* html h1.apc { margin-bottom:-7px; }
|
||
+h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
|
||
+h1.apc div.logo span.logo {
|
||
+ background:rgb(119,123,180);
|
||
+ color:black;
|
||
+ border-right: solid black 1px;
|
||
+ border-bottom: solid black 1px;
|
||
+ font-style:italic;
|
||
+ font-size:1em;
|
||
+ padding-left:1.2em;
|
||
+ padding-right:1.2em;
|
||
+ text-align:right;
|
||
+ }
|
||
+h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
|
||
+h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
|
||
+h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
|
||
+hr.apc {
|
||
+ background:white;
|
||
+ border-bottom:solid rgb(102,102,153) 1px;
|
||
+ border-style:none;
|
||
+ border-top:solid rgb(102,102,153) 10px;
|
||
+ height:12px;
|
||
+ margin:0;
|
||
+ margin-top:1px;
|
||
+ padding:0;
|
||
+}
|
||
+
|
||
+ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
|
||
+ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
|
||
+ol.menu a {
|
||
+ background:rgb(153,153,204);
|
||
+ border:solid rgb(102,102,153) 2px;
|
||
+ color:white;
|
||
+ font-weight:bold;
|
||
+ margin-right:0em;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ text-decoration:none;
|
||
+ margin-left: 5px;
|
||
+ }
|
||
+ol.menu a.child_active {
|
||
+ background:rgb(153,153,204);
|
||
+ border:solid rgb(102,102,153) 2px;
|
||
+ color:white;
|
||
+ font-weight:bold;
|
||
+ margin-right:0em;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ text-decoration:none;
|
||
+ border-left: solid black 5px;
|
||
+ margin-left: 0px;
|
||
+ }
|
||
+ol.menu span.active {
|
||
+ background:rgb(153,153,204);
|
||
+ border:solid rgb(102,102,153) 2px;
|
||
+ color:black;
|
||
+ font-weight:bold;
|
||
+ margin-right:0em;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ text-decoration:none;
|
||
+ border-left: solid black 5px;
|
||
+ }
|
||
+ol.menu span.inactive {
|
||
+ background:rgb(193,193,244);
|
||
+ border:solid rgb(182,182,233) 2px;
|
||
+ color:white;
|
||
+ font-weight:bold;
|
||
+ margin-right:0em;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ text-decoration:none;
|
||
+ margin-left: 5px;
|
||
+ }
|
||
+ol.menu a:hover {
|
||
+ background:rgb(193,193,244);
|
||
+ text-decoration:none;
|
||
+ }
|
||
+
|
||
+
|
||
+div.info {
|
||
+ background:rgb(204,204,204);
|
||
+ border:solid rgb(204,204,204) 1px;
|
||
+ margin-bottom:1em;
|
||
+ }
|
||
+div.info h2 {
|
||
+ background:rgb(204,204,204);
|
||
+ color:black;
|
||
+ font-size:1em;
|
||
+ margin:0;
|
||
+ padding:0.1em 1em 0.1em 1em;
|
||
+ }
|
||
+div.info table {
|
||
+ border:solid rgb(204,204,204) 1px;
|
||
+ border-spacing:0;
|
||
+ width:100%;
|
||
+ }
|
||
+div.info table th {
|
||
+ background:rgb(204,204,204);
|
||
+ color:white;
|
||
+ margin:0;
|
||
+ padding:0.1em 1em 0.1em 1em;
|
||
+ }
|
||
+div.info table th a.sortable { color:black; }
|
||
+div.info table tr.tr-0 { background:rgb(238,238,238); }
|
||
+div.info table tr.tr-1 { background:rgb(221,221,221); }
|
||
+div.info table td { padding:0.3em 1em 0.3em 1em; }
|
||
+div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
|
||
+div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
|
||
+div.info table td h3 {
|
||
+ color:black;
|
||
+ font-size:1.1em;
|
||
+ margin-left:-0.3em;
|
||
+ }
|
||
+
|
||
+div.graph { margin-bottom:1em }
|
||
+div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
|
||
+div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
|
||
+div.graph table td.td-0 { background:rgb(238,238,238); }
|
||
+div.graph table td.td-1 { background:rgb(221,221,221); }
|
||
+div.graph table td { padding:0.2em 1em 0.4em 1em; }
|
||
+
|
||
+div.div1,div.div2 { margin-bottom:1em; width:35em; }
|
||
+div.div3 { position:absolute; left:40em; top:1em; width:580px; }
|
||
+//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
|
||
+
|
||
+div.sorting { margin:1.5em 0em 1.5em 2em }
|
||
+.center { text-align:center }
|
||
+.aright { position:absolute;right:1em }
|
||
+.right { text-align:right }
|
||
+.ok { color:rgb(0,200,0); font-weight:bold}
|
||
+.failed { color:rgb(200,0,0); font-weight:bold}
|
||
+
|
||
+span.box {
|
||
+ border: black solid 1px;
|
||
+ border-right:solid black 2px;
|
||
+ border-bottom:solid black 2px;
|
||
+ padding:0 0.5em 0 0.5em;
|
||
+ margin-right:1em;
|
||
+}
|
||
+span.green { background:#60F060; padding:0 0.5em 0 0.5em}
|
||
+span.red { background:#D06030; padding:0 0.5em 0 0.5em }
|
||
+
|
||
+div.authneeded {
|
||
+ background:rgb(238,238,238);
|
||
+ border:solid rgb(204,204,204) 1px;
|
||
+ color:rgb(200,0,0);
|
||
+ font-size:1.2em;
|
||
+ font-weight:bold;
|
||
+ padding:2em;
|
||
+ text-align:center;
|
||
+ }
|
||
+
|
||
+input {
|
||
+ background:rgb(153,153,204);
|
||
+ border:solid rgb(102,102,153) 2px;
|
||
+ color:white;
|
||
+ font-weight:bold;
|
||
+ margin-right:1em;
|
||
+ padding:0.1em 0.5em 0.1em 0.5em;
|
||
+ }
|
||
+//-->
|
||
+</style>
|
||
+</head>
|
||
+<body>
|
||
+<div class="head">
|
||
+ <h1 class="apc">
|
||
+ <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
|
||
+ <div class="nameinfo">Opcode Cache</div>
|
||
+ </h1>
|
||
+ <div class="login">
|
||
+ <?php put_login_link(); ?>
|
||
+ </div>
|
||
+ <hr class="apc">
|
||
+</div>
|
||
+<?php
|
||
+
|
||
+
|
||
+// Display main Menu
|
||
+echo <<<EOB
|
||
+ <ol class=menu>
|
||
+ <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
|
||
+EOB;
|
||
+echo
|
||
+ menu_entry(1,'View Host Stats'),
|
||
+ menu_entry(2,'System Cache Entries');
|
||
+if ($AUTHENTICATED) {
|
||
+ echo menu_entry(4,'Per-Directory Entries');
|
||
+}
|
||
+echo
|
||
+ menu_entry(3,'User Cache Entries'),
|
||
+ menu_entry(9,'Version Check');
|
||
+
|
||
+if ($AUTHENTICATED) {
|
||
+ echo <<<EOB
|
||
+ <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>
|
||
+EOB;
|
||
+}
|
||
+echo <<<EOB
|
||
+ </ol>
|
||
+EOB;
|
||
+
|
||
+
|
||
+// CONTENT
|
||
+echo <<<EOB
|
||
+ <div class=content>
|
||
+EOB;
|
||
+
|
||
+// MAIN SWITCH STATEMENT
|
||
+
|
||
+switch ($MYREQUEST['OB']) {
|
||
+
|
||
+
|
||
+
|
||
+
|
||
+
|
||
+// -----------------------------------------------
|
||
+// Host Stats
|
||
+// -----------------------------------------------
|
||
+case OB_HOST_STATS:
|
||
+ $mem_size = $mem['num_seg']*$mem['seg_size'];
|
||
+ $mem_avail= $mem['avail_mem'];
|
||
+ $mem_used = $mem_size-$mem_avail;
|
||
+ $seg_size = bsize($mem['seg_size']);
|
||
+ $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
|
||
+ $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
|
||
+ $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
|
||
+ $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
|
||
+ $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
|
||
+ $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
|
||
+ $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
|
||
+ $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
|
||
+ $apcversion = phpversion('apc');
|
||
+ $phpversion = phpversion();
|
||
+ $number_files = $cache['num_entries'];
|
||
+ $size_files = bsize($cache['mem_size']);
|
||
+ $number_vars = $cache_user['num_entries'];
|
||
+ $size_vars = bsize($cache_user['mem_size']);
|
||
+ $i=0;
|
||
+ echo <<< EOB
|
||
+ <div class="info div1"><h2>General Cache Information</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+ <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
|
||
+EOB;
|
||
+
|
||
+ if(!empty($_SERVER['SERVER_NAME']))
|
||
+ echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
|
||
+ if(!empty($_SERVER['SERVER_SOFTWARE']))
|
||
+ echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
|
||
+
|
||
+ echo <<<EOB
|
||
+ <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
|
||
+ <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
|
||
+ </td></tr>
|
||
+EOB;
|
||
+ echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
|
||
+ echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
|
||
+ echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
|
||
+ echo <<<EOB
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+
|
||
+ <div class="info div1"><h2>File Cache Information</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+ <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+
|
||
+ <div class="info div1"><h2>User Cache Information</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+ <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
|
||
+ <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
|
||
+ <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
|
||
+
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+
|
||
+ <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
|
||
+EOB;
|
||
+
|
||
+ $j = 0;
|
||
+ foreach (ini_get_all('apc') as $k => $v) {
|
||
+ echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
|
||
+ $j = 1 - $j;
|
||
+ }
|
||
+
|
||
+ if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
|
||
+ $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
|
||
+ else
|
||
+ $mem_note = "Memory Usage";
|
||
+
|
||
+ echo <<< EOB
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+
|
||
+ <div class="graph div3"><h2>Host Status Diagrams</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+EOB;
|
||
+ $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
|
||
+ echo <<<EOB
|
||
+ <tr>
|
||
+ <td class=td-0>$mem_note</td>
|
||
+ <td class=td-1>Hits & Misses</td>
|
||
+ </tr>
|
||
+EOB;
|
||
+
|
||
+ echo
|
||
+ graphics_avail() ?
|
||
+ '<tr>'.
|
||
+ "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
|
||
+ "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
|
||
+ : "",
|
||
+ '<tr>',
|
||
+ '<td class=td-0><span class="green box"> </span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
|
||
+ '<td class=td-1><span class="green box"> </span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
|
||
+ '</tr>',
|
||
+ '<tr>',
|
||
+ '<td class=td-0><span class="red box"> </span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
|
||
+ '<td class=td-1><span class="red box"> </span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
|
||
+ echo <<< EOB
|
||
+ </tr>
|
||
+ </tbody></table>
|
||
+
|
||
+ <br/>
|
||
+ <h2>Detailed Memory Usage and Fragmentation</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+ <tr>
|
||
+ <td class=td-0 colspan=2><br/>
|
||
+EOB;
|
||
+
|
||
+ // Fragementation: (freeseg - 1) / total_seg
|
||
+ $nseg = $freeseg = $fragsize = $freetotal = 0;
|
||
+ for($i=0; $i<$mem['num_seg']; $i++) {
|
||
+ $ptr = 0;
|
||
+ foreach($mem['block_lists'][$i] as $block) {
|
||
+ if ($block['offset'] != $ptr) {
|
||
+ ++$nseg;
|
||
+ }
|
||
+ $ptr = $block['offset'] + $block['size'];
|
||
+ /* Only consider blocks <5M for the fragmentation % */
|
||
+ if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
|
||
+ $freetotal+=$block['size'];
|
||
+ }
|
||
+ $freeseg += count($mem['block_lists'][$i]);
|
||
+ }
|
||
+
|
||
+ if ($freeseg > 1) {
|
||
+ $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
|
||
+ } else {
|
||
+ $frag = "0%";
|
||
+ }
|
||
+
|
||
+ if (graphics_avail()) {
|
||
+ $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
|
||
+ echo <<<EOB
|
||
+ <img alt="" $size src="$PHP_SELF?IMG=3&$time">
|
||
+EOB;
|
||
+ }
|
||
+ echo <<<EOB
|
||
+ </br>Fragmentation: $frag
|
||
+ </td>
|
||
+ </tr>
|
||
+EOB;
|
||
+ if(isset($mem['adist'])) {
|
||
+ foreach($mem['adist'] as $i=>$v) {
|
||
+ $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
|
||
+ if($i==0) $range = "1";
|
||
+ else $range = "$cur - $nxt";
|
||
+ echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
|
||
+ }
|
||
+ }
|
||
+ echo <<<EOB
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+EOB;
|
||
+
|
||
+ break;
|
||
+
|
||
+
|
||
+// -----------------------------------------------
|
||
+// User Cache Entries
|
||
+// -----------------------------------------------
|
||
+case OB_USER_CACHE:
|
||
+ if (!$AUTHENTICATED) {
|
||
+ echo '<div class="authneeded">You need to login to see the user values here!<br/> <br/>';
|
||
+ put_login_link("Login now!");
|
||
+ echo '</div>';
|
||
+ break;
|
||
+ }
|
||
+ $fieldname='info';
|
||
+ $fieldheading='User Entry Label';
|
||
+ $fieldkey='info';
|
||
+
|
||
+// -----------------------------------------------
|
||
+// System Cache Entries
|
||
+// -----------------------------------------------
|
||
+case OB_SYS_CACHE:
|
||
+ if (!isset($fieldname))
|
||
+ {
|
||
+ $fieldname='filename';
|
||
+ $fieldheading='Script Filename';
|
||
+ if(ini_get("apc.stat")) $fieldkey='inode';
|
||
+ else $fieldkey='filename';
|
||
+ }
|
||
+ if (!empty($MYREQUEST['SH']))
|
||
+ {
|
||
+ echo <<< EOB
|
||
+ <div class="info"><table cellspacing=0><tbody>
|
||
+ <tr><th>Attribute</th><th>Value</th></tr>
|
||
+EOB;
|
||
+
|
||
+ $m=0;
|
||
+ foreach($scope_list as $j => $list) {
|
||
+ foreach($cache[$list] as $i => $entry) {
|
||
+ if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
|
||
+ foreach($entry as $k => $value) {
|
||
+ if (!$AUTHENTICATED) {
|
||
+ // hide all path entries if not logged in
|
||
+ $value=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$value);
|
||
+ }
|
||
+
|
||
+ if ($k == "num_hits") {
|
||
+ $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
|
||
+ }
|
||
+ if ($k == 'deletion_time') {
|
||
+ if(!$entry['deletion_time']) $value = "None";
|
||
+ }
|
||
+ echo
|
||
+ "<tr class=tr-$m>",
|
||
+ "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
|
||
+ "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
|
||
+ "</tr>";
|
||
+ $m=1-$m;
|
||
+ }
|
||
+ if($fieldkey=='info') {
|
||
+ echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
|
||
+ $output = var_export(apc_fetch($entry[$fieldkey]),true);
|
||
+ echo htmlspecialchars($output);
|
||
+ echo "</pre></td></tr>\n";
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ echo <<<EOB
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+EOB;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ $cols=6;
|
||
+ echo <<<EOB
|
||
+ <div class=sorting><form>Scope:
|
||
+ <input type=hidden name=OB value={$MYREQUEST['OB']}>
|
||
+ <select name=SCOPE>
|
||
+EOB;
|
||
+ echo
|
||
+ "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
|
||
+ "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
|
||
+ "</select>",
|
||
+ ", Sorting:<select name=SORT1>",
|
||
+ "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
|
||
+ "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
|
||
+ "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
|
||
+ "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
|
||
+ "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
|
||
+ "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
|
||
+ "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
|
||
+ if($fieldname=='info') echo
|
||
+ "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
|
||
+ echo
|
||
+ '</select>',
|
||
+ '<select name=SORT2>',
|
||
+ '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
|
||
+ '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
|
||
+ '</select>',
|
||
+ '<select name=COUNT onChange="form.submit()">',
|
||
+ '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
|
||
+ '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
|
||
+ '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
|
||
+ '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
|
||
+ '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
|
||
+ '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
|
||
+ '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
|
||
+ '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
|
||
+ '</select>',
|
||
+ ' Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
|
||
+ ' <input type=submit value="GO!">',
|
||
+ '</form></div>',
|
||
+
|
||
+ '<div class="info"><table cellspacing=0><tbody>',
|
||
+ '<tr>',
|
||
+ '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>';
|
||
+
|
||
+ if($fieldname=='info') {
|
||
+ $cols+=2;
|
||
+ echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
|
||
+ }
|
||
+ echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
|
||
+
|
||
+ // builds list with alpha numeric sortable keys
|
||
+ //
|
||
+ $list = array();
|
||
+ foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
|
||
+ switch($MYREQUEST['SORT1']) {
|
||
+ case 'A': $k=sprintf('%015d-',$entry['access_time']); break;
|
||
+ case 'H': $k=sprintf('%015d-',$entry['num_hits']); break;
|
||
+ case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break;
|
||
+ case 'M': $k=sprintf('%015d-',$entry['mtime']); break;
|
||
+ case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
|
||
+ case 'T': $k=sprintf('%015d-',$entry['ttl']); break;
|
||
+ case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
|
||
+ case 'S': $k=''; break;
|
||
+ }
|
||
+ if (!$AUTHENTICATED) {
|
||
+ // hide all path entries if not logged in
|
||
+ $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$entry);
|
||
+ } else {
|
||
+ $list[$k.$entry[$fieldname]]=$entry;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if ($list) {
|
||
+
|
||
+ // sort list
|
||
+ //
|
||
+ switch ($MYREQUEST['SORT2']) {
|
||
+ case "A": krsort($list); break;
|
||
+ case "D": ksort($list); break;
|
||
+ }
|
||
+
|
||
+ // output list
|
||
+ $i=0;
|
||
+ foreach($list as $k => $entry) {
|
||
+ if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {
|
||
+ echo
|
||
+ '<tr class=tr-',$i%2,'>',
|
||
+ "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
|
||
+ '<td class="td-n center">',$entry['num_hits'],'</td>',
|
||
+ '<td class="td-n right">',$entry['mem_size'],'</td>',
|
||
+ '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
|
||
+ '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
|
||
+ '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
|
||
+
|
||
+ if($fieldname=='info') {
|
||
+ if($entry['ttl'])
|
||
+ echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
|
||
+ else
|
||
+ echo '<td class="td-n center">None</td>';
|
||
+ }
|
||
+ if ($entry['deletion_time']) {
|
||
+
|
||
+ echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
|
||
+ } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
|
||
+
|
||
+ echo '<td class="td-last center">';
|
||
+ echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
|
||
+ echo '</td>';
|
||
+ } else {
|
||
+ echo '<td class="td-last center"> </td>';
|
||
+ }
|
||
+ echo '</tr>';
|
||
+ $i++;
|
||
+ if ($i == $MYREQUEST['COUNT'])
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ } else {
|
||
+ echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
|
||
+ }
|
||
+ echo <<< EOB
|
||
+ </tbody></table>
|
||
+EOB;
|
||
+
|
||
+ if ($list && $i < count($list)) {
|
||
+ echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
|
||
+ }
|
||
+
|
||
+ echo <<< EOB
|
||
+ </div>
|
||
+EOB;
|
||
+ break;
|
||
+
|
||
+
|
||
+// -----------------------------------------------
|
||
+// Per-Directory System Cache Entries
|
||
+// -----------------------------------------------
|
||
+case OB_SYS_CACHE_DIR:
|
||
+ if (!$AUTHENTICATED) {
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ echo <<<EOB
|
||
+ <div class=sorting><form>Scope:
|
||
+ <input type=hidden name=OB value={$MYREQUEST['OB']}>
|
||
+ <select name=SCOPE>
|
||
+EOB;
|
||
+ echo
|
||
+ "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
|
||
+ "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
|
||
+ "</select>",
|
||
+ ", Sorting:<select name=SORT1>",
|
||
+ "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
|
||
+ "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
|
||
+ "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
|
||
+ "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
|
||
+ "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
|
||
+ "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
|
||
+ '</select>',
|
||
+ '<select name=SORT2>',
|
||
+ '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
|
||
+ '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
|
||
+ '</select>',
|
||
+ '<select name=COUNT onChange="form.submit()">',
|
||
+ '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
|
||
+ '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
|
||
+ '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
|
||
+ '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
|
||
+ '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
|
||
+ '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
|
||
+ '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
|
||
+ '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
|
||
+ '</select>',
|
||
+ ", Group By Dir Level:<select name=AGGR>",
|
||
+ "<option value='' selected>None</option>";
|
||
+ for ($i = 1; $i < 10; $i++)
|
||
+ echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
|
||
+ echo '</select>',
|
||
+ ' <input type=submit value="GO!">',
|
||
+ '</form></div>',
|
||
+
|
||
+ '<div class="info"><table cellspacing=0><tbody>',
|
||
+ '<tr>',
|
||
+ '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>',
|
||
+ '</tr>';
|
||
+
|
||
+ // builds list with alpha numeric sortable keys
|
||
+ //
|
||
+ $tmp = $list = array();
|
||
+ foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
|
||
+ $n = dirname($entry['filename']);
|
||
+ if ($MYREQUEST['AGGR'] > 0) {
|
||
+ $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
|
||
+ }
|
||
+ if (!isset($tmp[$n])) {
|
||
+ $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
|
||
+ }
|
||
+ $tmp[$n]['hits'] += $entry['num_hits'];
|
||
+ $tmp[$n]['size'] += $entry['mem_size'];
|
||
+ ++$tmp[$n]['ents'];
|
||
+ }
|
||
+
|
||
+ foreach ($tmp as $k => $v) {
|
||
+ switch($MYREQUEST['SORT1']) {
|
||
+ case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
|
||
+ case 'T': $kn=sprintf('%015d-',$v['ents']); break;
|
||
+ case 'H': $kn=sprintf('%015d-',$v['hits']); break;
|
||
+ case 'Z': $kn=sprintf('%015d-',$v['size']); break;
|
||
+ case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
|
||
+ case 'S': $kn = $k; break;
|
||
+ }
|
||
+ $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
|
||
+ }
|
||
+
|
||
+ if ($list) {
|
||
+
|
||
+ // sort list
|
||
+ //
|
||
+ switch ($MYREQUEST['SORT2']) {
|
||
+ case "A": krsort($list); break;
|
||
+ case "D": ksort($list); break;
|
||
+ }
|
||
+
|
||
+ // output list
|
||
+ $i = 0;
|
||
+ foreach($list as $entry) {
|
||
+ echo
|
||
+ '<tr class=tr-',$i%2,'>',
|
||
+ "<td class=td-0>",$entry[0],'</a></td>',
|
||
+ '<td class="td-n center">',$entry[1],'</td>',
|
||
+ '<td class="td-n center">',$entry[2],'</td>',
|
||
+ '<td class="td-n center">',$entry[3],'</td>',
|
||
+ '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
|
||
+ '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
|
||
+ '</tr>';
|
||
+
|
||
+ if (++$i == $MYREQUEST['COUNT']) break;
|
||
+ }
|
||
+
|
||
+ } else {
|
||
+ echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
|
||
+ }
|
||
+ echo <<< EOB
|
||
+ </tbody></table>
|
||
+EOB;
|
||
+
|
||
+ if ($list && $i < count($list)) {
|
||
+ echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
|
||
+ }
|
||
+
|
||
+ echo <<< EOB
|
||
+ </div>
|
||
+EOB;
|
||
+ break;
|
||
+
|
||
+// -----------------------------------------------
|
||
+// Version check
|
||
+// -----------------------------------------------
|
||
+case OB_VERSION_CHECK:
|
||
+ echo <<<EOB
|
||
+ <div class="info"><h2>APC Version Information</h2>
|
||
+ <table cellspacing=0><tbody>
|
||
+ <tr>
|
||
+ <th></th>
|
||
+ </tr>
|
||
+EOB;
|
||
+
|
||
+ $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
|
||
+ if (!$rss) {
|
||
+ echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
|
||
+ } else {
|
||
+ $apcversion = phpversion('apc');
|
||
+
|
||
+ preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
|
||
+ echo '<tr class="tr-0 center"><td>';
|
||
+ if (version_compare($apcversion, $match[1], '>=')) {
|
||
+ echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
|
||
+ $i = 3;
|
||
+ } else {
|
||
+ echo '<div class="failed">You are running an older version of APC ('.$apcversion.'),
|
||
+ newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
|
||
+ http://pecl.php.net/package/APC/'.$match[1].'</a>
|
||
+ </div>';
|
||
+ $i = -1;
|
||
+ }
|
||
+ echo '</td></tr>';
|
||
+ echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
|
||
+
|
||
+ preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
|
||
+ next($match[2]); next($match[2]);
|
||
+
|
||
+ while (list(,$v) = each($match[2])) {
|
||
+ list(,$ver) = explode(' ', $v, 2);
|
||
+ if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
|
||
+ break;
|
||
+ } else if (!$i--) {
|
||
+ break;
|
||
+ }
|
||
+ echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
|
||
+ echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
|
||
+ next($match[2]);
|
||
+ }
|
||
+ echo '</td></tr>';
|
||
+ }
|
||
+ echo <<< EOB
|
||
+ </tbody></table>
|
||
+ </div>
|
||
+EOB;
|
||
+ break;
|
||
+
|
||
+}
|
||
+
|
||
+echo <<< EOB
|
||
+ </div>
|
||
+EOB;
|
||
+
|
||
+?>
|
||
+
|
||
+<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
|
||
+</body>
|
||
+</html>
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_php.h php-5.2.5/ext/apc/apc_php.h
|
||
--- php-5.2.5-orig/ext/apc/apc_php.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_php.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,71 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
|
||
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
|
||
+
|
||
+#ifndef APC_PHP_H
|
||
+#define APC_PHP_H
|
||
+
|
||
+/*
|
||
+ * The purpose of this header file is to include all PHP and Zend headers that
|
||
+ * are typically needed elsewhere in APC. This makes it easy to insure that
|
||
+ * all required headers are available.
|
||
+ */
|
||
+
|
||
+#include "php.h"
|
||
+#include "zend.h"
|
||
+#include "zend_API.h"
|
||
+#include "zend_compile.h"
|
||
+#include "zend_hash.h"
|
||
+#include "zend_extensions.h"
|
||
+
|
||
+#if ZEND_MODULE_API_NO > 20050922
|
||
+#define ZEND_ENGINE_2_2
|
||
+#endif
|
||
+#if ZEND_MODULE_API_NO > 20050921
|
||
+#define ZEND_ENGINE_2_1
|
||
+#endif
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+#include "zend_vm.h"
|
||
+#endif
|
||
+
|
||
+#include "rfc1867.h"
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthreadmutex.c
|
||
--- php-5.2.5-orig/ext/apc/apc_pthreadmutex.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_pthreadmutex.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,111 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_pthreadmutex.c,v 3.3 2007/12/21 01:36:51 shire Exp $ */
|
||
+
|
||
+#include "apc_pthreadmutex.h"
|
||
+
|
||
+#ifdef APC_PTHREADMUTEX_LOCKS
|
||
+
|
||
+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock)
|
||
+{
|
||
+ int result;
|
||
+ pthread_mutexattr_t* attr;
|
||
+ attr = malloc(sizeof(pthread_mutexattr_t));
|
||
+
|
||
+ result = pthread_mutexattr_init(attr);
|
||
+ if(result == ENOMEM) {
|
||
+ apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
|
||
+ } else if(result == EINVAL) {
|
||
+ apc_eprint("pthread mutex error: attr does not point to writeable memory.");
|
||
+ } else if(result == EFAULT) {
|
||
+ apc_eprint("pthread mutex error: attr is an invalid pointer.");
|
||
+ }
|
||
+
|
||
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||
+ result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
|
||
+ if (result == EINVAL) {
|
||
+ apc_eprint("pthread_mutexattr_settype: unable to set adaptive mutexes");
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
|
||
+ result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
|
||
+ if(result == EINVAL) {
|
||
+ apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
|
||
+ } else if(result == EFAULT) {
|
||
+ apc_eprint("pthread mutex error: attr is an invalid pointer.");
|
||
+ } else if(result == ENOTSUP) {
|
||
+ apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
|
||
+ }
|
||
+
|
||
+ if(pthread_mutex_init(lock, attr)) {
|
||
+ apc_eprint("unable to initialize pthread lock");
|
||
+ }
|
||
+ return lock;
|
||
+}
|
||
+
|
||
+void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
|
||
+{
|
||
+ return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
|
||
+}
|
||
+
|
||
+void apc_pthreadmutex_lock(pthread_mutex_t *lock)
|
||
+{
|
||
+ int result;
|
||
+ result = pthread_mutex_lock(lock);
|
||
+ if(result == EINVAL) {
|
||
+ apc_eprint("unable to obtain pthread lock (EINVAL)");
|
||
+ } else if(result == EDEADLK) {
|
||
+ apc_eprint("unable to obtain pthread lock (EDEADLK)");
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
|
||
+{
|
||
+ if(pthread_mutex_unlock(lock)) {
|
||
+ apc_eprint("unable to unlock pthread lock");
|
||
+ }
|
||
+}
|
||
+
|
||
+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
|
||
+{
|
||
+ int rval;
|
||
+ rval = pthread_mutex_trylock(lock);
|
||
+ if(rval == EBUSY) { /* Lock is already held */
|
||
+ return 0;
|
||
+ } else if(rval == 0) { /* Obtained lock */
|
||
+ return 1;
|
||
+ } else { /* Other error */
|
||
+ apc_eprint("unable to obtain pthread trylock");
|
||
+ return 0;
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthreadmutex.h
|
||
--- php-5.2.5-orig/ext/apc/apc_pthreadmutex.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_pthreadmutex.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,48 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
|
||
+
|
||
+#ifndef APC_PTHREADMUTEX_H
|
||
+#define APC_PTHREADMUTEX_H
|
||
+
|
||
+#include "apc.h"
|
||
+
|
||
+#ifdef APC_PTHREADMUTEX_LOCKS
|
||
+
|
||
+#include <pthread.h>
|
||
+
|
||
+pthread_mutex_t *apc_pthreadmutex_create();
|
||
+void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
|
||
+void apc_pthreadmutex_lock(pthread_mutex_t *lock);
|
||
+void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
|
||
+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
|
||
+
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
|
||
--- php-5.2.5-orig/ext/apc/apc_rfc1867.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_rfc1867.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,195 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_rfc1867.c,v 3.12 2007/10/18 20:37:20 rasmus Exp $*/
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_globals.h"
|
||
+#include "rfc1867.h"
|
||
+
|
||
+#ifdef PHP_WIN32
|
||
+#include "win32/time.h"
|
||
+#endif
|
||
+
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
|
||
+
|
||
+static double my_time() {
|
||
+ struct timeval a;
|
||
+ double t;
|
||
+ gettimeofday(&a, NULL);
|
||
+ t = a.tv_sec + (a.tv_usec/1000000.00);
|
||
+ return t;
|
||
+}
|
||
+
|
||
+void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
|
||
+ static char tracking_key[64];
|
||
+ static int key_length = 0;
|
||
+ static size_t content_length = 0;
|
||
+ static char filename[128];
|
||
+ static char name[64];
|
||
+ static char *temp_filename=NULL;
|
||
+ static int cancel_upload = 0;
|
||
+ static double start_time;
|
||
+ static size_t bytes_processed = 0;
|
||
+ static size_t prev_bytes_processed = 0;
|
||
+ static int update_freq = 0;
|
||
+ static double rate;
|
||
+ zval *track = NULL;
|
||
+
|
||
+ switch (event) {
|
||
+ case MULTIPART_EVENT_START:
|
||
+ {
|
||
+ multipart_event_start *data = (multipart_event_start *) event_data;
|
||
+ content_length = data->content_length;
|
||
+ *tracking_key = '\0';
|
||
+ *name = '\0';
|
||
+ cancel_upload = 0;
|
||
+ temp_filename = NULL;
|
||
+ *filename= '\0';
|
||
+ key_length = 0;
|
||
+ start_time = my_time();
|
||
+ bytes_processed = 0;
|
||
+ rate = 0;
|
||
+ update_freq = APCG(rfc1867_freq);
|
||
+ if(update_freq < 0) { // frequency is a percentage, not bytes
|
||
+ update_freq = content_length * APCG(rfc1867_freq) / 100;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case MULTIPART_EVENT_FORMDATA:
|
||
+ {
|
||
+ int prefix_len = strlen(APCG(rfc1867_prefix));
|
||
+ multipart_event_formdata *data = (multipart_event_formdata *) event_data;
|
||
+ if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) && data->value && data->length && data->length < sizeof(tracking_key) - prefix_len) {
|
||
+ strlcat(tracking_key, APCG(rfc1867_prefix), 63);
|
||
+ strlcat(tracking_key, *data->value, 63);
|
||
+ key_length = data->length + prefix_len;
|
||
+ bytes_processed = data->post_bytes_processed;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case MULTIPART_EVENT_FILE_START:
|
||
+ if(*tracking_key) {
|
||
+ multipart_event_file_start *data = (multipart_event_file_start *) event_data;
|
||
+
|
||
+ bytes_processed = data->post_bytes_processed;
|
||
+ strncpy(filename,*data->filename,127);
|
||
+ temp_filename = NULL;
|
||
+ strncpy(name,data->name,63);
|
||
+ ALLOC_INIT_ZVAL(track);
|
||
+ array_init(track);
|
||
+ add_assoc_long(track, "total", content_length);
|
||
+ add_assoc_long(track, "current", bytes_processed);
|
||
+ add_assoc_string(track, "filename", filename, 1);
|
||
+ add_assoc_string(track, "name", name, 1);
|
||
+ add_assoc_long(track, "done", 0);
|
||
+ add_assoc_double(track, "start_time", start_time);
|
||
+ _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
|
||
+ zval_ptr_dtor(&track);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case MULTIPART_EVENT_FILE_DATA:
|
||
+ if(*tracking_key) {
|
||
+ multipart_event_file_data *data = (multipart_event_file_data *) event_data;
|
||
+ bytes_processed = data->post_bytes_processed;
|
||
+ ALLOC_INIT_ZVAL(track);
|
||
+ array_init(track);
|
||
+ add_assoc_long(track, "total", content_length);
|
||
+ add_assoc_long(track, "current", bytes_processed);
|
||
+ add_assoc_string(track, "filename", filename, 1);
|
||
+ add_assoc_string(track, "name", name, 1);
|
||
+ add_assoc_long(track, "done", 0);
|
||
+ add_assoc_double(track, "start_time", start_time);
|
||
+ if(bytes_processed - prev_bytes_processed > update_freq) {
|
||
+ _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
|
||
+ prev_bytes_processed = bytes_processed;
|
||
+ }
|
||
+ zval_ptr_dtor(&track);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case MULTIPART_EVENT_FILE_END:
|
||
+ if(*tracking_key) {
|
||
+ multipart_event_file_end *data = (multipart_event_file_end *) event_data;
|
||
+ bytes_processed = data->post_bytes_processed;
|
||
+ cancel_upload = data->cancel_upload;
|
||
+ temp_filename = data->temp_filename;
|
||
+ ALLOC_INIT_ZVAL(track);
|
||
+ array_init(track);
|
||
+ add_assoc_long(track, "total", content_length);
|
||
+ add_assoc_long(track, "current", bytes_processed);
|
||
+ add_assoc_string(track, "filename", filename, 1);
|
||
+ add_assoc_string(track, "name", name, 1);
|
||
+ add_assoc_string(track, "temp_filename", temp_filename, 1);
|
||
+ add_assoc_long(track, "cancel_upload", cancel_upload);
|
||
+ add_assoc_long(track, "done", 0);
|
||
+ add_assoc_double(track, "start_time", start_time);
|
||
+ _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
|
||
+ zval_ptr_dtor(&track);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case MULTIPART_EVENT_END:
|
||
+ if(*tracking_key) {
|
||
+ double now = my_time();
|
||
+ multipart_event_end *data = (multipart_event_end *) event_data;
|
||
+ bytes_processed = data->post_bytes_processed;
|
||
+ if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
|
||
+ else rate = 8.0*bytes_processed; /* Too quick */
|
||
+ ALLOC_INIT_ZVAL(track);
|
||
+ array_init(track);
|
||
+ add_assoc_long(track, "total", content_length);
|
||
+ add_assoc_long(track, "current", bytes_processed);
|
||
+ add_assoc_double(track, "rate", rate);
|
||
+ add_assoc_string(track, "filename", filename, 1);
|
||
+ add_assoc_string(track, "name", name, 1);
|
||
+ if(temp_filename) {
|
||
+ add_assoc_string(track, "temp_filename", temp_filename, 1);
|
||
+ }
|
||
+ add_assoc_long(track, "cancel_upload", cancel_upload);
|
||
+ add_assoc_long(track, "done", 1);
|
||
+ add_assoc_double(track, "start_time", start_time);
|
||
+ _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
|
||
+ zval_ptr_dtor(&track);
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+#endif
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.c php-5.2.5/ext/apc/apc_sem.c
|
||
--- php-5.2.5-orig/ext/apc/apc_sem.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_sem.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,177 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#include "apc_sem.h"
|
||
+#include "apc.h"
|
||
+#include "php.h"
|
||
+#include <sys/types.h>
|
||
+#include <sys/ipc.h>
|
||
+#include <sys/sem.h>
|
||
+#include <sys/stat.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+#if HAVE_SEMUN
|
||
+/* we have semun, no need to define */
|
||
+#else
|
||
+#undef HAVE_SEMUN
|
||
+union semun {
|
||
+ int val; /* value for SETVAL */
|
||
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
|
||
+ unsigned short *array; /* array for GETALL, SETALL */
|
||
+ /* Linux specific part: */
|
||
+ struct seminfo *__buf; /* buffer for IPC_INFO */
|
||
+};
|
||
+#define HAVE_SEMUN 1
|
||
+#endif
|
||
+
|
||
+#ifndef SEM_R
|
||
+# define SEM_R 0444
|
||
+#endif
|
||
+#ifndef SEM_A
|
||
+# define SEM_A 0222
|
||
+#endif
|
||
+
|
||
+/* always use SEM_UNDO, otherwise we risk deadlock */
|
||
+#define USE_SEM_UNDO
|
||
+
|
||
+#ifdef USE_SEM_UNDO
|
||
+# define UNDO SEM_UNDO
|
||
+#else
|
||
+# define UNDO 0
|
||
+#endif
|
||
+
|
||
+int apc_sem_create(const char* pathname, int proj, int initval)
|
||
+{
|
||
+ int semid;
|
||
+ int perms;
|
||
+ union semun arg;
|
||
+ key_t key;
|
||
+
|
||
+ perms = 0777;
|
||
+
|
||
+ key = IPC_PRIVATE;
|
||
+ if (pathname != NULL) {
|
||
+ if ((key = ftok(pathname, proj)) < 0) {
|
||
+ apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
|
||
+ /* sempahore created for the first time, initialize now */
|
||
+ arg.val = initval;
|
||
+ if (semctl(semid, 0, SETVAL, arg) < 0) {
|
||
+ apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
|
||
+ }
|
||
+ }
|
||
+ else if (errno == EEXIST) {
|
||
+ /* sempahore already exists, don't initialize */
|
||
+ if ((semid = semget(key, 1, perms)) < 0) {
|
||
+ apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
|
||
+ }
|
||
+ /* insert <sleazy way to avoid race condition> here */
|
||
+ }
|
||
+ else {
|
||
+ apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
|
||
+ }
|
||
+
|
||
+ return semid;
|
||
+}
|
||
+
|
||
+void apc_sem_destroy(int semid)
|
||
+{
|
||
+ /* we expect this call to fail often, so we do not check */
|
||
+ union semun arg;
|
||
+ semctl(semid, 0, IPC_RMID, arg);
|
||
+}
|
||
+
|
||
+void apc_sem_lock(int semid)
|
||
+{
|
||
+ struct sembuf op;
|
||
+
|
||
+ op.sem_num = 0;
|
||
+ op.sem_op = -1;
|
||
+ op.sem_flg = UNDO;
|
||
+
|
||
+ if (semop(semid, &op, 1) < 0) {
|
||
+ if (errno != EINTR) {
|
||
+ apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_sem_unlock(int semid)
|
||
+{
|
||
+ struct sembuf op;
|
||
+
|
||
+ op.sem_num = 0;
|
||
+ op.sem_op = 1;
|
||
+ op.sem_flg = UNDO;
|
||
+
|
||
+ if (semop(semid, &op, 1) < 0) {
|
||
+ if (errno != EINTR) {
|
||
+ apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_sem_wait_for_zero(int semid)
|
||
+{
|
||
+ struct sembuf op;
|
||
+
|
||
+ op.sem_num = 0;
|
||
+ op.sem_op = 0;
|
||
+ op.sem_flg = UNDO;
|
||
+
|
||
+ if (semop(semid, &op, 1) < 0) {
|
||
+ if (errno != EINTR) {
|
||
+ apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+int apc_sem_get_value(int semid)
|
||
+{
|
||
+ union semun arg;
|
||
+ unsigned short val[1];
|
||
+
|
||
+ arg.array = val;
|
||
+ if (semctl(semid, 0, GETALL, arg) < 0) {
|
||
+ apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
|
||
+ }
|
||
+ return val[0];
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.h php-5.2.5/ext/apc/apc_sem.h
|
||
--- php-5.2.5-orig/ext/apc/apc_sem.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_sem.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,51 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#ifndef APC_SEM_H
|
||
+#define APC_SEM_H
|
||
+
|
||
+/* Wrapper functions for SysV sempahores */
|
||
+
|
||
+extern int apc_sem_create(const char* pathname, int proj, int initval);
|
||
+extern void apc_sem_destroy(int semid);
|
||
+extern void apc_sem_lock(int semid);
|
||
+extern void apc_sem_unlock(int semid);
|
||
+extern void apc_sem_wait_for_zero(int semid);
|
||
+extern int apc_sem_get_value(int semid);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.c php-5.2.5/ext/apc/apc_shm.c
|
||
--- php-5.2.5-orig/ext/apc/apc_shm.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_shm.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,110 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_shm.c,v 3.11 2007/05/09 22:15:33 shire Exp $ */
|
||
+
|
||
+#include "apc_shm.h"
|
||
+#include "apc.h"
|
||
+#ifdef PHP_WIN32
|
||
+/* shm functions are available in TSRM */
|
||
+#include <tsrm/tsrm_win32.h>
|
||
+#define key_t long
|
||
+#else
|
||
+#include <sys/ipc.h>
|
||
+#include <sys/shm.h>
|
||
+#include <sys/stat.h>
|
||
+#endif
|
||
+
|
||
+#ifndef SHM_R
|
||
+# define SHM_R 0444 /* read permission */
|
||
+#endif
|
||
+#ifndef SHM_A
|
||
+# define SHM_A 0222 /* write permission */
|
||
+#endif
|
||
+
|
||
+int apc_shm_create(const char* pathname, int proj, size_t size)
|
||
+{
|
||
+ int shmid; /* shared memory id */
|
||
+ int oflag; /* permissions on shm */
|
||
+ key_t key; /* shm key returned by ftok */
|
||
+
|
||
+ key = IPC_PRIVATE;
|
||
+#ifndef PHP_WIN32
|
||
+ /* no ftok yet for win32 */
|
||
+ if (pathname != NULL) {
|
||
+ if ((key = ftok(pathname, proj)) < 0) {
|
||
+ apc_eprint("apc_shm_create: ftok failed:");
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ oflag = IPC_CREAT | SHM_R | SHM_A;
|
||
+ if ((shmid = shmget(key, size, oflag)) < 0) {
|
||
+ 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));
|
||
+ }
|
||
+
|
||
+ return shmid;
|
||
+}
|
||
+
|
||
+void apc_shm_destroy(int shmid)
|
||
+{
|
||
+ /* we expect this call to fail often, so we do not check */
|
||
+ shmctl(shmid, IPC_RMID, 0);
|
||
+}
|
||
+
|
||
+void* apc_shm_attach(int shmid)
|
||
+{
|
||
+ void* shmaddr; /* the shared memory address */
|
||
+
|
||
+ if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
|
||
+ apc_eprint("apc_shm_attach: shmat failed:");
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * We set the shmid for removal immediately after attaching to it. The
|
||
+ * segment won't disappear until all processes have detached from it.
|
||
+ */
|
||
+ apc_shm_destroy(shmid);
|
||
+ return shmaddr;
|
||
+}
|
||
+
|
||
+void apc_shm_detach(void* shmaddr)
|
||
+{
|
||
+ if (shmdt(shmaddr) < 0) {
|
||
+ apc_eprint("apc_shm_detach: shmdt failed:");
|
||
+ }
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.h php-5.2.5/ext/apc/apc_shm.h
|
||
--- php-5.2.5-orig/ext/apc/apc_shm.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_shm.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,54 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_shm.h,v 3.8 2007/05/23 01:23:21 auroraeosrose Exp $ */
|
||
+
|
||
+#ifndef APC_SHM_H
|
||
+#define APC_SHM_H
|
||
+
|
||
+#include <sys/types.h>
|
||
+#ifdef PHP_WIN32
|
||
+#include <time.h>
|
||
+#endif
|
||
+
|
||
+/* Wrapper functions for unix shared memory */
|
||
+
|
||
+extern int apc_shm_create(const char* name, int proj, size_t size);
|
||
+extern void apc_shm_destroy(int shmid);
|
||
+extern void* apc_shm_attach(int shmid);
|
||
+extern void apc_shm_detach(void* shmaddr);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.c php-5.2.5/ext/apc/apc_signal.c
|
||
--- php-5.2.5-orig/ext/apc/apc_signal.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_signal.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,178 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Lucas Nealan <lucas@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Facebook Inc. in 2007.
|
||
+
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Facebook Inc. as the original contributor of this module by leaving
|
||
+ this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+ */
|
||
+
|
||
+ /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */
|
||
+
|
||
+ /* Allows apc to install signal handlers and maintain signalling
|
||
+ to already registered handlers. Registers all signals that
|
||
+ coredump by default and unmaps the shared memory segment
|
||
+ before the coredump. Note: PHP module init is called before
|
||
+ signals are set by Apache and thus apc_set_signals should
|
||
+ be called in request init (RINIT)
|
||
+ */
|
||
+
|
||
+#include <signal.h>
|
||
+#include "apc_globals.h"
|
||
+#include "apc_sma.h"
|
||
+#include "apc_signal.h"
|
||
+
|
||
+static apc_signal_info_t apc_signal_info = {0};
|
||
+
|
||
+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
|
||
+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
|
||
+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
|
||
+
|
||
+/* {{{ apc_core_unmap
|
||
+ * Coredump signal handler, unmaps shm and calls previously installed handlers
|
||
+ */
|
||
+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context)
|
||
+{
|
||
+ apc_sma_cleanup();
|
||
+ apc_rehandle_signal(signo, siginfo, context);
|
||
+
|
||
+#if !defined(WIN32) && !defined(NETWARE)
|
||
+ kill(getpid(), signo);
|
||
+#else
|
||
+ raise(signo);
|
||
+#endif
|
||
+} /* }}} */
|
||
+
|
||
+/* {{{ apc_rehandle_signal
|
||
+ * Call the previously registered handler for a signal
|
||
+ */
|
||
+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
|
||
+{
|
||
+ int i;
|
||
+ apc_signal_entry_t p_sig = {0};
|
||
+
|
||
+ for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) {
|
||
+ p_sig = *apc_signal_info.prev[i];
|
||
+ if (p_sig.signo == signo) {
|
||
+ if (p_sig.siginfo) {
|
||
+ (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
|
||
+ } else {
|
||
+ (*(void (*)(int))p_sig.handler)(signo);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+} /* }}} */
|
||
+
|
||
+/* {{{ apc_register_signal
|
||
+ * Set a handler for a previously installed signal and save so we can
|
||
+ * callback when handled
|
||
+ */
|
||
+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
|
||
+{
|
||
+#if HAVE_SIGACTION
|
||
+ struct sigaction sa = {0};
|
||
+ apc_signal_entry_t p_sig = {0};
|
||
+
|
||
+ if (sigaction(signo, NULL, &sa) == 0) {
|
||
+ if ((void*)sa.sa_handler == (void*)handler) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
|
||
+ p_sig.signo = signo;
|
||
+ p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
|
||
+ p_sig.handler = (void *)sa.sa_handler;
|
||
+
|
||
+ apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
|
||
+ apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
|
||
+ *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
|
||
+ } else {
|
||
+ /* inherit flags and mask if already set */
|
||
+ sigemptyset(&sa.sa_mask);
|
||
+ sa.sa_flags = 0;
|
||
+ sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
|
||
+#if defined(SA_ONESHOT)
|
||
+ sa.sa_flags = SA_ONESHOT;
|
||
+#elif defined(SA_RESETHAND)
|
||
+ sa.sa_flags = SA_RESETHAND;
|
||
+#endif
|
||
+ }
|
||
+ sa.sa_handler = (void*)handler;
|
||
+
|
||
+ if (sigaction(signo, &sa, NULL) < 0) {
|
||
+ apc_wprint("Error installing apc signal handler for %d", signo);
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+ }
|
||
+#endif
|
||
+ return FAILURE;
|
||
+} /* }}} */
|
||
+
|
||
+/* {{{ apc_set_signals
|
||
+ * Install our signal handlers */
|
||
+void apc_set_signals(TSRMLS_D)
|
||
+{
|
||
+ if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
|
||
+ /* ISO C standard signals that coredump */
|
||
+ apc_register_signal(SIGSEGV, apc_core_unmap);
|
||
+ apc_register_signal(SIGABRT, apc_core_unmap);
|
||
+ apc_register_signal(SIGFPE, apc_core_unmap);
|
||
+ apc_register_signal(SIGILL, apc_core_unmap);
|
||
+ /* extended signals that coredump */
|
||
+#ifdef SIGBUS
|
||
+ apc_register_signal(SIGBUS, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGABORT
|
||
+ apc_register_signal(SIGABORT, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGEMT
|
||
+ apc_register_signal(SIGEMT, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGIOT
|
||
+ apc_register_signal(SIGIOT, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGQUIT
|
||
+ apc_register_signal(SIGQUIT, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGSYS
|
||
+ apc_register_signal(SIGSYS, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGTRAP
|
||
+ apc_register_signal(SIGTRAP, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGXCPU
|
||
+ apc_register_signal(SIGXCPU, apc_core_unmap);
|
||
+#endif
|
||
+#ifdef SIGXFSZ
|
||
+ apc_register_signal(SIGXFSZ, apc_core_unmap);
|
||
+#endif
|
||
+ }
|
||
+} /* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.h php-5.2.5/ext/apc/apc_signal.h
|
||
--- php-5.2.5-orig/ext/apc/apc_signal.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_signal.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,50 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Lucas Nealan <lucas@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_signal.h,v 1.1 2007/12/26 22:36:06 rasmus Exp $ */
|
||
+
|
||
+#ifndef APC_SIGNAL_H
|
||
+#define APC_SIGNAL_H
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_php.h"
|
||
+
|
||
+typedef struct apc_signal_entry_t {
|
||
+ int signo; /* signal number */
|
||
+ int siginfo; /* siginfo style handler calling */
|
||
+ void* handler; /* signal handler */
|
||
+} apc_signal_entry_t;
|
||
+
|
||
+typedef struct apc_signal_info_t {
|
||
+ int installed; /* How many signals we've installed handles for */
|
||
+ apc_signal_entry_t **prev; /* Previous signal handlers */
|
||
+} apc_signal_info_t;
|
||
+
|
||
+void apc_set_signals(TSRMLS_D);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.c php-5.2.5/ext/apc/apc_sma.c
|
||
--- php-5.2.5-orig/ext/apc/apc_sma.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_sma.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,628 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_sma.c,v 1.69 2007/12/26 21:35:39 gopalv Exp $ */
|
||
+
|
||
+#include "apc_sma.h"
|
||
+#include "apc.h"
|
||
+#include "apc_globals.h"
|
||
+#include "apc_lock.h"
|
||
+#include "apc_shm.h"
|
||
+#include <limits.h>
|
||
+#if APC_MMAP
|
||
+void *apc_mmap(char *file_mask, size_t size);
|
||
+void apc_unmap(void* shmaddr, size_t size);
|
||
+#endif
|
||
+
|
||
+/* {{{ locking macros */
|
||
+#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
|
||
+#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
|
||
+#define UNLOCK(c) { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
|
||
+/* }}} */
|
||
+
|
||
+enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
|
||
+
|
||
+static int sma_initialized = 0; /* true if the sma has been initialized */
|
||
+static unsigned int sma_numseg; /* number of shm segments to allow */
|
||
+static size_t sma_segsize; /* size of each shm segment */
|
||
+static size_t* sma_segments; /* array of shm segment ids */
|
||
+static void** sma_shmaddrs; /* array of shm segment addresses */
|
||
+static int sma_lastseg = 0; /* index of MRU segment */
|
||
+
|
||
+typedef struct header_t header_t;
|
||
+struct header_t {
|
||
+ apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */
|
||
+ size_t segsize; /* size of entire segment */
|
||
+ size_t avail; /* bytes available (not necessarily contiguous) */
|
||
+ size_t nfoffset; /* start next fit search from this offset */
|
||
+#if ALLOC_DISTRIBUTION
|
||
+ size_t adist[30];
|
||
+#endif
|
||
+};
|
||
+
|
||
+
|
||
+/* do not enable for threaded http servers */
|
||
+/* #define __APC_SMA_DEBUG__ 1 */
|
||
+
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+/* global counter for identifying blocks
|
||
+ * Technically it is possible to do the same
|
||
+ * using offsets, but double allocations of the
|
||
+ * same offset can happen. */
|
||
+static volatile size_t block_id = 0;
|
||
+#endif
|
||
+
|
||
+#define APC_SMA_CANARIES 1
|
||
+
|
||
+typedef struct block_t block_t;
|
||
+struct block_t {
|
||
+ size_t size; /* size of this block */
|
||
+ size_t next; /* offset in segment of next free block */
|
||
+#ifdef APC_SMA_CANARIES
|
||
+ size_t canary; /* canary to check for memory overwrites */
|
||
+#endif
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ size_t id; /* identifier for the memory block */
|
||
+#endif
|
||
+};
|
||
+
|
||
+/* The macros BLOCKAT and OFFSET are used for convenience throughout this
|
||
+ * module. Both assume the presence of a variable shmaddr that points to the
|
||
+ * beginning of the shared memory segment in question. */
|
||
+
|
||
+#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
|
||
+#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
|
||
+
|
||
+/* Canary macros for setting, checking and resetting memory canaries */
|
||
+#ifdef APC_SMA_CANARIES
|
||
+ #define SET_CANARY(v) (v)->canary = 0x42424242
|
||
+ #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
|
||
+ #define RESET_CANARY(v) (v)->canary = -42
|
||
+#else
|
||
+ #define SET_CANARY(v)
|
||
+ #define CHECK_CANARY(v)
|
||
+ #define RESET_CANARY(v)
|
||
+#endif
|
||
+
|
||
+
|
||
+#ifdef max
|
||
+#undef max
|
||
+#endif
|
||
+#define max(a, b) ((a) > (b) ? (a) : (b))
|
||
+
|
||
+/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
|
||
+typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
|
||
+#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
|
||
+#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ sma_allocate: tries to allocate size bytes in a segment */
|
||
+static int sma_allocate(void* shmaddr, size_t size)
|
||
+{
|
||
+ header_t* header; /* header of shared memory segment */
|
||
+ block_t* prv; /* block prior to working block */
|
||
+ block_t* cur; /* working block in list */
|
||
+ block_t* prvnextfit; /* block before next fit */
|
||
+ size_t realsize; /* actual size of block needed, including header */
|
||
+ size_t last_offset; /* save the last search offset */
|
||
+ int wrapped=0;
|
||
+ const size_t block_size = ALIGNWORD(sizeof(struct block_t));
|
||
+
|
||
+ realsize = ALIGNWORD(size + block_size);
|
||
+
|
||
+ /*
|
||
+ * First, insure that the segment contains at least realsize free bytes,
|
||
+ * even if they are not contiguous.
|
||
+ */
|
||
+ header = (header_t*) shmaddr;
|
||
+ if (header->avail < realsize) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ prvnextfit = 0; /* initially null (no fit) */
|
||
+ last_offset = 0;
|
||
+
|
||
+ /* If we have a next fit offset, start searching from there */
|
||
+ if(header->nfoffset) {
|
||
+ prv = BLOCKAT(header->nfoffset);
|
||
+ /* if prv is the last block, jump to the beginning */
|
||
+ if(prv->next == 0) {
|
||
+ prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+ wrapped = 1;
|
||
+ }
|
||
+ } else {
|
||
+ prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+ }
|
||
+
|
||
+ CHECK_CANARY(prv);
|
||
+
|
||
+ while (prv->next != header->nfoffset) {
|
||
+ cur = BLOCKAT(prv->next);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(cur);
|
||
+#endif
|
||
+ /* If it can fit realiszie bytes in cur block, stop searching */
|
||
+ if (cur->size >= realsize) {
|
||
+ prvnextfit = prv;
|
||
+ break;
|
||
+ }
|
||
+ last_offset = prv->next;
|
||
+ prv = cur;
|
||
+ if(wrapped && (prv->next >= header->nfoffset)) break;
|
||
+
|
||
+ /* Check to see if we need to wrap around and search from the top */
|
||
+ if(header->nfoffset && prv->next == 0) {
|
||
+ prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(prv);
|
||
+#endif
|
||
+ last_offset = 0;
|
||
+ wrapped = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (prvnextfit == 0) {
|
||
+ header->nfoffset = 0;
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ prv = prvnextfit;
|
||
+ cur = BLOCKAT(prv->next);
|
||
+
|
||
+ CHECK_CANARY(prv);
|
||
+ CHECK_CANARY(cur);
|
||
+
|
||
+ if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
|
||
+ /* cur is big enough for realsize, but too small to split - unlink it */
|
||
+ prv->next = cur->next;
|
||
+ }
|
||
+ else {
|
||
+ block_t* nxt; /* the new block (chopped part of cur) */
|
||
+ size_t nxtoffset; /* offset of the block currently after cur */
|
||
+ size_t oldsize; /* size of cur before split */
|
||
+
|
||
+ /* nextfit is too big; split it into two smaller blocks */
|
||
+ nxtoffset = cur->next;
|
||
+ oldsize = cur->size;
|
||
+ prv->next += realsize; /* skip over newly allocated block */
|
||
+ cur->size = realsize; /* Set the size of this new block */
|
||
+ nxt = BLOCKAT(prv->next);
|
||
+ nxt->next = nxtoffset; /* Re-link the shortened block */
|
||
+ nxt->size = oldsize - realsize; /* and fix the size */
|
||
+ SET_CANARY(nxt);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ nxt->id = -1;
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ /* update the block header */
|
||
+ header->avail -= cur->size;
|
||
+#if ALLOC_DISTRIBUTION
|
||
+ header->adist[(int)(log(size)/log(2))]++;
|
||
+#endif
|
||
+
|
||
+ header->nfoffset = last_offset;
|
||
+
|
||
+ SET_CANARY(cur);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ cur->id = ++block_id;
|
||
+ fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
|
||
+#endif
|
||
+
|
||
+ return OFFSET(cur) + block_size;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ sma_deallocate: deallocates the block at the given offset */
|
||
+static int sma_deallocate(void* shmaddr, int offset)
|
||
+{
|
||
+ header_t* header; /* header of shared memory segment */
|
||
+ block_t* cur; /* the new block to insert */
|
||
+ block_t* prv; /* the block before cur */
|
||
+ block_t* nxt; /* the block after cur */
|
||
+ size_t size; /* size of deallocated block */
|
||
+
|
||
+ offset -= ALIGNWORD(sizeof(struct block_t));
|
||
+ assert(offset >= 0);
|
||
+
|
||
+ /* find position of new block in free list */
|
||
+ cur = BLOCKAT(offset);
|
||
+ prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+
|
||
+ CHECK_CANARY(cur);
|
||
+
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(prv);
|
||
+ fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
|
||
+#endif
|
||
+ while (prv->next != 0 && prv->next < offset) {
|
||
+ prv = BLOCKAT(prv->next);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(prv);
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ CHECK_CANARY(prv);
|
||
+
|
||
+ /* insert new block after prv */
|
||
+ cur->next = prv->next;
|
||
+ prv->next = offset;
|
||
+
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(cur);
|
||
+ cur->id = -1;
|
||
+#endif
|
||
+
|
||
+ /* update the block header */
|
||
+ header = (header_t*) shmaddr;
|
||
+ header->avail += cur->size;
|
||
+ size = cur->size;
|
||
+
|
||
+ if (((char *)prv) + prv->size == (char *) cur) {
|
||
+ /* cur and prv share an edge, combine them */
|
||
+ prv->size += cur->size;
|
||
+ prv->next = cur->next;
|
||
+ RESET_CANARY(cur);
|
||
+ cur = prv;
|
||
+ }
|
||
+
|
||
+ nxt = BLOCKAT(cur->next);
|
||
+
|
||
+ if (((char *)cur) + cur->size == (char *) nxt) {
|
||
+ /* cur and nxt shared an edge, combine them */
|
||
+ cur->size += nxt->size;
|
||
+ cur->next = nxt->next;
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(nxt);
|
||
+ nxt->id = -1; /* assert this or set it ? */
|
||
+#endif
|
||
+ RESET_CANARY(nxt);
|
||
+ }
|
||
+ header->nfoffset = 0; /* Reset the next fit search marker */
|
||
+
|
||
+ return size;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_init */
|
||
+
|
||
+void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ if (sma_initialized) {
|
||
+ return;
|
||
+ }
|
||
+ sma_initialized = 1;
|
||
+
|
||
+#if APC_MMAP
|
||
+ /*
|
||
+ * I don't think multiple anonymous mmaps makes any sense
|
||
+ * so force sma_numseg to 1 in this case
|
||
+ */
|
||
+ if(!mmap_file_mask ||
|
||
+ (mmap_file_mask && !strlen(mmap_file_mask)) ||
|
||
+ (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
|
||
+ sma_numseg = 1;
|
||
+ } else {
|
||
+ sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
|
||
+ }
|
||
+#else
|
||
+ sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
|
||
+#endif
|
||
+
|
||
+ sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
|
||
+
|
||
+ sma_segments = (size_t*) apc_emalloc(sma_numseg*sizeof(size_t));
|
||
+ sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
|
||
+
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ header_t* header;
|
||
+ block_t* block;
|
||
+ void* shmaddr;
|
||
+
|
||
+#if APC_MMAP
|
||
+ sma_segments[i] = sma_segsize;
|
||
+ sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
|
||
+ if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
|
||
+#else
|
||
+ sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
|
||
+ sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
|
||
+#endif
|
||
+ shmaddr = sma_shmaddrs[i];
|
||
+
|
||
+ header = (header_t*) shmaddr;
|
||
+ apc_lck_create(NULL, 0, 1, header->sma_lock);
|
||
+ header->segsize = sma_segsize;
|
||
+ header->avail = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
|
||
+ header->nfoffset = 0;
|
||
+#if ALLOC_DISTRIBUTION
|
||
+ {
|
||
+ int j;
|
||
+ for(j=0; j<30; j++) header->adist[j] = 0;
|
||
+ }
|
||
+#endif
|
||
+ block = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+ block->size = 0;
|
||
+ block->next = ALIGNWORD(sizeof(header_t)) + ALIGNWORD(sizeof(block_t));
|
||
+ SET_CANARY(block);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ block->id = -1;
|
||
+#endif
|
||
+ block = BLOCKAT(block->next);
|
||
+ block->size = header->avail;
|
||
+ block->next = 0;
|
||
+ SET_CANARY(block);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ block->id = -1;
|
||
+#endif
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_cleanup */
|
||
+void apc_sma_cleanup()
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ assert(sma_initialized);
|
||
+
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+#if APC_MMAP
|
||
+ apc_unmap(sma_shmaddrs[i], sma_segments[i]);
|
||
+#else
|
||
+ apc_shm_detach(sma_shmaddrs[i]);
|
||
+#endif
|
||
+ }
|
||
+ sma_initialized = 0;
|
||
+ apc_efree(sma_segments);
|
||
+ apc_efree(sma_shmaddrs);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_malloc */
|
||
+void* apc_sma_malloc(size_t n)
|
||
+{
|
||
+ int off;
|
||
+ int i;
|
||
+
|
||
+ TSRMLS_FETCH();
|
||
+ assert(sma_initialized);
|
||
+ LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
|
||
+
|
||
+ off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
|
||
+ if (off != -1) {
|
||
+ void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
|
||
+ if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
|
||
+ return p;
|
||
+ }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
|
||
+
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ if (i == sma_lastseg) {
|
||
+ continue;
|
||
+ }
|
||
+ LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ off = sma_allocate(sma_shmaddrs[i], n);
|
||
+ if (off != -1) {
|
||
+ void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
|
||
+ if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ sma_lastseg = i;
|
||
+ return p;
|
||
+ }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_realloc */
|
||
+void* apc_sma_realloc(void *p, size_t n)
|
||
+{
|
||
+ apc_sma_free(p);
|
||
+ return apc_sma_malloc(n);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_strdup */
|
||
+char* apc_sma_strdup(const char* s)
|
||
+{
|
||
+ void* q;
|
||
+ int len;
|
||
+
|
||
+ if(!s) return NULL;
|
||
+
|
||
+ len = strlen(s)+1;
|
||
+ q = apc_sma_malloc(len);
|
||
+ if(!q) return NULL;
|
||
+ memcpy(q, s, len);
|
||
+ return q;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_free */
|
||
+void apc_sma_free(void* p)
|
||
+{
|
||
+ int i;
|
||
+ size_t offset;
|
||
+ size_t d_size;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ if (p == NULL) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ assert(sma_initialized);
|
||
+
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
|
||
+ if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
|
||
+ d_size = sma_deallocate(sma_shmaddrs[i], offset);
|
||
+ if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ return;
|
||
+ }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ }
|
||
+
|
||
+ apc_eprint("apc_sma_free: could not locate address %p", p);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_info */
|
||
+apc_sma_info_t* apc_sma_info(zend_bool limited)
|
||
+{
|
||
+ apc_sma_info_t* info;
|
||
+ apc_sma_link_t** link;
|
||
+ int i;
|
||
+ char* shmaddr;
|
||
+ block_t* prv;
|
||
+
|
||
+ if (!sma_initialized) {
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
|
||
+ info->num_seg = sma_numseg;
|
||
+ info->seg_size = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
|
||
+
|
||
+ info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ info->list[i] = NULL;
|
||
+ }
|
||
+
|
||
+ if(limited) return info;
|
||
+
|
||
+ /* For each segment */
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ shmaddr = sma_shmaddrs[i];
|
||
+ prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+
|
||
+ link = &info->list[i];
|
||
+
|
||
+ /* For each block in this segment */
|
||
+ while (prv->next != 0) {
|
||
+ block_t* cur = BLOCKAT(prv->next);
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ CHECK_CANARY(cur);
|
||
+#endif
|
||
+
|
||
+ *link = apc_emalloc(sizeof(apc_sma_link_t));
|
||
+ (*link)->size = cur->size;
|
||
+ (*link)->offset = prv->next;
|
||
+ (*link)->next = NULL;
|
||
+ link = &(*link)->next;
|
||
+
|
||
+ prv = cur;
|
||
+ }
|
||
+ UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
|
||
+ }
|
||
+
|
||
+ return info;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_free_info */
|
||
+void apc_sma_free_info(apc_sma_info_t* info)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ for (i = 0; i < info->num_seg; i++) {
|
||
+ apc_sma_link_t* p = info->list[i];
|
||
+ while (p) {
|
||
+ apc_sma_link_t* q = p;
|
||
+ p = p->next;
|
||
+ apc_efree(q);
|
||
+ }
|
||
+ }
|
||
+ apc_efree(info->list);
|
||
+ apc_efree(info);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_sma_get_avail_mem */
|
||
+size_t apc_sma_get_avail_mem()
|
||
+{
|
||
+ size_t avail_mem = 0;
|
||
+ int i;
|
||
+
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ header_t* header = (header_t*) sma_shmaddrs[i];
|
||
+ avail_mem += header->avail;
|
||
+ }
|
||
+ return avail_mem;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#if ALLOC_DISTRIBUTION
|
||
+size_t *apc_sma_get_alloc_distribution(void) {
|
||
+ header_t* header = (header_t*) sma_shmaddrs[0];
|
||
+ return header->adist;
|
||
+}
|
||
+#endif
|
||
+
|
||
+#if 0
|
||
+/* {{{ apc_sma_check_integrity */
|
||
+void apc_sma_check_integrity()
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ /* For each segment */
|
||
+ for (i = 0; i < sma_numseg; i++) {
|
||
+ char* shmaddr = sma_shmaddrs[i];
|
||
+ header_t* header = (header_t*) shmaddr;
|
||
+ block_t* prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
|
||
+ int avail = 0;
|
||
+
|
||
+ /* For each block in this segment */
|
||
+ while (prv->next != 0) {
|
||
+ block_t* cur = BLOCKAT(prv->next);
|
||
+ avail += cur->size;
|
||
+ prv = cur;
|
||
+ }
|
||
+
|
||
+ assert(avail == header->avail);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.h php-5.2.5/ext/apc/apc_sma.h
|
||
--- php-5.2.5-orig/ext/apc/apc_sma.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_sma.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,82 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_sma.h,v 1.18 2007/05/11 01:46:31 shire Exp $ */
|
||
+
|
||
+#ifndef APC_SMA_H
|
||
+#define APC_SMA_H
|
||
+
|
||
+#define ALLOC_DISTRIBUTION 0
|
||
+
|
||
+#include "apc.h"
|
||
+
|
||
+/* Simple shared memory allocator */
|
||
+
|
||
+extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask);
|
||
+extern void apc_sma_cleanup();
|
||
+extern void* apc_sma_malloc(size_t size);
|
||
+extern void* apc_sma_realloc(void* p, size_t size);
|
||
+extern char* apc_sma_strdup(const char *s);
|
||
+extern void apc_sma_free(void* p);
|
||
+#if ALLOC_DISTRIBUTION
|
||
+extern size_t *apc_sma_get_alloc_distribution();
|
||
+#endif
|
||
+
|
||
+/* {{{ struct definition: apc_sma_link_t */
|
||
+typedef struct apc_sma_link_t apc_sma_link_t;
|
||
+struct apc_sma_link_t {
|
||
+ long size; /* size of this free block */
|
||
+ long offset; /* offset in segment of this block */
|
||
+ apc_sma_link_t* next; /* link to next free block */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct definition: apc_sma_info_t */
|
||
+typedef struct apc_sma_info_t apc_sma_info_t;
|
||
+struct apc_sma_info_t {
|
||
+ int num_seg; /* number of shared memory segments */
|
||
+ long seg_size; /* size of each shared memory segment */
|
||
+ apc_sma_link_t** list; /* there is one list per segment */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+extern apc_sma_info_t* apc_sma_info(zend_bool limited);
|
||
+extern void apc_sma_free_info(apc_sma_info_t* info);
|
||
+
|
||
+extern size_t apc_sma_get_avail_mem();
|
||
+extern void apc_sma_check_integrity();
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
|
||
--- php-5.2.5-orig/ext/apc/apc_spin.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_spin.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,65 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2007 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
|
||
+
|
||
+#include "apc_spin.h"
|
||
+
|
||
+#ifdef APC_SPIN_LOCKS
|
||
+
|
||
+slock_t *apc_slock_create(slock_t *lock)
|
||
+{
|
||
+ S_INIT_LOCK(lock);
|
||
+}
|
||
+
|
||
+void apc_slock_destroy(slock_t *lock)
|
||
+{
|
||
+ S_LOCK_FREE(lock);
|
||
+}
|
||
+
|
||
+void apc_slock_lock(slock_t *lock)
|
||
+{
|
||
+ S_LOCK(lock);
|
||
+}
|
||
+
|
||
+void apc_slock_unlock(slock_t *lock)
|
||
+{
|
||
+ S_UNLOCK(lock);
|
||
+}
|
||
+
|
||
+zend_bool apc_slock_nonblocking_lock(slock_t *lock)
|
||
+{
|
||
+ /* Technically we aren't supposed to call this directly, but the original
|
||
+ * code provides no method for absolute non-blocking locks, so we'll call into
|
||
+ * the TAS (test and set) functionality directly
|
||
+ */
|
||
+ return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */
|
||
+}
|
||
+
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
|
||
--- php-5.2.5-orig/ext/apc/apc_spin.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_spin.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,48 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2007 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
|
||
+
|
||
+#ifndef APC_SPIN_H
|
||
+#define APC_SPIN_H
|
||
+
|
||
+#include "apc.h"
|
||
+
|
||
+#ifdef APC_SPIN_LOCKS
|
||
+
|
||
+#include "pgsql_s_lock.h"
|
||
+
|
||
+pthread_mutex_t *apc_spin_create();
|
||
+void apc_spin_destroy(pthread_mutex_t *lock);
|
||
+void apc_spin_lock(pthread_mutex_t *lock);
|
||
+void apc_spin_unlock(pthread_mutex_t *lock);
|
||
+zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
|
||
+
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
|
||
--- php-5.2.5-orig/ext/apc/apc_stack.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_stack.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,105 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#include "apc_stack.h"
|
||
+#include "apc.h"
|
||
+
|
||
+struct apc_stack_t {
|
||
+ void** data;
|
||
+ int capacity;
|
||
+ int size;
|
||
+};
|
||
+
|
||
+apc_stack_t* apc_stack_create(int size_hint)
|
||
+{
|
||
+ apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
|
||
+
|
||
+ stack->capacity = (size_hint > 0) ? size_hint : 10;
|
||
+ stack->size = 0;
|
||
+ stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
|
||
+
|
||
+ return stack;
|
||
+}
|
||
+
|
||
+void apc_stack_destroy(apc_stack_t* stack)
|
||
+{
|
||
+ if (stack != NULL) {
|
||
+ apc_efree(stack->data);
|
||
+ apc_efree(stack);
|
||
+ }
|
||
+}
|
||
+
|
||
+void apc_stack_clear(apc_stack_t* stack)
|
||
+{
|
||
+ assert(stack != NULL);
|
||
+ stack->size = 0;
|
||
+}
|
||
+
|
||
+void apc_stack_push(apc_stack_t* stack, void* item)
|
||
+{
|
||
+ assert(stack != NULL);
|
||
+ if (stack->size == stack->capacity) {
|
||
+ stack->capacity *= 2;
|
||
+ stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
|
||
+ }
|
||
+ stack->data[stack->size++] = item;
|
||
+}
|
||
+
|
||
+void* apc_stack_pop(apc_stack_t* stack)
|
||
+{
|
||
+ assert(stack != NULL && stack->size > 0);
|
||
+ return stack->data[--stack->size];
|
||
+}
|
||
+
|
||
+void* apc_stack_top(apc_stack_t* stack)
|
||
+{
|
||
+ assert(stack != NULL && stack->size > 0);
|
||
+ return stack->data[stack->size-1];
|
||
+}
|
||
+
|
||
+void* apc_stack_get(apc_stack_t* stack, int n)
|
||
+{
|
||
+ assert(stack != NULL && stack->size > n);
|
||
+ return stack->data[n];
|
||
+}
|
||
+
|
||
+int apc_stack_size(apc_stack_t* stack)
|
||
+{
|
||
+ assert(stack != NULL);
|
||
+ return stack->size;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.h php-5.2.5/ext/apc/apc_stack.h
|
||
--- php-5.2.5-orig/ext/apc/apc_stack.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_stack.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,58 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#ifndef APC_STACK_H
|
||
+#define APC_STACK_H
|
||
+
|
||
+/* Basic stack datatype */
|
||
+
|
||
+#define T apc_stack_t*
|
||
+typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
|
||
+
|
||
+extern T apc_stack_create(int size_hint);
|
||
+extern void apc_stack_destroy(T stack);
|
||
+extern void apc_stack_clear(T stack);
|
||
+extern void apc_stack_push(T stack, void* item);
|
||
+extern void* apc_stack_pop(T stack);
|
||
+extern void* apc_stack_top(T stack);
|
||
+extern void* apc_stack_get(T stack, int n);
|
||
+extern int apc_stack_size(T stack);
|
||
+
|
||
+#undef T
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.c php-5.2.5/ext/apc/apc_zend.c
|
||
--- php-5.2.5-orig/ext/apc/apc_zend.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_zend.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,277 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
|
||
+
|
||
+#include "apc_zend.h"
|
||
+#include "apc_globals.h"
|
||
+
|
||
+void* apc_php_malloc(size_t n)
|
||
+{
|
||
+ return emalloc(n);
|
||
+}
|
||
+
|
||
+void apc_php_free(void* p)
|
||
+{
|
||
+ efree(p);
|
||
+}
|
||
+
|
||
+#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
|
||
+# define ZEND_VM_KIND_CALL 1
|
||
+#endif
|
||
+
|
||
+#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
|
||
+# define ZEND_VM_KIND ZEND_VM_KIND_CALL
|
||
+#endif
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
|
||
+# define APC_OPCODE_OVERRIDE
|
||
+#endif
|
||
+
|
||
+#ifdef APC_OPCODE_OVERRIDE
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+/* Taken from Zend/zend_vm_execute.h */
|
||
+#define _CONST_CODE 0
|
||
+#define _TMP_CODE 1
|
||
+#define _VAR_CODE 2
|
||
+#define _UNUSED_CODE 3
|
||
+#define _CV_CODE 4
|
||
+static inline int _apc_opcode_handler_decode(zend_op *opline)
|
||
+{
|
||
+ static const int apc_vm_decode[] = {
|
||
+ _UNUSED_CODE, /* 0 */
|
||
+ _CONST_CODE, /* 1 = IS_CONST */
|
||
+ _TMP_CODE, /* 2 = IS_TMP_VAR */
|
||
+ _UNUSED_CODE, /* 3 */
|
||
+ _VAR_CODE, /* 4 = IS_VAR */
|
||
+ _UNUSED_CODE, /* 5 */
|
||
+ _UNUSED_CODE, /* 6 */
|
||
+ _UNUSED_CODE, /* 7 */
|
||
+ _UNUSED_CODE, /* 8 = IS_UNUSED */
|
||
+ _UNUSED_CODE, /* 9 */
|
||
+ _UNUSED_CODE, /* 10 */
|
||
+ _UNUSED_CODE, /* 11 */
|
||
+ _UNUSED_CODE, /* 12 */
|
||
+ _UNUSED_CODE, /* 13 */
|
||
+ _UNUSED_CODE, /* 14 */
|
||
+ _UNUSED_CODE, /* 15 */
|
||
+ _CV_CODE /* 16 = IS_CV */
|
||
+ };
|
||
+ return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
|
||
+}
|
||
+
|
||
+# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline;
|
||
+# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline)
|
||
+# if PHP_MAJOR_VERSION >= 6
|
||
+# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1)
|
||
+# else
|
||
+# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1)
|
||
+# endif
|
||
+# 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; }
|
||
+
|
||
+#else /* ZE2.0 */
|
||
+# define APC_ZEND_ONLINE
|
||
+# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode)
|
||
+# define APC_OPCODE_HANDLER_COUNT 512
|
||
+# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname;
|
||
+#endif
|
||
+
|
||
+static opcode_handler_t *apc_original_opcode_handlers;
|
||
+static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
|
||
+
|
||
+#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
|
||
+
|
||
+static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
|
||
+{
|
||
+ *freeval = NULL;
|
||
+
|
||
+ switch (node->op_type) {
|
||
+ case IS_CONST:
|
||
+ return &(node->u.constant);
|
||
+ case IS_VAR:
|
||
+ return APC_EX_T(node->u.var).var.ptr;
|
||
+ case IS_TMP_VAR:
|
||
+ return (*freeval = &APC_EX_T(node->u.var).tmp_var);
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ case IS_CV:
|
||
+ {
|
||
+ zval ***ret = &execute_data->CVs[node->u.var];
|
||
+
|
||
+ if (!*ret) {
|
||
+ zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
|
||
+
|
||
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
|
||
+ apc_nprint("Undefined variable: %s", cv->name);
|
||
+ return &EG(uninitialized_zval);
|
||
+ }
|
||
+ }
|
||
+ return **ret;
|
||
+ }
|
||
+#endif
|
||
+ case IS_UNUSED:
|
||
+ default:
|
||
+ return NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
|
||
+{
|
||
+ APC_ZEND_OPLINE
|
||
+ zval *freeop1 = NULL;
|
||
+ zval *inc_filename = NULL, tmp_inc_filename;
|
||
+ char realpath[MAXPATHLEN];
|
||
+ php_stream_wrapper *wrapper;
|
||
+ char *path_for_open;
|
||
+ int ret = 0;
|
||
+ #ifdef ZEND_ENGINE_2
|
||
+ apc_opflags_t* flags = NULL;
|
||
+ #endif
|
||
+
|
||
+ if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
|
||
+ Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
|
||
+ return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||
+ }
|
||
+
|
||
+ inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
|
||
+ if (Z_TYPE_P(inc_filename) != IS_STRING) {
|
||
+ tmp_inc_filename = *inc_filename;
|
||
+ zval_copy_ctor(&tmp_inc_filename);
|
||
+ convert_to_string(&tmp_inc_filename);
|
||
+ inc_filename = &tmp_inc_filename;
|
||
+ }
|
||
+
|
||
+ wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
|
||
+ if (wrapper != &php_plain_files_wrapper ||
|
||
+ !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
|
||
+ !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
|
||
+ /* Fallback to original handler */
|
||
+ if (inc_filename == &tmp_inc_filename) {
|
||
+ zval_dtor(&tmp_inc_filename);
|
||
+ }
|
||
+ return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||
+ }
|
||
+
|
||
+ if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
|
||
+ if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
|
||
+ ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
|
||
+ ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
|
||
+ }
|
||
+ if (inc_filename == &tmp_inc_filename) {
|
||
+ zval_dtor(&tmp_inc_filename);
|
||
+ }
|
||
+ if (freeop1) {
|
||
+ zval_dtor(freeop1);
|
||
+ }
|
||
+ execute_data->opline++;
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if (inc_filename == &tmp_inc_filename) {
|
||
+ zval_dtor(&tmp_inc_filename);
|
||
+ }
|
||
+
|
||
+ if(APCG(reserved_offset) != -1) {
|
||
+ /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
|
||
+ flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if(flags && flags->deep_copy == 1) {
|
||
+ /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily
|
||
+ * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
|
||
+ */
|
||
+ Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
|
||
+ ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||
+ Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
|
||
+#else
|
||
+ if(0) {
|
||
+ /* do nothing, have nothing, be nothing */
|
||
+#endif
|
||
+ } else {
|
||
+ ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+void apc_zend_init(TSRMLS_D)
|
||
+{
|
||
+ zend_extension dummy_ext;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext);
|
||
+ assert(APCG(reserved_offset) == dummy_ext.resource_number);
|
||
+ assert(APCG(reserved_offset) != -1);
|
||
+ assert(sizeof(apc_opflags_t) <= sizeof(void*));
|
||
+#endif
|
||
+ if (!APCG(include_once)) {
|
||
+ /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
|
||
+
|
||
+ /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ apc_original_opcode_handlers = zend_opcode_handlers;
|
||
+ zend_opcode_handlers = apc_opcode_handlers;
|
||
+#else
|
||
+ apc_original_opcode_handlers = apc_opcode_handlers;
|
||
+#endif
|
||
+
|
||
+ APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
|
||
+}
|
||
+
|
||
+void apc_zend_shutdown(TSRMLS_D)
|
||
+{
|
||
+ if (!APCG(include_once)) {
|
||
+ /* Nothing changed, nothing to restore */
|
||
+ return;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2_1
|
||
+ zend_opcode_handlers = apc_original_opcode_handlers;
|
||
+#else
|
||
+ memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
|
||
+#endif
|
||
+}
|
||
+
|
||
+#else /* Opcode Overrides unavailable */
|
||
+
|
||
+void apc_zend_init(TSRMLS_D) { }
|
||
+void apc_zend_shutdown(TSRMLS_D) { }
|
||
+
|
||
+#endif /* APC_OPCODE_OVERRIDE */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
|
||
--- php-5.2.5-orig/ext/apc/apc_zend.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/apc_zend.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,53 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
|
||
+
|
||
+#ifndef APC_ZEND_H
|
||
+#define APC_ZEND_H
|
||
+
|
||
+/* Utilities for interfacing with the zend engine */
|
||
+
|
||
+#include "apc.h"
|
||
+#include "apc_php.h"
|
||
+
|
||
+extern void* apc_php_malloc(size_t n);
|
||
+extern void apc_php_free(void* p);
|
||
+
|
||
+extern void apc_zend_init(TSRMLS_D);
|
||
+extern void apc_zend_shutdown(TSRMLS_D);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/arch/atomic.h php-5.2.5/ext/apc/arch/atomic.h
|
||
--- php-5.2.5-orig/ext/apc/arch/atomic.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/arch/atomic.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,38 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
|
||
+
|
||
+#ifndef APC_ARCH_ATOMIC_H
|
||
+
|
||
+#define APC_ARCH_ATOMIC_H
|
||
+
|
||
+#if defined __x86_64__
|
||
+#include "x86_64/atomic.h"
|
||
+
|
||
+#elif defined __i386__
|
||
+#include "i386/atomic.h"
|
||
+
|
||
+#else
|
||
+#error "Unknown or Unsupported Architecture. If you would like futex suupport for your architecture, please file a request at http://pecl.php.net/bugs/report.php?package=APC"
|
||
+
|
||
+#endif
|
||
+
|
||
+
|
||
+#endif
|
||
diff -ubrN php-5.2.5-orig/ext/apc/arch/i386/atomic.h php-5.2.5/ext/apc/arch/i386/atomic.h
|
||
--- php-5.2.5-orig/ext/apc/arch/i386/atomic.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/arch/i386/atomic.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,79 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
|
||
+
|
||
+
|
||
+#include <sys/syscall.h>
|
||
+#include <sys/time.h>
|
||
+#include <linux/futex.h>
|
||
+
|
||
+/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
|
||
+static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
|
||
+
|
||
+ long int ret;
|
||
+
|
||
+ /* i386 system calls are performed with nt 80h operation.
|
||
+ * the argument order is a, b, c, d, S, D
|
||
+ */
|
||
+ asm volatile ("int $0x80"
|
||
+ : "=a" (ret)
|
||
+ : "0" (SYS_futex),
|
||
+ "b" (futex),
|
||
+ "c" (op),
|
||
+ "d" (val),
|
||
+ "S" (timeout)
|
||
+ : "memory"
|
||
+ );
|
||
+
|
||
+ return ret;
|
||
+
|
||
+}
|
||
+
|
||
+
|
||
+static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
|
||
+
|
||
+ int prev;
|
||
+
|
||
+ asm volatile ("LOCK cmpxchgl %1, %2"
|
||
+ : "=a" (prev)
|
||
+ : "r" (new),
|
||
+ "m" (*(ptr)),
|
||
+ "0"(old)
|
||
+ : "memory", "cc"
|
||
+ );
|
||
+
|
||
+ return prev;
|
||
+}
|
||
+
|
||
+static inline int apc_xchg(volatile int *ptr, int new) {
|
||
+
|
||
+ int ret;
|
||
+
|
||
+ asm volatile ("LOCK xchgl %[new], %[ptr]"
|
||
+ : "=a" (ret)
|
||
+ : [new] "0" (new),
|
||
+ [ptr] "m" (*(ptr))
|
||
+ : "memory"
|
||
+ );
|
||
+
|
||
+ return ret;
|
||
+
|
||
+}
|
||
+
|
||
diff -ubrN php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h php-5.2.5/ext/apc/arch/x86_64/atomic.h
|
||
--- php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/arch/x86_64/atomic.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,80 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
|
||
+
|
||
+
|
||
+#include <sys/syscall.h>
|
||
+#include <sys/time.h>
|
||
+#include <linux/futex.h>
|
||
+
|
||
+/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
|
||
+static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
|
||
+
|
||
+ long int ret;
|
||
+
|
||
+ /* x86_64 system calls are performed with the faster SYSCALL operation.
|
||
+ * the argument order is D, S, d, c, b, a rather than
|
||
+ * a, b, c, d, S, D as on the i386 int 80h call.
|
||
+ */
|
||
+ asm volatile ("syscall"
|
||
+ : "=a" (ret)
|
||
+ : "0" (SYS_futex),
|
||
+ "D" (futex),
|
||
+ "S" (op),
|
||
+ "d" (val),
|
||
+ "c" (timeout)
|
||
+ : "r11", "rcx", "memory"
|
||
+ );
|
||
+
|
||
+ return ret;
|
||
+
|
||
+}
|
||
+
|
||
+
|
||
+static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
|
||
+
|
||
+ int prev;
|
||
+
|
||
+ asm volatile ("LOCK cmpxchgl %1, %2"
|
||
+ : "=a" (prev)
|
||
+ : "r" (new),
|
||
+ "m" (*(ptr)),
|
||
+ "0"(old)
|
||
+ : "memory", "cc"
|
||
+ );
|
||
+
|
||
+ return prev;
|
||
+}
|
||
+
|
||
+static inline int apc_xchg(volatile int *ptr, int new) {
|
||
+
|
||
+ int ret;
|
||
+
|
||
+ asm volatile ("LOCK xchgl %[new], %[ptr]"
|
||
+ : "=a" (ret)
|
||
+ : [new] "0" (new),
|
||
+ [ptr] "m" (*(ptr))
|
||
+ : "memory"
|
||
+ );
|
||
+
|
||
+ return ret;
|
||
+
|
||
+}
|
||
+
|
||
diff -ubrN php-5.2.5-orig/ext/apc/CHANGELOG php-5.2.5/ext/apc/CHANGELOG
|
||
--- php-5.2.5-orig/ext/apc/CHANGELOG 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/CHANGELOG 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,211 @@
|
||
+3.0.16: 2007-12-26
|
||
+- Fix for longstanding cache-full crash (Christian Seiler)
|
||
+ http://news.php.net/php.pecl.dev/4951 for the details
|
||
+- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
|
||
+- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
|
||
+- Minor cleanups (Lucas Nealan)
|
||
+- Added configure option to enable apc_cache_info('filehits') (Shire)
|
||
+
|
||
+3.0.15: 2007-10-18
|
||
+- Eliminate a per-request time() syscall (Rasmus)
|
||
+- Added rfc1867 prefix, name, and freq ini options (Shire)
|
||
+- Allow deletion of individual user cache entries via apc.php (Sara)
|
||
+- Fix overzealous cleanup during RSHUTDOWN (Gopal)
|
||
+- Fix memory alignment and locking issues (Gopal)
|
||
+- Make apc_compile insert/replace entries (Shire)
|
||
+- Make mixed inheritance recompile & cache afresh (Gopal)
|
||
+- Make nostat mode search include_path for canonicalization (Gopal)
|
||
+- ZTS & other compile fixes (Gopal, Edin, Shire)
|
||
+
|
||
+3.0.14: 2007-03-21
|
||
+- Build fix (Shire)
|
||
+- Don't hook the upload hook if APC is disabled (Rasmus)
|
||
+- Local shadow cache support (Gopal)
|
||
+- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
|
||
+- Fix apc_add() to overwrite timed out user entries (Rasmus)
|
||
+- Fix double inclusion of files with conditional classes in php4 (Gopal)
|
||
+- Allocator fixes to reduce fragmentation (Gopal)
|
||
+
|
||
+3.0.13: 2007-02-24
|
||
+- File upload progress (Rasmus)
|
||
+- Pthread mutex and spin locks (Shire)
|
||
+- Recursive zval support for apc_fetch/_store (Shire, Gopal)
|
||
+- apc.stat_ctime flag for ctime checks (Rasmus)
|
||
+- Multiple key fetches with apc_fetch (Shire)
|
||
+- Canary checks for shm memory deallocation (Gopal)
|
||
+- Add hooks for external optimizer (Shire)
|
||
+- Obsolete and remove apc optimizer (Gopal)
|
||
+- APC info changes - cache insert rate, hit and miss rates (Shire)
|
||
+- Fix apc_load_constants (Gopal)
|
||
+- Rewrite dump opcode code to use vld (Gopal)
|
||
+- Use apc_[ewn]print functions for error reporting (Shire)
|
||
+- Auto global fixes and refactoring (Gopal, Shire)
|
||
+- Fix memory leaks in object serialization (Ilia)
|
||
+- Memory cleanup code for destructor order (Gopal)
|
||
+- Win32 build fixes (Ilia, Wez)
|
||
+- ZTS and Php 4 build fixes (Bjori)
|
||
+- Add apc_add() function (Rasmus)
|
||
+- Add optional limited flag to apc_sma_info() (Rasmus)
|
||
+
|
||
+3.0.12p2: 2006-09-05
|
||
+- Package version up
|
||
+
|
||
+3.0,12p1: 2006-09-05
|
||
+- PHP4 build fixes
|
||
+
|
||
+3.0.12: 2006-09-05
|
||
+- PHP 5.2 compatibility (Gopal)
|
||
+- TSRM fixes (Gopal)
|
||
+- Add extra flags to op_array->reserved to improve op array
|
||
+ processing code (Gopal)
|
||
+- Fix crashes in optimizer and cli mode (Ilia)
|
||
+- Optimizer fixes for PHP5 (Ilia, Gopal)
|
||
+- Allow multiple inclusions of a file with a dynamic class (Gopal)
|
||
+- Php 4 function table and properties fixes (Gopal)
|
||
+- Fix memory leaks in apc_cache_info (Gopal)
|
||
+
|
||
+3.0.11: 2006-08-16
|
||
+- Made --enable-apc-mmap the default compile option (for real this time)
|
||
+- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
|
||
+ only fetch header information to make it useful when you have tens of
|
||
+ thousands of entries. (Brian Shire)
|
||
+- 64-bit fixes (George)
|
||
+- Don't mix Full Path and Inode keys (George)
|
||
+- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
|
||
+ require_once() and include_once() statements. (Sara)
|
||
+- Add a non-blocking write_lock for cache inserts. This is a better approach
|
||
+ to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
|
||
+- A bit of work on the optimizer. (Sara)
|
||
+- Various memory issues resolved. (Gopal)
|
||
+
|
||
+3.0.10: 2006-03-11
|
||
+- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
|
||
+ includes will not be stat'ed for any changes. You will have to restart the server if you
|
||
+ change anything. This mode increases performance quite a bit, especially if you have a
|
||
+ lot of includes.
|
||
+
|
||
+- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
|
||
+ than it solves. I'll need to revisit locking and signal handling at some point soon.
|
||
+
|
||
+3.0.9: 2006-03-04
|
||
+- Eliminate rand() call when slam_defense is not set (Rasmus)
|
||
+- Fix for __isset problem (Gopal)
|
||
+- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
|
||
+- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
|
||
+- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
|
||
+- Add cache busy flag which is set when an expunge is underway (Rasmus)
|
||
+- Add automatic serialization of objects in apc_store() (Marcus)
|
||
+- 64-bit .ini flag fix (Rasmus)
|
||
+- Static members fix (Gopal)
|
||
+- sma_cleanup() mem leak fix (Rasmus)
|
||
+- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
|
||
+- Fix autoglobals JIT bug (Gopal)
|
||
+- Fix instance bug (Gopal)
|
||
+- Add a lock cleanup safety net to request shutdown (Rasmus)
|
||
+- Fix apc.slam_defense edge-case bug (Rasmus)
|
||
+- User entry memory usage tracking support (Ilia)
|
||
+- 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)
|
||
+
|
||
+3.0.8: 2005-08-24
|
||
+Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
|
||
+Cache corruption fix in cache-full cleanup code (Gopal)
|
||
+
|
||
+3.0.7: 2005-08-16
|
||
+- Fix to apc.php to show final segment in frag chart. (Ilia)
|
||
+- A couple of win32 fixes. (Frank)
|
||
+- Add apc.enable_cli ini directive. (Rasmus)
|
||
+- Add test cases. (Marcus)
|
||
+- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
|
||
+- Simplify user cache handling by removing the user_cache_stack (Rasmus)
|
||
+- Fix apc_fetch() memory corruption (Andrei,Rasmus)
|
||
+- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
|
||
+
|
||
+3.0.6: 2005-07-30
|
||
+- Added apc.php to package.xml file.
|
||
+- Track per-entry memory usage. (Val)
|
||
+- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
|
||
+- fcntl locking robustness fixes. (Rasmus)
|
||
+- Shared read-locks where possible. (Rasmus)
|
||
+- Added file_update_protection configuration parameter. (Rasmus)
|
||
+- Windows ZTS fixes (Frank)
|
||
+
|
||
+3.0.5: 2005-07-27
|
||
+- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
|
||
+- Support extensions such as bcompiler that need to hook into compile_file. (Val)
|
||
+- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
|
||
+- Segfault in cache cleanup code (Ilia, Rasmus)
|
||
+
|
||
+3.0.4: 2005-07-18
|
||
+- Add win32 support (Edin )
|
||
+- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
|
||
+- A couple of other minor fixes
|
||
+
|
||
+3.0.3: 2005-07-05
|
||
+- Fix compile problem against PHP 5.0.x
|
||
+
|
||
+3.0.2: 2005-07-05
|
||
+- Better shm error message
|
||
+
|
||
+3.0.1: 2005-07-05
|
||
+- PHP4 build fix
|
||
+
|
||
+3.0: 2005-06-23
|
||
+- PHP 5.1 support (Arun, Gopal, Rasmus)
|
||
+- Major Inheritance bug fix (Arun, Gopal)
|
||
+
|
||
+2.0: 2003-02-10
|
||
+- ground-up rewrite sharing none of the original source code (djc)
|
||
+
|
||
+1.0.10:
|
||
+- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
|
||
+- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
|
||
+ this parameter to your php.ini file to activate apc shm or mmap caching
|
||
+- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
|
||
+ 2001-05-15]
|
||
+- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
|
||
+- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
|
||
+- experminental 'fast' cache-retrieval [djc 2001-05-20]
|
||
+- fixed regex support [gws 2001-05-16]
|
||
+- enhanced reader-writer lock support [rg 2001-05-07]
|
||
+
|
||
+1.0.9:
|
||
+- fixed (?) memory alignment bug on 64 bit archiecures
|
||
+- added many cache visibiliy functions
|
||
+- added opional fcntl locks under shm version
|
||
+- numerous bug fixes
|
||
+
|
||
+1.0.8:
|
||
+- added ability to detect and decompile compiled files placed as 'source'
|
||
+ [gws,dw 2001-01-30]
|
||
+- fixed apc_rstat bug [gws 2001-01-29]
|
||
+- added hack to support included urls [gws 2001-01-30]
|
||
+- fixed apc_cache_index [mb 2001-01-31]
|
||
+- added multiple regex support [gs 2001-02-03]
|
||
+- added apc_cache_info [mb,gs 2001-02-03]
|
||
+
|
||
+1.0.7:
|
||
+- partially fixed for Solaris [gws 2001-01-29]
|
||
+- fixed mtime support for relative includes [gws 2001-01-29]
|
||
+- code cleanup [yg,ta,gws 2001-01-29]
|
||
+
|
||
+1.0.6:
|
||
+- support for mtime in mmap [yg,gws 2001-01-27]
|
||
+- fixed indexed-array initialization bug [djc,gws 2001-01-27]
|
||
+
|
||
+1.0.5:
|
||
+- support for relative include paths [djc,gws 2001-01-19]
|
||
+- class member array support fixed [djc 2001-01-18]
|
||
+- added apc_cache_index [gws 2001-01-18]
|
||
+
|
||
+1.0.4:
|
||
+- support for class hierarchies greater than two levels deep [djc 2001-01-17]
|
||
+
|
||
+1.0.3:
|
||
+- fixed support for class inheritance [djc 2001-01-16]
|
||
+
|
||
+1.0.2:
|
||
+- support for inherited classes [gws 2001-01-15]
|
||
+- support for intialization of class variables and objects [gws 2001-01-13]
|
||
+
|
||
+1.0.1:
|
||
+- added optional file modification time check [djc 2001-01-12]
|
||
diff -ubrN php-5.2.5-orig/ext/apc/config.m4 php-5.2.5/ext/apc/config.m4
|
||
--- php-5.2.5-orig/ext/apc/config.m4 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/config.m4 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,238 @@
|
||
+dnl
|
||
+dnl $Id: config.m4,v 3.30 2007/12/26 22:31:20 rasmus Exp $
|
||
+dnl
|
||
+
|
||
+AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
|
||
+AC_ARG_WITH(apxs,
|
||
+[ --with-apxs[=FILE] Get compiler flags from apxs -q. Provide the
|
||
+ pathname to the Apache apxs tool; defaults to "apxs".],[
|
||
+ if test "$withval" != "no"; then
|
||
+ if test "$withval" = "yes"; then
|
||
+ APXS=apxs
|
||
+ $APXS -q CFLAGS >/dev/null 2>&1
|
||
+ if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
|
||
+ APXS=/usr/sbin/apxs
|
||
+ elif test -x /usr/bin/apxs2; then
|
||
+ APXS=/usr/bin/apxs2
|
||
+ elif test -x /usr/sbin/apxs2; then
|
||
+ APXS=/usr/sbin/apxs2
|
||
+ fi
|
||
+ else
|
||
+ PHP_EXPAND_PATH($withval, APXS)
|
||
+ fi
|
||
+
|
||
+ $APXS -q CFLAGS >/dev/null 2>&1
|
||
+ if test "$?" != "0"; then
|
||
+ AC_MSG_RESULT()
|
||
+ AC_MSG_RESULT()
|
||
+ AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:])
|
||
+ AC_MSG_RESULT()
|
||
+ AC_MSG_RESULT([1. Perl is not installed;])
|
||
+ AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);])
|
||
+ AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs])
|
||
+ AC_MSG_RESULT([The output of $APXS follows])
|
||
+ $APXS -q CFLAGS
|
||
+ AC_MSG_ERROR([Aborting])
|
||
+ fi
|
||
+
|
||
+ APC_CFLAGS=`$APXS -q CFLAGS`
|
||
+ AC_MSG_RESULT(yes)
|
||
+ else
|
||
+ AC_MSG_RESULT(no)
|
||
+ fi
|
||
+],[
|
||
+ AC_MSG_RESULT(no)
|
||
+])
|
||
+
|
||
+PHP_ARG_ENABLE(apc, whether to enable APC support,
|
||
+[ --enable-apc Enable APC support])
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should enable cache request file info)
|
||
+AC_ARG_ENABLE(apc-filehits,
|
||
+[ --enable-apc-filehits Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
|
||
+[
|
||
+ PHP_APC_FILEHITS=$enableval
|
||
+ AC_MSG_RESULT($enableval)
|
||
+],
|
||
+[
|
||
+ PHP_APC_FILEHITS=no
|
||
+ AC_MSG_RESULT(no)
|
||
+])
|
||
+
|
||
+
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should use mmap)
|
||
+AC_ARG_ENABLE(apc-mmap,
|
||
+[ --disable-apc-mmap
|
||
+ Disable mmap support and use IPC shm instead],
|
||
+[
|
||
+ PHP_APC_MMAP=$enableval
|
||
+ AC_MSG_RESULT($enableval)
|
||
+], [
|
||
+ PHP_APC_MMAP=yes
|
||
+ AC_MSG_RESULT(yes)
|
||
+])
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
|
||
+AC_ARG_ENABLE(apc-sem,
|
||
+[ --enable-apc-sem
|
||
+ Enable semaphore locks instead of fcntl],
|
||
+[
|
||
+ PHP_APC_SEM=$enableval
|
||
+ AC_MSG_RESULT($enableval)
|
||
+], [
|
||
+ PHP_APC_SEM=no
|
||
+ AC_MSG_RESULT(no)
|
||
+])
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should use futex locking)
|
||
+AC_ARG_ENABLE(apc-futex,
|
||
+[ --enable-apc-futex
|
||
+ Enable linux futex based locks EXPERIMENTAL ],
|
||
+[
|
||
+ PHP_APC_FUTEX=$enableval
|
||
+ AC_MSG_RESULT($enableval)
|
||
+],
|
||
+[
|
||
+ PHP_APC_FUTEX=no
|
||
+ AC_MSG_RESULT(no)
|
||
+])
|
||
+
|
||
+if test "$PHP_APC_FUTEX" != "no"; then
|
||
+ 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.]); ] )
|
||
+fi
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
|
||
+AC_ARG_ENABLE(apc-pthreadmutex,
|
||
+[ --disable-apc-pthreadmutex
|
||
+ Disable pthread mutex locking ],
|
||
+[
|
||
+ PHP_APC_PTHREADMUTEX=no
|
||
+ AC_MSG_RESULT(no)
|
||
+],
|
||
+[
|
||
+ PHP_APC_PTHREADMUTEX=yes
|
||
+ AC_MSG_RESULT(yes)
|
||
+])
|
||
+if test "$PHP_APC_PTHREADMUTEX" != "no"; then
|
||
+ orig_LIBS="$LIBS"
|
||
+ LIBS="$LIBS -lpthread"
|
||
+ AC_TRY_RUN(
|
||
+ [
|
||
+ #include <sys/types.h>
|
||
+ #include <pthread.h>
|
||
+ main() {
|
||
+ pthread_mutex_t mutex;
|
||
+ pthread_mutexattr_t attr;
|
||
+
|
||
+ if(pthread_mutexattr_init(&attr)) {
|
||
+ puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
|
||
+ return -1;
|
||
+ }
|
||
+ if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||
+ puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
|
||
+ return -1;
|
||
+ }
|
||
+ if(pthread_mutex_init(&mutex, &attr)) {
|
||
+ puts("Unable to initialize the mutex (pthread_mutex_init).");
|
||
+ return -1;
|
||
+ }
|
||
+ if(pthread_mutexattr_destroy(&attr)) {
|
||
+ puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
|
||
+ return -1;
|
||
+ }
|
||
+ if(pthread_mutex_destroy(&mutex)) {
|
||
+ puts("Unable to destroy mutex (pthread_mutex_destroy).");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ puts("pthread mutex's are supported!");
|
||
+ return 0;
|
||
+ }
|
||
+ ],
|
||
+ [ dnl -Success-
|
||
+ PHP_ADD_LIBRARY(pthread)
|
||
+ ],
|
||
+ [ dnl -Failure-
|
||
+ AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
|
||
+ PHP_APC_PTHREADMUTEX=no
|
||
+ ],
|
||
+ [
|
||
+ PHP_ADD_LIBRARY(pthread)
|
||
+ ]
|
||
+ )
|
||
+ LIBS="$orig_LIBS"
|
||
+fi
|
||
+
|
||
+AC_MSG_CHECKING(Checking whether we should use spin locks)
|
||
+AC_ARG_ENABLE(apc-spinlocks,
|
||
+[ --enable-apc-spinlocks
|
||
+ Enable spin locks EXPERIMENTAL ],
|
||
+[
|
||
+ PHP_APC_SPINLOCKS=$enableval
|
||
+ AC_MSG_RESULT($enableval)
|
||
+],
|
||
+[
|
||
+ PHP_APC_SPINLOCKS=no
|
||
+ AC_MSG_RESULT(no)
|
||
+])
|
||
+
|
||
+if test "$PHP_APC" != "no"; then
|
||
+ test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
|
||
+ test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
|
||
+
|
||
+ if test "$PHP_APC_SEM" != "no"; then
|
||
+ AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
|
||
+ elif test "$PHP_APC_FUTEX" != "no"; then
|
||
+ AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
|
||
+ elif test "$PHP_APC_SPINLOCKS" != "no"; then
|
||
+ AC_DEFINE(APC_SPIN_LOCKS, 1, [ ])
|
||
+ elif test "$PHP_APC_PTHREADMUTEX" != "no"; then
|
||
+ AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
|
||
+ fi
|
||
+
|
||
+ AC_CHECK_FUNCS(sigaction)
|
||
+ AC_CACHE_CHECK(for union semun, php_cv_semun,
|
||
+ [
|
||
+ AC_TRY_COMPILE([
|
||
+#include <sys/types.h>
|
||
+#include <sys/ipc.h>
|
||
+#include <sys/sem.h>
|
||
+ ], [union semun x;], [
|
||
+ php_cv_semun=yes
|
||
+ ],[
|
||
+ php_cv_semun=no
|
||
+ ])
|
||
+ ])
|
||
+ if test "$php_cv_semun" = "yes"; then
|
||
+ AC_DEFINE(HAVE_SEMUN, 1, [ ])
|
||
+ else
|
||
+ AC_DEFINE(HAVE_SEMUN, 0, [ ])
|
||
+ fi
|
||
+
|
||
+ apc_sources="apc.c php_apc.c \
|
||
+ apc_cache.c \
|
||
+ apc_compile.c \
|
||
+ apc_debug.c \
|
||
+ apc_fcntl.c \
|
||
+ apc_main.c \
|
||
+ apc_mmap.c \
|
||
+ apc_sem.c \
|
||
+ apc_shm.c \
|
||
+ apc_futex.c \
|
||
+ apc_pthreadmutex.c \
|
||
+ apc_spin.c \
|
||
+ pgsql_s_lock.c \
|
||
+ apc_sma.c \
|
||
+ apc_stack.c \
|
||
+ apc_zend.c \
|
||
+ apc_rfc1867.c \
|
||
+ apc_signal.c "
|
||
+
|
||
+ PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
|
||
+ PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
|
||
+ PHP_SUBST(APC_SHARED_LIBADD)
|
||
+ PHP_SUBST(APC_CFLAGS)
|
||
+ AC_DEFINE(HAVE_APC, 1, [ ])
|
||
+fi
|
||
+
|
||
diff -ubrN php-5.2.5-orig/ext/apc/INSTALL php-5.2.5/ext/apc/INSTALL
|
||
--- php-5.2.5-orig/ext/apc/INSTALL 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/INSTALL 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,422 @@
|
||
+Installation Instructions for APC
|
||
+---------------------------------
|
||
+
|
||
+This version of APC should work on PHP 4.3.0 - 4.4.x and
|
||
+5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer
|
||
+supported. Upgrade to PHP 5.1.x or 5.2.x and you will
|
||
+notice all sorts of performance increases.
|
||
+
|
||
+CVS Instructions
|
||
+----------------
|
||
+Building from CVS can be done like this:
|
||
+
|
||
+ cvs -d :pserver:cvsread@cvs.php.net:/repository login
|
||
+ Password: phpfi
|
||
+ cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
|
||
+ cd pecl/apc
|
||
+ phpize
|
||
+ ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
|
||
+ make
|
||
+ make install
|
||
+
|
||
+Suggested Configuration (in your php.ini file)
|
||
+----------------------------------------------
|
||
+ extension=apc.so
|
||
+ apc.enabled=1
|
||
+ apc.shm_segments=1
|
||
+ apc.shm_size=128
|
||
+ apc.ttl=7200
|
||
+ apc.user_ttl=7200
|
||
+ apc.num_files_hint=1024
|
||
+ apc.mmap_file_mask=/tmp/apc.XXXXXX
|
||
+ apc.enable_cli=1
|
||
+
|
||
+These are fully described at the bottom of this file.
|
||
+
|
||
+PHP 4 Optimization
|
||
+------------------
|
||
+If you are trying to get every little bit of speed out of PHP4+APC, you need
|
||
+to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
|
||
+your CPPFLAGS. (if you don't have httpd.h, install the apache_dev package
|
||
+for your OS) and do:
|
||
+ export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
|
||
+ setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
|
||
+and then re-run your configure script.
|
||
+
|
||
+This optimization saves a stat syscall on the main script file. In PHP5 this
|
||
+optimization is automatic and doesn't need any special build flags.
|
||
+
|
||
+The second thing you are going to want to do to save another syscall is to
|
||
+compile using the --with-apxs configure switch. This should work for both
|
||
+Apache1 and Apache2. Point it directly at your apxs2 script for Apache2.
|
||
+eg. --with-apxs=/usr/local/bin/apxs2
|
||
+
|
||
++---------------------+
|
||
+| QUICK INSTALL (DSO) |
|
||
++---------------------+
|
||
+
|
||
+These instructions assume your PHP installation is located in /usr/local/php and you
|
||
+want Apache optimizations (--with-apxs).
|
||
+
|
||
+$ gunzip -c apc_x.y.tar.gz | tar xf -
|
||
+$ cd apc_x.y
|
||
+$ /usr/local/php/bin/phpize
|
||
+$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
|
||
+$ make
|
||
+$ make install
|
||
+
|
||
+You will probably need to run the final command (make install) as root.
|
||
+
|
||
+The above sequence of commands will install a .so file in your PHP
|
||
+installation extension directory. The output of make install should display
|
||
+that path to the screen.
|
||
+
|
||
+Next you must edit your php.ini file, which is normally located in
|
||
+/usr/local/php/lib/php.ini, and add the following line:
|
||
+
|
||
+ extension="apc.so"
|
||
+
|
||
+Replace "/path/to/php/extensions" with whatever path was displayed when you
|
||
+ran make install above.
|
||
+
|
||
+Then restart your web server and consult the output of phpinfo(). If there is
|
||
+an informational section for APC, the installation was successful.
|
||
+
|
||
++------------------------+
|
||
+| QUICK INSTALL (Static) |
|
||
++------------------------+
|
||
+
|
||
+APC will not successfully compile on all systems as a DSO. If you run into
|
||
+problems using the DSO quick install, you can try to compile it statically
|
||
+into PHP. (The DSO install is recommended, though.)
|
||
+
|
||
+These instructions assume the current directory is the root of the PHP source
|
||
+tree, and that you have already configured PHP by running its bundled
|
||
+configure script.
|
||
+
|
||
+$ cd ext
|
||
+$ gunzip -c apc_x.y.tar.gz | tar xf -
|
||
+$ cd ..
|
||
+$ ./buildconf
|
||
+$ ./config.nice
|
||
+$ make
|
||
+$ make install
|
||
+
|
||
+Once this is complete, simply restart your web server. You do not need to
|
||
+modify your php.ini file to enable APC.
|
||
+
|
||
++-----------------+
|
||
+| VERBOSE INSTALL |
|
||
++-----------------+
|
||
+
|
||
+These instructions assume your PHP installation is located in /usr/local/php.
|
||
+
|
||
+1. Unpack your distribution file.
|
||
+
|
||
+ You will have downloaded a file named something like apc_x.y.tar.gz.
|
||
+ Unzip this file with a command like
|
||
+
|
||
+ gunzip apc_x.y.tar.gz
|
||
+
|
||
+ Next you have to untar it with
|
||
+
|
||
+ tar xvf apc_x.y.tar
|
||
+
|
||
+ This will create an apc_x.y directory. cd into this new directory:
|
||
+
|
||
+ cd apc_x.y
|
||
+
|
||
+2. Run phpize.
|
||
+
|
||
+ phpize is a script that should have been installed with PHP, and is
|
||
+ normally located in /usr/local/php/bin assuming you installed PHP in
|
||
+ /usr/local/php. (If you do not have the phpize script, you must reinstall
|
||
+ PHP and be sure not to disable PEAR.)
|
||
+
|
||
+ Run the phpize command:
|
||
+
|
||
+ /usr/local/php/bin/phpize
|
||
+
|
||
+ Its output should resemble this:
|
||
+
|
||
+ autoheader: `config.h.in' is created
|
||
+ You should update your `aclocal.m4' by running aclocal.
|
||
+ Configuring for:
|
||
+ PHP Api Version: 20020918
|
||
+ Zend Module Api No: 20020429
|
||
+ Zend Extension Api No: 20021010
|
||
+
|
||
+ phpize should create a configure script in the current directory. If you
|
||
+ get errors instead, you might be missing some required development tools,
|
||
+ such as autoconf or libtool. You can try downloading the latest versions
|
||
+ of those tools and running phpize again.
|
||
+
|
||
+3. Run the configure script.
|
||
+
|
||
+ phpize creates a configure script. The only option you need to specify is
|
||
+ the location of your php-config script:
|
||
+
|
||
+ ./configure --enable-apc
|
||
+
|
||
+ php-config should be located in the same directory as phpize.
|
||
+
|
||
+ If you prefer to use mmap instead of the default IPC shared memory support,
|
||
+ add --enable-apc-mmap to your configure line.
|
||
+
|
||
+ If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
|
||
+ --enable-sem to your configure line. If you don't have a problem
|
||
+ with your server segaulting, or any other unnatural accumulation of
|
||
+ semaphores on your system, the semaphore based locking is slightly faster.
|
||
+
|
||
+4. Compile and install the files. Simply type: make install
|
||
+
|
||
+ (You may need to be root in order to install)
|
||
+
|
||
+ If you encounter errors from libtool or gcc during this step, please
|
||
+ contact the project maintainer (dcowgill@php.net).
|
||
+
|
||
+5. Edit your php.ini
|
||
+
|
||
+ make install should have printed a line resembling the following:
|
||
+
|
||
+ Installing shared extensions: /path/to/extension/
|
||
+
|
||
+ Copy the path /path/to/extension/ and add the following line to your
|
||
+ php.ini file (normally located in /usr/local/php/lib/php.ini):
|
||
+
|
||
+ extension="apc.so"
|
||
+
|
||
+ If you don't have a php.ini file in that location, you can create it now.
|
||
+
|
||
+6. Restart the web server and test the installation.
|
||
+
|
||
+ Restart your web server now (for apache, it's apachectl restart) and
|
||
+ create a small test PHP file in your document root. The file should
|
||
+ contain just the following line:
|
||
+
|
||
+ <?php phpinfo() ?>
|
||
+
|
||
+ Request that file in a web browser. If there is an entry for APC in the
|
||
+ list of installed modules, the installation was successful.
|
||
+
|
||
+ If APC is not listed, consult your web server error log. If it contains an
|
||
+ error message saying that it can't load the APC extension, your system
|
||
+ might not be able to load shared libraries created with PHP's build
|
||
+ system. One alternative would be to compile APC statically into PHP. See
|
||
+ the Quick Install (Static) instructions above.
|
||
+
|
||
+ You should consult your error log anyway to see if APC generated any
|
||
+ errors. On BSD-based platforms, it is typical for APC to be unable to
|
||
+ allocate the default-sized shared memory segment. See below for hints on
|
||
+ raising your system's shared memory limitations.
|
||
+
|
||
++-----------------+
|
||
+| CONFIGURING APC |
|
||
++-----------------+
|
||
+
|
||
+Although the default APC settings are fine for many installations, serious
|
||
+users should consider tuning the following parameters:
|
||
+
|
||
+ OPTION DESCRIPTION
|
||
+ ------------------ --------------------------------------------------
|
||
+ apc.enabled This can be set to 0 to disable APC. This is
|
||
+ primarily useful when APC is statically compiled
|
||
+ into PHP, since there is no other way to disable
|
||
+ it (when compiled as a DSO, the zend_extension
|
||
+ line can just be commented-out).
|
||
+ (Default: 1)
|
||
+
|
||
+ apc.shm_segments The number of shared memory segments to allocate
|
||
+ for the compiler cache. If APC is running out of
|
||
+ shared memory but you have already set
|
||
+ apc.shm_size as high as your system allows, you
|
||
+ can try raising this value. Setting this to a
|
||
+ value other than 1 has no effect in mmap mode
|
||
+ since mmap'ed shm segments don't have size limits.
|
||
+ (Default: 1)
|
||
+
|
||
+ apc.shm_size The size of each shared memory segment in MB.
|
||
+ By default, some systems (including most BSD
|
||
+ variants) have very low limits on the size of a
|
||
+ shared memory segment.
|
||
+ (Default: 30)
|
||
+
|
||
+ apc.optimization This option has been deprecated.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.num_files_hint A "hint" about the number of distinct source files
|
||
+ that will be included or requested on your web
|
||
+ server. Set to zero or omit if you're not sure;
|
||
+ this setting is mainly useful for sites that have
|
||
+ many thousands of source files.
|
||
+ (Default: 1000)
|
||
+
|
||
+ apc.user_entries_hint Just like num_files_hint, a "hint" about the number
|
||
+ of distinct user cache variables to store.
|
||
+ Set to zero or omit if you're not sure;
|
||
+ (Default: 4096)
|
||
+
|
||
+ apc.ttl The number of seconds a cache entry is allowed to
|
||
+ idle in a slot in case this cache entry slot is
|
||
+ needed by another entry. Leaving this at zero
|
||
+ means that your cache could potentially fill up
|
||
+ with stale entries while newer entries won't be
|
||
+ cached.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.user_ttl The number of seconds a user cache entry is allowed
|
||
+ to idle in a slot in case this cache entry slot is
|
||
+ needed by another entry. Leaving this at zero
|
||
+ means that your cache could potentially fill up
|
||
+ with stale entries while newer entries won't be
|
||
+ cached.
|
||
+ (Default: 0)
|
||
+
|
||
+
|
||
+ apc.gc_ttl The number of seconds that a cache entry may
|
||
+ remain on the garbage-collection list. This value
|
||
+ provides a failsafe in the event that a server
|
||
+ process dies while executing a cached source file;
|
||
+ if that source file is modified, the memory
|
||
+ allocated for the old version will not be
|
||
+ reclaimed until this TTL reached. Set to zero to
|
||
+ disable this feature.
|
||
+ (Default: 3600)
|
||
+
|
||
+ apc.cache_by_default On by default, but can be set to off and used in
|
||
+ conjunction with positive apc.filters so that files
|
||
+ are only cached if matched by a positive filter.
|
||
+ (Default: On)
|
||
+
|
||
+ apc.filters A comma-separated list of POSIX extended regular
|
||
+ expressions. If any pattern matches the source
|
||
+ filename, the file will not be cached. Note that
|
||
+ the filename used for matching is the one passed
|
||
+ to include/require, not the absolute path. If the
|
||
+ first character of the expression is a + then the
|
||
+ expression will be additive in the sense that any
|
||
+ files matched by the expression will be cached, and
|
||
+ if the first character is a - then anything matched
|
||
+ will not be cached. The - case is the default, so
|
||
+ it can be left off.
|
||
+ (Default: "")
|
||
+
|
||
+ apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap
|
||
+ this is the mktemp-style file_mask to pass to the
|
||
+ mmap module for determing whether your mmap'ed memory
|
||
+ region is going to be file-backed or shared memory
|
||
+ backed. For straight file-backed mmap, set it to
|
||
+ something like /tmp/apc.XXXXXX (exactly 6 X's).
|
||
+ To use POSIX-style shm_open/mmap put a ".shm"
|
||
+ somewhere in your mask. eg. "/apc.shm.XXXXXX"
|
||
+ You can also set it to "/dev/zero" to use your
|
||
+ kernel's /dev/zero interface to anonymous mmap'ed
|
||
+ memory. Leaving it undefined will force an
|
||
+ anonymous mmap.
|
||
+ (Default: "")
|
||
+
|
||
+ apc.slam_defense ** DEPRECATED - Use apc.write_lock instead **
|
||
+ On very busy servers whenever you start the server or
|
||
+ modify files you can create a race of many processes
|
||
+ all trying to cache the same file at the same time.
|
||
+ This option sets the percentage of processes that will
|
||
+ skip trying to cache an uncached file. Or think of it
|
||
+ as the probability of a single process to skip caching.
|
||
+ For example, setting this to 75 would mean that there is
|
||
+ a 75% chance that the process will not cache an uncached
|
||
+ file. So the higher the setting the greater the defense
|
||
+ against cache slams. Setting this to 0 disables this
|
||
+ feature.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.file_update_protection
|
||
+ When you modify a file on a live web server you really
|
||
+ should do so in an atomic manner. That is, write to a
|
||
+ temporary file and rename (mv) the file into its permanent
|
||
+ position when it is ready. Many text editors, cp, tar and
|
||
+ other such programs don't do this. This means that there
|
||
+ is a chance that a file is accessed (and cached) while it
|
||
+ is still being written to. This file_update_protection
|
||
+ setting puts a delay on caching brand new files. The
|
||
+ default is 2 seconds which means that if the modification
|
||
+ timestamp (mtime) on a file shows that it is less than 2
|
||
+ seconds old when it is accessed, it will not be cached.
|
||
+ The unfortunate person who accessed this half-written file
|
||
+ will still see weirdness, but at least it won't persist.
|
||
+ If you are certain you always atomically update your files
|
||
+ by using something like rsync which does this correctly, you
|
||
+ can turn this protection off by setting it to 0. If you
|
||
+ have a system that is flooded with io causing some update
|
||
+ procedure to take longer than 2 seconds, you may want to
|
||
+ increase this a bit.
|
||
+ (Default: 2)
|
||
+
|
||
+ apc.enable_cli Mostly for testing and debugging. Setting this enables APC
|
||
+ for the CLI version of PHP. Normally you wouldn't want to
|
||
+ create, populate and tear down the APC cache on every CLI
|
||
+ request, but for various test scenarios it is handy to be
|
||
+ able to enable APC for the CLI version of APC easily.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.max_file_size Prevents large files from being cached.
|
||
+ (Default: 1M)
|
||
+
|
||
+ apc.stat Whether to stat the main script file and the fullpath
|
||
+ includes. If you turn this off you will need to restart
|
||
+ your server in order to update scripts.
|
||
+ (Default: 1)
|
||
+
|
||
+ apc.write_lock On busy servers when you first start up the server, or when
|
||
+ many files are modified, you can end up with all your processes
|
||
+ trying to compile and cache the same files. With write_lock
|
||
+ enabled, only one process at a time will try to compile an
|
||
+ uncached script while the other processes will run uncached
|
||
+ instead of sitting around waiting on a lock.
|
||
+ (Default: 1)
|
||
+
|
||
+ apc.report_autofilter Logs any scripts that were automatically excluded from being
|
||
+ cached due to early/late binding issues.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.rfc1867 RFC1867 File Upload Progress hook handler is only available
|
||
+ if you compiled APC against PHP 5.2.0 or later. When enabled
|
||
+ any file uploads which includes a field called
|
||
+ APC_UPLOAD_PROGRESS before the file field in an upload form
|
||
+ will cause APC to automatically create an upload_<key>
|
||
+ user cache entry where <key> is the value of the
|
||
+ APC_UPLOAD_PROGRESS form entry.
|
||
+
|
||
+ Note that the file upload tracking is not threadsafe at this
|
||
+ point, so new uploads that happen while a previous one is
|
||
+ still going will disable the tracking for the previous.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.rfc1867_prefix Key prefix to use for the user cache entry generated by
|
||
+ rfc1867 upload progress functionality.
|
||
+ (Default: "upload_")
|
||
+
|
||
+ apc.rfc1867_name Specify the hidden form entry name that activates APC upload
|
||
+ progress and specifies the user cache key suffix.
|
||
+ (Default: "APC_UPLOAD_PROGRESS")
|
||
+
|
||
+ apc.rfc1867_freq The frequency that updates should be made to the user cache
|
||
+ entry for upload progress. This can take the form of a
|
||
+ percentage of the total file size or a size in bytes
|
||
+ optionally suffixed with 'k', 'm', or 'g' for kilobytes,
|
||
+ megabytes, or gigabytes respectively (case insensitive).
|
||
+ A setting of 0 updates as often as possible, which may cause
|
||
+ slower uploads.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.localcache This enables a lock-free local process shadow-cache which
|
||
+ reduces lock contention when the cache is being written to.
|
||
+ (Default: 0)
|
||
+
|
||
+ apc.localcache.size The size of the local process shadow-cache, should be set to
|
||
+ a sufficently large value, approximately half of num_files_hint.
|
||
+ (Default: 512)
|
||
+
|
||
+ apc.include_once_override
|
||
+ Optimize include_once and require_once calls and avoid the
|
||
+ expensive system calls used.
|
||
+ (Default: 0)
|
||
diff -ubrN php-5.2.5-orig/ext/apc/LICENSE php-5.2.5/ext/apc/LICENSE
|
||
--- php-5.2.5-orig/ext/apc/LICENSE 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/LICENSE 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,68 @@
|
||
+--------------------------------------------------------------------
|
||
+ The PHP License, version 3.01
|
||
+Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
|
||
+--------------------------------------------------------------------
|
||
+
|
||
+Redistribution and use in source and binary forms, with or without
|
||
+modification, is permitted provided that the following conditions
|
||
+are met:
|
||
+
|
||
+ 1. Redistributions of source code must retain the above copyright
|
||
+ notice, this list of conditions and the following disclaimer.
|
||
+
|
||
+ 2. Redistributions in binary form must reproduce the above copyright
|
||
+ notice, this list of conditions and the following disclaimer in
|
||
+ the documentation and/or other materials provided with the
|
||
+ distribution.
|
||
+
|
||
+ 3. The name "PHP" must not be used to endorse or promote products
|
||
+ derived from this software without prior written permission. For
|
||
+ written permission, please contact group@php.net.
|
||
+
|
||
+ 4. Products derived from this software may not be called "PHP", nor
|
||
+ may "PHP" appear in their name, without prior written permission
|
||
+ from group@php.net. You may indicate that your software works in
|
||
+ conjunction with PHP by saying "Foo for PHP" instead of calling
|
||
+ it "PHP Foo" or "phpfoo"
|
||
+
|
||
+ 5. The PHP Group may publish revised and/or new versions of the
|
||
+ license from time to time. Each version will be given a
|
||
+ distinguishing version number.
|
||
+ Once covered code has been published under a particular version
|
||
+ of the license, you may always continue to use it under the terms
|
||
+ of that version. You may also choose to use such covered code
|
||
+ under the terms of any subsequent version of the license
|
||
+ published by the PHP Group. No one other than the PHP Group has
|
||
+ the right to modify the terms applicable to covered code created
|
||
+ under this License.
|
||
+
|
||
+ 6. Redistributions of any form whatsoever must retain the following
|
||
+ acknowledgment:
|
||
+ "This product includes PHP software, freely available from
|
||
+ <http://www.php.net/software/>".
|
||
+
|
||
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
|
||
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
|
||
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||
+OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
+
|
||
+--------------------------------------------------------------------
|
||
+
|
||
+This software consists of voluntary contributions made by many
|
||
+individuals on behalf of the PHP Group.
|
||
+
|
||
+The PHP Group can be contacted via Email at group@php.net.
|
||
+
|
||
+For more information on the PHP Group and the PHP project,
|
||
+please see <http://www.php.net>.
|
||
+
|
||
+PHP includes the Zend Engine, freely available at
|
||
+<http://www.zend.com>.
|
||
diff -ubrN php-5.2.5-orig/ext/apc/NOTICE php-5.2.5/ext/apc/NOTICE
|
||
--- php-5.2.5-orig/ext/apc/NOTICE 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/NOTICE 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,43 @@
|
||
+This is the NOTICE file that holds acknowledgements and stuff.
|
||
+
|
||
+The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
|
||
+This extension is being released under the PHP License for complete compliance
|
||
+with PHP and to encourage wide-spread use. It is our intention that this
|
||
+project be kept open source and that all commercial spin-offs contribute their
|
||
+modifications back into the public source-tree.
|
||
+
|
||
+Creators:
|
||
+ Daniel Cowgill
|
||
+ George Schlossnagle
|
||
+
|
||
+PHP5 support and major features by:
|
||
+ Arun C. Murthy
|
||
+ Gopal Vijayaraghavan
|
||
+ Rasmus Lerdorf
|
||
+
|
||
+This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+Future revisions and derivatives of this source code must acknowledge
|
||
+Community Connect Inc. as the original contributor of this module by
|
||
+leaving this note intact in the source code.
|
||
+
|
||
+All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting
|
||
+this project and providing a challenging and stimulating environment in
|
||
+which exciting projects can happen.
|
||
+
|
||
+Contributors:
|
||
+ Mike Bretz bug fixes, GUI, and lots of work
|
||
+ Ricardo Galli changed read-write locks to prefer readers
|
||
+ Yann Grossel bug fixes
|
||
+ Thies Arntzen bug fixes
|
||
+ Sara Golemon optimizer work
|
||
+
|
||
+Special Thanks:
|
||
+ Florian Baumert help debugging phplib problems
|
||
+ Thomas Duffey help debugging inheritance issues
|
||
+ Vibol Hou help debugging phplib problems
|
||
+ Angel Li diffs for ANSI comment compliance
|
||
+ Christian Rish<73>j help debugging phplib problems
|
||
+ Sascha Schumann memory error bug fix
|
||
diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
|
||
--- php-5.2.5-orig/ext/apc/package.xml 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/package.xml 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,534 @@
|
||
+<?xml version="1.0" encoding="UTF-8"?>
|
||
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
|
||
+ <name>APC</name>
|
||
+ <channel>pecl.php.net</channel>
|
||
+ <summary>Alternative PHP Cache</summary>
|
||
+ <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
|
||
+ <lead>
|
||
+ <name>Daniel Cowgill</name>
|
||
+ <user>dcowgill</user>
|
||
+ <email>dan@mail.communityconnect.com</email>
|
||
+ <active>no</active>
|
||
+ </lead>
|
||
+ <lead>
|
||
+ <name>George Schlossnagle</name>
|
||
+ <user>gschlossnagle</user>
|
||
+ <email>george@omniti.com</email>
|
||
+ <active>no</active>
|
||
+ </lead>
|
||
+ <lead>
|
||
+ <name>Rasmus Lerdorf</name>
|
||
+ <user>rasmus</user>
|
||
+ <email>rasmus@php.net</email>
|
||
+ <active>yes</active>
|
||
+ </lead>
|
||
+ <lead>
|
||
+ <name>Gopal Vijayaraghavan</name>
|
||
+ <user>gopalv</user>
|
||
+ <email>gopalv@php.net</email>
|
||
+ <active>yes</active>
|
||
+ </lead>
|
||
+ <developer>
|
||
+ <name>Edin Kadribasic</name>
|
||
+ <user>edink</user>
|
||
+ <email>edink@emini.dk</email>
|
||
+ <active>yes</active>
|
||
+ </developer>
|
||
+ <developer>
|
||
+ <name>Ilia Alshanetsky</name>
|
||
+ <user>iliaa</user>
|
||
+ <email>ilia@prohost.org</email>
|
||
+ <active>yes</active>
|
||
+ </developer>
|
||
+ <developer>
|
||
+ <name>Marcus Börger</name>
|
||
+ <user>helly</user>
|
||
+ <email>helly@php.net</email>
|
||
+ <active>yes</active>
|
||
+ </developer>
|
||
+ <developer>
|
||
+ <name>Sara Golemon</name>
|
||
+ <user>pollita</user>
|
||
+ <email>pollita@php.net</email>
|
||
+ <active>yes</active>
|
||
+ </developer>
|
||
+ <developer>
|
||
+ <name>Brian Shire</name>
|
||
+ <user>shire</user>
|
||
+ <email>shire@php.net</email>
|
||
+ <active>yes</active>
|
||
+ </developer>
|
||
+ <date>2007-12-26</date>
|
||
+ <time>14:51:32</time>
|
||
+ <version>
|
||
+ <release>3.0.16</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <license uri="http://www.php.net/license">PHP License</license>
|
||
+ <notes>* Fix for longstanding cache-full crash (Christian Seiler)
|
||
+ http://news.php.net/php.pecl.dev/4951 for the details
|
||
+* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
|
||
+* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
|
||
+* Minor cleanups (Lucas Nealan)
|
||
+* Added configure option to enable apc_cache_info('filehits') (Shire)</notes>
|
||
+ <contents>
|
||
+ <dir name="/">
|
||
+ <file md5sum="841596cff3b9bd83e79d01ccb591ff55" name="tests/apc_001.phpt" role="test" />
|
||
+ <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
|
||
+ <file md5sum="411fdc85b170ec696298d38f93132d6b" name="tests/apc_003.phpt" role="test" />
|
||
+ <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
|
||
+ <file md5sum="2a2e8b29dba8df697dbd81b306ccbe73" name="arch/i386/atomic.h" role="src" />
|
||
+ <file md5sum="7f01c5cd3a1742c20d6d285f119596a6" name="arch/x86_64/atomic.h" role="src" />
|
||
+ <file md5sum="26748a0d6567c5611408eb69fb25c671" name="arch/atomic.h" role="src" />
|
||
+ <file md5sum="0714a0039d9ea63cfc26043a7d86f04c" name="CHANGELOG" role="doc" />
|
||
+ <file md5sum="3b6ad608e37fb34b24afb90084b4770b" name="INSTALL" role="doc" />
|
||
+ <file md5sum="694f49a7e1f276ba75a3dd2c5acd580d" name="LICENSE" role="doc" />
|
||
+ <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
|
||
+ <file md5sum="efa40416571fc54aa59912203c0391e6" name="TODO" role="doc" />
|
||
+ <file md5sum="b7dd14328e218d3ecc97d85fb83d7ba7" name="TECHNOTES.txt" role="doc" />
|
||
+ <file md5sum="c4384f370db6a6112d6c21268bc9a278" name="apc.c" role="src" />
|
||
+ <file md5sum="09a525ff9a3850e6de42eee2adf07463" name="apc.dsp" role="src" />
|
||
+ <file md5sum="109694ee417962096eb3e962d6bcce8a" name="apc.h" role="src" />
|
||
+ <file md5sum="ee19b49ef26dbd491b846a19f9bc9e6a" name="apc_cache.c" role="src" />
|
||
+ <file md5sum="e0a4f0c5a49a0beba10f2f831e1b63b6" name="apc_cache.h" role="src" />
|
||
+ <file md5sum="7576310688084dd737f7c7bc11c75e22" name="apc_compile.c" role="src" />
|
||
+ <file md5sum="a0eea1abcf4ec395ea9a195e98c2cc65" name="apc_compile.h" role="src" />
|
||
+ <file md5sum="64bbe1f8cf18261255ef5874039e76e9" name="apc_debug.c" role="src" />
|
||
+ <file md5sum="46d182a6122f3c29a1904f62af7cfb51" name="apc_debug.h" role="src" />
|
||
+ <file md5sum="3dbdb44d0fc2d45ae15719b4fc5746cd" name="apc_fcntl.c" role="src" />
|
||
+ <file md5sum="f4fc86769ce871d42ce0085fa7323d79" name="apc_fcntl.h" role="src" />
|
||
+ <file md5sum="9dffe726c9b6cfdd640e07782a0f409b" name="apc_futex.c" role="src" />
|
||
+ <file md5sum="ff999238a10bfb6b715e4e8f54ec8326" name="apc_futex.h" role="src" />
|
||
+ <file md5sum="33d241202d41095bc1b6fdafc1063cb9" name="apc_globals.h" role="src" />
|
||
+ <file md5sum="3e6f98c635b18902aab221f29d8b70ec" name="apc_lock.h" role="src" />
|
||
+ <file md5sum="0667187c715fea98569b51a491fb445b" name="apc_main.c" role="src" />
|
||
+ <file md5sum="2e8f99d31b4d088eb14859c6e137544a" name="apc_main.h" role="src" />
|
||
+ <file md5sum="e9e447ef3994b85d064c9a49f7ed0917" name="apc_mmap.c" role="src" />
|
||
+ <file md5sum="a22df1256e20fef8160bbf9529723b50" name="apc_php.h" role="src" />
|
||
+ <file md5sum="c285337c2e0b852de9f79ac5015a3fa7" name="apc_pthreadmutex.c" role="src" />
|
||
+ <file md5sum="e4e6943b0cfb31facd1148c2dbfc4c93" name="apc_pthreadmutex.h" role="src" />
|
||
+ <file md5sum="ea3822772adb45e0046faef855c32aba" name="apc_sem.c" role="src" />
|
||
+ <file md5sum="1a7fb689f8d5b01fad537b277c81d59f" name="apc_sem.h" role="src" />
|
||
+ <file md5sum="632e60d387e5555f4aa03a8948f52ea7" name="apc_shm.c" role="src" />
|
||
+ <file md5sum="6de8e94976f01b2f48ef97020a008774" name="apc_shm.h" role="src" />
|
||
+ <file md5sum="25d3e2a3d1c2f9afa8e103492ca7e89e" name="apc_sma.c" role="src" />
|
||
+ <file md5sum="fdc0aebc501f2e29389611fa61084da0" name="apc_sma.h" role="src" />
|
||
+ <file md5sum="ecd6cc1d56d99dbb7364d40c975fca5e" name="apc_spin.c" role="src" />
|
||
+ <file md5sum="c716852258453471a6927f95a617e30f" name="apc_spin.h" role="src" />
|
||
+ <file md5sum="17cceda297a61a9185bcafd7d897fad4" name="apc_stack.c" role="src" />
|
||
+ <file md5sum="db2f213a3e616313d7864222874197ea" name="apc_stack.h" role="src" />
|
||
+ <file md5sum="8cccb8ecfa2d5a893537b2c1a8b6b718" name="apc_zend.c" role="src" />
|
||
+ <file md5sum="2ee61624ec5d779d02746ba7254aed14" name="apc_zend.h" role="src" />
|
||
+ <file md5sum="113d74a5e70119a63fb86815bf50d03b" name="apc_signal.c" role="src" />
|
||
+ <file md5sum="af4c7d0595ce32346f7ee37707d7dada" name="apc_signal.h" role="src" />
|
||
+ <file md5sum="5cbb3cbe6477799e7e5fd816eda69937" name="config.m4" role="src" />
|
||
+ <file md5sum="b748744f64eb4fbe201cce84cc3d7e33" name="php_apc.c" role="src" />
|
||
+ <file md5sum="8c092033ef0cd8a5d207acb4f6ecec11" name="php_apc.h" role="src" />
|
||
+ <file md5sum="76fe025ee14897783cee848dc1a77fa6" name="pgsql_s_lock.c" role="src" />
|
||
+ <file md5sum="b67725b96ecf0e6851eccce632bab289" name="pgsql_s_lock.h" role="src" />
|
||
+ <file md5sum="298e1c6721b21635ef46094c6a175af5" name="apc_fcntl_win32.c" role="src" />
|
||
+ <file md5sum="072c127617c90a92331372a3b99494d3" name="apc_rfc1867.c" role="src" />
|
||
+ <file md5sum="41fb805e7a151dc6edfe78780b5102d0" name="apc.php" role="php" />
|
||
+ </dir>
|
||
+ </contents>
|
||
+ <dependencies>
|
||
+ <required>
|
||
+ <php>
|
||
+ <min>4.3.0</min>
|
||
+ <exclude>5.0.0</exclude>
|
||
+ <exclude>5.0.1</exclude>
|
||
+ <exclude>5.0.2</exclude>
|
||
+ <exclude>5.0.3</exclude>
|
||
+ <exclude>5.0.4</exclude>
|
||
+ <exclude>5.0.5</exclude>
|
||
+ </php>
|
||
+ <pearinstaller>
|
||
+ <min>1.4.0</min>
|
||
+ </pearinstaller>
|
||
+ </required>
|
||
+ </dependencies>
|
||
+ <providesextension>apc</providesextension>
|
||
+ <extsrcrelease>
|
||
+ <configureoption default="yes" name="with-apxs" prompt="Use apxs to set compile flags (if using APC with Apache)?" />
|
||
+ </extsrcrelease>
|
||
+ <changelog>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>2.0.0</release>
|
||
+ <api>2.0.0</api>
|
||
+ </version>
|
||
+ <date>2003-07-01</date>
|
||
+ <notes>Complete rework.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>2.0.1</release>
|
||
+ <api>2.0.0</api>
|
||
+ </version>
|
||
+ <date>2003-07-01</date>
|
||
+ <notes>Win32 support added.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>2.0.2</release>
|
||
+ <api>2.0.0</api>
|
||
+ </version>
|
||
+ <date>2004-03-12</date>
|
||
+ <notes>Fixed non-existant class bug.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.0</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-05</date>
|
||
+ <notes>PHP-5.1 Support and numerous fixes</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.1</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-05</date>
|
||
+ <notes>PHP4 build fix</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.2</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-05</date>
|
||
+ <notes>Default to mmap and add a better error message for shmget failures</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.3</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-07</date>
|
||
+ <notes>Fix compile problem against PHP 5.0.x</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.4</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-18</date>
|
||
+ <notes>Add win32 support from Edin.
|
||
+Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches
|
||
+A couple of other minor fixes.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.5</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-27</date>
|
||
+ <notes>Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
|
||
+Support extensions such as bcompiler that need to hook into compile_file. (Val)
|
||
+Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
|
||
+Segfault in cache cleanup code (Ilia, Rasmus)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.6</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-07-30</date>
|
||
+ <notes>Added apc.php to package.xml file.
|
||
+Track per-entry memory usage. (Val)
|
||
+Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
|
||
+fcntl locking robustness fixes. (Rasmus)
|
||
+Shared read-locks where possible. (Rasmus)
|
||
+Added file_update_protection configuration parameter. (Rasmus)
|
||
+Windows ZTS fixes (Frank)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.7</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-08-16</date>
|
||
+ <notes>Fix to apc.php to show final segment in frag chart. (Ilia)
|
||
+A couple of win32 fixes. (Frank)
|
||
+Add apc.enable_cli ini directive. (Rasmus)
|
||
+Add test cases. (Marcus)
|
||
+Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
|
||
+Simplify user cache handling by removing the user_cache_stack (Rasmus)
|
||
+Fix apc_fetch() memory corruption (Andrei,Rasmus)
|
||
+Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.8</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2005-08-24</date>
|
||
+ <notes>Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
|
||
+Cache corruption fix in cache-full cleanup code (Gopal)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.9</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-03-04</date>
|
||
+ <notes>Eliminate rand() call when slam_defense is not set (Rasmus)
|
||
+Fix for __isset problem (Gopal)
|
||
+Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
|
||
+Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
|
||
+Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
|
||
+Add cache busy flag which is set when an expunge is underway (Rasmus)
|
||
+Add automatic serialization of objects in apc_store() (Marcus)
|
||
+64-bit .ini flag fix (Rasmus)
|
||
+Static members fix (Gopal)
|
||
+sma_cleanup() mem leak fix (Rasmus)
|
||
+Fix for http://pecl.php.net/bugs/5311 (Rasmus)
|
||
+Fix autoglobals JIT bug (Gopal)
|
||
+Fix instance bug (Gopal)
|
||
+Add a lock cleanup safety net to request shutdown (Rasmus)
|
||
+Fix apc.slam_defense edge-case bug (Rasmus)
|
||
+User entry memory usage tracking support (Ilia)
|
||
+Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.10</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-03-11</date>
|
||
+ <notes>* Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
|
||
+ includes will not be stat'ed for any changes. You will have to restart the server if you
|
||
+ change anything. This mode increases performance quite a bit, especially if you have a
|
||
+ lot of includes.
|
||
+
|
||
+* Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
|
||
+ than it solves. I'll need to revisit locking and signal handling at some point soon.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.11</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-08-16</date>
|
||
+ <notes>* Made --enable-apc-mmap the default compile option (for real this time)
|
||
+
|
||
+* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
|
||
+ only fetch header information to make it useful when you have tens of
|
||
+ thousands of entries. (Brian Shire)
|
||
+
|
||
+* 64-bit fixes (George)
|
||
+
|
||
+* Don't mix Full Path and Inode keys (George)
|
||
+
|
||
+* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
|
||
+ require_once() and include_once() statements. (Sara)
|
||
+
|
||
+* Add a non-blocking write_lock for cache inserts. This is a better approach
|
||
+ to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
|
||
+
|
||
+* A bit of work on the optimizer. (Sara)
|
||
+
|
||
+* Various memory issues resolved. (Gopal)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.12</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-09-04</date>
|
||
+ <notes>* Fix stray debug message
|
||
+
|
||
+* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
|
||
+
|
||
+* Performance boost - Replace multiple loops over the opcode
|
||
+ array with a single loop for copying, jump fixups and auto
|
||
+ global pre-fetches. (Gopal)
|
||
+
|
||
+* Perform fetch_global checks only in php5 and only if
|
||
+ auto_globals_jit is enabled. (Gopal)
|
||
+
|
||
+* Fix bug #8579 - scrub php4 classes' function_table and default
|
||
+ properties before inserting into cache. (Gopal)
|
||
+
|
||
+* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a
|
||
+ op1->type. The opcodes applicable are ZEND_FETCH_R and
|
||
+ ZEND_FETCH_W. (Gopal)
|
||
+
|
||
+* PHP 5.2 Compatibility (Gopal)
|
||
+
|
||
+* Make the include_once override optional - default off (Sara)
|
||
+
|
||
+* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
|
||
+
|
||
+* Ensure that the apc_globals->cache_stack is cleared before the
|
||
+ shm cache is destroyed. Fixes segfault for corner-case i.e request
|
||
+ shutdown (apc_deactivate) is not called before module shutdown
|
||
+ calls (php_apc_shutdown_globals) (Gopal)
|
||
+
|
||
+* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
|
||
+
|
||
+* Fix memory leak of apc_cache_info_t->deleted_list (Gopal)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.12p1</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-09-05</date>
|
||
+ <notes>* The only change here is a trivial PHP 4 build fix.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.12p2</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2006-09-05</date>
|
||
+ <notes>* Let's get the version number right. 3.0.12p2 now.</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.13</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2007-02-24</date>
|
||
+ <notes>* PHP 5.2 file upload progress tracking support (Rasmus)
|
||
+* Pthread mutex and spin locks (Shire)
|
||
+* Recursive zval support for apc_fetch/_store (Shire, Gopal)
|
||
+* apc.stat_ctime flag for ctime checks (Rasmus)
|
||
+* Multiple key fetches with apc_fetch (Shire)
|
||
+* Canary checks for shm memory deallocation (Gopal)
|
||
+* Add hooks for external optimizer (Shire)
|
||
+* Obsolete and remove apc optimizer (Gopal)
|
||
+* APC info changes - cache insert rate, hit and miss rates (Shire)
|
||
+* Fix apc_load_constants (Gopal)
|
||
+* Rewrite dump opcode code to use vld (Gopal)
|
||
+* Use apc_[ewn]print functions for error reporting (Shire)
|
||
+* Auto global fixes and refactoring (Gopal, Shire)
|
||
+* Fix memory leaks in object serialization (Ilia)
|
||
+* Memory cleanup code for destructor order (Gopal)
|
||
+* Win32 build fixes (Ilia, Wez)
|
||
+* ZTS and Php 4 build fixes (Bjori)
|
||
+* Add apc_add() function (Rasmus)
|
||
+* Add optional limited flag to apc_sma_info() (Rasmus)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.14</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2007-04-02</date>
|
||
+ <notes>* Build fix (Shire)
|
||
+* Don't hook the upload hook if APC is disabled (Rasmus)
|
||
+* Local shadow cache support (Gopal)
|
||
+* Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
|
||
+* Fix apc_add() to overwrite timed out user entries (Rasmus)
|
||
+* Fix double inclusion of files with conditional classes in php4 (Gopal)
|
||
+* Allocator fixes to reduce fragmentation (Gopal)</notes>
|
||
+ </release>
|
||
+ <release>
|
||
+ <stability>
|
||
+ <release>stable</release>
|
||
+ <api>stable</api>
|
||
+ </stability>
|
||
+ <version>
|
||
+ <release>3.0.15</release>
|
||
+ <api>3.0.0</api>
|
||
+ </version>
|
||
+ <date>2007-10-18</date>
|
||
+ <notes>* Eliminate a per-request time() syscall (Rasmus)
|
||
+* Added rfc1867 prefix, name, and freq ini options (Shire)
|
||
+* Allow deletion of individual user cache entries via apc.php (Sara)
|
||
+* Fix overzealous cleanup during RSHUTDOWN (Gopal)
|
||
+* Fix memory alignment and locking issues (Gopal)
|
||
+* Make apc_compile insert/replace entries (Shire)
|
||
+* Make mixed inheritance recompile & cache afresh (Gopal)
|
||
+* Make nostat mode search include_path for canonicalization (Gopal)
|
||
+* ZTS & other compile fixes (Gopal, Edin, Shire)</notes>
|
||
+ </release>
|
||
+ </changelog>
|
||
+</package>
|
||
diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.c php-5.2.5/ext/apc/pgsql_s_lock.c
|
||
--- php-5.2.5-orig/ext/apc/pgsql_s_lock.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/pgsql_s_lock.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,481 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2007 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | The following code was ported from the PostgreSQL project, please |
|
||
+ | see appropriate copyright notices that follow. |
|
||
+ | Initial conversion by Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
|
||
+
|
||
+/*-------------------------------------------------------------------------
|
||
+ *
|
||
+ * s_lock.c
|
||
+ * Hardware-dependent implementation of spinlocks.
|
||
+ *
|
||
+ *
|
||
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||
+ * Portions Copyright (c) 1994, Regents of the University of California
|
||
+ *
|
||
+ *
|
||
+ * IDENTIFICATION
|
||
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
|
||
+ *
|
||
+ *-------------------------------------------------------------------------
|
||
+ */
|
||
+/* #include "postgres.h" -- Removed for APC */
|
||
+
|
||
+/* -- Added for APC -- */
|
||
+#include "apc.h"
|
||
+#ifdef APC_SPIN_LOCKS
|
||
+
|
||
+#ifdef S_LOCK_TEST
|
||
+#include <stdio.h>
|
||
+#endif
|
||
+#ifndef WIN32
|
||
+#include <sys/select.h>
|
||
+#endif
|
||
+/* ---- */
|
||
+
|
||
+#include <time.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+/* #include "storage/s_lock.h" -- Removed for APC */
|
||
+#include "pgsql_s_lock.h"
|
||
+
|
||
+static int spins_per_delay = DEFAULT_SPINS_PER_DELAY;
|
||
+
|
||
+
|
||
+/* -- APC specific additions ------------------------------*/
|
||
+/* The following dependencies have been copied from
|
||
+ * other pgsql source files. The original locations
|
||
+ * have been noted.
|
||
+ */
|
||
+
|
||
+/* -- from include/c.h -- */
|
||
+#ifndef TRUE
|
||
+#define TRUE 1
|
||
+#endif
|
||
+
|
||
+#ifndef FALSE
|
||
+#define FALSE 0
|
||
+#endif
|
||
+
|
||
+/* -- from include/pg_config_manual.h -- */
|
||
+#define MAX_RANDOM_VALUE (0x7FFFFFFF)
|
||
+
|
||
+/*
|
||
+ * Max
|
||
+ * Return the maximum of two numbers.
|
||
+ */
|
||
+#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||
+
|
||
+/* -- from include/c.h -- */
|
||
+/*
|
||
+ * Min
|
||
+ * Return the minimum of two numbers.
|
||
+ */
|
||
+#define Min(x, y) ((x) < (y) ? (x) : (y))
|
||
+
|
||
+
|
||
+/* -- from backend/port/win32/signal.c -- */
|
||
+/*
|
||
+ * pg_usleep --- delay the specified number of microseconds.
|
||
+ *
|
||
+ * NOTE: although the delay is specified in microseconds, the effective
|
||
+ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
|
||
+ * the requested delay to be rounded up to the next resolution boundary.
|
||
+ *
|
||
+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
|
||
+ */
|
||
+void
|
||
+pg_usleep(long microsec)
|
||
+{
|
||
+ if (microsec > 0)
|
||
+ {
|
||
+#ifndef WIN32
|
||
+ struct timeval delay;
|
||
+
|
||
+ delay.tv_sec = microsec / 1000000L;
|
||
+ delay.tv_usec = microsec % 1000000L;
|
||
+ (void) select(0, NULL, NULL, NULL, &delay);
|
||
+#else
|
||
+ SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
|
||
+#endif
|
||
+ }
|
||
+}
|
||
+
|
||
+/* -- End APC specific additions ------------------------------*/
|
||
+
|
||
+
|
||
+/*
|
||
+ * s_lock_stuck() - complain about a stuck spinlock
|
||
+ */
|
||
+static void
|
||
+s_lock_stuck(volatile slock_t *lock, const char *file, int line)
|
||
+{
|
||
+#if defined(S_LOCK_TEST)
|
||
+ fprintf(stderr,
|
||
+ "\nStuck spinlock (%p) detected at %s:%d.\n",
|
||
+ lock, file, line);
|
||
+ exit(1);
|
||
+#else
|
||
+ /* -- Removed for APC
|
||
+ elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
|
||
+ lock, file, line);
|
||
+ */
|
||
+ apc_eprint("Stuck spinlock (%p) detected", lock);
|
||
+#endif
|
||
+}
|
||
+
|
||
+
|
||
+/*
|
||
+ * s_lock(lock) - platform-independent portion of waiting for a spinlock.
|
||
+ */
|
||
+void
|
||
+s_lock(volatile slock_t *lock, const char *file, int line)
|
||
+{
|
||
+ /*
|
||
+ * We loop tightly for awhile, then delay using pg_usleep() and try again.
|
||
+ * Preferably, "awhile" should be a small multiple of the maximum time we
|
||
+ * expect a spinlock to be held. 100 iterations seems about right as an
|
||
+ * initial guess. However, on a uniprocessor the loop is a waste of
|
||
+ * cycles, while in a multi-CPU scenario it's usually better to spin a bit
|
||
+ * longer than to call the kernel, so we try to adapt the spin loop count
|
||
+ * depending on whether we seem to be in a uniprocessor or multiprocessor.
|
||
+ *
|
||
+ * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
|
||
+ * be wrong; there are platforms where that can result in a "stuck
|
||
+ * spinlock" failure. This has been seen particularly on Alphas; it seems
|
||
+ * that the first TAS after returning from kernel space will always fail
|
||
+ * on that hardware.
|
||
+ *
|
||
+ * Once we do decide to block, we use randomly increasing pg_usleep()
|
||
+ * delays. The first delay is 1 msec, then the delay randomly increases to
|
||
+ * about one second, after which we reset to 1 msec and start again. The
|
||
+ * idea here is that in the presence of heavy contention we need to
|
||
+ * increase the delay, else the spinlock holder may never get to run and
|
||
+ * release the lock. (Consider situation where spinlock holder has been
|
||
+ * nice'd down in priority by the scheduler --- it will not get scheduled
|
||
+ * until all would-be acquirers are sleeping, so if we always use a 1-msec
|
||
+ * sleep, there is a real possibility of starvation.) But we can't just
|
||
+ * clamp the delay to an upper bound, else it would take a long time to
|
||
+ * make a reasonable number of tries.
|
||
+ *
|
||
+ * We time out and declare error after NUM_DELAYS delays (thus, exactly
|
||
+ * that many tries). With the given settings, this will usually take 2 or
|
||
+ * so minutes. It seems better to fix the total number of tries (and thus
|
||
+ * the probability of unintended failure) than to fix the total time
|
||
+ * spent.
|
||
+ *
|
||
+ * The pg_usleep() delays are measured in milliseconds because 1 msec is a
|
||
+ * common resolution limit at the OS level for newer platforms. On older
|
||
+ * platforms the resolution limit is usually 10 msec, in which case the
|
||
+ * total delay before timeout will be a bit more.
|
||
+ */
|
||
+#define MIN_SPINS_PER_DELAY 10
|
||
+#define MAX_SPINS_PER_DELAY 1000
|
||
+#define NUM_DELAYS 1000
|
||
+#define MIN_DELAY_MSEC 1
|
||
+#define MAX_DELAY_MSEC 1000
|
||
+
|
||
+ int spins = 0;
|
||
+ int delays = 0;
|
||
+ int cur_delay = 0;
|
||
+
|
||
+ while (TAS(lock))
|
||
+ {
|
||
+ /* CPU-specific delay each time through the loop */
|
||
+ SPIN_DELAY();
|
||
+
|
||
+ /* Block the process every spins_per_delay tries */
|
||
+ if (++spins >= spins_per_delay)
|
||
+ {
|
||
+ if (++delays > NUM_DELAYS)
|
||
+ s_lock_stuck(lock, file, line);
|
||
+
|
||
+ if (cur_delay == 0) /* first time to delay? */
|
||
+ cur_delay = MIN_DELAY_MSEC;
|
||
+
|
||
+ pg_usleep(cur_delay * 1000L);
|
||
+
|
||
+#if defined(S_LOCK_TEST)
|
||
+ fprintf(stdout, "*");
|
||
+ fflush(stdout);
|
||
+#endif
|
||
+
|
||
+ /* increase delay by a random fraction between 1X and 2X */
|
||
+ cur_delay += (int) (cur_delay *
|
||
+ ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
|
||
+ /* wrap back to minimum delay when max is exceeded */
|
||
+ if (cur_delay > MAX_DELAY_MSEC)
|
||
+ cur_delay = MIN_DELAY_MSEC;
|
||
+
|
||
+ spins = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * If we were able to acquire the lock without delaying, it's a good
|
||
+ * indication we are in a multiprocessor. If we had to delay, it's a sign
|
||
+ * (but not a sure thing) that we are in a uniprocessor. Hence, we
|
||
+ * decrement spins_per_delay slowly when we had to delay, and increase it
|
||
+ * rapidly when we didn't. It's expected that spins_per_delay will
|
||
+ * converge to the minimum value on a uniprocessor and to the maximum
|
||
+ * value on a multiprocessor.
|
||
+ *
|
||
+ * Note: spins_per_delay is local within our current process. We want to
|
||
+ * average these observations across multiple backends, since it's
|
||
+ * relatively rare for this function to even get entered, and so a single
|
||
+ * backend might not live long enough to converge on a good value. That
|
||
+ * is handled by the two routines below.
|
||
+ */
|
||
+ if (cur_delay == 0)
|
||
+ {
|
||
+ /* we never had to delay */
|
||
+ if (spins_per_delay < MAX_SPINS_PER_DELAY)
|
||
+ spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (spins_per_delay > MIN_SPINS_PER_DELAY)
|
||
+ spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
|
||
+/*
|
||
+ * Set local copy of spins_per_delay during backend startup.
|
||
+ *
|
||
+ * NB: this has to be pretty fast as it is called while holding a spinlock
|
||
+ */
|
||
+void
|
||
+set_spins_per_delay(int shared_spins_per_delay)
|
||
+{
|
||
+ spins_per_delay = shared_spins_per_delay;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Update shared estimate of spins_per_delay during backend exit.
|
||
+ *
|
||
+ * NB: this has to be pretty fast as it is called while holding a spinlock
|
||
+ */
|
||
+int
|
||
+update_spins_per_delay(int shared_spins_per_delay)
|
||
+{
|
||
+ /*
|
||
+ * We use an exponential moving average with a relatively slow adaption
|
||
+ * rate, so that noise in any one backend's result won't affect the shared
|
||
+ * value too much. As long as both inputs are within the allowed range,
|
||
+ * the result must be too, so we need not worry about clamping the result.
|
||
+ *
|
||
+ * We deliberately truncate rather than rounding; this is so that single
|
||
+ * adjustments inside a backend can affect the shared estimate (see the
|
||
+ * asymmetric adjustment rules above).
|
||
+ */
|
||
+ return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
|
||
+}
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Various TAS implementations that cannot live in s_lock.h as no inline
|
||
+ * definition exists (yet).
|
||
+ * In the future, get rid of tas.[cso] and fold it into this file.
|
||
+ *
|
||
+ * If you change something here, you will likely need to modify s_lock.h too,
|
||
+ * because the definitions for these are split between this file and s_lock.h.
|
||
+ */
|
||
+
|
||
+
|
||
+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
|
||
+
|
||
+
|
||
+#if defined(__GNUC__)
|
||
+
|
||
+/*
|
||
+ * All the gcc flavors that are not inlined
|
||
+ */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Note: all the if-tests here probably ought to be testing gcc version
|
||
+ * rather than platform, but I don't have adequate info to know what to
|
||
+ * write. Ideally we'd flush all this in favor of the inline version.
|
||
+ */
|
||
+#if defined(__m68k__) && !defined(__linux__)
|
||
+/* really means: extern int tas(slock_t* **lock); */
|
||
+static void
|
||
+tas_dummy()
|
||
+{
|
||
+ __asm__ __volatile__(
|
||
+#if defined(__NetBSD__) && defined(__ELF__)
|
||
+/* no underscore for label and % for registers */
|
||
+ "\
|
||
+.global tas \n\
|
||
+tas: \n\
|
||
+ movel %sp@(0x4),%a0 \n\
|
||
+ tas %a0@ \n\
|
||
+ beq _success \n\
|
||
+ moveq #-128,%d0 \n\
|
||
+ rts \n\
|
||
+_success: \n\
|
||
+ moveq #0,%d0 \n\
|
||
+ rts \n"
|
||
+#else
|
||
+ "\
|
||
+.global _tas \n\
|
||
+_tas: \n\
|
||
+ movel sp@(0x4),a0 \n\
|
||
+ tas a0@ \n\
|
||
+ beq _success \n\
|
||
+ moveq #-128,d0 \n\
|
||
+ rts \n\
|
||
+_success: \n\
|
||
+ moveq #0,d0 \n\
|
||
+ rts \n"
|
||
+#endif /* __NetBSD__ && __ELF__ */
|
||
+ );
|
||
+}
|
||
+#endif /* __m68k__ && !__linux__ */
|
||
+#else /* not __GNUC__ */
|
||
+
|
||
+/*
|
||
+ * All non gcc
|
||
+ */
|
||
+
|
||
+
|
||
+#if defined(sun3)
|
||
+static void
|
||
+tas_dummy() /* really means: extern int tas(slock_t
|
||
+ * *lock); */
|
||
+{
|
||
+ asm("LLA0:");
|
||
+ asm(" .data");
|
||
+ asm(" .text");
|
||
+ asm("|#PROC# 04");
|
||
+ asm(" .globl _tas");
|
||
+ asm("_tas:");
|
||
+ asm("|#PROLOGUE# 1");
|
||
+ asm(" movel sp@(0x4),a0");
|
||
+ asm(" tas a0@");
|
||
+ asm(" beq LLA1");
|
||
+ asm(" moveq #-128,d0");
|
||
+ asm(" rts");
|
||
+ asm("LLA1:");
|
||
+ asm(" moveq #0,d0");
|
||
+ asm(" rts");
|
||
+ asm(" .data");
|
||
+}
|
||
+#endif /* sun3 */
|
||
+#endif /* not __GNUC__ */
|
||
+#endif /* HAVE_SPINLOCKS */
|
||
+
|
||
+
|
||
+
|
||
+/*****************************************************************************/
|
||
+#if defined(S_LOCK_TEST)
|
||
+
|
||
+/*
|
||
+ * test program for verifying a port's spinlock support.
|
||
+ */
|
||
+
|
||
+struct test_lock_struct
|
||
+{
|
||
+ char pad1;
|
||
+ slock_t lock;
|
||
+ char pad2;
|
||
+};
|
||
+
|
||
+volatile struct test_lock_struct test_lock;
|
||
+
|
||
+int
|
||
+main()
|
||
+{
|
||
+ srandom((unsigned int) time(NULL));
|
||
+
|
||
+ test_lock.pad1 = test_lock.pad2 = 0x44;
|
||
+
|
||
+ S_INIT_LOCK(&test_lock.lock);
|
||
+
|
||
+ if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if (!S_LOCK_FREE(&test_lock.lock))
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, lock not initialized\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ S_LOCK(&test_lock.lock);
|
||
+
|
||
+ if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if (S_LOCK_FREE(&test_lock.lock))
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, lock not locked\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ S_UNLOCK(&test_lock.lock);
|
||
+
|
||
+ if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if (!S_LOCK_FREE(&test_lock.lock))
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, lock not unlocked\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ S_LOCK(&test_lock.lock);
|
||
+
|
||
+ if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if (S_LOCK_FREE(&test_lock.lock))
|
||
+ {
|
||
+ printf("S_LOCK_TEST: failed, lock not re-locked\n");
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
|
||
+ printf(" exit with a 'stuck spinlock' message\n");
|
||
+ printf(" if S_LOCK() and TAS() are working.\n");
|
||
+ fflush(stdout);
|
||
+
|
||
+ s_lock(&test_lock.lock, __FILE__, __LINE__);
|
||
+
|
||
+ printf("S_LOCK_TEST: failed, lock not locked\n");
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+#endif /* S_LOCK_TEST */
|
||
+
|
||
+#endif /* APC_SPIN_LOCKS */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.h php-5.2.5/ext/apc/pgsql_s_lock.h
|
||
--- php-5.2.5-orig/ext/apc/pgsql_s_lock.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/pgsql_s_lock.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,928 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2007 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | The following code was ported from the PostgreSQL project, please |
|
||
+ | see appropriate copyright notices that follow. |
|
||
+ | Initial conversion by Brian Shire <shire@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
|
||
+
|
||
+/*-------------------------------------------------------------------------
|
||
+ *
|
||
+ * s_lock.h
|
||
+ * Hardware-dependent implementation of spinlocks.
|
||
+ *
|
||
+ * NOTE: none of the macros in this file are intended to be called directly.
|
||
+ * Call them through the hardware-independent macros in spin.h.
|
||
+ *
|
||
+ * The following hardware-dependent macros must be provided for each
|
||
+ * supported platform:
|
||
+ *
|
||
+ * void S_INIT_LOCK(slock_t *lock)
|
||
+ * Initialize a spinlock (to the unlocked state).
|
||
+ *
|
||
+ * void S_LOCK(slock_t *lock)
|
||
+ * Acquire a spinlock, waiting if necessary.
|
||
+ * Time out and abort() if unable to acquire the lock in a
|
||
+ * "reasonable" amount of time --- typically ~ 1 minute.
|
||
+ *
|
||
+ * void S_UNLOCK(slock_t *lock)
|
||
+ * Unlock a previously acquired lock.
|
||
+ *
|
||
+ * bool S_LOCK_FREE(slock_t *lock)
|
||
+ * Tests if the lock is free. Returns TRUE if free, FALSE if locked.
|
||
+ * This does *not* change the state of the lock.
|
||
+ *
|
||
+ * void SPIN_DELAY(void)
|
||
+ * Delay operation to occur inside spinlock wait loop.
|
||
+ *
|
||
+ * Note to implementors: there are default implementations for all these
|
||
+ * macros at the bottom of the file. Check if your platform can use
|
||
+ * these or needs to override them.
|
||
+ *
|
||
+ * Usually, S_LOCK() is implemented in terms of an even lower-level macro
|
||
+ * TAS():
|
||
+ *
|
||
+ * int TAS(slock_t *lock)
|
||
+ * Atomic test-and-set instruction. Attempt to acquire the lock,
|
||
+ * but do *not* wait. Returns 0 if successful, nonzero if unable
|
||
+ * to acquire the lock.
|
||
+ *
|
||
+ * TAS() is NOT part of the API, and should never be called directly.
|
||
+ *
|
||
+ * CAUTION: on some platforms TAS() may sometimes report failure to acquire
|
||
+ * a lock even when the lock is not locked. For example, on Alpha TAS()
|
||
+ * will "fail" if interrupted. Therefore TAS() should always be invoked
|
||
+ * in a retry loop, even if you are certain the lock is free.
|
||
+ *
|
||
+ * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
|
||
+ * points, ie, loads and stores of other values must not be moved across
|
||
+ * a lock or unlock. In most cases it suffices to make the operation be
|
||
+ * done through a "volatile" pointer.
|
||
+ *
|
||
+ * On most supported platforms, TAS() uses a tas() function written
|
||
+ * in assembly language to execute a hardware atomic-test-and-set
|
||
+ * instruction. Equivalent OS-supplied mutex routines could be used too.
|
||
+ *
|
||
+ * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
|
||
+ * defined), then we fall back on an emulation that uses SysV semaphores
|
||
+ * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
|
||
+ * implementation, because of the cost of a kernel call per lock or unlock.
|
||
+ * An old report is that Postgres spends around 40% of its time in semop(2)
|
||
+ * when using the SysV semaphore code.
|
||
+ *
|
||
+ *
|
||
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||
+ * Portions Copyright (c) 1994, Regents of the University of California
|
||
+ *
|
||
+ * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
|
||
+ *
|
||
+ *-------------------------------------------------------------------------
|
||
+ */
|
||
+#ifndef S_LOCK_H
|
||
+#define S_LOCK_H
|
||
+
|
||
+/** APC namespace protection ************************************************/
|
||
+/* hack to protect against any possible runtime namespace collisions...*/
|
||
+#define pg_usleep apc_spin_pg_usleep
|
||
+#define s_lock apc_spin_s_lock
|
||
+#define spins_per_delay apc_spin_spins_per_delay
|
||
+/****************************************************************************/
|
||
+
|
||
+
|
||
+/* #include "storage/pg_sema.h" -- Removed for APC */
|
||
+
|
||
+#define HAVE_SPINLOCKS 1 /* -- Added for APC */
|
||
+
|
||
+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
|
||
+
|
||
+
|
||
+#if defined(__GNUC__) || defined(__ICC)
|
||
+/*************************************************************************
|
||
+ * All the gcc inlines
|
||
+ * Gcc consistently defines the CPU as __cpu__.
|
||
+ * Other compilers use __cpu or __cpu__ so we test for both in those cases.
|
||
+ */
|
||
+
|
||
+/*----------
|
||
+ * Standard gcc asm format (assuming "volatile slock_t *lock"):
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " instruction \n"
|
||
+ " instruction \n"
|
||
+ " instruction \n"
|
||
+: "=r"(_res), "+m"(*lock) // return register, in/out lock value
|
||
+: "r"(lock) // lock pointer, in input register
|
||
+: "memory", "cc"); // show clobbered registers here
|
||
+
|
||
+ * The output-operands list (after first colon) should always include
|
||
+ * "+m"(*lock), whether or not the asm code actually refers to this
|
||
+ * operand directly. This ensures that gcc believes the value in the
|
||
+ * lock variable is used and set by the asm code. Also, the clobbers
|
||
+ * list (after third colon) should always include "memory"; this prevents
|
||
+ * gcc from thinking it can cache the values of shared-memory fields
|
||
+ * across the asm code. Add "cc" if your asm code changes the condition
|
||
+ * code register, and also list any temp registers the code uses.
|
||
+ *----------
|
||
+ */
|
||
+
|
||
+
|
||
+#ifdef __i386__ /* 32-bit i386 */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register slock_t _res = 1;
|
||
+
|
||
+ /*
|
||
+ * Use a non-locking test before asserting the bus lock. Note that the
|
||
+ * extra test appears to be a small loss on some x86 platforms and a small
|
||
+ * win on others; it's by no means clear that we should keep it.
|
||
+ */
|
||
+ __asm__ __volatile__(
|
||
+ " cmpb $0,%1 \n"
|
||
+ " jne 1f \n"
|
||
+ " lock \n"
|
||
+ " xchgb %0,%1 \n"
|
||
+ "1: \n"
|
||
+: "+q"(_res), "+m"(*lock)
|
||
+:
|
||
+: "memory", "cc");
|
||
+ return (int) _res;
|
||
+}
|
||
+
|
||
+#define SPIN_DELAY() spin_delay()
|
||
+
|
||
+static __inline__ void
|
||
+spin_delay(void)
|
||
+{
|
||
+ /*
|
||
+ * This sequence is equivalent to the PAUSE instruction ("rep" is
|
||
+ * ignored by old IA32 processors if the following instruction is
|
||
+ * not a string operation); the IA-32 Architecture Software
|
||
+ * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
|
||
+ * PAUSE in the inner loop of a spin lock is necessary for good
|
||
+ * performance:
|
||
+ *
|
||
+ * The PAUSE instruction improves the performance of IA-32
|
||
+ * processors supporting Hyper-Threading Technology when
|
||
+ * executing spin-wait loops and other routines where one
|
||
+ * thread is accessing a shared lock or semaphore in a tight
|
||
+ * polling loop. When executing a spin-wait loop, the
|
||
+ * processor can suffer a severe performance penalty when
|
||
+ * exiting the loop because it detects a possible memory order
|
||
+ * violation and flushes the core processor's pipeline. The
|
||
+ * PAUSE instruction provides a hint to the processor that the
|
||
+ * code sequence is a spin-wait loop. The processor uses this
|
||
+ * hint to avoid the memory order violation and prevent the
|
||
+ * pipeline flush. In addition, the PAUSE instruction
|
||
+ * de-pipelines the spin-wait loop to prevent it from
|
||
+ * consuming execution resources excessively.
|
||
+ */
|
||
+ __asm__ __volatile__(
|
||
+ " rep; nop \n");
|
||
+}
|
||
+
|
||
+#endif /* __i386__ */
|
||
+
|
||
+
|
||
+#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register slock_t _res = 1;
|
||
+
|
||
+ /*
|
||
+ * On Opteron, using a non-locking test before the locking instruction
|
||
+ * is a huge loss. On EM64T, it appears to be a wash or small loss,
|
||
+ * so we needn't bother to try to distinguish the sub-architectures.
|
||
+ */
|
||
+ __asm__ __volatile__(
|
||
+ " lock \n"
|
||
+ " xchgb %0,%1 \n"
|
||
+: "+q"(_res), "+m"(*lock)
|
||
+:
|
||
+: "memory", "cc");
|
||
+ return (int) _res;
|
||
+}
|
||
+
|
||
+#define SPIN_DELAY() spin_delay()
|
||
+
|
||
+static __inline__ void
|
||
+spin_delay(void)
|
||
+{
|
||
+ /*
|
||
+ * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
|
||
+ * Opteron, but it may be of some use on EM64T, so we keep it.
|
||
+ */
|
||
+ __asm__ __volatile__(
|
||
+ " rep; nop \n");
|
||
+}
|
||
+
|
||
+#endif /* __x86_64__ */
|
||
+
|
||
+
|
||
+#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned int slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+#ifndef __INTEL_COMPILER
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ long int ret;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " xchg4 %0=%1,%2 \n"
|
||
+: "=r"(ret), "+m"(*lock)
|
||
+: "r"(1)
|
||
+: "memory");
|
||
+ return (int) ret;
|
||
+}
|
||
+
|
||
+#else /* __INTEL_COMPILER */
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+#endif /* __INTEL_COMPILER */
|
||
+#endif /* __ia64__ || __ia64 */
|
||
+
|
||
+
|
||
+#if defined(__arm__) || defined(__arm)
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register slock_t _res = 1;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " swpb %0, %0, [%2] \n"
|
||
+: "+r"(_res), "+m"(*lock)
|
||
+: "r"(lock)
|
||
+: "memory");
|
||
+ return (int) _res;
|
||
+}
|
||
+
|
||
+#endif /* __arm__ */
|
||
+
|
||
+
|
||
+/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
|
||
+#if defined(__s390__) || defined(__s390x__)
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned int slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ int _res = 0;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " cs %0,%3,0(%2) \n"
|
||
+: "+d"(_res), "+m"(*lock)
|
||
+: "a"(lock), "d"(1)
|
||
+: "memory", "cc");
|
||
+ return _res;
|
||
+}
|
||
+
|
||
+#endif /* __s390__ || __s390x__ */
|
||
+
|
||
+
|
||
+#if defined(__sparc__) /* Sparc */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register slock_t _res;
|
||
+
|
||
+ /*
|
||
+ * See comment in /pg/backend/port/tas/solaris_sparc.s for why this
|
||
+ * uses "ldstub", and that file uses "cas". gcc currently generates
|
||
+ * sparcv7-targeted binaries, so "cas" use isn't possible.
|
||
+ */
|
||
+ __asm__ __volatile__(
|
||
+ " ldstub [%2], %0 \n"
|
||
+: "=r"(_res), "+m"(*lock)
|
||
+: "r"(lock)
|
||
+: "memory");
|
||
+ return (int) _res;
|
||
+}
|
||
+
|
||
+#endif /* __sparc__ */
|
||
+
|
||
+
|
||
+/* PowerPC */
|
||
+#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+#if defined(__ppc64__) || defined(__powerpc64__)
|
||
+typedef unsigned long slock_t;
|
||
+#else
|
||
+typedef unsigned int slock_t;
|
||
+#endif
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+/*
|
||
+ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
|
||
+ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
|
||
+ */
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ slock_t _t;
|
||
+ int _res;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+" lwarx %0,0,%3 \n"
|
||
+" cmpwi %0,0 \n"
|
||
+" bne 1f \n"
|
||
+" addi %0,%0,1 \n"
|
||
+" stwcx. %0,0,%3 \n"
|
||
+" beq 2f \n"
|
||
+"1: li %1,1 \n"
|
||
+" b 3f \n"
|
||
+"2: \n"
|
||
+" isync \n"
|
||
+" li %1,0 \n"
|
||
+"3: \n"
|
||
+
|
||
+: "=&r"(_t), "=r"(_res), "+m"(*lock)
|
||
+: "r"(lock)
|
||
+: "memory", "cc");
|
||
+ return _res;
|
||
+}
|
||
+
|
||
+/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
|
||
+#define S_UNLOCK(lock) \
|
||
+do \
|
||
+{ \
|
||
+ __asm__ __volatile__ (" sync \n"); \
|
||
+ *((volatile slock_t *) (lock)) = 0; \
|
||
+} while (0)
|
||
+
|
||
+#endif /* powerpc */
|
||
+
|
||
+
|
||
+/* Linux Motorola 68k */
|
||
+#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register int rv;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " clrl %0 \n"
|
||
+ " tas %1 \n"
|
||
+ " sne %0 \n"
|
||
+: "=d"(rv), "+m"(*lock)
|
||
+:
|
||
+: "memory", "cc");
|
||
+ return rv;
|
||
+}
|
||
+
|
||
+#endif /* (__mc68000__ || __m68k__) && __linux__ */
|
||
+
|
||
+
|
||
+/*
|
||
+ * VAXen -- even multiprocessor ones
|
||
+ * (thanks to Tom Ivar Helbekkmo)
|
||
+ */
|
||
+#if defined(__vax__)
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register int _res;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " movl $1, %0 \n"
|
||
+ " bbssi $0, (%2), 1f \n"
|
||
+ " clrl %0 \n"
|
||
+ "1: \n"
|
||
+: "=&r"(_res), "+m"(*lock)
|
||
+: "r"(lock)
|
||
+: "memory");
|
||
+ return _res;
|
||
+}
|
||
+
|
||
+#endif /* __vax__ */
|
||
+
|
||
+
|
||
+#if defined(__ns32k__) /* National Semiconductor 32K */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register int _res;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " sbitb 0, %1 \n"
|
||
+ " sfsd %0 \n"
|
||
+: "=r"(_res), "+m"(*lock)
|
||
+:
|
||
+: "memory");
|
||
+ return _res;
|
||
+}
|
||
+
|
||
+#endif /* __ns32k__ */
|
||
+
|
||
+
|
||
+#if defined(__alpha) || defined(__alpha__) /* Alpha */
|
||
+/*
|
||
+ * Correct multi-processor locking methods are explained in section 5.5.3
|
||
+ * of the Alpha AXP Architecture Handbook, which at this writing can be
|
||
+ * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
|
||
+ * For gcc we implement the handbook's code directly with inline assembler.
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned long slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register slock_t _res;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " ldq $0, %1 \n"
|
||
+ " bne $0, 2f \n"
|
||
+ " ldq_l %0, %1 \n"
|
||
+ " bne %0, 2f \n"
|
||
+ " mov 1, $0 \n"
|
||
+ " stq_c $0, %1 \n"
|
||
+ " beq $0, 2f \n"
|
||
+ " mb \n"
|
||
+ " br 3f \n"
|
||
+ "2: mov 1, %0 \n"
|
||
+ "3: \n"
|
||
+: "=&r"(_res), "+m"(*lock)
|
||
+:
|
||
+: "memory", "0");
|
||
+ return (int) _res;
|
||
+}
|
||
+
|
||
+#define S_UNLOCK(lock) \
|
||
+do \
|
||
+{\
|
||
+ __asm__ __volatile__ (" mb \n"); \
|
||
+ *((volatile slock_t *) (lock)) = 0; \
|
||
+} while (0)
|
||
+
|
||
+#endif /* __alpha || __alpha__ */
|
||
+
|
||
+
|
||
+#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
|
||
+/* Note: on SGI we use the OS' mutex ABI, see below */
|
||
+/* Note: R10000 processors require a separate SYNC */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned int slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ register volatile slock_t *_l = lock;
|
||
+ register int _res;
|
||
+ register int _tmp;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " .set push \n"
|
||
+ " .set mips2 \n"
|
||
+ " .set noreorder \n"
|
||
+ " .set nomacro \n"
|
||
+ " ll %0, %2 \n"
|
||
+ " or %1, %0, 1 \n"
|
||
+ " sc %1, %2 \n"
|
||
+ " xori %1, 1 \n"
|
||
+ " or %0, %0, %1 \n"
|
||
+ " sync \n"
|
||
+ " .set pop "
|
||
+: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
|
||
+:
|
||
+: "memory");
|
||
+ return _res;
|
||
+}
|
||
+
|
||
+/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
|
||
+#define S_UNLOCK(lock) \
|
||
+do \
|
||
+{ \
|
||
+ __asm__ __volatile__( \
|
||
+ " .set push \n" \
|
||
+ " .set mips2 \n" \
|
||
+ " .set noreorder \n" \
|
||
+ " .set nomacro \n" \
|
||
+ " sync \n" \
|
||
+ " .set pop "); \
|
||
+ *((volatile slock_t *) (lock)) = 0; \
|
||
+} while (0)
|
||
+
|
||
+#endif /* __mips__ && !__sgi */
|
||
+
|
||
+
|
||
+/* These live in s_lock.c, but only for gcc */
|
||
+
|
||
+
|
||
+#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+#endif
|
||
+
|
||
+
|
||
+#endif /* __GNUC__ */
|
||
+
|
||
+
|
||
+
|
||
+/*
|
||
+ * ---------------------------------------------------------------------
|
||
+ * Platforms that use non-gcc inline assembly:
|
||
+ * ---------------------------------------------------------------------
|
||
+ */
|
||
+
|
||
+#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
|
||
+
|
||
+
|
||
+#if defined(USE_UNIVEL_CC) /* Unixware compiler */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+
|
||
+asm int
|
||
+tas(volatile slock_t *s_lock)
|
||
+{
|
||
+/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
|
||
+%mem s_lock
|
||
+ pushl %ebx
|
||
+ movl s_lock, %ebx
|
||
+ movl $255, %eax
|
||
+ lock
|
||
+ xchgb %al, (%ebx)
|
||
+ popl %ebx
|
||
+}
|
||
+
|
||
+#endif /* defined(USE_UNIVEL_CC) */
|
||
+
|
||
+
|
||
+#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */
|
||
+/*
|
||
+ * The Tru64 compiler doesn't support gcc-style inline asm, but it does
|
||
+ * have some builtin functions that accomplish much the same results.
|
||
+ * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
|
||
+ * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only
|
||
+ * operate on an int (ie, longword), but that's OK as long as we define
|
||
+ * S_INIT_LOCK to zero out the whole quadword.
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned long slock_t;
|
||
+
|
||
+#include <alpha/builtins.h>
|
||
+#define S_INIT_LOCK(lock) (*(lock) = 0)
|
||
+#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
|
||
+#define S_UNLOCK(lock) __UNLOCK_LONG(lock)
|
||
+
|
||
+#endif /* __alpha || __alpha__ */
|
||
+
|
||
+
|
||
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
|
||
+/*
|
||
+ * HP's PA-RISC
|
||
+ *
|
||
+ * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
|
||
+ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
|
||
+ * struct. The active word in the struct is whichever has the aligned address;
|
||
+ * the other three words just sit at -1.
|
||
+ *
|
||
+ * When using gcc, we can inline the required assembly code.
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef struct
|
||
+{
|
||
+ int sema[4];
|
||
+} slock_t;
|
||
+
|
||
+#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
|
||
+
|
||
+#if defined(__GNUC__)
|
||
+
|
||
+static __inline__ int
|
||
+tas(volatile slock_t *lock)
|
||
+{
|
||
+ volatile int *lockword = TAS_ACTIVE_WORD(lock);
|
||
+ register int lockval;
|
||
+
|
||
+ __asm__ __volatile__(
|
||
+ " ldcwx 0(0,%2),%0 \n"
|
||
+: "=r"(lockval), "+m"(*lockword)
|
||
+: "r"(lockword)
|
||
+: "memory");
|
||
+ return (lockval == 0);
|
||
+}
|
||
+
|
||
+#endif /* __GNUC__ */
|
||
+
|
||
+#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
|
||
+
|
||
+#define S_INIT_LOCK(lock) \
|
||
+ do { \
|
||
+ volatile slock_t *lock_ = (lock); \
|
||
+ lock_->sema[0] = -1; \
|
||
+ lock_->sema[1] = -1; \
|
||
+ lock_->sema[2] = -1; \
|
||
+ lock_->sema[3] = -1; \
|
||
+ } while (0)
|
||
+
|
||
+#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
|
||
+
|
||
+#endif /* __hppa || __hppa__ */
|
||
+
|
||
+
|
||
+#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
|
||
+
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned int slock_t;
|
||
+
|
||
+#include <ia64/sys/inline.h>
|
||
+#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
|
||
+
|
||
+#endif /* HPUX on IA64, non gcc */
|
||
+
|
||
+
|
||
+#if defined(__sgi) /* SGI compiler */
|
||
+/*
|
||
+ * SGI IRIX 5
|
||
+ * slock_t is defined as a unsigned long. We use the standard SGI
|
||
+ * mutex API.
|
||
+ *
|
||
+ * The following comment is left for historical reasons, but is probably
|
||
+ * not a good idea since the mutex ABI is supported.
|
||
+ *
|
||
+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
|
||
+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
|
||
+ * for the R3000 chips out there.
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned long slock_t;
|
||
+
|
||
+#include "mutex.h"
|
||
+#define TAS(lock) (test_and_set(lock,1))
|
||
+#define S_UNLOCK(lock) (test_then_and(lock,0))
|
||
+#define S_INIT_LOCK(lock) (test_then_and(lock,0))
|
||
+#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
|
||
+#endif /* __sgi */
|
||
+
|
||
+
|
||
+#if defined(sinix) /* Sinix */
|
||
+/*
|
||
+ * SINIX / Reliant UNIX
|
||
+ * slock_t is defined as a struct abilock_t, which has a single unsigned long
|
||
+ * member. (Basically same as SGI)
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+#include "abi_mutex.h"
|
||
+typedef abilock_t slock_t;
|
||
+
|
||
+#define TAS(lock) (!acquire_lock(lock))
|
||
+#define S_UNLOCK(lock) release_lock(lock)
|
||
+#define S_INIT_LOCK(lock) init_lock(lock)
|
||
+#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
|
||
+#endif /* sinix */
|
||
+
|
||
+
|
||
+#if defined(_AIX) /* AIX */
|
||
+/*
|
||
+ * AIX (POWER)
|
||
+ */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned int slock_t;
|
||
+
|
||
+#define TAS(lock) _check_lock(lock, 0, 1)
|
||
+#define S_UNLOCK(lock) _clear_lock(lock, 0)
|
||
+#endif /* _AIX */
|
||
+
|
||
+
|
||
+#if defined (nextstep) /* Nextstep */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef struct mutex slock_t;
|
||
+
|
||
+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */
|
||
+
|
||
+#define S_LOCK(lock) mutex_lock(lock)
|
||
+#define S_UNLOCK(lock) mutex_unlock(lock)
|
||
+#define S_INIT_LOCK(lock) mutex_init(lock)
|
||
+/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
|
||
+#define S_LOCK_FREE(alock) ((alock)->lock == 0)
|
||
+#endif /* nextstep */
|
||
+
|
||
+
|
||
+/* These are in s_lock.c */
|
||
+
|
||
+
|
||
+#if defined(sun3) /* Sun3 */
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+typedef unsigned char slock_t;
|
||
+#endif
|
||
+
|
||
+
|
||
+#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
|
||
+#define HAS_TEST_AND_SET
|
||
+
|
||
+#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
|
||
+typedef unsigned int slock_t;
|
||
+#else
|
||
+typedef unsigned char slock_t;
|
||
+#endif
|
||
+
|
||
+extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
|
||
+ slock_t cmp);
|
||
+
|
||
+#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
|
||
+#endif
|
||
+
|
||
+
|
||
+#ifdef WIN32_ONLY_COMPILER
|
||
+typedef LONG slock_t;
|
||
+
|
||
+#define HAS_TEST_AND_SET
|
||
+#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
|
||
+
|
||
+#define SPIN_DELAY() spin_delay()
|
||
+
|
||
+static __forceinline void
|
||
+spin_delay(void)
|
||
+{
|
||
+ /* See comment for gcc code. Same code, MASM syntax */
|
||
+ __asm rep nop;
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+
|
||
+#endif /* !defined(HAS_TEST_AND_SET) */
|
||
+
|
||
+
|
||
+/* Blow up if we didn't have any way to do spinlocks */
|
||
+#ifndef HAS_TEST_AND_SET
|
||
+/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
|
||
+#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
|
||
+/* #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. */
|
||
+#endif
|
||
+
|
||
+
|
||
+#else /* !HAVE_SPINLOCKS */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Fake spinlock implementation using semaphores --- slow and prone
|
||
+ * to fall foul of kernel limits on number of semaphores, so don't use this
|
||
+ * unless you must! The subroutines appear in spin.c.
|
||
+ */
|
||
+
|
||
+/* -- Removed for APC
|
||
+typedef PGSemaphoreData slock_t;
|
||
+
|
||
+extern bool s_lock_free_sema(volatile slock_t *lock);
|
||
+extern void s_unlock_sema(volatile slock_t *lock);
|
||
+extern void s_init_lock_sema(volatile slock_t *lock);
|
||
+extern int tas_sema(volatile slock_t *lock);
|
||
+
|
||
+#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
|
||
+#define S_UNLOCK(lock) s_unlock_sema(lock)
|
||
+#define S_INIT_LOCK(lock) s_init_lock_sema(lock)
|
||
+#define TAS(lock) tas_sema(lock)
|
||
+*/
|
||
+
|
||
+#endif /* HAVE_SPINLOCKS */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Default Definitions - override these above as needed.
|
||
+ */
|
||
+
|
||
+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
|
||
+
|
||
+#if !defined(S_LOCK)
|
||
+#define S_LOCK(lock) \
|
||
+ do { \
|
||
+ if (TAS(lock)) \
|
||
+ s_lock((lock), __FILE__, __LINE__); \
|
||
+ } while (0)
|
||
+#endif /* S_LOCK */
|
||
+
|
||
+#if !defined(S_LOCK_FREE)
|
||
+#define S_LOCK_FREE(lock) (*(lock) == 0)
|
||
+#endif /* S_LOCK_FREE */
|
||
+
|
||
+#if !defined(S_UNLOCK)
|
||
+#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
|
||
+#endif /* S_UNLOCK */
|
||
+
|
||
+#if !defined(S_INIT_LOCK)
|
||
+#define S_INIT_LOCK(lock) S_UNLOCK(lock)
|
||
+#endif /* S_INIT_LOCK */
|
||
+
|
||
+#if !defined(SPIN_DELAY)
|
||
+#define SPIN_DELAY() ((void) 0)
|
||
+#endif /* SPIN_DELAY */
|
||
+
|
||
+#if !defined(TAS)
|
||
+extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
|
||
+ * s_lock.c */
|
||
+
|
||
+#define TAS(lock) tas(lock)
|
||
+#endif /* TAS */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Platform-independent out-of-line support routines
|
||
+ */
|
||
+extern void s_lock(volatile slock_t *lock, const char *file, int line);
|
||
+
|
||
+/* Support for dynamic adjustment of spins_per_delay */
|
||
+#define DEFAULT_SPINS_PER_DELAY 100
|
||
+
|
||
+#if 0 /* -- Removed from APC use -- */
|
||
+extern void set_spins_per_delay(int shared_spins_per_delay);
|
||
+extern int update_spins_per_delay(int shared_spins_per_delay);
|
||
+#endif
|
||
+
|
||
+#endif /* S_LOCK_H */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/php_apc.c php-5.2.5/ext/apc/php_apc.c
|
||
--- php-5.2.5-orig/ext/apc/php_apc.c 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/php_apc.c 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,991 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: php_apc.c,v 3.154 2007/12/26 22:31:20 rasmus Exp $ */
|
||
+
|
||
+#include "apc_zend.h"
|
||
+#include "apc_cache.h"
|
||
+#include "apc_main.h"
|
||
+#include "apc_sma.h"
|
||
+#include "apc_lock.h"
|
||
+#include "php_globals.h"
|
||
+#include "php_ini.h"
|
||
+#include "ext/standard/info.h"
|
||
+#include "SAPI.h"
|
||
+#include "rfc1867.h"
|
||
+#include "php_apc.h"
|
||
+#if PHP_API_VERSION <= 20020918
|
||
+#if HAVE_APACHE
|
||
+#ifdef APC_PHP4_STAT
|
||
+#undef XtOffsetOf
|
||
+#include "httpd.h"
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+#if HAVE_SIGACTION
|
||
+#include "apc_signal.h"
|
||
+#endif
|
||
+
|
||
+/* {{{ PHP_FUNCTION declarations */
|
||
+PHP_FUNCTION(apc_cache_info);
|
||
+PHP_FUNCTION(apc_clear_cache);
|
||
+PHP_FUNCTION(apc_sma_info);
|
||
+PHP_FUNCTION(apc_store);
|
||
+PHP_FUNCTION(apc_fetch);
|
||
+PHP_FUNCTION(apc_delete);
|
||
+PHP_FUNCTION(apc_compile_file);
|
||
+PHP_FUNCTION(apc_define_constants);
|
||
+PHP_FUNCTION(apc_load_constants);
|
||
+PHP_FUNCTION(apc_add);
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
|
||
+ZEND_DECLARE_MODULE_GLOBALS(apc)
|
||
+
|
||
+/* True globals */
|
||
+apc_cache_t* apc_cache = NULL;
|
||
+apc_cache_t* apc_user_cache = NULL;
|
||
+void* apc_compiled_filters = NULL;
|
||
+
|
||
+static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
|
||
+{
|
||
+ apc_globals->filters = NULL;
|
||
+ apc_globals->initialized = 0;
|
||
+ apc_globals->cache_stack = apc_stack_create(0);
|
||
+ apc_globals->cache_by_default = 1;
|
||
+ apc_globals->slam_defense = 0;
|
||
+ apc_globals->mem_size_ptr = NULL;
|
||
+ apc_globals->fpstat = 1;
|
||
+ apc_globals->stat_ctime = 0;
|
||
+ apc_globals->write_lock = 1;
|
||
+ apc_globals->report_autofilter = 0;
|
||
+ apc_globals->apc_optimize_function = NULL;
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+ apc_globals->rfc1867 = 0;
|
||
+#endif
|
||
+ apc_globals->copied_zvals = NULL;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ apc_globals->reserved_offset = -1;
|
||
+#endif
|
||
+ apc_globals->localcache = 0;
|
||
+ apc_globals->localcache_size = 0;
|
||
+ apc_globals->lcache = NULL;
|
||
+ apc_globals->force_file_update = 0;
|
||
+ apc_globals->coredump_unmap = 0;
|
||
+}
|
||
+
|
||
+static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
|
||
+{
|
||
+ /* deallocate the ignore patterns */
|
||
+ if (apc_globals->filters != NULL) {
|
||
+ int i;
|
||
+ for (i=0; apc_globals->filters[i] != NULL; i++) {
|
||
+ apc_efree(apc_globals->filters[i]);
|
||
+ }
|
||
+ apc_efree(apc_globals->filters);
|
||
+ }
|
||
+
|
||
+ /* the stack should be empty */
|
||
+ assert(apc_stack_size(apc_globals->cache_stack) == 0);
|
||
+
|
||
+ /* apc cleanup */
|
||
+ apc_stack_destroy(apc_globals->cache_stack);
|
||
+
|
||
+ /* the rest of the globals are cleaned up in apc_module_shutdown() */
|
||
+}
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_INI */
|
||
+
|
||
+static PHP_INI_MH(OnUpdate_filters) /* {{{ */
|
||
+{
|
||
+ APCG(filters) = apc_tokenize(new_value, ',');
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
|
||
+{
|
||
+#if APC_MMAP
|
||
+ if(atoi(new_value)!=1) {
|
||
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
|
||
+ }
|
||
+ APCG(shm_segments) = 1;
|
||
+#else
|
||
+ APCG(shm_segments) = atoi(new_value);
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
|
||
+{
|
||
+ int tmp;
|
||
+ tmp = zend_atoi(new_value, new_value_length);
|
||
+ if(tmp < 0) {
|
||
+ apc_eprint("rfc1867_freq must be greater than or equal to zero.");
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if(new_value[new_value_length-1] == '%') {
|
||
+ if(tmp > 100) {
|
||
+ apc_eprint("rfc1867_freq cannot be over 100%%");
|
||
+ return FAILURE;
|
||
+ }
|
||
+ APCG(rfc1867_freq) = tmp / 100.0;
|
||
+ } else {
|
||
+ APCG(rfc1867_freq) = tmp;
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+#define OnUpdateInt OnUpdateLong
|
||
+#endif
|
||
+
|
||
+PHP_INI_BEGIN()
|
||
+STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
|
||
+#if APC_MMAP
|
||
+STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
|
||
+#endif
|
||
+PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
|
||
+STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
|
||
+#endif
|
||
+STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size, zend_apc_globals, apc_globals)
|
||
+STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
|
||
+PHP_INI_END()
|
||
+
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_MINFO_FUNCTION(apc) */
|
||
+static PHP_MINFO_FUNCTION(apc)
|
||
+{
|
||
+ php_info_print_table_start();
|
||
+ php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
|
||
+ php_info_print_table_row(2, "Version", APC_VERSION);
|
||
+#if APC_MMAP
|
||
+ php_info_print_table_row(2, "MMAP Support", "Enabled");
|
||
+ php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
|
||
+#else
|
||
+ php_info_print_table_row(2, "MMAP Support", "Disabled");
|
||
+#endif
|
||
+#if APC_SEM_LOCKS
|
||
+ php_info_print_table_row(2, "Locking type", "IPC Semaphore");
|
||
+#elif APC_FUTEX_LOCKS
|
||
+ php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
|
||
+#elif APC_PTHREADMUTEX_LOCKS
|
||
+ php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
|
||
+#elif APC_SPIN_LOCKS
|
||
+ php_info_print_table_row(2, "Locking type", "spin Locks");
|
||
+#else
|
||
+ php_info_print_table_row(2, "Locking type", "File Locks");
|
||
+#endif
|
||
+ php_info_print_table_row(2, "Revision", "$Revision: 3.154 $");
|
||
+ php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
|
||
+ php_info_print_table_end();
|
||
+ DISPLAY_INI_ENTRIES();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
|
||
+#endif
|
||
+
|
||
+/* {{{ PHP_MINIT_FUNCTION(apc) */
|
||
+static PHP_MINIT_FUNCTION(apc)
|
||
+{
|
||
+ ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
|
||
+
|
||
+ REGISTER_INI_ENTRIES();
|
||
+
|
||
+ /* Disable APC in cli mode unless overridden by apc.enable_cli */
|
||
+ if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
|
||
+ APCG(enabled) = 0;
|
||
+ }
|
||
+
|
||
+ if (APCG(enabled)) {
|
||
+ if(APCG(initialized)) {
|
||
+ apc_process_init(module_number TSRMLS_CC);
|
||
+ } else {
|
||
+ apc_module_init(module_number TSRMLS_CC);
|
||
+ apc_zend_init(TSRMLS_C);
|
||
+ apc_process_init(module_number TSRMLS_CC);
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+ /* File upload progress tracking */
|
||
+ if(APCG(rfc1867)) {
|
||
+ php_rfc1867_callback = apc_rfc1867_progress;
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
|
||
+static PHP_MSHUTDOWN_FUNCTION(apc)
|
||
+{
|
||
+ if(APCG(enabled)) {
|
||
+ apc_process_shutdown(TSRMLS_C);
|
||
+ apc_zend_shutdown(TSRMLS_C);
|
||
+ apc_module_shutdown(TSRMLS_C);
|
||
+#ifndef ZTS
|
||
+ php_apc_shutdown_globals(&apc_globals);
|
||
+#endif
|
||
+ }
|
||
+#ifdef ZTS
|
||
+ ts_free_id(apc_globals_id);
|
||
+#endif
|
||
+ UNREGISTER_INI_ENTRIES();
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_RINIT_FUNCTION(apc) */
|
||
+static PHP_RINIT_FUNCTION(apc)
|
||
+{
|
||
+ if(APCG(enabled)) {
|
||
+ apc_request_init(TSRMLS_C);
|
||
+
|
||
+#if HAVE_SIGACTION
|
||
+ apc_set_signals();
|
||
+#endif
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
|
||
+static PHP_RSHUTDOWN_FUNCTION(apc)
|
||
+{
|
||
+ if(APCG(enabled)) {
|
||
+ apc_request_shutdown(TSRMLS_C);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
|
||
+PHP_FUNCTION(apc_cache_info)
|
||
+{
|
||
+ apc_cache_info_t* info;
|
||
+ apc_cache_link_t* p;
|
||
+ zval* list;
|
||
+ char *cache_type;
|
||
+ int ct_len;
|
||
+ zend_bool limited=0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(ZEND_NUM_ARGS()) {
|
||
+ if(!strcasecmp(cache_type,"user")) {
|
||
+ info = apc_cache_info(apc_user_cache, limited);
|
||
+ } else if(!strcasecmp(cache_type,"filehits")) {
|
||
+#ifdef APC_FILEHITS
|
||
+ RETVAL_ZVAL(APCG(filehits), 1, 0);
|
||
+ return;
|
||
+#else
|
||
+ RETURN_FALSE;
|
||
+#endif
|
||
+ } else {
|
||
+ info = apc_cache_info(apc_cache, limited);
|
||
+ }
|
||
+ } else info = apc_cache_info(apc_cache, limited);
|
||
+
|
||
+ if(!info) {
|
||
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ array_init(return_value);
|
||
+ add_assoc_long(return_value, "num_slots", info->num_slots);
|
||
+ add_assoc_long(return_value, "ttl", info->ttl);
|
||
+ add_assoc_long(return_value, "num_hits", info->num_hits);
|
||
+ add_assoc_long(return_value, "num_misses", info->num_misses);
|
||
+ add_assoc_long(return_value, "start_time", info->start_time);
|
||
+ add_assoc_long(return_value, "expunges", info->expunges);
|
||
+ add_assoc_long(return_value, "mem_size", info->mem_size);
|
||
+ add_assoc_long(return_value, "num_entries", info->num_entries);
|
||
+ add_assoc_long(return_value, "num_inserts", info->num_inserts);
|
||
+#ifdef MULTIPART_EVENT_FORMDATA
|
||
+ add_assoc_long(return_value, "file_upload_progress", 1);
|
||
+#else
|
||
+ add_assoc_long(return_value, "file_upload_progress", 0);
|
||
+#endif
|
||
+#if APC_MMAP
|
||
+ add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
|
||
+#else
|
||
+ add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
|
||
+#endif
|
||
+#if APC_SEM_LOCKS
|
||
+ add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
|
||
+#elif APC_FUTEX_LOCKS
|
||
+ add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
|
||
+#elif APC_PTHREADMUTEX_LOCKS
|
||
+ add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
|
||
+#elif APC_SPIN_LOCKS
|
||
+ add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
|
||
+#else
|
||
+ add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
|
||
+#endif
|
||
+ if(limited) {
|
||
+ apc_cache_free_info(info);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ ALLOC_INIT_ZVAL(list);
|
||
+ array_init(list);
|
||
+
|
||
+ for (p = info->list; p != NULL; p = p->next) {
|
||
+ zval* link;
|
||
+
|
||
+ ALLOC_INIT_ZVAL(link);
|
||
+ array_init(link);
|
||
+
|
||
+ if(p->type == APC_CACHE_ENTRY_FILE) {
|
||
+ add_assoc_string(link, "filename", p->data.file.filename, 1);
|
||
+ add_assoc_long(link, "device", p->data.file.device);
|
||
+ add_assoc_long(link, "inode", p->data.file.inode);
|
||
+ add_assoc_string(link, "type", "file", 1);
|
||
+ } else if(p->type == APC_CACHE_ENTRY_USER) {
|
||
+ add_assoc_string(link, "info", p->data.user.info, 1);
|
||
+ add_assoc_long(link, "ttl", (long)p->data.user.ttl);
|
||
+ add_assoc_string(link, "type", "user", 1);
|
||
+ }
|
||
+ add_assoc_long(link, "num_hits", p->num_hits);
|
||
+ add_assoc_long(link, "mtime", p->mtime);
|
||
+ add_assoc_long(link, "creation_time", p->creation_time);
|
||
+ add_assoc_long(link, "deletion_time", p->deletion_time);
|
||
+ add_assoc_long(link, "access_time", p->access_time);
|
||
+ add_assoc_long(link, "ref_count", p->ref_count);
|
||
+ add_assoc_long(link, "mem_size", p->mem_size);
|
||
+ add_next_index_zval(list, link);
|
||
+ }
|
||
+ add_assoc_zval(return_value, "cache_list", list);
|
||
+
|
||
+ ALLOC_INIT_ZVAL(list);
|
||
+ array_init(list);
|
||
+
|
||
+ for (p = info->deleted_list; p != NULL; p = p->next) {
|
||
+ zval* link;
|
||
+
|
||
+ ALLOC_INIT_ZVAL(link);
|
||
+ array_init(link);
|
||
+
|
||
+ if(p->type == APC_CACHE_ENTRY_FILE) {
|
||
+ add_assoc_string(link, "filename", p->data.file.filename, 1);
|
||
+ add_assoc_long(link, "device", p->data.file.device);
|
||
+ add_assoc_long(link, "inode", p->data.file.inode);
|
||
+ add_assoc_string(link, "type", "file", 1);
|
||
+ } else if(p->type == APC_CACHE_ENTRY_USER) {
|
||
+ add_assoc_string(link, "info", p->data.user.info, 1);
|
||
+ add_assoc_long(link, "ttl", (long)p->data.user.ttl);
|
||
+ add_assoc_string(link, "type", "user", 1);
|
||
+ }
|
||
+ add_assoc_long(link, "num_hits", p->num_hits);
|
||
+ add_assoc_long(link, "mtime", p->mtime);
|
||
+ add_assoc_long(link, "creation_time", p->creation_time);
|
||
+ add_assoc_long(link, "deletion_time", p->deletion_time);
|
||
+ add_assoc_long(link, "access_time", p->access_time);
|
||
+ add_assoc_long(link, "ref_count", p->ref_count);
|
||
+ add_assoc_long(link, "mem_size", p->mem_size);
|
||
+ add_next_index_zval(list, link);
|
||
+ }
|
||
+ add_assoc_zval(return_value, "deleted_list", list);
|
||
+
|
||
+ apc_cache_free_info(info);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void apc_clear_cache() */
|
||
+PHP_FUNCTION(apc_clear_cache)
|
||
+{
|
||
+ char *cache_type;
|
||
+ int ct_len;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(ZEND_NUM_ARGS()) {
|
||
+ if(!strcasecmp(cache_type,"user")) {
|
||
+ apc_cache_clear(apc_user_cache);
|
||
+ RETURN_TRUE;
|
||
+ }
|
||
+ }
|
||
+ apc_cache_clear(apc_cache);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array apc_sma_info([bool limited]) */
|
||
+PHP_FUNCTION(apc_sma_info)
|
||
+{
|
||
+ apc_sma_info_t* info;
|
||
+ zval* block_lists;
|
||
+ int i;
|
||
+ zend_bool limited = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ info = apc_sma_info(limited);
|
||
+
|
||
+ if(!info) {
|
||
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ array_init(return_value);
|
||
+ add_assoc_long(return_value, "num_seg", info->num_seg);
|
||
+ add_assoc_long(return_value, "seg_size", info->seg_size);
|
||
+ add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
|
||
+
|
||
+ if(limited) {
|
||
+ apc_sma_free_info(info);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+#if ALLOC_DISTRIBUTION
|
||
+ {
|
||
+ size_t *adist = apc_sma_get_alloc_distribution();
|
||
+ zval* list;
|
||
+ ALLOC_INIT_ZVAL(list);
|
||
+ array_init(list);
|
||
+ for(i=0; i<30; i++) {
|
||
+ add_next_index_long(list, adist[i]);
|
||
+ }
|
||
+ add_assoc_zval(return_value, "adist", list);
|
||
+ }
|
||
+#endif
|
||
+ ALLOC_INIT_ZVAL(block_lists);
|
||
+ array_init(block_lists);
|
||
+
|
||
+ for (i = 0; i < info->num_seg; i++) {
|
||
+ apc_sma_link_t* p;
|
||
+ zval* list;
|
||
+
|
||
+ ALLOC_INIT_ZVAL(list);
|
||
+ array_init(list);
|
||
+
|
||
+ for (p = info->list[i]; p != NULL; p = p->next) {
|
||
+ zval* link;
|
||
+
|
||
+ ALLOC_INIT_ZVAL(link);
|
||
+ array_init(link);
|
||
+
|
||
+ add_assoc_long(link, "size", p->size);
|
||
+ add_assoc_long(link, "offset", p->offset);
|
||
+ add_next_index_zval(list, link);
|
||
+ }
|
||
+ add_next_index_zval(block_lists, list);
|
||
+ }
|
||
+ add_assoc_zval(return_value, "block_lists", block_lists);
|
||
+ apc_sma_free_info(info);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ _apc_store */
|
||
+int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
|
||
+ apc_cache_entry_t *entry;
|
||
+ apc_cache_key_t key;
|
||
+ time_t t;
|
||
+ size_t mem_size = 0;
|
||
+
|
||
+#if PHP_API_VERSION < 20041225
|
||
+#if HAVE_APACHE && defined(APC_PHP4_STAT)
|
||
+ t = ((request_rec *)SG(server_context))->request_time;
|
||
+#else
|
||
+ t = time(0);
|
||
+#endif
|
||
+#else
|
||
+ t = sapi_get_request_time(TSRMLS_C);
|
||
+#endif
|
||
+
|
||
+ if(!APCG(enabled)) return 0;
|
||
+
|
||
+ HANDLE_BLOCK_INTERRUPTIONS();
|
||
+
|
||
+ APCG(mem_size_ptr) = &mem_size;
|
||
+ if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+ apc_cache_free_entry(entry);
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+ apc_cache_free_entry(entry);
|
||
+ apc_cache_expunge(apc_cache,t);
|
||
+ apc_cache_expunge(apc_user_cache,t);
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ APCG(mem_size_ptr) = NULL;
|
||
+
|
||
+ HANDLE_UNBLOCK_INTERRUPTIONS();
|
||
+
|
||
+ return 1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int apc_store(string key, zval var [, ttl ])
|
||
+ */
|
||
+PHP_FUNCTION(apc_store) {
|
||
+ zval *val;
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+ long ttl = 0L;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+
|
||
+ if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
|
||
+ RETURN_FALSE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int apc_add(string key, zval var [, ttl ])
|
||
+ */
|
||
+PHP_FUNCTION(apc_add) {
|
||
+ zval *val;
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+ long ttl = 0L;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+
|
||
+ if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
|
||
+ RETURN_FALSE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+void *apc_erealloc_wrapper(void *ptr, size_t size) {
|
||
+ return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
|
||
+}
|
||
+
|
||
+/* {{{ RETURN_ZVAL for php4 */
|
||
+#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
|
||
+#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
|
||
+#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
|
||
+#define ZVAL_ZVAL(z, zv, copy, dtor) { \
|
||
+ int is_ref, refcount; \
|
||
+ is_ref = (z)->is_ref; \
|
||
+ refcount = (z)->refcount; \
|
||
+ *(z) = *(zv); \
|
||
+ if (copy) { \
|
||
+ zval_copy_ctor(z); \
|
||
+ } \
|
||
+ if (dtor) { \
|
||
+ if (!copy) { \
|
||
+ ZVAL_NULL(zv); \
|
||
+ } \
|
||
+ zval_ptr_dtor(&zv); \
|
||
+ } \
|
||
+ (z)->is_ref = is_ref; \
|
||
+ (z)->refcount = refcount; \
|
||
+ }
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed apc_fetch(mixed key)
|
||
+ */
|
||
+PHP_FUNCTION(apc_fetch) {
|
||
+ zval *key;
|
||
+ HashTable *hash;
|
||
+ HashPosition hpos;
|
||
+ zval **hentry;
|
||
+ zval *result;
|
||
+ zval *result_entry;
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+ apc_cache_entry_t* entry;
|
||
+ time_t t;
|
||
+
|
||
+ if(!APCG(enabled)) RETURN_FALSE;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+#if PHP_API_VERSION < 20041225
|
||
+#if HAVE_APACHE && defined(APC_PHP4_STAT)
|
||
+ t = ((request_rec *)SG(server_context))->request_time;
|
||
+#else
|
||
+ t = time(0);
|
||
+#endif
|
||
+#else
|
||
+ t = sapi_get_request_time(TSRMLS_C);
|
||
+#endif
|
||
+
|
||
+ if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
|
||
+ convert_to_string(key);
|
||
+ }
|
||
+
|
||
+ if(Z_TYPE_P(key) == IS_STRING) {
|
||
+ strkey = Z_STRVAL_P(key);
|
||
+ strkey_len = Z_STRLEN_P(key);
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+ entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
|
||
+ if(entry) {
|
||
+ /* deep-copy returned shm zval to emalloc'ed return_value */
|
||
+ apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
|
||
+ apc_cache_release(apc_user_cache, entry);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ } else if(Z_TYPE_P(key) == IS_ARRAY) {
|
||
+ hash = Z_ARRVAL_P(key);
|
||
+ MAKE_STD_ZVAL(result);
|
||
+ array_init(result);
|
||
+ zend_hash_internal_pointer_reset_ex(hash, &hpos);
|
||
+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
|
||
+ if(Z_TYPE_PP(hentry) != IS_STRING) {
|
||
+ apc_wprint("apc_fetch() expects a string or array of strings.");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
|
||
+ if(entry) {
|
||
+ /* deep-copy returned shm zval to emalloc'ed return_value */
|
||
+ MAKE_STD_ZVAL(result_entry);
|
||
+ apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
|
||
+ apc_cache_release(apc_user_cache, entry);
|
||
+ zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
|
||
+ } /* don't set values we didn't find */
|
||
+ zend_hash_move_forward_ex(hash, &hpos);
|
||
+ }
|
||
+ RETURN_ZVAL(result, 0, 1);
|
||
+ } else {
|
||
+ apc_wprint("apc_fetch() expects a string or array of strings.");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ return;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed apc_delete(string key)
|
||
+ */
|
||
+PHP_FUNCTION(apc_delete) {
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+
|
||
+ if(!APCG(enabled)) RETURN_FALSE;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+
|
||
+ if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
|
||
+ RETURN_TRUE;
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
|
||
+ char *const_key;
|
||
+ unsigned int const_key_len;
|
||
+ zval **entry;
|
||
+ HashPosition pos;
|
||
+
|
||
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
|
||
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
|
||
+ zend_constant c;
|
||
+ int key_type;
|
||
+ ulong num_key;
|
||
+
|
||
+ key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
|
||
+ if(key_type != HASH_KEY_IS_STRING) {
|
||
+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
|
||
+ continue;
|
||
+ }
|
||
+ switch(Z_TYPE_PP(entry)) {
|
||
+ case IS_LONG:
|
||
+ case IS_DOUBLE:
|
||
+ case IS_STRING:
|
||
+ case IS_BOOL:
|
||
+ case IS_RESOURCE:
|
||
+ case IS_NULL:
|
||
+ break;
|
||
+ default:
|
||
+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
|
||
+ continue;
|
||
+ }
|
||
+ c.value = **entry;
|
||
+ zval_copy_ctor(&c.value);
|
||
+ c.flags = case_sensitive;
|
||
+ c.name = zend_strndup(const_key, const_key_len);
|
||
+ c.name_len = const_key_len;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ c.module_number = PHP_USER_CONSTANT;
|
||
+#endif
|
||
+ zend_register_constant(&c TSRMLS_CC);
|
||
+
|
||
+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
|
||
+ */
|
||
+PHP_FUNCTION(apc_define_constants) {
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+ zval *constants = NULL;
|
||
+ zend_bool case_sensitive = 1;
|
||
+ int argc = ZEND_NUM_ARGS();
|
||
+
|
||
+ if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+
|
||
+ _apc_define_constants(constants, case_sensitive TSRMLS_CC);
|
||
+ if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
|
||
+ RETURN_FALSE;
|
||
+} /* }}} */
|
||
+
|
||
+/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
|
||
+ */
|
||
+PHP_FUNCTION(apc_load_constants) {
|
||
+ char *strkey;
|
||
+ int strkey_len;
|
||
+ apc_cache_entry_t* entry;
|
||
+ time_t t;
|
||
+ zend_bool case_sensitive = 1;
|
||
+
|
||
+ if(!APCG(enabled)) RETURN_FALSE;
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!strkey_len) RETURN_FALSE;
|
||
+
|
||
+#if PHP_API_VERSION < 20041225
|
||
+#if HAVE_APACHE && defined(APC_PHP4_STAT)
|
||
+ t = ((request_rec *)SG(server_context))->request_time;
|
||
+#else
|
||
+ t = time(0);
|
||
+#endif
|
||
+#else
|
||
+ t = sapi_get_request_time(TSRMLS_C);
|
||
+#endif
|
||
+
|
||
+ entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
|
||
+
|
||
+ if(entry) {
|
||
+ _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
|
||
+ apc_cache_release(apc_user_cache, entry);
|
||
+ RETURN_TRUE;
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto boolean apc_compile_file(string filename)
|
||
+ */
|
||
+PHP_FUNCTION(apc_compile_file) {
|
||
+ char *filename;
|
||
+ int filename_len;
|
||
+ zend_file_handle file_handle;
|
||
+ zend_op_array *op_array;
|
||
+ long slam_defense = 0;
|
||
+ char** filters = NULL;
|
||
+ zend_bool cache_by_default = 1;
|
||
+ HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
|
||
+ HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
|
||
+
|
||
+ if(!APCG(enabled)) RETURN_FALSE;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if(!filename) RETURN_FALSE;
|
||
+
|
||
+ /* reset slam defense, filters, and cache_by_default */
|
||
+ slam_defense = APCG(slam_defense);
|
||
+ APCG(slam_defense) = 0;
|
||
+
|
||
+ filters = APCG(filters);
|
||
+ APCG(filters) = NULL;
|
||
+
|
||
+ cache_by_default = APCG(cache_by_default);
|
||
+ APCG(cache_by_default) = 1;
|
||
+
|
||
+ /* Replace function/class tables to avoid namespace conflicts */
|
||
+ zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||
+ cg_orig_function_table = CG(function_table);
|
||
+ CG(function_table) = &cg_function_table;
|
||
+ zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||
+ cg_orig_class_table = CG(class_table);
|
||
+ CG(class_table) = &cg_class_table;
|
||
+ eg_orig_function_table = EG(function_table);
|
||
+ EG(function_table) = CG(function_table);
|
||
+ eg_orig_class_table = EG(class_table);
|
||
+ EG(class_table) = CG(class_table);
|
||
+ APCG(force_file_update) = 1;
|
||
+
|
||
+ /* Compile the file, loading it into the cache */
|
||
+ file_handle.type = ZEND_HANDLE_FILENAME;
|
||
+ file_handle.filename = filename;
|
||
+ file_handle.free_filename = 0;
|
||
+ file_handle.opened_path = NULL;
|
||
+ zend_try {
|
||
+ op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
|
||
+ } zend_catch {
|
||
+ apc_wprint("Error compiling %s in apc_compile_file.", filename);
|
||
+ op_array = NULL;
|
||
+ } zend_end_try();
|
||
+
|
||
+ /* Return class/function tables to previous states, destroy temp tables */
|
||
+ APCG(force_file_update) = 0;
|
||
+ CG(function_table) = cg_orig_function_table;
|
||
+ zend_hash_destroy(&cg_function_table);
|
||
+ CG(class_table) = cg_orig_class_table;
|
||
+ zend_hash_destroy(&cg_class_table);
|
||
+ EG(function_table) = eg_orig_function_table;
|
||
+ EG(class_table) = eg_orig_class_table;
|
||
+
|
||
+ /* Restore global settings */
|
||
+ APCG(slam_defense) = slam_defense;
|
||
+ APCG(filters) = filters;
|
||
+ APCG(cache_by_default) = cache_by_default;
|
||
+
|
||
+ if(op_array == NULL) { RETURN_FALSE; }
|
||
+
|
||
+ /* Free up everything */
|
||
+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ destroy_op_array(op_array TSRMLS_CC);
|
||
+#else
|
||
+ destroy_op_array(op_array);
|
||
+#endif
|
||
+ efree(op_array);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ apc_functions[] */
|
||
+function_entry apc_functions[] = {
|
||
+ PHP_FE(apc_cache_info, NULL)
|
||
+ PHP_FE(apc_clear_cache, NULL)
|
||
+ PHP_FE(apc_sma_info, NULL)
|
||
+ PHP_FE(apc_store, NULL)
|
||
+ PHP_FE(apc_fetch, NULL)
|
||
+ PHP_FE(apc_delete, NULL)
|
||
+ PHP_FE(apc_define_constants, NULL)
|
||
+ PHP_FE(apc_load_constants, NULL)
|
||
+ PHP_FE(apc_compile_file, NULL)
|
||
+ PHP_FE(apc_add, NULL)
|
||
+ {NULL, NULL, NULL}
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ module definition structure */
|
||
+
|
||
+zend_module_entry apc_module_entry = {
|
||
+ STANDARD_MODULE_HEADER,
|
||
+ "apc",
|
||
+ apc_functions,
|
||
+ PHP_MINIT(apc),
|
||
+ PHP_MSHUTDOWN(apc),
|
||
+ PHP_RINIT(apc),
|
||
+ PHP_RSHUTDOWN(apc),
|
||
+ PHP_MINFO(apc),
|
||
+ APC_VERSION,
|
||
+ STANDARD_MODULE_PROPERTIES
|
||
+};
|
||
+
|
||
+#ifdef COMPILE_DL_APC
|
||
+ZEND_GET_MODULE(apc)
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/php_apc.h php-5.2.5/ext/apc/php_apc.h
|
||
--- php-5.2.5-orig/ext/apc/php_apc.h 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/php_apc.h 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,52 @@
|
||
+/*
|
||
+ +----------------------------------------------------------------------+
|
||
+ | APC |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Copyright (c) 2006 The PHP Group |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | This source file is subject to version 3.01 of the PHP license, |
|
||
+ | that is bundled with this package in the file LICENSE, and is |
|
||
+ | available through the world-wide-web at the following url: |
|
||
+ | http://www.php.net/license/3_01.txt |
|
||
+ | If you did not receive a copy of the PHP license and are unable to |
|
||
+ | obtain it through the world-wide-web, please send a note to |
|
||
+ | license@php.net so we can mail you a copy immediately. |
|
||
+ +----------------------------------------------------------------------+
|
||
+ | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
|
||
+ | George Schlossnagle <george@omniti.com> |
|
||
+ | Rasmus Lerdorf <rasmus@php.net> |
|
||
+ +----------------------------------------------------------------------+
|
||
+
|
||
+ This software was contributed to PHP by Community Connect Inc. in 2002
|
||
+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
|
||
+ Future revisions and derivatives of this source code must acknowledge
|
||
+ Community Connect Inc. as the original contributor of this module by
|
||
+ leaving this note intact in the source code.
|
||
+
|
||
+ All other licensing and usage conditions are those of the PHP Group.
|
||
+
|
||
+ */
|
||
+
|
||
+/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
|
||
+
|
||
+#ifndef PHP_APC_H
|
||
+#define PHP_APC_H
|
||
+
|
||
+#include "apc_php.h"
|
||
+#include "apc_globals.h"
|
||
+
|
||
+extern zend_module_entry apc_module_entry;
|
||
+#define apc_module_ptr &apc_module_entry
|
||
+
|
||
+#define phpext_apc_ptr apc_module_ptr
|
||
+
|
||
+#endif /* PHP_APC_H */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
|
||
+ * vim<600: expandtab sw=4 ts=4 sts=4
|
||
+ */
|
||
diff -ubrN php-5.2.5-orig/ext/apc/TECHNOTES.txt php-5.2.5/ext/apc/TECHNOTES.txt
|
||
--- php-5.2.5-orig/ext/apc/TECHNOTES.txt 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/TECHNOTES.txt 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,361 @@
|
||
+APC Quick-Start Braindump
|
||
+
|
||
+This is a rapidly written braindump of how APC currently works in the
|
||
+form of a quick-start guide to start hacking on APC.
|
||
+
|
||
+1. Install and use APC a bit so you know what it does from the end-user's
|
||
+ perspective.
|
||
+ user-space functions are all explained here:
|
||
+
|
||
+2. Grab the current APC code from CVS:
|
||
+
|
||
+ cvs -d:pserver:cvsread@cvs.php.net:/repository login
|
||
+ Password: phpfi
|
||
+ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
|
||
+
|
||
+ apc/php_apc.c has most of the code for the user-visible stuff. It is
|
||
+ also a regular PHP extension in the sense that there are MINIT, MINFO,
|
||
+ MSHUTDOWN, RSHUTDOWN, etc. functions.
|
||
+
|
||
+3. Build it.
|
||
+
|
||
+ cd pecl/apc
|
||
+ phpize
|
||
+ ./configure --enable-apc --enable-mmap
|
||
+ make
|
||
+ cp modules/apc.so /usr/local/lib/php
|
||
+ apachectl restart
|
||
+
|
||
+4. Debugging Hints
|
||
+
|
||
+ apachectl stop
|
||
+ gdb /usr/bin/httpd
|
||
+ break ??
|
||
+ run -X
|
||
+
|
||
+ Grab the .gdbinit from the PHP source tree and have a look at the macros.
|
||
+
|
||
+5. Look through apc/apc_sma.c
|
||
+ It is a pretty standard memory allocator.
|
||
+
|
||
+ apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
|
||
+ caller just like malloc, realloc, strdup and free
|
||
+
|
||
+ On server startup the MINIT hook in php_apc.c calls apc_module_init() in
|
||
+ apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into
|
||
+ apc_mmap.c to mmap the specified sized segment (I tend to just use a single
|
||
+ segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and
|
||
+ then unlinks that file right after the mmap to provide automatic shared memory
|
||
+ cleanup in case the process dies.
|
||
+
|
||
+ Once the region has been initialized we stick a header_t at the beginning
|
||
+ of the region. It contains the total size in header->segsize and the number
|
||
+ of bytes available in header->avail.
|
||
+
|
||
+ After the header comes a bit of a hack. A zero-sized block is inserted just
|
||
+ to make things easier later on. And then a huge block that is basically
|
||
+ the size of the entire segment minus the two (for the 0-sized block, and this one)
|
||
+ block headers.
|
||
+
|
||
+ The code for this is:
|
||
+
|
||
+ header = (header_t*) shmaddr;
|
||
+ header->segsize = sma_segsize;
|
||
+ header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
|
||
+ memset(&header->lock,0,sizeof(header->lock));
|
||
+ sma_lock = &header->lock;
|
||
+ block = BLOCKAT(sizeof(header_t));
|
||
+ block->size = 0;
|
||
+ block->next = sizeof(header_t) + sizeof(block_t);
|
||
+ block = BLOCKAT(block->next);
|
||
+ block->size = header->avail;
|
||
+ block->next = 0;
|
||
+
|
||
+ So the shared memory looks like this:
|
||
+
|
||
+ +--------+-------+---------------------------------+
|
||
+ | header | block | block |
|
||
+ +--------+-------+---------------------------------+
|
||
+
|
||
+ sma_shmaddrs[0] gives you the address of header
|
||
+
|
||
+ The blocks are just a simple offset-based linked list (so no pointers):
|
||
+
|
||
+ typedef struct block_t block_t;
|
||
+ struct block_t {
|
||
+ size_t size; /* size of this block */
|
||
+ size_t next; /* offset in segment of next free block */
|
||
+ size_t canary; /* canary to check for memory overwrites */
|
||
+#ifdef __APC_SMA_DEBUG__
|
||
+ int id; /* identifier for the memory block */
|
||
+#endif
|
||
+ };
|
||
+
|
||
+ The BLOCKAT macro turns an offset into an actual address for you:
|
||
+
|
||
+ #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
|
||
+
|
||
+ where shmaddr = sma_shaddrs[0]
|
||
+
|
||
+ And the OFFSET macro goes the other way:
|
||
+
|
||
+ #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
|
||
+
|
||
+ Allocating a block with a call to apc_sma_allocate() walks through the
|
||
+ linked list of blocks until it finds one that is >= to the requested size.
|
||
+ The first call to apc_sma_allocate() will hit the second block. We then
|
||
+ chop up that block so it looks like this:
|
||
+
|
||
+ +--------+-------+-------+-------------------------+
|
||
+ | header | block | block | block |
|
||
+ +--------+-------+-------+-------------------------+
|
||
+
|
||
+ Then we unlink that block from the linked list so it won't show up
|
||
+ as an available block on the next allocate. So we actually have:
|
||
+
|
||
+ +--------+-------+ +-------------------------+
|
||
+ | header | block |------>| block |
|
||
+ +--------+-------+ +-------------------------+
|
||
+
|
||
+ And header->avail along with block->size of the remaining large
|
||
+ block are updated accordingly. The arrow there representing the
|
||
+ link which now points to a block with an offset further along in
|
||
+ the segment.
|
||
+
|
||
+ When the block is freed using apc_sma_deallocate() the steps are
|
||
+ basically just reversed. The block is put back and then the deallocate
|
||
+ code looks at the block before and after to see if the block immediately
|
||
+ before and after are free and if so the blocks are combined. So you never
|
||
+ have 2 free blocks next to each other, apart from at the front with that
|
||
+ 0-sized dummy block. This mostly prevents fragmentation. I have been
|
||
+ toying with the idea of always allocating block at 2^n boundaries to make
|
||
+ it more likely that they will be re-used to cut down on fragmentation further.
|
||
+ That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
|
||
+
|
||
+ Of course, anytime we fiddle with our shared memory segment we lock using
|
||
+ the locking macros, LOCK() and UNLOCK().
|
||
+
|
||
+ That should mostly take care of the low-level shared memory handling.
|
||
+
|
||
+6. Next up is apc_main.c and apc_cache.c which implement the meat of the
|
||
+ cache logic.
|
||
+
|
||
+ The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
|
||
+ and apc_cache.c for actual cache manipulation.
|
||
+
|
||
+ After the shared memory segment is created and the caches are initialized,
|
||
+ apc_module_init() installs the my_compile_file() function overriding Zend's
|
||
+ version. I'll talk about my_compile_file() and the rest of apc_compile.c
|
||
+ in the next section. For now I will stick with apc_main.c and apc_cache.c
|
||
+ and talk about the actual caches. A cache consists of a block of shared
|
||
+ memory returned by apc_sma_allocate() via apc_sma_malloc(). You will
|
||
+ notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper
|
||
+ around PHP's own emalloc() function which allocates per-process memory from
|
||
+ PHP's pool-based memory allocator. Don't confuse apc_emalloc() and
|
||
+ apc_sma_malloc() as the first is per-process and the second is shared memory.
|
||
+
|
||
+ The cache is stored in/described by this struct allocated locally using
|
||
+ emalloc():
|
||
+
|
||
+ struct apc_cache_t {
|
||
+ void* shmaddr; /* process (local) address of shared cache */
|
||
+ header_t* header; /* cache header (stored in SHM) */
|
||
+ slot_t** slots; /* array of cache slots (stored in SHM) */
|
||
+ int num_slots; /* number of slots in cache */
|
||
+ int gc_ttl; /* maximum time on GC list for a slot */
|
||
+ int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
|
||
+ };
|
||
+
|
||
+ Whenever you see functions that take a 'cache' argument, this is what they
|
||
+ take. And apc_cache_create() returns a pointer to this populated struct.
|
||
+
|
||
+ At the beginning of the cache we have a header. Remember, we are down a level now
|
||
+ from the sma stuff. The sma stuff is the low-level shared-memory allocator which
|
||
+ has its own header which is completely separate and invisible to apc_cache.c.
|
||
+ As far as apc_cache.c is concerned the block of memory it is working with could
|
||
+ have come from a call to malloc().
|
||
+
|
||
+ The header looks like this:
|
||
+
|
||
+ typedef struct header_t header_t;
|
||
+ struct header_t {
|
||
+ int num_hits; /* total successful hits in cache */
|
||
+ int num_misses; /* total unsuccessful hits in cache */
|
||
+ slot_t* deleted_list; /* linked list of to-be-deleted slots */
|
||
+ };
|
||
+
|
||
+ Since this is at the start of the shared memory segment, these values are accessible
|
||
+ across all the yapache processes and hence access to them has to be locked.
|
||
+
|
||
+ After the header we have an array of slots. The number of slots is user-defined
|
||
+ through the apc.num_slots ini hint. Each slot is described by:
|
||
+
|
||
+ typedef struct slot_t slot_t;
|
||
+ struct slot_t {
|
||
+ apc_cache_key_t key; /* slot key */
|
||
+ apc_cache_entry_t* value; /* slot value */
|
||
+ slot_t* next; /* next slot in linked list */
|
||
+ int num_hits; /* number of hits to this bucket */
|
||
+ time_t creation_time; /* time slot was initialized */
|
||
+ time_t deletion_time; /* time slot was removed from cache */
|
||
+ time_t access_time; /* time slot was last accessed */
|
||
+ };
|
||
+
|
||
+ The slot_t *next there is a linked list to other slots that happened to hash to the
|
||
+ same array position.
|
||
+
|
||
+ apc_cache_insert() shows what happens on a new cache insert.
|
||
+
|
||
+ slot = &cache->slots[hash(key) % cache->num_slots];
|
||
+
|
||
+ cache->slots is our array of slots in the segment. hash() is simply:
|
||
+
|
||
+ static unsigned int hash(apc_cache_key_t key)
|
||
+ {
|
||
+ return key.data.file.device + key.data.file.inode;
|
||
+ }
|
||
+
|
||
+ That is, we use the file's device and inode to uniquely identify it. Initially
|
||
+ we had used the file's full path, but getting that requires a realpath() call which
|
||
+ is amazingly expensive since it has to stat each component of the path to resolve
|
||
+ symlinks and get rid of relative path components. By using the device+inode we
|
||
+ can uniquely identify a file with a single stat.
|
||
+
|
||
+ So, on an insert we find the array position in the slots array by hasing the device+inode.
|
||
+ If there are currently no other slots there, we just create the slot and stick it into
|
||
+ the array:
|
||
+
|
||
+ *slot = make_slot(key, value, *slot, t)
|
||
+
|
||
+ If there are other slots already at this position we walk the link list to get to
|
||
+ the end. Here is the loop:
|
||
+
|
||
+ while (*slot) {
|
||
+ if (key_equals((*slot)->key.data.file, key.data.file)) {
|
||
+ /* If existing slot for the same device+inode is different, remove it and insert the new version */
|
||
+ if ((*slot)->key.mtime != key.mtime) {
|
||
+ remove_slot(cache, slot);
|
||
+ break;
|
||
+ }
|
||
+ UNLOCK(cache);
|
||
+ return 0;
|
||
+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
|
||
+ remove_slot(cache, slot);
|
||
+ continue;
|
||
+ }
|
||
+ slot = &(*slot)->next;
|
||
+ }
|
||
+
|
||
+ That first key_equals() check sees if we have an exact match meaning the file
|
||
+ is already in the cache. Since we try to find the file in the cache before doing
|
||
+ an insert, this will generally only happen if another process managed to beat us
|
||
+ to inserting it. If we have a newer version of the file at this point we remove
|
||
+ it an insert the new version. If our version is not newer we just return without
|
||
+ doing anything.
|
||
+
|
||
+ While walking the linked list we also check to see if the cache has a TTL defined.
|
||
+ If while walking the linked list we see a slot that has expired, we remove it
|
||
+ since we are right there looking at it. This is the only place we remove stale
|
||
+ entries unless the shared memory segment fills up and we force a full expunge via
|
||
+ apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks
|
||
+ down every linked list removing stale slots to free up room. This is obviously
|
||
+ slow and thus only happens when we have run out of room.
|
||
+
|
||
+ apc_cache_find() simply hashes and returns the entry if it is there. If it is there
|
||
+ but older than the mtime in the entry we are looking for, we delete the one that is
|
||
+ there and return indicating we didn't find it.
|
||
+
|
||
+ Next we need to understand what an actual cache entry looks like. Have a look at
|
||
+ apc_cache.h for the structs. I sort of glossed over the key part earlier saying
|
||
+ that we just used the device+inode to find a hash slot. It is actually a bit more
|
||
+ complex than that because we have two kinds of caches. We have the standard file
|
||
+ cache containing opcode arrays, but we also have a user-controlled cache that the
|
||
+ user can insert whatever they want into via apc_store(). For the user cache we
|
||
+ obviously don't have a device+inode. The actual identifier is provided by the user
|
||
+ as a char *. So the key is actually a union that looks like this:
|
||
+
|
||
+ typedef union _apc_cache_key_data_t {
|
||
+ struct {
|
||
+ int device; /* the filesystem device */
|
||
+ int inode; /* the filesystem inode */
|
||
+ } file;
|
||
+ struct {
|
||
+ char *identifier;
|
||
+ } user;
|
||
+ } apc_cache_key_data_t;
|
||
+
|
||
+ struct apc_cache_key_t {
|
||
+ apc_cache_key_data_t data;
|
||
+ int mtime; /* the mtime of this cached entry */
|
||
+ };
|
||
+
|
||
+ And we have two sets of functions to do inserts and finds. apc_cache_user_find()
|
||
+ and apc_cache_user_insert() operate on the user cache.
|
||
+
|
||
+ Ok, on to the actual cache entry. Again, because we have two kinds of caches, we
|
||
+ also have the corresponding two kinds of cache entries described by this union:
|
||
+
|
||
+ typedef union _apc_cache_entry_value_t {
|
||
+ struct {
|
||
+ char *filename; /* absolute path to source file */
|
||
+ zend_op_array* op_array; /* op_array allocated in shared memory */
|
||
+ apc_function_t* functions; /* array of apc_function_t's */
|
||
+ apc_class_t* classes; /* array of apc_class_t's */
|
||
+ } file;
|
||
+ struct {
|
||
+ char *info;
|
||
+ zval *val;
|
||
+ unsigned int ttl;
|
||
+ } user;
|
||
+ } apc_cache_entry_value_t;
|
||
+
|
||
+ And then the actual cache entry:
|
||
+
|
||
+ struct apc_cache_entry_t {
|
||
+ apc_cache_entry_value_t data;
|
||
+ unsigned char type;
|
||
+ int ref_count;
|
||
+ };
|
||
+
|
||
+ The user entry is pretty simple and not all that important for now. I will
|
||
+ concentrate on the file entries since that is what holds the actual compiled
|
||
+ opcode arrays along with the functions and classes required by the executor.
|
||
+
|
||
+ apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
|
||
+ The main thing to understand here is that we need more than just the opcode
|
||
+ array, we also need the functions and classes created by the compiler when it
|
||
+ created the opcode array. As far as the executor is concerned, it doesn't know
|
||
+ that it isn't operating in normal mode being called right after the parse/compile
|
||
+ phase, so we need to recreate everything so it looks exactly like it would at
|
||
+ that point.
|
||
+
|
||
+7. my_compile_file() and apc_compile.c
|
||
+
|
||
+ my_compile_file() in apc_main.c controls where we get the opcodes from. If
|
||
+ the user-specified filters exclude the file from being cached, then we just
|
||
+ call the original compile function and return. Otherwise we fetch the request
|
||
+ time from Apache to avoid an extra syscall, create the key so we can look up
|
||
+ the file in the cache. If we find it we stick it on a local stack which we
|
||
+ use at cleanup time to make sure we return everything back to normal after a
|
||
+ request and call cached_compile() which installs the functions and classes
|
||
+ associated with the op_array in this entry and then copy the op_array down
|
||
+ into our memory space for execution.
|
||
+
|
||
+ If we didn't find the file in the cache, we need to compile it and insert it.
|
||
+ To compile it we simply call the original compile function:
|
||
+
|
||
+ op_array = old_compile_file(h, type TSRMLS_CC);
|
||
+
|
||
+ To do the insert we need to copy the functions, classes and the opcode array
|
||
+ the compile phase created into shared memory. This all happens in apc_compile.c
|
||
+ in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
|
||
+ functions. Then we make the file entry and do the insert. Both of these
|
||
+ operations were described in the previous section.
|
||
+
|
||
+8. The Optimizer
|
||
+
|
||
+ The optimizer has been deprecated.
|
||
+
|
||
+If you made it to the end of this, you should have a pretty good idea of where things are in
|
||
+the code. I skimmed over a lot of things, so plan on spending some time reading through the code.
|
||
+
|
||
diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_001.phpt php-5.2.5/ext/apc/tests/apc_001.phpt
|
||
--- php-5.2.5-orig/ext/apc/tests/apc_001.phpt 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/tests/apc_001.phpt 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,27 @@
|
||
+--TEST--
|
||
+APC: apc_store/fetch with strings
|
||
+--SKIPIF--
|
||
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||
+--INI--
|
||
+apc.enabled=1
|
||
+apc.enable_cli=1
|
||
+apc.file_update_protection=0
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+$foo = 'hello world';
|
||
+var_dump($foo);
|
||
+apc_store('foo',$foo);
|
||
+$bar = apc_fetch('foo');
|
||
+var_dump($bar);
|
||
+$bar = 'nice';
|
||
+var_dump($bar);
|
||
+
|
||
+?>
|
||
+===DONE===
|
||
+<?php exit(0); ?>
|
||
+--EXPECTF--
|
||
+string(11) "hello world"
|
||
+string(11) "hello world"
|
||
+string(4) "nice"
|
||
+===DONE===
|
||
diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_002.phpt php-5.2.5/ext/apc/tests/apc_002.phpt
|
||
--- php-5.2.5-orig/ext/apc/tests/apc_002.phpt 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/tests/apc_002.phpt 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,34 @@
|
||
+--TEST--
|
||
+APC: apc_store/fetch with objects
|
||
+--SKIPIF--
|
||
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||
+--INI--
|
||
+apc.enabled=1
|
||
+apc.enable_cli=1
|
||
+apc.file_update_protection=0
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+class foo { }
|
||
+$foo = new foo;
|
||
+var_dump($foo);
|
||
+apc_store('foo',$foo);
|
||
+unset($foo);
|
||
+$bar = apc_fetch('foo');
|
||
+var_dump($bar);
|
||
+$bar->a = true;
|
||
+var_dump($bar);
|
||
+
|
||
+?>
|
||
+===DONE===
|
||
+<?php exit(0); ?>
|
||
+--EXPECTF--
|
||
+object(foo)#%d (0) {
|
||
+}
|
||
+object(foo)#%d (0) {
|
||
+}
|
||
+object(foo)#%d (1) {
|
||
+ ["a"]=>
|
||
+ bool(true)
|
||
+}
|
||
+===DONE===
|
||
diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_003.phpt php-5.2.5/ext/apc/tests/apc_003.phpt
|
||
--- php-5.2.5-orig/ext/apc/tests/apc_003.phpt 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/tests/apc_003.phpt 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,112 @@
|
||
+--TEST--
|
||
+APC: apc_store/fetch with objects
|
||
+--SKIPIF--
|
||
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||
+--INI--
|
||
+apc.enabled=1
|
||
+apc.enable_cli=1
|
||
+apc.file_update_protection=0
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+class foo { }
|
||
+$foo = new foo;
|
||
+var_dump($foo);
|
||
+apc_store('foo',$foo);
|
||
+unset($foo);
|
||
+$bar = apc_fetch('foo');
|
||
+var_dump($bar);
|
||
+$bar->a = true;
|
||
+var_dump($bar);
|
||
+
|
||
+class bar extends foo
|
||
+{
|
||
+ public $pub = 'bar';
|
||
+ protected $pro = 'bar';
|
||
+ private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
|
||
+
|
||
+ function __construct()
|
||
+ {
|
||
+ $this->bar = true;
|
||
+ }
|
||
+
|
||
+ function change()
|
||
+ {
|
||
+ $this->pri = 'mod';
|
||
+ }
|
||
+}
|
||
+
|
||
+class baz extends bar
|
||
+{
|
||
+ private $pri = 'baz';
|
||
+
|
||
+ function __construct()
|
||
+ {
|
||
+ parent::__construct();
|
||
+ $this->baz = true;
|
||
+ }
|
||
+}
|
||
+
|
||
+$baz = new baz;
|
||
+var_dump($baz);
|
||
+$baz->change();
|
||
+var_dump($baz);
|
||
+apc_store('baz', $baz);
|
||
+unset($baz);
|
||
+var_dump(apc_fetch('baz'));
|
||
+
|
||
+?>
|
||
+===DONE===
|
||
+<?php exit(0); ?>
|
||
+--EXPECTF--
|
||
+object(foo)#%d (0) {
|
||
+}
|
||
+object(foo)#%d (0) {
|
||
+}
|
||
+object(foo)#%d (1) {
|
||
+ ["a"]=>
|
||
+ bool(true)
|
||
+}
|
||
+object(baz)#%d (6) {
|
||
+ ["pri:private"]=>
|
||
+ string(3) "baz"
|
||
+ ["pub"]=>
|
||
+ string(3) "bar"
|
||
+ ["pro:protected"]=>
|
||
+ string(3) "bar"
|
||
+ ["pri:private"]=>
|
||
+ string(3) "bar"
|
||
+ ["bar"]=>
|
||
+ bool(true)
|
||
+ ["baz"]=>
|
||
+ bool(true)
|
||
+}
|
||
+object(baz)#%d (6) {
|
||
+ ["pri:private"]=>
|
||
+ string(3) "baz"
|
||
+ ["pub"]=>
|
||
+ string(3) "bar"
|
||
+ ["pro:protected"]=>
|
||
+ string(3) "bar"
|
||
+ ["pri:private"]=>
|
||
+ string(3) "mod"
|
||
+ ["bar"]=>
|
||
+ bool(true)
|
||
+ ["baz"]=>
|
||
+ bool(true)
|
||
+}
|
||
+object(baz)#%d (6) {
|
||
+ ["pri:private"]=>
|
||
+ string(3) "baz"
|
||
+ ["pub"]=>
|
||
+ string(3) "bar"
|
||
+ ["pro:protected"]=>
|
||
+ string(3) "bar"
|
||
+ ["pri:private"]=>
|
||
+ string(3) "mod"
|
||
+ ["bar"]=>
|
||
+ bool(true)
|
||
+ ["baz"]=>
|
||
+ bool(true)
|
||
+}
|
||
+===DONE===
|
||
diff -ubrN php-5.2.5-orig/ext/apc/tests/skipif.inc php-5.2.5/ext/apc/tests/skipif.inc
|
||
--- php-5.2.5-orig/ext/apc/tests/skipif.inc 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/tests/skipif.inc 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,6 @@
|
||
+<?php
|
||
+
|
||
+if (!extension_loaded("apc")) die("skip");
|
||
+//if (!ini_get('apc.enabled')) die("skip apc not enabled");
|
||
+
|
||
+?>
|
||
diff -ubrN php-5.2.5-orig/ext/apc/TODO php-5.2.5/ext/apc/TODO
|
||
--- php-5.2.5-orig/ext/apc/TODO 1969-12-31 18:00:00.000000000 -0600
|
||
+++ php-5.2.5/ext/apc/TODO 2007-12-26 16:51:32.000000000 -0600
|
||
@@ -0,0 +1,30 @@
|
||
+Known Bugs
|
||
+
|
||
+1. Gallery2 doesn't work with PHP5+APC. There is something wrong
|
||
+ with the way methods are restored in some edge case I haven't
|
||
+ been able to figure out yet.
|
||
+ To reproduce install gallery2 and click down to an individual photo.
|
||
+
|
||
+2. apc_store() probably needs some checks to skip trying to store
|
||
+ internal classes. Something along the lines of:
|
||
+
|
||
+ if(Z_TYPE_P(val) == IS_OBJECT) {
|
||
+ zend_class_entry *ce = Z_OBJCE_P(val);
|
||
+ if(ce->type == ZEND_INTERNAL_CLASS) {
|
||
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ in the apc_store() function in php_apc.c but I am wondering if it needs to do more
|
||
+ than that.
|
||
+
|
||
+Enhancements
|
||
+
|
||
+1. Some faster platform-specific locking mechanisms wouldd be nice. futex support
|
||
+ for the 2.6 Linux kernels, and/or x86-specific spinlock support.
|
||
+
|
||
+2. The optimizer needs a lot of work.
|
||
+
|
||
+3. Assert() elimination in the optimizer when some debug flag somewhere isn't set.
|
||
+
|