[-]
[+]
|
Changed |
php5-pecl-memcache.changes
|
|
[-]
[+]
|
Changed |
php5-pecl-memcache.spec
^
|
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/README
^
|
@@ -1,14 +0,0 @@
-memcached module for PHP
-------------------------
-This module requires zlib library, used for on-the-fly data (de)compression.
-Also, you'll need memcached to use it =)
-
-The memcached website is here:
- http://www.danga.com/memcached/
-
-You will probably need libevent to install memcached:
-You can download it here: http://www.monkey.org/~provos/libevent/
-
-Maintainers:
-Mikael Johansson mikael at synd dot info
-Antony Dovgal tony2001 at phpclub dot net
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/config.m4
^
|
@@ -1,4 +0,0 @@
-dnl $Id: config.m4,v 1.11 2006/11/15 21:05:03 tony2001 Exp $
-dnl this file is required by phpize
-
-sinclude(config9.m4)
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/config.w32
^
|
@@ -1,14 +0,0 @@
-// $Id: config.w32,v 1.7 2007/11/26 20:12:00 mikl Exp $
-// vim:ft=javascript
-
-ARG_ENABLE("memcache", "memcache support", "no");
-
-if (PHP_MEMCACHE != "no") {
- if (!PHP_ZLIB_SHARED || CHECK_LIB("zlib.lib", "memcache", PHP_MEMCACHE)) {
- EXTENSION("memcache", "memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c");
- AC_DEFINE('HAVE_MEMCACHE', 1, 'Have memcache support');
- ADD_FLAG("CFLAGS_MEMCACHE", "/D HAVE_MEMCACHE_SESSION=1");
- } else {
- WARNING("memcache not enabled; libraries and headers not found");
- }
-}
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/config9.m4
^
|
@@ -1,112 +0,0 @@
-dnl
-dnl $Id: config9.m4,v 1.9 2007/11/01 14:30:16 mikl Exp $
-dnl
-
-PHP_ARG_ENABLE(memcache, whether to enable memcache support,
-[ --enable-memcache Enable memcache support])
-
-PHP_ARG_ENABLE(memcache-session, whether to enable memcache session handler support,
-[ --disable-memcache-session Disable memcache session handler support], yes, no)
-
-if test -z "$PHP_ZLIB_DIR"; then
-PHP_ARG_WITH(zlib-dir, for the location of ZLIB,
-[ --with-zlib-dir[=DIR] memcache: Set the path to ZLIB install prefix.], no, no)
-fi
-
-if test -z "$PHP_DEBUG"; then
- AC_ARG_ENABLE(debug,
- [ --enable-debug compile with debugging symbols],[
- PHP_DEBUG=$enableval
- ],[
- PHP_DEBUG=no
- ])
-fi
-
-if test "$PHP_MEMCACHE" != "no"; then
-
- if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then
- if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then
- PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
- PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib"
- elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then
- PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
- PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include"
- else
- AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"])
- fi
- else
- for i in /usr/local /usr; do
- if test -f "$i/include/zlib/zlib.h"; then
- PHP_ZLIB_DIR="$i"
- PHP_ZLIB_INCDIR="$i/include/zlib"
- elif test -f "$i/include/zlib.h"; then
- PHP_ZLIB_DIR="$i"
- PHP_ZLIB_INCDIR="$i/include"
- fi
- done
- fi
-
- dnl # zlib
- AC_MSG_CHECKING([for the location of zlib])
- if test "$PHP_ZLIB_DIR" = "no"; then
- AC_MSG_ERROR([memcache support requires ZLIB. Use --with-zlib-dir=<DIR> to specify prefix where ZLIB include and library are located])
- else
- AC_MSG_RESULT([$PHP_ZLIB_DIR])
- if test "z$PHP_LIBDIR" != "z"; then
- dnl PHP5+
- PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHE_SHARED_LIBADD)
- else
- dnl PHP4
- PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/lib, MEMCACHE_SHARED_LIBADD)
- fi
- PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR)
- fi
-
- if test "$PHP_MEMCACHE_SESSION" != "no"; then
- AC_MSG_CHECKING([for session includes])
- session_inc_path=""
-
- if test -f "$abs_srcdir/include/php/ext/session/php_session.h"; then
- session_inc_path="$abs_srcdir/include/php"
- elif test -f "$abs_srcdir/ext/session/php_session.h"; then
- session_inc_path="$abs_srcdir"
- elif test -f "$phpincludedir/ext/session/php_session.h"; then
- session_inc_path="$phpincludedir"
- else
- for i in php php4 php5 php6; do
- if test -f "$prefix/include/$i/ext/session/php_session.h"; then
- session_inc_path="$prefix/include/$i"
- fi
- done
- fi
-
- if test "$session_inc_path" = ""; then
- AC_MSG_ERROR([Cannot find php_session.h])
- else
- AC_MSG_RESULT([$session_inc_path])
- fi
- fi
-
- AC_MSG_CHECKING([for memcache session support])
- if test "$PHP_MEMCACHE_SESSION" != "no"; then
- AC_MSG_RESULT([enabled])
- AC_DEFINE(HAVE_MEMCACHE_SESSION,1,[Whether memcache session handler is enabled])
- AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support])
- PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c, $ext_shared,,-I$session_inc_path)
- ifdef([PHP_ADD_EXTENSION_DEP],
- [
- PHP_ADD_EXTENSION_DEP(memcache, session)
- ])
- else
- AC_MSG_RESULT([disabled])
- AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support])
- PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c, $ext_shared)
- fi
-
-dnl this is needed to build the extension with phpize and -Wall
-
- if test "$PHP_DEBUG" = "yes"; then
- CFLAGS="$CFLAGS -Wall"
- fi
-
-fi
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache.c
^
|
@@ -1,2600 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache.c,v 1.98 2008/02/05 19:46:16 mikl Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include <stdio.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#include <zlib.h>
-#include <time.h>
-#include "ext/standard/crc32.h"
-#include "ext/standard/info.h"
-#include "ext/standard/php_string.h"
-#include "ext/standard/php_var.h"
-#include "ext/standard/php_smart_str.h"
-#include "php_network.h"
-#include "php_memcache.h"
-#include "memcache_queue.h"
-
-#ifndef ZEND_ENGINE_2
-#define OnUpdateLong OnUpdateInt
-#endif
-
-/* True global resources - no need for thread safety here */
-static int le_memcache_pool, le_pmemcache;
-static zend_class_entry *memcache_class_entry_ptr;
-
-ZEND_DECLARE_MODULE_GLOBALS(memcache)
-
-/* {{{ memcache_functions[]
- */
-zend_function_entry memcache_functions[] = {
- PHP_FE(memcache_connect, NULL)
- PHP_FE(memcache_pconnect, NULL)
- PHP_FE(memcache_add_server, NULL)
- PHP_FE(memcache_set_server_params, NULL)
- PHP_FE(memcache_get_server_status, NULL)
- PHP_FE(memcache_get_version, NULL)
- PHP_FE(memcache_add, NULL)
- PHP_FE(memcache_set, NULL)
- PHP_FE(memcache_replace, NULL)
- PHP_FE(memcache_get, NULL)
- PHP_FE(memcache_delete, NULL)
- PHP_FE(memcache_debug, NULL)
- PHP_FE(memcache_get_stats, NULL)
- PHP_FE(memcache_get_extended_stats, NULL)
- PHP_FE(memcache_set_compress_threshold, NULL)
- PHP_FE(memcache_increment, NULL)
- PHP_FE(memcache_decrement, NULL)
- PHP_FE(memcache_close, NULL)
- PHP_FE(memcache_flush, NULL)
- {NULL, NULL, NULL}
-};
-
-static zend_function_entry php_memcache_class_functions[] = {
- PHP_FALIAS(connect, memcache_connect, NULL)
- PHP_FALIAS(pconnect, memcache_pconnect, NULL)
- PHP_FALIAS(addserver, memcache_add_server, NULL)
- PHP_FALIAS(setserverparams, memcache_set_server_params, NULL)
- PHP_FALIAS(getserverstatus, memcache_get_server_status, NULL)
- PHP_FALIAS(getversion, memcache_get_version, NULL)
- PHP_FALIAS(add, memcache_add, NULL)
- PHP_FALIAS(set, memcache_set, NULL)
- PHP_FALIAS(replace, memcache_replace, NULL)
- PHP_FALIAS(get, memcache_get, NULL)
- PHP_FALIAS(delete, memcache_delete, NULL)
- PHP_FALIAS(getstats, memcache_get_stats, NULL)
- PHP_FALIAS(getextendedstats, memcache_get_extended_stats, NULL)
- PHP_FALIAS(setcompressthreshold, memcache_set_compress_threshold, NULL)
- PHP_FALIAS(increment, memcache_increment, NULL)
- PHP_FALIAS(decrement, memcache_decrement, NULL)
- PHP_FALIAS(close, memcache_close, NULL)
- PHP_FALIAS(flush, memcache_flush, NULL)
- {NULL, NULL, NULL}
-};
-
-/* }}} */
-
-/* {{{ memcache_module_entry
- */
-zend_module_entry memcache_module_entry = {
-#if ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
-#endif
- "memcache",
- memcache_functions,
- PHP_MINIT(memcache),
- PHP_MSHUTDOWN(memcache),
- PHP_RINIT(memcache),
- NULL,
- PHP_MINFO(memcache),
-#if ZEND_MODULE_API_NO >= 20010901
- PHP_MEMCACHE_VERSION,
-#endif
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-#ifdef COMPILE_DL_MEMCACHE
-ZEND_GET_MODULE(memcache)
-#endif
-
-static PHP_INI_MH(OnUpdateChunkSize) /* {{{ */
-{
- long int lval;
-
- lval = strtol(new_value, NULL, 10);
- if (lval <= 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.chunk_size must be a positive integer ('%s' given)", new_value);
- return FAILURE;
- }
-
- return OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
-}
-/* }}} */
-
-static PHP_INI_MH(OnUpdateFailoverAttempts) /* {{{ */
-{
- long int lval;
-
- lval = strtol(new_value, NULL, 10);
- if (lval <= 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.max_failover_attempts must be a positive integer ('%s' given)", new_value);
- return FAILURE;
- }
-
- return OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
-}
-/* }}} */
-
-static PHP_INI_MH(OnUpdateHashStrategy) /* {{{ */
-{
- if (!strcasecmp(new_value, "standard")) {
- MEMCACHE_G(hash_strategy) = MMC_STANDARD_HASH;
- }
- else if (!strcasecmp(new_value, "consistent")) {
- MEMCACHE_G(hash_strategy) = MMC_CONSISTENT_HASH;
- }
- else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.hash_strategy must be in set {standard, consistent} ('%s' given)", new_value);
- return FAILURE;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-static PHP_INI_MH(OnUpdateHashFunction) /* {{{ */
-{
- if (!strcasecmp(new_value, "crc32")) {
- MEMCACHE_G(hash_function) = MMC_HASH_CRC32;
- }
- else if (!strcasecmp(new_value, "fnv")) {
- MEMCACHE_G(hash_function) = MMC_HASH_FNV1A;
- }
- else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.hash_function must be in set {crc32, fnv} ('%s' given)", new_value);
- return FAILURE;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_INI */
-PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("memcache.allow_failover", "1", PHP_INI_ALL, OnUpdateLong, allow_failover, zend_memcache_globals, memcache_globals)
- STD_PHP_INI_ENTRY("memcache.max_failover_attempts", "20", PHP_INI_ALL, OnUpdateFailoverAttempts, max_failover_attempts, zend_memcache_globals, memcache_globals)
- STD_PHP_INI_ENTRY("memcache.default_port", "11211", PHP_INI_ALL, OnUpdateLong, default_port, zend_memcache_globals, memcache_globals)
- STD_PHP_INI_ENTRY("memcache.chunk_size", "8192", PHP_INI_ALL, OnUpdateChunkSize, chunk_size, zend_memcache_globals, memcache_globals)
- STD_PHP_INI_ENTRY("memcache.hash_strategy", "standard", PHP_INI_ALL, OnUpdateHashStrategy, hash_strategy, zend_memcache_globals, memcache_globals)
- STD_PHP_INI_ENTRY("memcache.hash_function", "crc32", PHP_INI_ALL, OnUpdateHashFunction, hash_function, zend_memcache_globals, memcache_globals)
-PHP_INI_END()
-/* }}} */
-
-/* {{{ internal function protos */
-static void _mmc_pool_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
-static void _mmc_pserver_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
-
-static void mmc_server_free(mmc_t * TSRMLS_DC);
-static void mmc_server_disconnect(mmc_t * TSRMLS_DC);
-static int mmc_server_store(mmc_t *, const char *, int TSRMLS_DC);
-
-static int mmc_compress(char **, unsigned long *, const char *, int TSRMLS_DC);
-static int mmc_uncompress(char **, unsigned long *, const char *, int);
-static int mmc_get_pool(zval *, mmc_pool_t ** TSRMLS_DC);
-static int mmc_readline(mmc_t * TSRMLS_DC);
-static char * mmc_get_version(mmc_t * TSRMLS_DC);
-static int mmc_str_left(char *, char *, int, int);
-static int mmc_sendcmd(mmc_t *, const char *, int TSRMLS_DC);
-static int mmc_parse_response(mmc_t *mmc, char *, int, char **, int *, int *, int *);
-static int mmc_exec_retrieval_cmd_multi(mmc_pool_t *, zval *, zval **, zval * TSRMLS_DC);
-static int mmc_read_value(mmc_t *, char **, int *, char **, int *, int * TSRMLS_DC);
-static int mmc_flush(mmc_t *, int TSRMLS_DC);
-static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, char *, int);
-static int mmc_get_stats(mmc_t *, char *, int, int, zval * TSRMLS_DC);
-static int mmc_incr_decr(mmc_t *, int, char *, int, int, long * TSRMLS_DC);
-static void php_mmc_incr_decr(INTERNAL_FUNCTION_PARAMETERS, int);
-static void php_mmc_connect(INTERNAL_FUNCTION_PARAMETERS, int);
-/* }}} */
-
-/* {{{ hash strategies */
-extern mmc_hash_t mmc_standard_hash;
-extern mmc_hash_t mmc_consistent_hash;
-/* }}} */
-
-/* {{{ php_memcache_init_globals()
-*/
-static void php_memcache_init_globals(zend_memcache_globals *memcache_globals_p TSRMLS_DC)
-{
- MEMCACHE_G(debug_mode) = 0;
- MEMCACHE_G(num_persistent) = 0;
- MEMCACHE_G(compression_level) = Z_DEFAULT_COMPRESSION;
- MEMCACHE_G(hash_strategy) = MMC_STANDARD_HASH;
- MEMCACHE_G(hash_function) = MMC_HASH_CRC32;
-}
-/* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION
- */
-PHP_MINIT_FUNCTION(memcache)
-{
- zend_class_entry memcache_class_entry;
- INIT_CLASS_ENTRY(memcache_class_entry, "Memcache", php_memcache_class_functions);
- memcache_class_entry_ptr = zend_register_internal_class(&memcache_class_entry TSRMLS_CC);
-
- le_memcache_pool = zend_register_list_destructors_ex(_mmc_pool_list_dtor, NULL, "memcache connection", module_number);
- le_pmemcache = zend_register_list_destructors_ex(NULL, _mmc_pserver_list_dtor, "persistent memcache connection", module_number);
-
-#ifdef ZTS
- ts_allocate_id(&memcache_globals_id, sizeof(zend_memcache_globals), (ts_allocate_ctor) php_memcache_init_globals, NULL);
-#else
- php_memcache_init_globals(&memcache_globals TSRMLS_CC);
-#endif
-
- REGISTER_LONG_CONSTANT("MEMCACHE_COMPRESSED", MMC_COMPRESSED, CONST_CS | CONST_PERSISTENT);
- REGISTER_INI_ENTRIES();
-
-#if HAVE_MEMCACHE_SESSION
- REGISTER_LONG_CONSTANT("MEMCACHE_HAVE_SESSION", 1, CONST_CS | CONST_PERSISTENT);
- php_session_register_module(ps_memcache_ptr);
-#else
- REGISTER_LONG_CONSTANT("MEMCACHE_HAVE_SESSION", 0, CONST_CS | CONST_PERSISTENT);
-#endif
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-PHP_MSHUTDOWN_FUNCTION(memcache)
-{
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_RINIT_FUNCTION
- */
-PHP_RINIT_FUNCTION(memcache)
-{
- MEMCACHE_G(debug_mode) = 0;
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION
- */
-PHP_MINFO_FUNCTION(memcache)
-{
- char buf[MAX_LENGTH_OF_LONG + 1];
-
- sprintf(buf, "%ld", MEMCACHE_G(num_persistent));
-
- php_info_print_table_start();
- php_info_print_table_header(2, "memcache support", "enabled");
- php_info_print_table_row(2, "Active persistent connections", buf);
- php_info_print_table_row(2, "Version", PHP_MEMCACHE_VERSION);
- php_info_print_table_row(2, "Revision", "$Revision: 1.98 $");
- php_info_print_table_end();
-
- DISPLAY_INI_ENTRIES();
-}
-/* }}} */
-
-/* ------------------
- internal functions
- ------------------ */
-
-#if ZEND_DEBUG
-void mmc_debug(const char *format, ...) /* {{{ */
-{
- TSRMLS_FETCH();
-
- if (MEMCACHE_G(debug_mode)) {
- char buffer[1024];
- va_list args;
-
- va_start(args, format);
- vsnprintf(buffer, sizeof(buffer)-1, format, args);
- va_end(args);
- buffer[sizeof(buffer)-1] = '\0';
- php_printf("%s<br />\n", buffer);
- }
-}
-/* }}} */
-#endif
-
-static void _mmc_pool_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
-{
- mmc_pool_free((mmc_pool_t *)rsrc->ptr TSRMLS_CC);
-}
-/* }}} */
-
-static void _mmc_pserver_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
-{
- mmc_server_free((mmc_t *)rsrc->ptr TSRMLS_CC);
-}
-/* }}} */
-
-mmc_t *mmc_server_new(char *host, int host_len, unsigned short port, int persistent, int timeout, int retry_interval TSRMLS_DC) /* {{{ */
-{
- mmc_t *mmc = pemalloc(sizeof(mmc_t), persistent);
- memset(mmc, 0, sizeof(*mmc));
-
- mmc->host = pemalloc(host_len + 1, persistent);
- memcpy(mmc->host, host, host_len);
- mmc->host[host_len] = '\0';
-
- mmc->port = port;
- mmc->status = MMC_STATUS_DISCONNECTED;
-
- mmc->persistent = persistent;
- if (persistent) {
- MEMCACHE_G(num_persistent)++;
- }
-
- mmc->timeout = timeout;
- mmc->retry_interval = retry_interval;
-
- return mmc;
-}
-/* }}} */
-
-static void mmc_server_callback_dtor(zval **callback TSRMLS_DC) /* {{{ */
-{
- zval **this_obj;
-
- if (!callback || !*callback) return;
-
- if (Z_TYPE_PP(callback) == IS_ARRAY &&
- zend_hash_index_find(Z_ARRVAL_PP(callback), 0, (void **)&this_obj) == SUCCESS &&
- Z_TYPE_PP(this_obj) == IS_OBJECT) {
- zval_ptr_dtor(this_obj);
- }
- zval_ptr_dtor(callback);
-}
-/* }}} */
-
-static void mmc_server_callback_ctor(zval **callback TSRMLS_DC) /* {{{ */
-{
- zval **this_obj;
-
- if (!callback || !*callback) return;
-
- if (Z_TYPE_PP(callback) == IS_ARRAY &&
- zend_hash_index_find(Z_ARRVAL_PP(callback), 0, (void **)&this_obj) == SUCCESS &&
- Z_TYPE_PP(this_obj) == IS_OBJECT) {
- zval_add_ref(this_obj);
- }
- zval_add_ref(callback);
-}
-/* }}} */
-
-static void mmc_server_sleep(mmc_t *mmc TSRMLS_DC) /*
- prepare server struct for persistent sleep {{{ */
-{
- mmc_server_callback_dtor(&mmc->failure_callback TSRMLS_CC);
- mmc->failure_callback = NULL;
-
- if (mmc->error != NULL) {
- efree(mmc->error);
- mmc->error = NULL;
- }
-}
-/* }}} */
-
-static void mmc_server_free(mmc_t *mmc TSRMLS_DC) /* {{{ */
-{
- if (mmc->in_free) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "Recursive reference detected, bailing out");
- return;
- }
- mmc->in_free = 1;
-
- mmc_server_sleep(mmc TSRMLS_CC);
-
- if (mmc->persistent) {
- free(mmc->host);
- free(mmc);
- MEMCACHE_G(num_persistent)--;
- }
- else {
- if (mmc->stream != NULL) {
- php_stream_close(mmc->stream);
- }
- efree(mmc->host);
- efree(mmc);
- }
-}
-/* }}} */
-
-static void mmc_server_seterror(mmc_t *mmc, const char *error, int errnum) /* {{{ */
-{
- if (error != NULL) {
- if (mmc->error != NULL) {
- efree(mmc->error);
- }
-
- mmc->error = estrdup(error);
- mmc->errnum = errnum;
- }
-}
-/* }}} */
-
-static void mmc_server_received_error(mmc_t *mmc, int response_len) /* {{{ */
-{
- if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1))
- {
- mmc->inbuf[response_len < MMC_BUF_SIZE - 1 ? response_len : MMC_BUF_SIZE - 1] = '\0';
- mmc_server_seterror(mmc, mmc->inbuf, 0);
- }
- else {
- mmc_server_seterror(mmc, "Received malformed response", 0);
- }
-}
-/* }}} */
-
-int mmc_server_failure(mmc_t *mmc TSRMLS_DC) /*
- determines if a request should be retried or is a hard network failure {{{ */
-{
- switch (mmc->status) {
- case MMC_STATUS_DISCONNECTED:
- return 0;
-
- /* attempt reconnect of sockets in unknown state */
- case MMC_STATUS_UNKNOWN:
- mmc->status = MMC_STATUS_DISCONNECTED;
- return 0;
- }
-
- mmc_server_deactivate(mmc TSRMLS_CC);
- return 1;
-}
-/* }}} */
-
-static int mmc_server_store(mmc_t *mmc, const char *request, int request_len TSRMLS_DC) { /* {{{ */
- int response_len;
-
- if (php_stream_write(mmc->stream, request, request_len) != request_len) {
- mmc_server_seterror(mmc, "Failed sending command and value to stream", 0);
- return -1;
- }
-
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
- return -1;
- }
-
- if(mmc_str_left(mmc->inbuf, "STORED", response_len, sizeof("STORED") - 1)) {
- return 1;
- }
-
- /* return FALSE */
- if(mmc_str_left(mmc->inbuf, "NOT_STORED", response_len, sizeof("NOT_STORED") - 1)) {
- return 0;
- }
-
- /* return FALSE without failover */
- if (mmc_str_left(mmc->inbuf, "SERVER_ERROR out of memory", response_len, sizeof("SERVER_ERROR out of memory") - 1) ||
- mmc_str_left(mmc->inbuf, "SERVER_ERROR object too large", response_len, sizeof("SERVER_ERROR object too large")-1)) {
- return 0;
- }
-
- mmc_server_received_error(mmc, response_len);
- return -1;
-}
-/* }}} */
-
-int mmc_prepare_key_ex(const char *key, unsigned int key_len, char *result, unsigned int *result_len TSRMLS_DC) /* {{{ */
-{
- unsigned int i;
- if (key_len == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key cannot be empty");
- return MMC_REQUEST_FAILURE;
- }
-
- *result_len = key_len < MMC_KEY_MAX_SIZE ? key_len : MMC_KEY_MAX_SIZE;
- result[*result_len] = '\0';
-
- for (i=0; i<*result_len; i++) {
- result[i] = ((unsigned char)key[i]) > ' ' ? key[i] : '_';
- }
-
- return MMC_OK;
-}
-/* }}} */
-
-int mmc_prepare_key(zval *key, char *result, unsigned int *result_len TSRMLS_DC) /* {{{ */
-{
- if (Z_TYPE_P(key) == IS_STRING) {
- return mmc_prepare_key_ex(Z_STRVAL_P(key), Z_STRLEN_P(key), result, result_len TSRMLS_CC);
- } else {
- int res;
- zval *keytmp;
- ALLOC_ZVAL(keytmp);
-
- *keytmp = *key;
- zval_copy_ctor(keytmp);
- INIT_PZVAL(keytmp);
- convert_to_string(keytmp);
-
- res = mmc_prepare_key_ex(Z_STRVAL_P(keytmp), Z_STRLEN_P(keytmp), result, result_len TSRMLS_CC);
-
- zval_dtor(keytmp);
- FREE_ZVAL(keytmp);
-
- return res;
- }
-}
-/* }}} */
-
-static unsigned int mmc_hash_crc32(const char *key, int key_len) /*
- CRC32 hash {{{ */
-{
- unsigned int crc = ~0;
- int i;
-
- for (i=0; i<key_len; i++) {
- CRC32(crc, key[i]);
- }
-
- return ~crc;
-}
-/* }}} */
-
-static unsigned int mmc_hash_fnv1a(const char *key, int key_len) /*
- FNV-1a hash {{{ */
-{
- unsigned int hval = FNV_32_INIT;
- int i;
-
- for (i=0; i<key_len; i++) {
- hval ^= (unsigned int)key[i];
- hval *= FNV_32_PRIME;
- }
-
- return hval;
-}
-/* }}} */
-
-static void mmc_pool_init_hash(mmc_pool_t *pool TSRMLS_DC) /* {{{ */
-{
- mmc_hash_function hash;
-
- switch (MEMCACHE_G(hash_strategy)) {
- case MMC_CONSISTENT_HASH:
- pool->hash = &mmc_consistent_hash;
- break;
- default:
- pool->hash = &mmc_standard_hash;
- }
-
- switch (MEMCACHE_G(hash_function)) {
- case MMC_HASH_FNV1A:
- hash = &mmc_hash_fnv1a;
- break;
- default:
- hash = &mmc_hash_crc32;
- }
-
- pool->hash_state = pool->hash->create_state(hash);
-}
-/* }}} */
-
-mmc_pool_t *mmc_pool_new(TSRMLS_D) /* {{{ */
-{
- mmc_pool_t *pool = emalloc(sizeof(mmc_pool_t));
- pool->num_servers = 0;
- pool->compress_threshold = 0;
- pool->in_free = 0;
- pool->min_compress_savings = MMC_DEFAULT_SAVINGS;
-
- mmc_pool_init_hash(pool TSRMLS_CC);
-
- return pool;
-}
-/* }}} */
-
-void mmc_pool_free(mmc_pool_t *pool TSRMLS_DC) /* {{{ */
-{
- int i;
-
- if (pool->in_free) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "Recursive reference detected, bailing out");
- return;
- }
- pool->in_free = 1;
-
- for (i=0; i<pool->num_servers; i++) {
- if (!pool->servers[i]) {
- continue;
- }
- if (pool->servers[i]->persistent == 0 && pool->servers[i]->host != NULL) {
- mmc_server_free(pool->servers[i] TSRMLS_CC);
- } else {
- mmc_server_sleep(pool->servers[i] TSRMLS_CC);
- }
- pool->servers[i] = NULL;
- }
-
- if (pool->num_servers) {
- efree(pool->servers);
- efree(pool->requests);
- }
-
- pool->hash->free_state(pool->hash_state);
- efree(pool);
-}
-/* }}} */
-
-void mmc_pool_add(mmc_pool_t *pool, mmc_t *mmc, unsigned int weight) /* {{{ */
-{
- /* add server and a preallocated request pointer */
- if (pool->num_servers) {
- pool->servers = erealloc(pool->servers, sizeof(mmc_t *) * (pool->num_servers + 1));
- pool->requests = erealloc(pool->requests, sizeof(mmc_t *) * (pool->num_servers + 1));
- }
- else {
- pool->servers = emalloc(sizeof(mmc_t *));
- pool->requests = emalloc(sizeof(mmc_t *));
- }
-
- pool->servers[pool->num_servers] = mmc;
- pool->num_servers++;
-
- pool->hash->add_server(pool->hash_state, mmc, weight);
-}
-/* }}} */
-
-static int mmc_pool_close(mmc_pool_t *pool TSRMLS_DC) /*
- disconnects and removes all servers in the pool {{{ */
-{
- if (pool->num_servers) {
- int i;
-
- for (i=0; i<pool->num_servers; i++) {
- if (pool->servers[i]->persistent == 0 && pool->servers[i]->host != NULL) {
- mmc_server_free(pool->servers[i] TSRMLS_CC);
- } else {
- mmc_server_sleep(pool->servers[i] TSRMLS_CC);
- }
- }
-
- efree(pool->servers);
- pool->servers = NULL;
- pool->num_servers = 0;
-
- efree(pool->requests);
- pool->requests = NULL;
-
- /* reallocate the hash strategy state */
- pool->hash->free_state(pool->hash_state);
- mmc_pool_init_hash(pool TSRMLS_CC);
- }
-
- return 1;
-}
-/* }}} */
-
-int mmc_pool_store(mmc_pool_t *pool, const char *command, int command_len, const char *key, int key_len, int flags, int expire, const char *value, int value_len TSRMLS_DC) /* {{{ */
-{
- mmc_t *mmc;
- char *request;
- int request_len, result = -1;
- char *key_copy = NULL, *data = NULL;
-
- if (key_len > MMC_KEY_MAX_SIZE) {
- key = key_copy = estrndup(key, MMC_KEY_MAX_SIZE);
- key_len = MMC_KEY_MAX_SIZE;
- }
-
- /* autocompress large values */
- if (pool->compress_threshold && value_len >= pool->compress_threshold) {
- flags |= MMC_COMPRESSED;
- }
-
- if (flags & MMC_COMPRESSED) {
- unsigned long data_len;
-
- if (!mmc_compress(&data, &data_len, value, value_len TSRMLS_CC)) {
- mmc_server_seterror(mmc, "Failed to compress data", 0);
- return -1;
- }
-
- /* was enough space saved to motivate uncompress processing on get */
- if (data_len < value_len * (1 - pool->min_compress_savings)) {
- value = data;
- value_len = data_len;
- }
- else {
- flags &= ~MMC_COMPRESSED;
- efree(data);
- data = NULL;
- }
- }
-
- request = emalloc(
- command_len
- + 1 /* space */
- + key_len
- + 1 /* space */
- + MAX_LENGTH_OF_LONG
- + 1 /* space */
- + MAX_LENGTH_OF_LONG
- + 1 /* space */
- + MAX_LENGTH_OF_LONG
- + sizeof("\r\n") - 1
- + value_len
- + sizeof("\r\n") - 1
- + 1
- );
-
- request_len = sprintf(request, "%s %s %d %d %d\r\n", command, key, flags, expire, value_len);
-
- memcpy(request + request_len, value, value_len);
- request_len += value_len;
-
- memcpy(request + request_len, "\r\n", sizeof("\r\n") - 1);
- request_len += sizeof("\r\n") - 1;
-
- request[request_len] = '\0';
-
- while (result < 0 && (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
- if ((result = mmc_server_store(mmc, request, request_len TSRMLS_CC)) < 0) {
- mmc_server_failure(mmc TSRMLS_CC);
- }
- }
-
- if (key_copy != NULL) {
- efree(key_copy);
- }
-
- if (data != NULL) {
- efree(data);
- }
-
- efree(request);
-
- return result;
-}
-/* }}} */
-
-static int mmc_compress(char **result, unsigned long *result_len, const char *data, int data_len TSRMLS_DC) /* {{{ */
-{
- int status, level = MEMCACHE_G(compression_level);
-
- *result_len = data_len + (data_len / 1000) + 25 + 1; /* some magic from zlib.c */
- *result = (char *) emalloc(*result_len);
-
- if (!*result) {
- return 0;
- }
-
- if (level >= 0) {
- status = compress2((unsigned char *) *result, result_len, (unsigned const char *) data, data_len, level);
- } else {
- status = compress((unsigned char *) *result, result_len, (unsigned const char *) data, data_len);
- }
-
- if (status == Z_OK) {
- *result = erealloc(*result, *result_len + 1);
- (*result)[*result_len] = '\0';
- return 1;
- }
-
- switch (status) {
- case Z_MEM_ERROR:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough memory to perform compression");
- break;
- case Z_BUF_ERROR:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough room in the output buffer to perform compression");
- break;
- case Z_STREAM_ERROR:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid compression level");
- break;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error during compression");
- break;
- }
-
- efree(*result);
- return 0;
-}
-/* }}}*/
-
-static int mmc_uncompress(char **result, unsigned long *result_len, const char *data, int data_len) /* {{{ */
-{
- int status;
- unsigned int factor = 1, maxfactor = 16;
- char *tmp1 = NULL;
-
- do {
- *result_len = (unsigned long)data_len * (1 << factor++);
- *result = (char *) erealloc(tmp1, *result_len);
- status = uncompress((unsigned char *) *result, result_len, (unsigned const char *) data, data_len);
- tmp1 = *result;
- } while (status == Z_BUF_ERROR && factor < maxfactor);
-
- if (status == Z_OK) {
- *result = erealloc(*result, *result_len + 1);
- (*result)[*result_len] = '\0';
- return 1;
- }
-
- efree(*result);
- return 0;
-}
-/* }}}*/
-
-static int mmc_get_pool(zval *id, mmc_pool_t **pool TSRMLS_DC) /* {{{ */
-{
- zval **connection;
- int resource_type;
-
- if (Z_TYPE_P(id) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(id), "connection", sizeof("connection"), (void **) &connection) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to extract 'connection' variable from object");
- return 0;
- }
-
- *pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
-
- if (!*pool || resource_type != le_memcache_pool) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown connection identifier");
- return 0;
- }
-
- return Z_LVAL_PP(connection);
-}
-/* }}} */
-
-static int _mmc_open(mmc_t *mmc, char **error_string, int *errnum TSRMLS_DC) /* {{{ */
-{
- struct timeval tv;
- char *hostname = NULL, *hash_key = NULL, *errstr = NULL;
- int hostname_len, err = 0;
-
- /* close open stream */
- if (mmc->stream != NULL) {
- mmc_server_disconnect(mmc TSRMLS_CC);
- }
-
- tv.tv_sec = mmc->timeout;
- tv.tv_usec = 0;
-
- if (mmc->port) {
- hostname_len = spprintf(&hostname, 0, "%s:%d", mmc->host, mmc->port);
- }
- else {
- hostname_len = spprintf(&hostname, 0, "%s", mmc->host);
- }
-
- if (mmc->persistent) {
- spprintf(&hash_key, 0, "memcache:%s", hostname);
- }
-
-#if PHP_API_VERSION > 20020918
- mmc->stream = php_stream_xport_create( hostname, hostname_len,
- ENFORCE_SAFE_MODE | REPORT_ERRORS,
- STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
- hash_key, &tv, NULL, &errstr, &err);
-#else
- if (mmc->persistent) {
- switch(php_stream_from_persistent_id(hash_key, &(mmc->stream) TSRMLS_CC)) {
- case PHP_STREAM_PERSISTENT_SUCCESS:
- if (php_stream_eof(mmc->stream)) {
- php_stream_pclose(mmc->stream);
- mmc->stream = NULL;
- break;
- }
- case PHP_STREAM_PERSISTENT_FAILURE:
- break;
- }
- }
-
- if (!mmc->stream) {
- int socktype = SOCK_STREAM;
- mmc->stream = php_stream_sock_open_host(mmc->host, mmc->port, socktype, &tv, hash_key);
- }
-
-#endif
-
- efree(hostname);
- if (mmc->persistent) {
- efree(hash_key);
- }
-
- if (!mmc->stream) {
- MMC_DEBUG(("_mmc_open: can't open socket to host"));
- mmc_server_seterror(mmc, errstr != NULL ? errstr : "Connection failed", err);
- mmc_server_deactivate(mmc TSRMLS_CC);
-
- if (errstr) {
- if (error_string) {
- *error_string = errstr;
- }
- else {
- efree(errstr);
- }
- }
- if (errnum) {
- *errnum = err;
- }
-
- return 0;
- }
-
- php_stream_auto_cleanup(mmc->stream);
- php_stream_set_option(mmc->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
- php_stream_set_option(mmc->stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
- php_stream_set_chunk_size(mmc->stream, MEMCACHE_G(chunk_size));
-
- mmc->status = MMC_STATUS_CONNECTED;
-
- if (mmc->error != NULL) {
- efree(mmc->error);
- mmc->error = NULL;
- }
-
- return 1;
-}
-/* }}} */
-
-int mmc_open(mmc_t *mmc, int force_connect, char **error_string, int *errnum TSRMLS_DC) /* {{{ */
-{
- switch (mmc->status) {
- case MMC_STATUS_DISCONNECTED:
- return _mmc_open(mmc, error_string, errnum TSRMLS_CC);
-
- case MMC_STATUS_CONNECTED:
- return 1;
-
- case MMC_STATUS_UNKNOWN:
- /* check connection if needed */
- if (force_connect) {
- char *version;
- if ((version = mmc_get_version(mmc TSRMLS_CC)) == NULL && !_mmc_open(mmc, error_string, errnum TSRMLS_CC)) {
- break;
- }
- if (version) {
- efree(version);
- }
- mmc->status = MMC_STATUS_CONNECTED;
- }
- return 1;
-
- case MMC_STATUS_FAILED:
- if (mmc->retry_interval >= 0 && (long)time(NULL) >= mmc->failed + mmc->retry_interval) {
- if (_mmc_open(mmc, error_string, errnum TSRMLS_CC) /*&& mmc_flush(mmc, 0 TSRMLS_CC) > 0*/) {
- return 1;
- }
- }
- break;
- }
- return 0;
-}
-/* }}} */
-
-static void mmc_server_disconnect(mmc_t *mmc TSRMLS_DC) /* {{{ */
-{
- if (mmc->stream != NULL) {
- if (mmc->persistent) {
- php_stream_pclose(mmc->stream);
- }
- else {
- php_stream_close(mmc->stream);
- }
- mmc->stream = NULL;
- }
- mmc->status = MMC_STATUS_DISCONNECTED;
-}
-/* }}} */
-
-void mmc_server_deactivate(mmc_t *mmc TSRMLS_DC) /*
- disconnect and marks the server as down {{{ */
-{
- mmc_server_disconnect(mmc TSRMLS_CC);
- mmc->status = MMC_STATUS_FAILED;
- mmc->failed = (long)time(NULL);
-
- if (mmc->failure_callback != NULL) {
- zval *retval = NULL;
- zval *host, *tcp_port, *udp_port, *error, *errnum;
- zval **params[5] = {&host, &tcp_port, &udp_port, &error, &errnum};
-
- MAKE_STD_ZVAL(host);
- MAKE_STD_ZVAL(tcp_port); MAKE_STD_ZVAL(udp_port);
- MAKE_STD_ZVAL(error); MAKE_STD_ZVAL(errnum);
-
- ZVAL_STRING(host, mmc->host, 1);
- ZVAL_LONG(tcp_port, mmc->port); ZVAL_LONG(udp_port, 0);
-
- if (mmc->error != NULL) {
- ZVAL_STRING(error, mmc->error, 1);
- }
- else {
- ZVAL_NULL(error);
- }
- ZVAL_LONG(errnum, mmc->errnum);
-
- call_user_function_ex(EG(function_table), NULL, mmc->failure_callback, &retval, 5, params, 0, NULL TSRMLS_CC);
-
- zval_ptr_dtor(&host);
- zval_ptr_dtor(&tcp_port); zval_ptr_dtor(&udp_port);
- zval_ptr_dtor(&error); zval_ptr_dtor(&errnum);
-
- if (retval != NULL) {
- zval_ptr_dtor(&retval);
- }
- }
- else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Server %s (tcp %d) failed with: %s (%d)",
- mmc->host, mmc->port, mmc->error, mmc->errnum);
- }
-}
-/* }}} */
-
-static int mmc_readline(mmc_t *mmc TSRMLS_DC) /* {{{ */
-{
- char *response;
- size_t response_len;
-
- if (mmc->stream == NULL) {
- mmc_server_seterror(mmc, "Socket is closed", 0);
- return -1;
- }
-
- response = php_stream_get_line(mmc->stream, ZSTR(mmc->inbuf), MMC_BUF_SIZE, &response_len);
- if (response) {
- MMC_DEBUG(("mmc_readline: read data:"));
- MMC_DEBUG(("mmc_readline:---"));
- MMC_DEBUG(("%s", response));
- MMC_DEBUG(("mmc_readline:---"));
- return response_len;
- }
-
- mmc_server_seterror(mmc, "Failed reading line from stream", 0);
- return -1;
-}
-/* }}} */
-
-static char *mmc_get_version(mmc_t *mmc TSRMLS_DC) /* {{{ */
-{
- char *version_str;
- int response_len;
-
- if (mmc_sendcmd(mmc, "version", sizeof("version") - 1 TSRMLS_CC) < 0) {
- return NULL;
- }
-
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
- return NULL;
- }
-
- if (mmc_str_left(mmc->inbuf, "VERSION ", response_len, sizeof("VERSION ") - 1)) {
- version_str = estrndup(mmc->inbuf + sizeof("VERSION ") - 1, response_len - (sizeof("VERSION ") - 1) - (sizeof("\r\n") - 1) );
- return version_str;
- }
-
- mmc_server_seterror(mmc, "Malformed version string", 0);
- return NULL;
-}
-/* }}} */
-
-static int mmc_str_left(char *haystack, char *needle, int haystack_len, int needle_len) /* {{{ */
-{
- char *found;
-
- found = php_memnstr(haystack, needle, needle_len, haystack + haystack_len);
- if ((found - haystack) == 0) {
- return 1;
- }
- return 0;
-}
-/* }}} */
-
-static int mmc_sendcmd(mmc_t *mmc, const char *cmd, int cmdlen TSRMLS_DC) /* {{{ */
-{
- char *command;
- int command_len;
-
- if (!mmc || !cmd) {
- return -1;
- }
-
- MMC_DEBUG(("mmc_sendcmd: sending command '%s'", cmd));
-
- command = emalloc(cmdlen + sizeof("\r\n"));
- memcpy(command, cmd, cmdlen);
- memcpy(command + cmdlen, "\r\n", sizeof("\r\n") - 1);
- command_len = cmdlen + sizeof("\r\n") - 1;
- command[command_len] = '\0';
-
- if (php_stream_write(mmc->stream, command, command_len) != command_len) {
- mmc_server_seterror(mmc, "Failed writing command to stream", 0);
- efree(command);
- return -1;
- }
- efree(command);
-
- return 1;
-}
-/* }}}*/
-
-static int mmc_parse_response(mmc_t *mmc, char *response, int response_len, char **key, int *key_len, int *flags, int *value_len) /* {{{ */
-{
- int i=0, n=0;
- int spaces[3];
-
- if (!response || response_len <= 0) {
- mmc_server_seterror(mmc, "Empty response", 0);
- return -1;
- }
-
- MMC_DEBUG(("mmc_parse_response: got response '%s'", response));
-
- for (i=0, n=0; i < response_len && n < 3; i++) {
- if (response[i] == ' ') {
- spaces[n++] = i;
- }
- }
-
- MMC_DEBUG(("mmc_parse_response: found %d spaces", n));
-
- if (n < 3) {
- mmc_server_seterror(mmc, "Malformed VALUE header", 0);
- return -1;
- }
-
- if (key != NULL) {
- int len = spaces[1] - spaces[0] - 1;
-
- *key = emalloc(len + 1);
- *key_len = len;
-
- memcpy(*key, response + spaces[0] + 1, len);
- (*key)[len] = '\0';
- }
-
- *flags = atoi(response + spaces[1]);
- *value_len = atoi(response + spaces[2]);
-
- if (*flags < 0 || *value_len < 0) {
- mmc_server_seterror(mmc, "Malformed VALUE header", 0);
- return -1;
- }
-
- MMC_DEBUG(("mmc_parse_response: 1st space is at %d position", spaces[1]));
- MMC_DEBUG(("mmc_parse_response: 2nd space is at %d position", spaces[2]));
- MMC_DEBUG(("mmc_parse_response: flags = %d", *flags));
- MMC_DEBUG(("mmc_parse_response: value_len = %d ", *value_len));
-
- return 1;
-}
-/* }}} */
-
-static int mmc_postprocess_value(zval **return_value, char *value, int value_len TSRMLS_DC) /*
- post-process a value into a result zval struct, value will be free()'ed during process {{{ */
-{
- const char *value_tmp = value;
- php_unserialize_data_t var_hash;
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
-
- if (!php_var_unserialize(return_value, (const unsigned char **)&value_tmp, (const unsigned char *)(value_tmp + value_len), &var_hash TSRMLS_CC)) {
- ZVAL_FALSE(*return_value);
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- efree(value);
- return -1;
- }
-
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- efree(value);
- return 1;
-}
-/* }}} */
-
-int mmc_exec_retrieval_cmd(mmc_pool_t *pool, const char *key, int key_len, zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */
-{
- mmc_t *mmc;
- char *command, *value;
- int result = -1, command_len, response_len, value_len, flags = 0;
-
- MMC_DEBUG(("mmc_exec_retrieval_cmd: key '%s'", key));
-
- command_len = spprintf(&command, 0, "get %s", key);
-
- while (result < 0 && (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
- MMC_DEBUG(("mmc_exec_retrieval_cmd: found server '%s:%d' for key '%s'", mmc->host, mmc->port, key));
-
- /* send command and read value */
- if ((result = mmc_sendcmd(mmc, command, command_len TSRMLS_CC)) > 0 &&
- (result = mmc_read_value(mmc, NULL, NULL, &value, &value_len, &flags TSRMLS_CC)) >= 0) {
-
- /* not found */
- if (result == 0) {
- ZVAL_FALSE(*return_value);
- }
- /* read "END" */
- else if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0 || !mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END")-1)) {
- mmc_server_seterror(mmc, "Malformed END line", 0);
- result = -1;
- }
- else if (flags & MMC_SERIALIZED ) {
- result = mmc_postprocess_value(return_value, value, value_len TSRMLS_CC);
- }
- else {
- ZVAL_STRINGL(*return_value, value, value_len, 0);
- }
- }
-
- if (result < 0) {
- mmc_server_failure(mmc TSRMLS_CC);
- }
- }
-
- if (return_flags != NULL) {
- zval_dtor(return_flags);
- ZVAL_LONG(return_flags, flags);
- }
-
- efree(command);
- return result;
-}
-/* }}} */
-
-static int mmc_exec_retrieval_cmd_multi(mmc_pool_t *pool, zval *keys, zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */
-{
- mmc_t *mmc;
- HashPosition pos;
- zval **zkey;
- char *result_key, *value;
- char key[MMC_KEY_MAX_SIZE];
- unsigned int key_len;
-
- int i = 0, j, num_requests, result, result_status, result_key_len, value_len, flags;
- mmc_queue_t serialized = {0}; /* mmc_queue_t<zval *>, pointers to zvals which need unserializing */
-
- array_init(*return_value);
-
- if (return_flags != NULL) {
- zval_dtor(return_flags);
- array_init(return_flags);
- }
-
- /* until no retrival errors or all servers have failed */
- do {
- result_status = num_requests = 0;
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
-
- /* first pass to build requests for each server */
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&zkey, &pos) == SUCCESS) {
- if (mmc_prepare_key(*zkey, key, &key_len TSRMLS_CC) == MMC_OK) {
- /* schedule key if first round or if missing from result */
- if ((!i || !zend_hash_exists(Z_ARRVAL_PP(return_value), key, key_len)) &&
- (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
- if (!(mmc->outbuf.len)) {
- smart_str_appendl(&(mmc->outbuf), "get", sizeof("get")-1);
- pool->requests[num_requests++] = mmc;
- }
-
- smart_str_appendl(&(mmc->outbuf), " ", 1);
- smart_str_appendl(&(mmc->outbuf), key, key_len);
- MMC_DEBUG(("mmc_exec_retrieval_cmd_multi: scheduled key '%s' for '%s:%d' request length '%d'", key, mmc->host, mmc->port, mmc->outbuf.len));
- }
- }
-
- zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
- }
-
- /* second pass to send requests in parallel */
- for (j=0; j<num_requests; j++) {
- smart_str_0(&(pool->requests[j]->outbuf));
-
- if ((result = mmc_sendcmd(pool->requests[j], pool->requests[j]->outbuf.c, pool->requests[j]->outbuf.len TSRMLS_CC)) < 0) {
- mmc_server_failure(pool->requests[j] TSRMLS_CC);
- result_status = result;
- }
- }
-
- /* third pass to read responses */
- for (j=0; j<num_requests; j++) {
- if (pool->requests[j]->status != MMC_STATUS_FAILED) {
- for (value = NULL; (result = mmc_read_value(pool->requests[j], &result_key, &result_key_len, &value, &value_len, &flags TSRMLS_CC)) > 0; value = NULL) {
- if (flags & MMC_SERIALIZED) {
- zval *result;
- MAKE_STD_ZVAL(result);
- ZVAL_STRINGL(result, value, value_len, 0);
-
- /* don't store duplicate values */
- if (zend_hash_add(Z_ARRVAL_PP(return_value), result_key, result_key_len + 1, &result, sizeof(result), NULL) == SUCCESS) {
- mmc_queue_push(&serialized, result);
- }
- else {
- zval_ptr_dtor(&result);
- }
- }
- else {
- add_assoc_stringl_ex(*return_value, result_key, result_key_len + 1, value, value_len, 0);
- }
-
- if (return_flags != NULL) {
- add_assoc_long_ex(return_flags, result_key, result_key_len + 1, flags);
- }
-
- efree(result_key);
- }
-
- /* check for server failure */
- if (result < 0) {
- mmc_server_failure(pool->requests[j] TSRMLS_CC);
- result_status = result;
- }
- }
-
- smart_str_free(&(pool->requests[j]->outbuf));
- }
- } while (result_status < 0 && MEMCACHE_G(allow_failover) && i++ < MEMCACHE_G(max_failover_attempts));
-
- /* post-process serialized values */
- if (serialized.len) {
- zval *value;
-
- while ((value = (zval *)mmc_queue_pop(&serialized)) != NULL) {
- mmc_postprocess_value(&value, Z_STRVAL_P(value), Z_STRLEN_P(value) TSRMLS_CC);
- }
-
- mmc_queue_free(&serialized);
- }
-
- return result_status;
-}
-/* }}} */
-
-static int mmc_read_value(mmc_t *mmc, char **key, int *key_len, char **value, int *value_len, int *flags TSRMLS_DC) /* {{{ */
-{
- char *data;
- int response_len, data_len, i, size;
-
- /* read "VALUE <key> <flags> <bytes>\r\n" header line */
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
- MMC_DEBUG(("failed to read the server's response"));
- return -1;
- }
-
- /* reached the end of the data */
- if (mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END") - 1)) {
- return 0;
- }
-
- if (mmc_parse_response(mmc, mmc->inbuf, response_len, key, key_len, flags, &data_len) < 0) {
- return -1;
- }
-
- MMC_DEBUG(("mmc_read_value: data len is %d bytes", data_len));
-
- /* data_len + \r\n + \0 */
- data = emalloc(data_len + 3);
-
- for (i=0; i<data_len+2; i+=size) {
- if ((size = php_stream_read(mmc->stream, data + i, data_len + 2 - i)) == 0) {
- mmc_server_seterror(mmc, "Failed reading value response body", 0);
- if (key) {
- efree(*key);
- }
- efree(data);
- return -1;
- }
- }
-
- data[data_len] = '\0';
-
- if ((*flags & MMC_COMPRESSED) && data_len > 0) {
- char *result_data;
- unsigned long result_len = 0;
-
- if (!mmc_uncompress(&result_data, &result_len, data, data_len)) {
- mmc_server_seterror(mmc, "Failed to uncompress data", 0);
- if (key) {
- efree(*key);
- }
- efree(data);
- return -1;
- }
-
- efree(data);
- data = result_data;
- data_len = result_len;
- }
-
- *value = data;
- *value_len = data_len;
- return 1;
-}
-/* }}} */
-
-int mmc_delete(mmc_t *mmc, const char *key, int key_len, int time TSRMLS_DC) /* {{{ */
-{
- char *command;
- int command_len, response_len;
-
- command_len = spprintf(&command, 0, "delete %s %d", key, time);
-
- MMC_DEBUG(("mmc_delete: trying to delete '%s'", key));
-
- if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
- efree(command);
- return -1;
- }
- efree(command);
-
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0){
- MMC_DEBUG(("failed to read the server's response"));
- return -1;
- }
-
- MMC_DEBUG(("mmc_delete: server's response is '%s'", mmc->inbuf));
-
- if(mmc_str_left(mmc->inbuf,"DELETED", response_len, sizeof("DELETED") - 1)) {
- return 1;
- }
-
- if(mmc_str_left(mmc->inbuf,"NOT_FOUND", response_len, sizeof("NOT_FOUND") - 1)) {
- return 0;
- }
-
- mmc_server_received_error(mmc, response_len);
- return -1;
-}
-/* }}} */
-
-static int mmc_flush(mmc_t *mmc, int timestamp TSRMLS_DC) /* {{{ */
-{
- char *command;
- int command_len, response_len;
-
- MMC_DEBUG(("mmc_flush: flushing the cache"));
-
- if (timestamp) {
- command_len = spprintf(&command, 0, "flush_all %d", timestamp);
- }
- else {
- command_len = spprintf(&command, 0, "flush_all");
- }
-
- if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
- efree(command);
- return -1;
- }
- efree(command);
-
- /* get server's response */
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0){
- return -1;
- }
-
- MMC_DEBUG(("mmc_flush: server's response is '%s'", mmc->inbuf));
-
- if(mmc_str_left(mmc->inbuf, "OK", response_len, sizeof("OK") - 1)) {
- return 1;
- }
-
- mmc_server_received_error(mmc, response_len);
- return -1;
-}
-/* }}} */
-
-/*
- * STAT 6:chunk_size 64
- */
-static int mmc_stats_parse_stat(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
-{
- char *space, *colon, *key;
- long index = 0;
-
- /* find space delimiting key and value */
- if ((space = php_memnstr(start, " ", 1, end)) == NULL) {
- return 0;
- }
-
- /* find colon delimiting subkeys */
- if ((colon = php_memnstr(start, ":", 1, space - 1)) != NULL) {
- zval *element, **elem;
- key = estrndup(start, colon - start);
-
- /* find existing or create subkey array in result */
- if ((is_numeric_string(key, colon - start, &index, NULL, 0) &&
- zend_hash_index_find(Z_ARRVAL_P(result), index, (void **) &elem) != FAILURE) ||
- zend_hash_find(Z_ARRVAL_P(result), key, colon - start + 1, (void **) &elem) != FAILURE) {
- element = *elem;
- }
- else {
- MAKE_STD_ZVAL(element);
- array_init(element);
- add_assoc_zval_ex(result, key, colon - start + 1, element);
- }
-
- efree(key);
- return mmc_stats_parse_stat(colon + 1, end, element TSRMLS_CC);
- }
-
- /* no more subkeys, add value under last subkey */
- key = estrndup(start, space - start);
- add_assoc_stringl_ex(result, key, space - start + 1, space + 1, end - space, 1);
- efree(key);
-
- return 1;
-}
-/* }}} */
-
-/*
- * ITEM test_key [3 b; 1157099416 s]
- */
-static int mmc_stats_parse_item(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
-{
- char *space, *value, *value_end, *key;
- zval *element;
-
- /* find space delimiting key and value */
- if ((space = php_memnstr(start, " ", 1, end)) == NULL) {
- return 0;
- }
-
- MAKE_STD_ZVAL(element);
- array_init(element);
-
- /* parse each contained value */
- for (value = php_memnstr(space, "[", 1, end); value != NULL && value <= end; value = php_memnstr(value + 1, ";", 1, end)) {
- do {
- value++;
- } while (*value == ' ' && value <= end);
-
- if (value <= end && (value_end = php_memnstr(value, " ", 1, end)) != NULL && value_end <= end) {
- add_next_index_stringl(element, value, value_end - value, 1);
- }
- }
-
- /* add parsed values under key */
- key = estrndup(start, space - start);
- add_assoc_zval_ex(result, key, space - start + 1, element);
- efree(key);
-
- return 1;
-}
-/* }}} */
-
-static int mmc_stats_parse_generic(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
-{
- char *space, *key;
-
- /* "stats maps" returns "\n" delimited lines, other commands uses "\r\n" */
- if (*end == '\r') {
- end--;
- }
-
- if (start <= end) {
- if ((space = php_memnstr(start, " ", 1, end)) != NULL) {
- key = estrndup(start, space - start);
- add_assoc_stringl_ex(result, key, space - start + 1, space + 1, end - space, 1);
- efree(key);
- }
- else {
- add_next_index_stringl(result, start, end - start, 1);
- }
- }
-
- return 1;
-}
-/* }}} */
-
-static int mmc_get_stats(mmc_t *mmc, char *type, int slabid, int limit, zval *result TSRMLS_DC) /* {{{ */
-{
- char *command;
- int command_len, response_len;
-
- if (slabid) {
- command_len = spprintf(&command, 0, "stats %s %d %d", type, slabid, limit);
- }
- else if (type) {
- command_len = spprintf(&command, 0, "stats %s", type);
- }
- else {
- command_len = spprintf(&command, 0, "stats");
- }
-
- if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
- efree(command);
- return -1;
- }
-
- efree(command);
- array_init(result);
-
- while ((response_len = mmc_readline(mmc TSRMLS_CC)) >= 0) {
- if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1)) {
-
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
-
- ZVAL_FALSE(result);
- return 0;
- }
- else if (mmc_str_left(mmc->inbuf, "RESET", response_len, sizeof("RESET") - 1)) {
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
-
- ZVAL_TRUE(result);
- return 1;
- }
- else if (mmc_str_left(mmc->inbuf, "ITEM ", response_len, sizeof("ITEM ") - 1)) {
- if (!mmc_stats_parse_item(mmc->inbuf + (sizeof("ITEM ") - 1), mmc->inbuf + response_len - sizeof("\r\n"), result TSRMLS_CC)) {
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
- return -1;
- }
- }
- else if (mmc_str_left(mmc->inbuf, "STAT ", response_len, sizeof("STAT ") - 1)) {
- if (!mmc_stats_parse_stat(mmc->inbuf + (sizeof("STAT ") - 1), mmc->inbuf + response_len - sizeof("\r\n"), result TSRMLS_CC)) {
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
- return -1;
- }
- }
- else if (mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END") - 1)) {
- break;
- }
- else if (!mmc_stats_parse_generic(mmc->inbuf, mmc->inbuf + response_len - sizeof("\n"), result TSRMLS_CC)) {
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
- return -1;
- }
- }
-
- if (response_len < 0) {
- zend_hash_destroy(Z_ARRVAL_P(result));
- FREE_HASHTABLE(Z_ARRVAL_P(result));
- return -1;
- }
-
- return 1;
-}
-/* }}} */
-
-static int mmc_incr_decr(mmc_t *mmc, int cmd, char *key, int key_len, int value, long *number TSRMLS_DC) /* {{{ */
-{
- char *command;
- int command_len, response_len;
-
- if (cmd > 0) {
- command_len = spprintf(&command, 0, "incr %s %d", key, value);
- }
- else {
- command_len = spprintf(&command, 0, "decr %s %d", key, value);
- }
-
- if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
- efree(command);
- return -1;
- }
- efree(command);
-
- if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
- MMC_DEBUG(("failed to read the server's response"));
- return -1;
- }
-
- MMC_DEBUG(("mmc_incr_decr: server's answer is: '%s'", mmc->inbuf));
- if (mmc_str_left(mmc->inbuf, "NOT_FOUND", response_len, sizeof("NOT_FOUND") - 1)) {
- MMC_DEBUG(("failed to %sement variable - item with such key not found", cmd > 0 ? "incr" : "decr"));
- return 0;
- }
- else if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
- mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1)) {
- mmc_server_received_error(mmc, response_len);
- return -1;
- }
-
- *number = (long)atol(mmc->inbuf);
- return 1;
-}
-/* }}} */
-
-static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, char *command, int command_len) /* {{{ */
-{
- mmc_pool_t *pool;
- zval *var, *mmc_object = getThis();
-
- int result, value_len, key_len;
- char *value, *key;
- long flags = 0, expire = 0;
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- php_serialize_data_t var_hash;
- smart_str buf = {0};
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Osz|ll", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &var, &flags, &expire) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, &var, &flags, &expire) == FAILURE) {
- return;
- }
- }
-
- if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- RETURN_FALSE;
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
- RETURN_FALSE;
- }
-
- switch (Z_TYPE_P(var)) {
- case IS_STRING:
- value = Z_STRVAL_P(var);
- value_len = Z_STRLEN_P(var);
- break;
-
- case IS_LONG:
- case IS_DOUBLE:
- case IS_BOOL:
- convert_to_string(var);
- value = Z_STRVAL_P(var);
- value_len = Z_STRLEN_P(var);
- break;
-
- default: {
- zval var_copy, *var_copy_ptr;
-
- /* FIXME: we should be using 'Z' instead of this, but unfortunately it's PHP5-only */
- var_copy = *var;
- zval_copy_ctor(&var_copy);
-
- var_copy_ptr = &var_copy;
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &var_copy_ptr, &var_hash TSRMLS_CC);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- if (!buf.c) {
- /* something went really wrong */
- zval_dtor(&var_copy);
- RETURN_FALSE;
- }
-
- value = buf.c;
- value_len = buf.len;
- flags |= MMC_SERIALIZED;
- zval_dtor(&var_copy);
- }
- break;
- }
-
- result = mmc_pool_store(pool, command, command_len, key_tmp, key_tmp_len, flags, expire, value, value_len TSRMLS_CC);
-
- if (flags & MMC_SERIALIZED) {
- smart_str_free(&buf);
- }
-
- if (result > 0) {
- RETURN_TRUE;
- }
-
- RETURN_FALSE;
-}
-/* }}} */
-
-static void php_mmc_incr_decr(INTERNAL_FUNCTION_PARAMETERS, int cmd) /* {{{ */
-{
- mmc_t *mmc;
- mmc_pool_t *pool;
- int result = -1, key_len;
- long value = 1, number;
- char *key;
- zval *mmc_object = getThis();
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &value) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &value) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
- RETURN_FALSE;
- }
-
- if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- RETURN_FALSE;
- }
-
- while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
- if ((result = mmc_incr_decr(mmc, cmd, key_tmp, key_tmp_len, value, &number TSRMLS_CC)) < 0) {
- mmc_server_failure(mmc TSRMLS_CC);
- }
- }
-
- if (result > 0) {
- RETURN_LONG(number);
- }
- RETURN_FALSE;
-}
-/* }}} */
-
-static void php_mmc_connect (INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
-{
- zval **connection, *mmc_object = getThis();
- mmc_t *mmc = NULL;
- mmc_pool_t *pool;
- int resource_type, host_len, errnum = 0, list_id;
- char *host, *error_string = NULL;
- long port = MEMCACHE_G(default_port), timeout = MMC_DEFAULT_TIMEOUT;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout) == FAILURE) {
- return;
- }
-
- /* initialize and connect server struct */
- if (persistent) {
- mmc = mmc_find_persistent(host, host_len, port, timeout, MMC_DEFAULT_RETRY TSRMLS_CC);
- }
- else {
- MMC_DEBUG(("php_mmc_connect: creating regular connection"));
- mmc = mmc_server_new(host, host_len, port, 0, timeout, MMC_DEFAULT_RETRY TSRMLS_CC);
- }
-
- if (!mmc_open(mmc, 1, &error_string, &errnum TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't connect to %s:%ld, %s (%d)", host, port, error_string ? error_string : "Unknown error", errnum);
- if (!persistent) {
- mmc_server_free(mmc TSRMLS_CC);
- }
- if (error_string) {
- efree(error_string);
- }
- RETURN_FALSE;
- }
-
- /* initialize pool and object if need be */
- if (!mmc_object) {
- pool = mmc_pool_new(TSRMLS_C);
- mmc_pool_add(pool, mmc, 1);
-
- object_init_ex(return_value, memcache_class_entry_ptr);
- list_id = zend_list_insert(pool, le_memcache_pool);
- add_property_resource(return_value, "connection", list_id);
- }
- else if (zend_hash_find(Z_OBJPROP_P(mmc_object), "connection", sizeof("connection"), (void **) &connection) != FAILURE) {
- pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
- if (!pool || resource_type != le_memcache_pool) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown connection identifier");
- RETURN_FALSE;
- }
-
- mmc_pool_add(pool, mmc, 1);
- RETURN_TRUE;
- }
- else {
- pool = mmc_pool_new(TSRMLS_C);
- mmc_pool_add(pool, mmc, 1);
-
- list_id = zend_list_insert(pool, le_memcache_pool);
- add_property_resource(mmc_object, "connection", list_id);
- RETURN_TRUE;
- }
-}
-/* }}} */
-
-/* ----------------
- module functions
- ---------------- */
-
-/* {{{ proto object memcache_connect( string host [, int port [, int timeout ] ])
- Connects to server and returns a Memcache object */
-PHP_FUNCTION(memcache_connect)
-{
- php_mmc_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ proto object memcache_pconnect( string host [, int port [, int timeout ] ])
- Connects to server and returns a Memcache object */
-PHP_FUNCTION(memcache_pconnect)
-{
- php_mmc_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ proto bool memcache_add_server( string host [, int port [, bool persistent [, int weight [, int timeout [, int retry_interval [, bool status [, callback failure_callback ] ] ] ] ] ] ])
- Adds a connection to the pool. The order in which this function is called is significant */
-PHP_FUNCTION(memcache_add_server)
-{
- zval **connection, *mmc_object = getThis(), *failure_callback = NULL;
- mmc_pool_t *pool;
- mmc_t *mmc;
- long port = MEMCACHE_G(default_port), weight = 1, timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY;
- zend_bool persistent = 1, status = 1;
- int resource_type, host_len, list_id;
- char *host;
-
- if (mmc_object) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lblllbz", &host, &host_len, &port, &persistent, &weight, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lblllbz", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port, &persistent, &weight, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
- return;
- }
- }
-
- if (weight < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "weight must be a positive integer");
- RETURN_FALSE;
- }
-
- if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
- if (!zend_is_callable(failure_callback, 0, NULL)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid failure callback");
- RETURN_FALSE;
- }
- }
-
- /* lazy initialization of server struct */
- if (persistent) {
- mmc = mmc_find_persistent(host, host_len, port, timeout, retry_interval TSRMLS_CC);
- }
- else {
- MMC_DEBUG(("memcache_add_server: initializing regular struct"));
- mmc = mmc_server_new(host, host_len, port, 0, timeout, retry_interval TSRMLS_CC);
- }
-
- /* add server in failed mode */
- if (!status) {
- mmc->status = MMC_STATUS_FAILED;
- }
-
- if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
- mmc->failure_callback = failure_callback;
- mmc_server_callback_ctor(&mmc->failure_callback TSRMLS_CC);
- }
-
- /* initialize pool if need be */
- if (zend_hash_find(Z_OBJPROP_P(mmc_object), "connection", sizeof("connection"), (void **) &connection) == FAILURE) {
- pool = mmc_pool_new(TSRMLS_C);
- list_id = zend_list_insert(pool, le_memcache_pool);
- add_property_resource(mmc_object, "connection", list_id);
- }
- else {
- pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
- if (!pool || resource_type != le_memcache_pool) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to extract 'connection' variable from object");
- RETURN_FALSE;
- }
- }
-
- mmc_pool_add(pool, mmc, weight);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool memcache_set_server_params( string host [, int port [, int timeout [, int retry_interval [, bool status [, callback failure_callback ] ] ] ] ])
- Changes server parameters at runtime */
-PHP_FUNCTION(memcache_set_server_params)
-{
- zval *mmc_object = getThis(), *failure_callback = NULL;
- mmc_pool_t *pool;
- mmc_t *mmc = NULL;
- long port = MEMCACHE_G(default_port), timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY;
- zend_bool status = 1;
- int host_len, i;
- char *host;
-
- if (mmc_object) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lllbz", &host, &host_len, &port, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lllbz", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- for (i=0; i<pool->num_servers; i++) {
- if (!strcmp(pool->servers[i]->host, host) && pool->servers[i]->port == port) {
- mmc = pool->servers[i];
- break;
- }
- }
-
- if (!mmc) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server not found in pool");
- RETURN_FALSE;
- }
-
- if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
- if (!zend_is_callable(failure_callback, 0, NULL)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid failure callback");
- RETURN_FALSE;
- }
- }
-
- mmc->timeout = timeout;
- mmc->retry_interval = retry_interval;
-
- if (!status) {
- mmc->status = MMC_STATUS_FAILED;
- }
- else if (mmc->status == MMC_STATUS_FAILED) {
- mmc->status = MMC_STATUS_DISCONNECTED;
- }
-
- if (failure_callback != NULL) {
- if (mmc->failure_callback != NULL) {
- mmc_server_callback_dtor(&mmc->failure_callback TSRMLS_CC);
- }
-
- if (Z_TYPE_P(failure_callback) != IS_NULL) {
- mmc->failure_callback = failure_callback;
- mmc_server_callback_ctor(&mmc->failure_callback TSRMLS_CC);
- }
- else {
- mmc->failure_callback = NULL;
- }
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto int memcache_get_server_status( string host [, int port ])
- Returns server status (0 if server is failed, otherwise non-zero) */
-PHP_FUNCTION(memcache_get_server_status)
-{
- zval *mmc_object = getThis();
- mmc_pool_t *pool;
- mmc_t *mmc = NULL;
- long port = MEMCACHE_G(default_port);
- int host_len, i;
- char *host;
-
- if (mmc_object) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &host, &host_len, &port) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- for (i=0; i<pool->num_servers; i++) {
- if (!strcmp(pool->servers[i]->host, host) && pool->servers[i]->port == port) {
- mmc = pool->servers[i];
- break;
- }
- }
-
- if (!mmc) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server not found in pool");
- RETURN_FALSE;
- }
-
- RETURN_LONG(mmc->status);
-}
-/* }}} */
-
-mmc_t *mmc_find_persistent(char *host, int host_len, int port, int timeout, int retry_interval TSRMLS_DC) /* {{{ */
-{
- mmc_t *mmc;
- zend_rsrc_list_entry *le;
- char *hash_key;
- int hash_key_len;
-
- MMC_DEBUG(("mmc_find_persistent: seeking for persistent connection"));
- hash_key = emalloc(sizeof("mmc_connect___") - 1 + host_len + MAX_LENGTH_OF_LONG + 1);
- hash_key_len = sprintf(hash_key, "mmc_connect___%s:%d", host, port);
-
- if (zend_hash_find(&EG(persistent_list), hash_key, hash_key_len+1, (void **) &le) == FAILURE) {
- zend_rsrc_list_entry new_le;
- MMC_DEBUG(("mmc_find_persistent: connection wasn't found in the hash"));
-
- mmc = mmc_server_new(host, host_len, port, 1, timeout, retry_interval TSRMLS_CC);
- new_le.type = le_pmemcache;
- new_le.ptr = mmc;
-
- /* register new persistent connection */
- if (zend_hash_update(&EG(persistent_list), hash_key, hash_key_len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
- mmc_server_free(mmc TSRMLS_CC);
- mmc = NULL;
- } else {
- zend_list_insert(mmc, le_pmemcache);
- }
- }
- else if (le->type != le_pmemcache || le->ptr == NULL) {
- zend_rsrc_list_entry new_le;
- MMC_DEBUG(("mmc_find_persistent: something was wrong, reconnecting.."));
- zend_hash_del(&EG(persistent_list), hash_key, hash_key_len+1);
-
- mmc = mmc_server_new(host, host_len, port, 1, timeout, retry_interval TSRMLS_CC);
- new_le.type = le_pmemcache;
- new_le.ptr = mmc;
-
- /* register new persistent connection */
- if (zend_hash_update(&EG(persistent_list), hash_key, hash_key_len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
- mmc_server_free(mmc TSRMLS_CC);
- mmc = NULL;
- }
- else {
- zend_list_insert(mmc, le_pmemcache);
- }
- }
- else {
- MMC_DEBUG(("mmc_find_persistent: connection found in the hash"));
- mmc = (mmc_t *)le->ptr;
- mmc->timeout = timeout;
- mmc->retry_interval = retry_interval;
-
- /* attempt to reconnect this node before failover in case connection has gone away */
- if (mmc->status == MMC_STATUS_CONNECTED) {
- mmc->status = MMC_STATUS_UNKNOWN;
- }
- }
-
- efree(hash_key);
- return mmc;
-}
-/* }}} */
-
-/* {{{ proto string memcache_get_version( object memcache )
- Returns server's version */
-PHP_FUNCTION(memcache_get_version)
-{
- mmc_pool_t *pool;
- char *version;
- int i;
- zval *mmc_object = getThis();
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &mmc_object, memcache_class_entry_ptr) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- for (i=0; i<pool->num_servers; i++) {
- if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
- if ((version = mmc_get_version(pool->servers[i] TSRMLS_CC)) != NULL) {
- RETURN_STRING(version, 0);
- }
- else {
- mmc_server_failure(pool->servers[i] TSRMLS_CC);
- }
- }
- }
-
- RETURN_FALSE;
-}
-/* }}} */
-
-/* {{{ proto bool memcache_add( object memcache, string key, mixed var [, int flag [, int expire ] ] )
- Adds new item. Item with such key should not exist. */
-PHP_FUNCTION(memcache_add)
-{
- php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "add", sizeof("add") - 1);
-}
-/* }}} */
-
-/* {{{ proto bool memcache_set( object memcache, string key, mixed var [, int flag [, int expire ] ] )
- Sets the value of an item. Item may exist or not */
-PHP_FUNCTION(memcache_set)
-{
- php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "set", sizeof("set") - 1);
-}
-/* }}} */
-
-/* {{{ proto bool memcache_replace( object memcache, string key, mixed var [, int flag [, int expire ] ] )
- Replaces existing item. Returns false if item doesn't exist */
-PHP_FUNCTION(memcache_replace)
-{
- php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "replace", sizeof("replace") - 1);
-}
-/* }}} */
-
-/* {{{ proto mixed memcache_get( object memcache, mixed key [, mixed &flags ] )
- Returns value of existing item or false */
-PHP_FUNCTION(memcache_get)
-{
- mmc_pool_t *pool;
- zval *zkey, *mmc_object = getThis(), *flags = NULL;
- char key[MMC_KEY_MAX_SIZE];
- unsigned int key_len;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|z", &mmc_object, memcache_class_entry_ptr, &zkey, &flags) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &zkey, &flags) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
- RETURN_FALSE;
- }
-
- if (Z_TYPE_P(zkey) != IS_ARRAY) {
- if (mmc_prepare_key(zkey, key, &key_len TSRMLS_CC) == MMC_OK) {
- if (mmc_exec_retrieval_cmd(pool, key, key_len, &return_value, flags TSRMLS_CC) < 0) {
- zval_dtor(return_value);
- RETVAL_FALSE;
- }
- }
- else {
- RETVAL_FALSE;
- }
- } else if (zend_hash_num_elements(Z_ARRVAL_P(zkey))){
- if (mmc_exec_retrieval_cmd_multi(pool, zkey, &return_value, flags TSRMLS_CC) < 0) {
- zval_dtor(return_value);
- RETVAL_FALSE;
- }
- } else {
- RETVAL_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto bool memcache_delete( object memcache, string key [, int expire ])
- Deletes existing item */
-PHP_FUNCTION(memcache_delete)
-{
- mmc_t *mmc;
- mmc_pool_t *pool;
- int result = -1, key_len;
- zval *mmc_object = getThis();
- char *key;
- long time = 0;
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &time) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &time) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
- RETURN_FALSE;
- }
-
- if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- RETURN_FALSE;
- }
-
- while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
- if ((result = mmc_delete(mmc, key_tmp, key_tmp_len, time TSRMLS_CC)) < 0) {
- mmc_server_failure(mmc TSRMLS_CC);
- }
- }
-
- if (result > 0) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
-}
-/* }}} */
-
-/* {{{ proto bool memcache_debug( bool onoff )
- Turns on/off internal debugging */
-PHP_FUNCTION(memcache_debug)
-{
-#if ZEND_DEBUG
- zend_bool onoff;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &onoff) == FAILURE) {
- return;
- }
-
- MEMCACHE_G(debug_mode) = onoff ? 1 : 0;
-
- RETURN_TRUE;
-#else
- RETURN_FALSE;
-#endif
-
-}
-/* }}} */
-
-/* {{{ proto array memcache_get_stats( object memcache [, string type [, int slabid [, int limit ] ] ])
- Returns server's statistics */
-PHP_FUNCTION(memcache_get_stats)
-{
- mmc_pool_t *pool;
- int i, failures = 0;
- zval *mmc_object = getThis();
-
- char *type = NULL;
- int type_len = 0;
- long slabid = 0, limit = MMC_DEFAULT_CACHEDUMP_LIMIT;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|sll", &mmc_object, memcache_class_entry_ptr, &type, &type_len, &slabid, &limit) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sll", &type, &type_len, &slabid, &limit) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- for (i=0; i<pool->num_servers; i++) {
- if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
- if (mmc_get_stats(pool->servers[i], type, slabid, limit, return_value TSRMLS_CC) < 0) {
- mmc_server_failure(pool->servers[i] TSRMLS_CC);
- failures++;
- }
- else {
- break;
- }
- }
- else {
- failures++;
- }
- }
-
- if (failures >= pool->num_servers) {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto array memcache_get_extended_stats( object memcache [, string type [, int slabid [, int limit ] ] ])
- Returns statistics for each server in the pool */
-PHP_FUNCTION(memcache_get_extended_stats)
-{
- mmc_pool_t *pool;
- char *hostname;
- int i, hostname_len;
- zval *mmc_object = getThis(), *stats;
-
- char *type = NULL;
- int type_len = 0;
- long slabid = 0, limit = MMC_DEFAULT_CACHEDUMP_LIMIT;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|sll", &mmc_object, memcache_class_entry_ptr, &type, &type_len, &slabid, &limit) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sll", &type, &type_len, &slabid, &limit) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- array_init(return_value);
- for (i=0; i<pool->num_servers; i++) {
- MAKE_STD_ZVAL(stats);
-
- hostname = emalloc(strlen(pool->servers[i]->host) + MAX_LENGTH_OF_LONG + 1 + 1);
- hostname_len = sprintf(hostname, "%s:%d", pool->servers[i]->host, pool->servers[i]->port);
-
- if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
- if (mmc_get_stats(pool->servers[i], type, slabid, limit, stats TSRMLS_CC) < 0) {
- mmc_server_failure(pool->servers[i] TSRMLS_CC);
- ZVAL_FALSE(stats);
- }
- }
- else {
- ZVAL_FALSE(stats);
- }
-
- add_assoc_zval_ex(return_value, hostname, hostname_len + 1, stats);
- efree(hostname);
- }
-}
-/* }}} */
-
-/* {{{ proto array memcache_set_compress_threshold( object memcache, int threshold [, float min_savings ] )
- Set automatic compress threshold */
-PHP_FUNCTION(memcache_set_compress_threshold)
-{
- mmc_pool_t *pool;
- zval *mmc_object = getThis();
- long threshold;
- double min_savings = MMC_DEFAULT_SAVINGS;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|d", &mmc_object, memcache_class_entry_ptr, &threshold, &min_savings) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|d", &threshold, &min_savings) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- if (threshold < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "threshold must be a positive integer");
- RETURN_FALSE;
- }
- pool->compress_threshold = threshold;
-
- if (min_savings != MMC_DEFAULT_SAVINGS) {
- if (min_savings < 0 || min_savings > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "min_savings must be a float in the 0..1 range");
- RETURN_FALSE;
- }
- pool->min_compress_savings = min_savings;
- }
- else {
- pool->min_compress_savings = MMC_DEFAULT_SAVINGS;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto int memcache_increment( object memcache, string key [, int value ] )
- Increments existing variable */
-PHP_FUNCTION(memcache_increment)
-{
- php_mmc_incr_decr(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ proto int memcache_decrement( object memcache, string key [, int value ] )
- Decrements existing variable */
-PHP_FUNCTION(memcache_decrement)
-{
- php_mmc_incr_decr(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ proto bool memcache_close( object memcache )
- Closes connection to memcached */
-PHP_FUNCTION(memcache_close)
-{
- mmc_pool_t *pool;
- zval *mmc_object = getThis();
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &mmc_object, memcache_class_entry_ptr) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- if (!mmc_pool_close(pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool memcache_flush( object memcache [, int timestamp ] )
- Flushes cache, optionally at the specified time */
-PHP_FUNCTION(memcache_flush)
-{
- mmc_pool_t *pool;
- int i, failures = 0;
- zval *mmc_object = getThis();
- long timestamp = 0;
-
- if (mmc_object == NULL) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &mmc_object, memcache_class_entry_ptr, ×tamp) == FAILURE) {
- return;
- }
- }
- else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", ×tamp) == FAILURE) {
- return;
- }
- }
-
- if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- for (i=0; i<pool->num_servers; i++) {
- if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
- if (mmc_flush(pool->servers[i], timestamp TSRMLS_CC) < 0) {
- mmc_server_failure(pool->servers[i] TSRMLS_CC);
- failures++;
- }
- }
- else {
- failures++;
- }
- }
-
- if (failures && failures >= pool->num_servers) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache_consistent_hash.c
^
|
@@ -1,196 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache_consistent_hash.c,v 1.3 2007/09/02 10:48:13 mikl Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-
-#include "php.h"
-#include "php_memcache.h"
-
-ZEND_EXTERN_MODULE_GLOBALS(memcache)
-
-typedef struct mmc_consistent_point {
- mmc_t *server;
- unsigned int point;
-} mmc_consistent_point_t;
-
-typedef struct mmc_consistent_state {
- int num_servers;
- mmc_consistent_point_t *points;
- int num_points;
- mmc_t *buckets[MMC_CONSISTENT_BUCKETS];
- int buckets_populated;
- mmc_hash_function hash;
-} mmc_consistent_state_t;
-
-void *mmc_consistent_create_state(mmc_hash_function hash) /* {{{ */
-{
- mmc_consistent_state_t *state = emalloc(sizeof(mmc_consistent_state_t));
- memset(state, 0, sizeof(mmc_consistent_state_t));
- state->hash = hash;
- return state;
-}
-/* }}} */
-
-void mmc_consistent_free_state(void *s) /* {{{ */
-{
- mmc_consistent_state_t *state = s;
- if (state != NULL) {
- if (state->points != NULL) {
- efree(state->points);
- }
- efree(state);
- }
-}
-/* }}} */
-
-static int mmc_consistent_compare(const void *a, const void *b) /* {{{ */
-{
- if (((mmc_consistent_point_t *)a)->point < ((mmc_consistent_point_t *)b)->point) {
- return -1;
- }
- if (((mmc_consistent_point_t *)a)->point > ((mmc_consistent_point_t *)b)->point) {
- return 1;
- }
- return 0;
-}
-/* }}} */
-
-static mmc_t *mmc_consistent_find(mmc_consistent_state_t *state, unsigned int point) /* {{{ */
-{
- int lo = 0, hi = state->num_points - 1, mid;
-
- while (1) {
- /* point is outside interval or lo >= hi, wrap-around */
- if (point <= state->points[lo].point || point > state->points[hi].point) {
- return state->points[lo].server;
- }
-
- /* best guess with random distribution, distance between lowpoint and point scaled down to lo-hi interval */
- mid = lo + (hi - lo) * (point - state->points[lo].point) / (state->points[hi].point - state->points[lo].point);
- MMC_DEBUG(("mmc_consistent_find: lo %d, hi %d, mid %d, point %u, midpoint %u", lo, hi, mid, point, state->points[mid].point));
-
- /* perfect match */
- if (point <= state->points[mid].point && point > (mid ? state->points[mid-1].point : 0)) {
- return state->points[mid].server;
- }
-
- /* too low, go up */
- if (state->points[mid].point < point) {
- lo = mid + 1;
- }
- else {
- hi = mid - 1;
- }
- }
-}
-/* }}} */
-
-static void mmc_consistent_pupulate_buckets(mmc_consistent_state_t *state) /* {{{ */
-{
- unsigned int i, step = 0xffffffff / MMC_CONSISTENT_BUCKETS;
-
- qsort((void *)state->points, state->num_points, sizeof(mmc_consistent_point_t), mmc_consistent_compare);
- for (i=0; i<MMC_CONSISTENT_BUCKETS; i++) {
- state->buckets[i] = mmc_consistent_find(state, step * i);
- }
-
- state->buckets_populated = 1;
-}
-/* }}} */
-
-mmc_t *mmc_consistent_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */
-{
- mmc_consistent_state_t *state = s;
- mmc_t *mmc;
-
- if (state->num_servers > 1) {
- unsigned int i, hash = state->hash(key, key_len);
-
- if (!state->buckets_populated) {
- mmc_consistent_pupulate_buckets(state);
- }
-
- mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS];
-
- /* perform failover if needed */
- for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) {
- char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1);
- int next_len = sprintf(next_key, "%s-%d", key, i);
- MMC_DEBUG(("mmc_consistent_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status));
-
- hash = state->hash(next_key, next_len);
- mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS];
-
- efree(next_key);
- }
- }
- else {
- mmc = state->points[0].server;
- mmc_open(mmc, 0, NULL, NULL TSRMLS_CC);
- }
-
- return mmc->status != MMC_STATUS_FAILED ? mmc : NULL;
-}
-/* }}} */
-
-void mmc_consistent_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */
-{
- mmc_consistent_state_t *state = s;
- int i, key_len, points = weight * MMC_CONSISTENT_POINTS;
- char *key;
-
- /* add weight * MMC_CONSISTENT_POINTS number of points for this server */
- state->points = erealloc(state->points, sizeof(mmc_consistent_point_t) * (state->num_points + points));
-
- for (i=0; i<points; i++) {
- key_len = spprintf(&key, 0, "%s:%d-%d", mmc->host, mmc->port, i);
- state->points[state->num_points + i].server = mmc;
- state->points[state->num_points + i].point = state->hash(key, key_len);
- MMC_DEBUG(("mmc_consistent_add_server: key %s, point %lu", key, state->points[state->num_points + i].point));
- efree(key);
- }
-
- state->num_points += points;
- state->num_servers++;
-
- state->buckets_populated = 0;
-}
-/* }}} */
-
-mmc_hash_t mmc_consistent_hash = {
- mmc_consistent_create_state,
- mmc_consistent_free_state,
- mmc_consistent_find_server,
- mmc_consistent_add_server
-};
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache_queue.c
^
|
@@ -1,128 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache_queue.c,v 1.3 2008/01/11 10:10:56 tony2001 Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "memcache_queue.h"
-
-void mmc_queue_push(mmc_queue_t *queue, void *ptr) {
- if (queue->len >= queue->alloc) {
- int increase = 1 + MMC_QUEUE_PREALLOC;
- queue->alloc += increase;
- queue->items = erealloc(queue->items, sizeof(*queue->items) * queue->alloc);
-
- /* move tail segment downwards */
- if (queue->head < queue->tail) {
- memmove(queue->items + queue->tail + increase, queue->items + queue->tail, (queue->alloc - queue->tail - increase) * sizeof(*queue->items));
- queue->tail += increase;
- }
- }
-
- if (queue->len) {
- queue->head++;
-
- if (queue->head >= queue->alloc) {
- queue->head = 0;
- }
- }
-
- queue->items[queue->head] = ptr;
- queue->len++;
-}
-
-void *mmc_queue_pop(mmc_queue_t *queue) {
- if (queue->len) {
- void *ptr;
-
- ptr = queue->items[queue->tail];
- queue->len--;
-
- if (queue->len) {
- queue->tail++;
-
- if (queue->tail >= queue->alloc) {
- queue->tail = 0;
- }
- }
-
- return ptr;
- }
- return NULL;
-}
-
-int mmc_queue_contains(mmc_queue_t *queue, void *ptr) {
- if (queue != NULL) {
- int i;
-
- for (i=0; i < queue->len; i++) {
- if (mmc_queue_item(queue, i) == ptr) {
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-void mmc_queue_free(mmc_queue_t *queue) {
- if (queue->items != NULL) {
- efree(queue->items);
- }
- memset(queue, 0, sizeof(*queue));
-}
-
-void mmc_queue_copy(mmc_queue_t *source, mmc_queue_t *target) {
- if (target->alloc != source->alloc) {
- target->alloc = source->alloc;
- erealloc(target->items, sizeof(*target->items) * target->alloc);
- }
-
- memcpy(target->items, source->items, sizeof(*source->items) * source->alloc);
- target->head = source->head;
- target->tail = source->tail;
- target->len = source->len;
-}
-
-void mmc_queue_remove(mmc_queue_t *queue, void *ptr) {
- void *item;
- mmc_queue_t original = *queue;
- mmc_queue_release(queue);
-
- while ((item = mmc_queue_pop(&original)) != NULL) {
- if (item != ptr) {
- mmc_queue_push(queue, item);
- }
- }
-
- mmc_queue_free(&original);
-}
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache_queue.h
^
|
@@ -1,56 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache_queue.h,v 1.3 2008/01/11 10:10:56 tony2001 Exp $ */
-
-#ifndef MEMCACHE_QUEUE_H_
-#define MEMCACHE_QUEUE_H_
-
-/* request / server stack */
-#define MMC_QUEUE_PREALLOC 25
-
-typedef struct mmc_queue {
- void **items; /* items on queue */
- int alloc; /* allocated size */
- int head; /* head index in ring buffer */
- int tail; /* tail index in ring buffer */
- int len;
-} mmc_queue_t;
-
-#define mmc_queue_release(q) memset((q), 0, sizeof(*(q)))
-#define mmc_queue_reset(q) (q)->len = (q)->head = (q)->tail = 0
-#define mmc_queue_item(q, i) ((q)->tail + (i) < (q)->alloc ? (q)->items[(q)->tail + (i)] : (q)->items[(i) - ((q)->alloc - (q)->tail)])
-
-void mmc_queue_push(mmc_queue_t *, void *);
-void *mmc_queue_pop(mmc_queue_t *);
-int mmc_queue_contains(mmc_queue_t *, void *);
-void mmc_queue_free(mmc_queue_t *);
-void mmc_queue_copy(mmc_queue_t *, mmc_queue_t *);
-void mmc_queue_remove(mmc_queue_t *, void *);
-
-#endif /*MEMCACHE_QUEUE_H_*/
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache_session.c
^
|
@@ -1,244 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache_session.c,v 1.6 2007/11/01 14:01:38 mikl Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <ctype.h>
-#include "php.h"
-#include "php_ini.h"
-#include "php_variables.h"
-
-#include "SAPI.h"
-#include "ext/standard/url.h"
-#include "php_memcache.h"
-
-ps_module ps_mod_memcache = {
- PS_MOD(memcache)
-};
-
-/* {{{ PS_OPEN_FUNC
- */
-PS_OPEN_FUNC(memcache)
-{
- mmc_pool_t *pool;
- mmc_t *mmc;
-
- php_url *url;
- zval *params, **param;
- int i, j, path_len;
-
- pool = mmc_pool_new(TSRMLS_C);
-
- for (i=0,j=0,path_len=strlen(save_path); i<path_len; i=j+1) {
- /* find beginning of url */
- while (i<path_len && (isspace(save_path[i]) || save_path[i] == ','))
- i++;
-
- /* find end of url */
- j = i;
- while (j<path_len && !isspace(save_path[j]) && save_path[j] != ',')
- j++;
-
- if (i < j) {
- int persistent = 0, weight = 1, timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY;
- url = php_url_parse_ex(save_path+i, j-i);
-
- /* parse parameters */
- if (url->query != NULL) {
- MAKE_STD_ZVAL(params);
- array_init(params);
-
- sapi_module.treat_data(PARSE_STRING, estrdup(url->query), params TSRMLS_CC);
-
- if (zend_hash_find(Z_ARRVAL_P(params), "persistent", sizeof("persistent"), (void **) ¶m) != FAILURE) {
- convert_to_boolean_ex(param);
- persistent = Z_BVAL_PP(param);
- }
-
- if (zend_hash_find(Z_ARRVAL_P(params), "weight", sizeof("weight"), (void **) ¶m) != FAILURE) {
- convert_to_long_ex(param);
- weight = Z_LVAL_PP(param);
- }
-
- if (zend_hash_find(Z_ARRVAL_P(params), "timeout", sizeof("timeout"), (void **) ¶m) != FAILURE) {
- convert_to_long_ex(param);
- timeout = Z_LVAL_PP(param);
- }
-
- if (zend_hash_find(Z_ARRVAL_P(params), "retry_interval", sizeof("retry_interval"), (void **) ¶m) != FAILURE) {
- convert_to_long_ex(param);
- retry_interval = Z_LVAL_PP(param);
- }
-
- zval_ptr_dtor(¶ms);
- }
-
- if (url->host == NULL || weight <= 0 || timeout <= 0) {
- php_url_free(url);
- mmc_pool_free(pool TSRMLS_CC);
- PS_SET_MOD_DATA(NULL);
- return FAILURE;
- }
-
- if (persistent) {
- mmc = mmc_find_persistent(url->host, strlen(url->host), url->port, timeout, retry_interval TSRMLS_CC);
- }
- else {
- mmc = mmc_server_new(url->host, strlen(url->host), url->port, 0, timeout, retry_interval TSRMLS_CC);
- }
-
- mmc_pool_add(pool, mmc, 1);
- php_url_free(url);
- }
- }
-
- if (pool->num_servers) {
- PS_SET_MOD_DATA(pool);
- return SUCCESS;
- }
-
- mmc_pool_free(pool TSRMLS_CC);
- PS_SET_MOD_DATA(NULL);
- return FAILURE;
-}
-/* }}} */
-
-/* {{{ PS_CLOSE_FUNC
- */
-PS_CLOSE_FUNC(memcache)
-{
- mmc_pool_t *pool = PS_GET_MOD_DATA();
-
- if (pool) {
- mmc_pool_free(pool TSRMLS_CC);
- PS_SET_MOD_DATA(NULL);
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PS_READ_FUNC
- */
-PS_READ_FUNC(memcache)
-{
- mmc_pool_t *pool = PS_GET_MOD_DATA();
- zval *result;
-
- if (pool) {
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- return FAILURE;
- }
-
- MAKE_STD_ZVAL(result);
- ZVAL_NULL(result);
-
- if (mmc_exec_retrieval_cmd(pool, key_tmp, key_tmp_len, &result, NULL TSRMLS_CC) <= 0 || Z_TYPE_P(result) != IS_STRING) {
- zval_ptr_dtor(&result);
- return FAILURE;
- }
-
- *val = Z_STRVAL_P(result);
- *vallen = Z_STRLEN_P(result);
- FREE_ZVAL(result);
- return SUCCESS;
- }
-
- return FAILURE;
-}
-/* }}} */
-
-/* {{{ PS_WRITE_FUNC
- */
-PS_WRITE_FUNC(memcache)
-{
- mmc_pool_t *pool = PS_GET_MOD_DATA();
-
- if (pool) {
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- return FAILURE;
- }
-
- if (mmc_pool_store(pool, "set", sizeof("set")-1, key_tmp, key_tmp_len, 0, INI_INT("session.gc_maxlifetime"), val, vallen TSRMLS_CC)) {
- return SUCCESS;
- }
- }
-
- return FAILURE;
-}
-/* }}} */
-
-/* {{{ PS_DESTROY_FUNC
- */
-PS_DESTROY_FUNC(memcache)
-{
- mmc_pool_t *pool = PS_GET_MOD_DATA();
- mmc_t *mmc;
-
- int result = -1;
-
- if (pool) {
- char key_tmp[MMC_KEY_MAX_SIZE];
- unsigned int key_tmp_len;
-
- if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
- return FAILURE;
- }
-
- while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
- if ((result = mmc_delete(mmc, key_tmp, key_tmp_len, 0 TSRMLS_CC)) < 0) {
- mmc_server_failure(mmc TSRMLS_CC);
- }
- }
-
- if (result >= 0) {
- return SUCCESS;
- }
- }
-
- return FAILURE;
-}
-/* }}} */
-
-/* {{{ PS_GC_FUNC
- */
-PS_GC_FUNC(memcache)
-{
- return SUCCESS;
-}
-/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/memcache_standard_hash.c
^
|
@@ -1,132 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: memcache_standard_hash.c,v 1.4 2007/10/17 18:52:01 mikl Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_memcache.h"
-
-ZEND_EXTERN_MODULE_GLOBALS(memcache)
-
-typedef struct mmc_standard_state {
- int num_servers;
- mmc_t **buckets;
- int num_buckets;
- mmc_hash_function hash;
-} mmc_standard_state_t;
-
-void *mmc_standard_create_state(mmc_hash_function hash) /* {{{ */
-{
- mmc_standard_state_t *state = emalloc(sizeof(mmc_standard_state_t));
- memset(state, 0, sizeof(mmc_standard_state_t));
- state->hash = hash;
- return state;
-}
-/* }}} */
-
-void mmc_standard_free_state(void *s) /* {{{ */
-{
- mmc_standard_state_t *state = s;
- if (state != NULL) {
- if (state->buckets != NULL) {
- efree(state->buckets);
- }
- efree(state);
- }
-}
-/* }}} */
-
-static unsigned int mmc_hash(mmc_standard_state_t *state, const char *key, int key_len) /* {{{ */
-{
- unsigned int hash = (state->hash(key, key_len) >> 16) & 0x7fff;
- return hash ? hash : 1;
-}
-/* }}} */
-
-mmc_t *mmc_standard_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */
-{
- mmc_standard_state_t *state = s;
- mmc_t *mmc;
-
- if (state->num_servers > 1) {
- unsigned int hash = mmc_hash(state, key, key_len), i;
- mmc = state->buckets[hash % state->num_buckets];
-
- /* perform failover if needed */
- for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) {
- char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1);
- int next_len = sprintf(next_key, "%d%s", i+1, key);
- MMC_DEBUG(("mmc_standard_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status));
-
- hash += mmc_hash(state, next_key, next_len);
- mmc = state->buckets[hash % state->num_buckets];
-
- efree(next_key);
- }
- }
- else {
- mmc = state->buckets[0];
- mmc_open(mmc, 0, NULL, NULL TSRMLS_CC);
- }
-
- return mmc->status != MMC_STATUS_FAILED ? mmc : NULL;
-}
-/* }}} */
-
-void mmc_standard_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */
-{
- mmc_standard_state_t *state = s;
- int i;
-
- /* add weight number of buckets for this server */
- if (state->num_buckets) {
- state->buckets = erealloc(state->buckets, sizeof(mmc_t *) * (state->num_buckets + weight));
- }
- else {
- state->buckets = emalloc(sizeof(mmc_t *) * (weight));
- }
-
- for (i=0; i<weight; i++) {
- state->buckets[state->num_buckets + i] = mmc;
- }
-
- state->num_buckets += weight;
- state->num_servers++;
-}
-/* }}} */
-
-mmc_hash_t mmc_standard_hash = {
- mmc_standard_create_state,
- mmc_standard_free_state,
- mmc_standard_find_server,
- mmc_standard_add_server
-};
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
memcache-2.2.3.tgz/memcache-2.2.3/php_memcache.h
^
|
@@ -1,219 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony2001@phpclub.net> |
- | Mikael Johansson <mikael AT synd DOT info> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: php_memcache.h,v 1.32 2008/02/05 19:46:16 mikl Exp $ */
-
-#ifndef PHP_MEMCACHE_H
-#define PHP_MEMCACHE_H
-
-extern zend_module_entry memcache_module_entry;
-#define phpext_memcache_ptr &memcache_module_entry
-
-#ifdef PHP_WIN32
-#define PHP_MEMCACHE_API __declspec(dllexport)
-#else
-#define PHP_MEMCACHE_API
-#endif
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-#include "ext/standard/php_smart_str_public.h"
-
-PHP_MINIT_FUNCTION(memcache);
-PHP_MSHUTDOWN_FUNCTION(memcache);
-PHP_RINIT_FUNCTION(memcache);
-PHP_MINFO_FUNCTION(memcache);
-
-PHP_FUNCTION(memcache_connect);
-PHP_FUNCTION(memcache_pconnect);
-PHP_FUNCTION(memcache_add_server);
-PHP_FUNCTION(memcache_set_server_params);
-PHP_FUNCTION(memcache_get_server_status);
-PHP_FUNCTION(memcache_get_version);
-PHP_FUNCTION(memcache_add);
-PHP_FUNCTION(memcache_set);
-PHP_FUNCTION(memcache_replace);
-PHP_FUNCTION(memcache_get);
-PHP_FUNCTION(memcache_delete);
-PHP_FUNCTION(memcache_debug);
-PHP_FUNCTION(memcache_get_stats);
-PHP_FUNCTION(memcache_get_extended_stats);
-PHP_FUNCTION(memcache_set_compress_threshold);
-PHP_FUNCTION(memcache_increment);
-PHP_FUNCTION(memcache_decrement);
-PHP_FUNCTION(memcache_close);
-PHP_FUNCTION(memcache_flush);
-
-#define PHP_MEMCACHE_VERSION "2.2.3"
-
-#define MMC_BUF_SIZE 4096
-#define MMC_SERIALIZED 1
-#define MMC_COMPRESSED 2
-#define MMC_DEFAULT_TIMEOUT 1 /* seconds */
-#define MMC_KEY_MAX_SIZE 250 /* stoled from memcached sources =) */
-#define MMC_DEFAULT_RETRY 15 /* retry failed server after x seconds */
-#define MMC_DEFAULT_SAVINGS 0.2 /* minimum 20% savings for compression to be used */
-#define MMC_DEFAULT_CACHEDUMP_LIMIT 100 /* number of entries */
-
-#define MMC_STATUS_FAILED 0
-#define MMC_STATUS_DISCONNECTED 1
-#define MMC_STATUS_UNKNOWN 2
-#define MMC_STATUS_CONNECTED 3
-
-#define MMC_OK 0
-#define MMC_REQUEST_FAILURE -1
-
-#define MMC_STANDARD_HASH 1
-#define MMC_CONSISTENT_HASH 2
-#define MMC_HASH_CRC32 1 /* CRC32 hash function */
-#define MMC_HASH_FNV1A 2 /* FNV-1a hash function */
-
-#define MMC_CONSISTENT_POINTS 160 /* points per server */
-#define MMC_CONSISTENT_BUCKETS 1024 /* number of precomputed buckets, should be power of 2 */
-
-typedef struct mmc {
- php_stream *stream;
- char inbuf[MMC_BUF_SIZE];
- smart_str outbuf;
- char *host;
- unsigned short port;
- long timeout;
- long failed;
- long retry_interval;
- int persistent;
- int status;
- char *error; /* last error message */
- int errnum; /* last error code */
- zval *failure_callback;
- zend_bool in_free;
-} mmc_t;
-
-/* hashing strategy */
-typedef unsigned int (*mmc_hash_function)(const char *, int);
-typedef void * (*mmc_hash_create_state)(mmc_hash_function);
-typedef void (*mmc_hash_free_state)(void *);
-typedef mmc_t * (*mmc_hash_find_server)(void *, const char *, int TSRMLS_DC);
-typedef void (*mmc_hash_add_server)(void *, mmc_t *, unsigned int);
-
-#define mmc_pool_find(pool, key, key_len) \
- pool->hash->find_server(pool->hash_state, key, key_len)
-
-typedef struct mmc_hash {
- mmc_hash_create_state create_state;
- mmc_hash_free_state free_state;
- mmc_hash_find_server find_server;
- mmc_hash_add_server add_server;
-} mmc_hash_t;
-
-/* 32 bit magic FNV-1a prime and init */
-#define FNV_32_PRIME 0x01000193
-#define FNV_32_INIT 0x811c9dc5
-
-typedef struct mmc_pool {
- mmc_t **servers;
- int num_servers;
- mmc_t **requests;
- int compress_threshold;
- double min_compress_savings;
- zend_bool in_free;
- mmc_hash_t *hash;
- void *hash_state;
-} mmc_pool_t;
-
-/* our globals */
-ZEND_BEGIN_MODULE_GLOBALS(memcache)
- long debug_mode;
- long default_port;
- long num_persistent;
- long compression_level;
- long allow_failover;
- long chunk_size;
- long max_failover_attempts;
- long hash_strategy;
- long hash_function;
-ZEND_END_MODULE_GLOBALS(memcache)
-
-/* internal functions */
-mmc_t *mmc_server_new(char *, int, unsigned short, int, int, int TSRMLS_DC);
-mmc_t *mmc_find_persistent(char *, int, int, int, int TSRMLS_DC);
-int mmc_server_failure(mmc_t * TSRMLS_DC);
-void mmc_server_deactivate(mmc_t * TSRMLS_DC);
-
-int mmc_prepare_key(zval *, char *, unsigned int * TSRMLS_DC);
-int mmc_prepare_key_ex(const char *, unsigned int, char *, unsigned int * TSRMLS_DC);
-
-mmc_pool_t *mmc_pool_new(TSRMLS_D);
-void mmc_pool_free(mmc_pool_t * TSRMLS_DC);
-void mmc_pool_add(mmc_pool_t *, mmc_t *, unsigned int);
-int mmc_pool_store(mmc_pool_t *, const char *, int, const char *, int, int, int, const char *, int TSRMLS_DC);
-int mmc_open(mmc_t *, int, char **, int * TSRMLS_DC);
-int mmc_exec_retrieval_cmd(mmc_pool_t *, const char *, int, zval **, zval * TSRMLS_DC);
-int mmc_delete(mmc_t *, const char *, int, int TSRMLS_DC);
-
-/* session handler struct */
-#if HAVE_MEMCACHE_SESSION
-#include "ext/session/php_session.h"
-
-extern ps_module ps_mod_memcache;
-#define ps_memcache_ptr &ps_mod_memcache
-
-PS_FUNCS(memcache);
-#endif
-
-/* {{{ macros */
-#if ZEND_DEBUG
-
-void mmc_debug(const char *format, ...);
-
-#define MMC_DEBUG(info) \
-{\
- mmc_debug info; \
-}\
-
-#else
-
-#define MMC_DEBUG(info) \
-{\
-}\
-
-#endif
-/* }}} */
-
-#ifdef ZTS
-#define MEMCACHE_G(v) TSRMG(memcache_globals_id, zend_memcache_globals *, v)
-#else
-#define MEMCACHE_G(v) (memcache_globals.v)
-#endif
-
-#ifndef ZSTR
-#define ZSTR
-#endif
-
-#endif /* PHP_MEMCACHE_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
|
Deleted |
memcache-2.2.4.tgz
^
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/CREDITS
^
|
(renamed from memcache-2.2.3/CREDITS)
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/CREDITS
^
|
(renamed from memcache-2.2.3/CREDITS)
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/README
^
|
@@ -0,0 +1,14 @@
+memcached module for PHP
+------------------------
+This module requires zlib library, used for on-the-fly data (de)compression.
+Also, you'll need memcached to use it =)
+
+The memcached website is here:
+ http://www.danga.com/memcached/
+
+You will probably need libevent to install memcached:
+You can download it here: http://www.monkey.org/~provos/libevent/
+
+Maintainers:
+Mikael Johansson mikael at synd dot info
+Antony Dovgal tony at daylessday dot org
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/config.m4
^
|
@@ -0,0 +1,4 @@
+dnl $Id: config.m4 303962 2010-10-03 15:48:23Z hradtke $
+dnl this file is required by phpize
+
+sinclude(config9.m4)
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/config.w32
^
|
@@ -0,0 +1,19 @@
+// $Id: config.w32 303962 2010-10-03 15:48:23Z hradtke $
+// vim:ft=javascript
+
+ARG_ENABLE("memcache", "memcache support", "no");
+
+if (PHP_MEMCACHE != "no") {
+ if (
+ ((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "memcache", PHP_MEMCACHE) )) ||
+ (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "memcache", PHP_MEMCACHE)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))
+ ) {
+ EXTENSION("memcache", "memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c");
+ AC_DEFINE('HAVE_MEMCACHE', 1, 'Have memcache support');
+ ADD_FLAG("CFLAGS_MEMCACHE", "/D HAVE_MEMCACHE_SESSION=1");
+ ADD_EXTENSION_DEP('memcache', 'session');
+ } else {
+ WARNING("memcache not enabled; libraries and headers not found");
+ }
+}
+
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/config9.m4
^
|
@@ -0,0 +1,112 @@
+dnl
+dnl $Id: config9.m4 303962 2010-10-03 15:48:23Z hradtke $
+dnl
+
+PHP_ARG_ENABLE(memcache, whether to enable memcache support,
+[ --enable-memcache Enable memcache support])
+
+PHP_ARG_ENABLE(memcache-session, whether to enable memcache session handler support,
+[ --disable-memcache-session Disable memcache session handler support], yes, no)
+
+if test -z "$PHP_ZLIB_DIR"; then
+PHP_ARG_WITH(zlib-dir, for the location of ZLIB,
+[ --with-zlib-dir[=DIR] memcache: Set the path to ZLIB install prefix.], no, no)
+fi
+
+if test -z "$PHP_DEBUG"; then
+ AC_ARG_ENABLE(debug,
+ [ --enable-debug compile with debugging symbols],[
+ PHP_DEBUG=$enableval
+ ],[
+ PHP_DEBUG=no
+ ])
+fi
+
+if test "$PHP_MEMCACHE" != "no"; then
+
+ if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then
+ if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then
+ PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
+ PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib"
+ elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then
+ PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
+ PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include"
+ else
+ AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"])
+ fi
+ else
+ for i in /usr/local /usr; do
+ if test -f "$i/include/zlib/zlib.h"; then
+ PHP_ZLIB_DIR="$i"
+ PHP_ZLIB_INCDIR="$i/include/zlib"
+ elif test -f "$i/include/zlib.h"; then
+ PHP_ZLIB_DIR="$i"
+ PHP_ZLIB_INCDIR="$i/include"
+ fi
+ done
+ fi
+
+ dnl # zlib
+ AC_MSG_CHECKING([for the location of zlib])
+ if test "$PHP_ZLIB_DIR" = "no"; then
+ AC_MSG_ERROR([memcache support requires ZLIB. Use --with-zlib-dir=<DIR> to specify prefix where ZLIB include and library are located])
+ else
+ AC_MSG_RESULT([$PHP_ZLIB_DIR])
+ if test "z$PHP_LIBDIR" != "z"; then
+ dnl PHP5+
+ PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHE_SHARED_LIBADD)
+ else
+ dnl PHP4
+ PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/lib, MEMCACHE_SHARED_LIBADD)
+ fi
+ PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR)
+ fi
+
+ if test "$PHP_MEMCACHE_SESSION" != "no"; then
+ AC_MSG_CHECKING([for session includes])
+ session_inc_path=""
+
+ if test -f "$abs_srcdir/include/php/ext/session/php_session.h"; then
+ session_inc_path="$abs_srcdir/include/php"
+ elif test -f "$abs_srcdir/ext/session/php_session.h"; then
+ session_inc_path="$abs_srcdir"
+ elif test -f "$phpincludedir/ext/session/php_session.h"; then
+ session_inc_path="$phpincludedir"
+ else
+ for i in php php4 php5 php6; do
+ if test -f "$prefix/include/$i/ext/session/php_session.h"; then
+ session_inc_path="$prefix/include/$i"
+ fi
+ done
+ fi
+
+ if test "$session_inc_path" = ""; then
+ AC_MSG_ERROR([Cannot find php_session.h])
+ else
+ AC_MSG_RESULT([$session_inc_path])
+ fi
+ fi
+
+ AC_MSG_CHECKING([for memcache session support])
+ if test "$PHP_MEMCACHE_SESSION" != "no"; then
+ AC_MSG_RESULT([enabled])
+ AC_DEFINE(HAVE_MEMCACHE_SESSION,1,[Whether memcache session handler is enabled])
+ AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support])
+ PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c memcache_session.c, $ext_shared,,-I$session_inc_path)
+ ifdef([PHP_ADD_EXTENSION_DEP],
+ [
+ PHP_ADD_EXTENSION_DEP(memcache, session)
+ ])
+ else
+ AC_MSG_RESULT([disabled])
+ AC_DEFINE(HAVE_MEMCACHE,1,[Whether you want memcache support])
+ PHP_NEW_EXTENSION(memcache, memcache.c memcache_queue.c memcache_standard_hash.c memcache_consistent_hash.c, $ext_shared)
+ fi
+
+dnl this is needed to build the extension with phpize and -Wall
+
+ if test "$PHP_DEBUG" = "yes"; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+
+fi
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/example.php
^
|
(renamed from memcache-2.2.3/example.php)
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/example.php
^
|
(renamed from memcache-2.2.3/example.php)
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache.c
^
|
@@ -0,0 +1,2709 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache.c 303962 2010-10-03 15:48:23Z hradtke $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include <stdio.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#include <zlib.h>
+#include <time.h>
+#include "ext/standard/crc32.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
+#include "ext/standard/php_var.h"
+#include "ext/standard/php_smart_str.h"
+#include "php_network.h"
+#include "php_memcache.h"
+#include "memcache_queue.h"
+
+#if HAVE_MEMCACHE_SESSION
+#include "ext/session/php_session.h"
+#endif
+
+#ifndef ZEND_ENGINE_2
+#define OnUpdateLong OnUpdateInt
+#endif
+
+/* True global resources - no need for thread safety here */
+static int le_memcache_pool, le_pmemcache;
+static zend_class_entry *memcache_class_entry_ptr;
+
+ZEND_DECLARE_MODULE_GLOBALS(memcache)
+
+/* {{{ memcache_functions[]
+ */
+zend_function_entry memcache_functions[] = {
+ PHP_FE(memcache_connect, NULL)
+ PHP_FE(memcache_pconnect, NULL)
+ PHP_FE(memcache_add_server, NULL)
+ PHP_FE(memcache_set_server_params, NULL)
+ PHP_FE(memcache_get_server_status, NULL)
+ PHP_FE(memcache_get_version, NULL)
+ PHP_FE(memcache_add, NULL)
+ PHP_FE(memcache_set, NULL)
+ PHP_FE(memcache_replace, NULL)
+ PHP_FE(memcache_get, NULL)
+ PHP_FE(memcache_delete, NULL)
+ PHP_FE(memcache_debug, NULL)
+ PHP_FE(memcache_get_stats, NULL)
+ PHP_FE(memcache_get_extended_stats, NULL)
+ PHP_FE(memcache_set_compress_threshold, NULL)
+ PHP_FE(memcache_increment, NULL)
+ PHP_FE(memcache_decrement, NULL)
+ PHP_FE(memcache_close, NULL)
+ PHP_FE(memcache_flush, NULL)
+ PHP_FE(memcache_setoptimeout, NULL)
+ {NULL, NULL, NULL}
+};
+
+static zend_function_entry php_memcache_class_functions[] = {
+ PHP_FALIAS(connect, memcache_connect, NULL)
+ PHP_FALIAS(pconnect, memcache_pconnect, NULL)
+ PHP_FALIAS(addserver, memcache_add_server, NULL)
+ PHP_FALIAS(setserverparams, memcache_set_server_params, NULL)
+ PHP_FALIAS(getserverstatus, memcache_get_server_status, NULL)
+ PHP_FALIAS(getversion, memcache_get_version, NULL)
+ PHP_FALIAS(add, memcache_add, NULL)
+ PHP_FALIAS(set, memcache_set, NULL)
+ PHP_FALIAS(replace, memcache_replace, NULL)
+ PHP_FALIAS(get, memcache_get, NULL)
+ PHP_FALIAS(delete, memcache_delete, NULL)
+ PHP_FALIAS(getstats, memcache_get_stats, NULL)
+ PHP_FALIAS(getextendedstats, memcache_get_extended_stats, NULL)
+ PHP_FALIAS(setcompressthreshold, memcache_set_compress_threshold, NULL)
+ PHP_FALIAS(increment, memcache_increment, NULL)
+ PHP_FALIAS(decrement, memcache_decrement, NULL)
+ PHP_FALIAS(close, memcache_close, NULL)
+ PHP_FALIAS(flush, memcache_flush, NULL)
+ PHP_FALIAS(setoptimeout, memcache_setoptimeout, NULL)
+ {NULL, NULL, NULL}
+};
+
+/* }}} */
+
+/* {{{ memcache_module_entry
+ */
+zend_module_entry memcache_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "memcache",
+ memcache_functions,
+ PHP_MINIT(memcache),
+ PHP_MSHUTDOWN(memcache),
+ PHP_RINIT(memcache),
+ NULL,
+ PHP_MINFO(memcache),
+#if ZEND_MODULE_API_NO >= 20010901
+ PHP_MEMCACHE_VERSION,
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_MEMCACHE
+ZEND_GET_MODULE(memcache)
+#endif
+
+static PHP_INI_MH(OnUpdateChunkSize) /* {{{ */
+{
+ long int lval;
+
+ lval = strtol(new_value, NULL, 10);
+ if (lval <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.chunk_size must be a positive integer ('%s' given)", new_value);
+ return FAILURE;
+ }
+
+ return OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateFailoverAttempts) /* {{{ */
+{
+ long int lval;
+
+ lval = strtol(new_value, NULL, 10);
+ if (lval <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.max_failover_attempts must be a positive integer ('%s' given)", new_value);
+ return FAILURE;
+ }
+
+ return OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateHashStrategy) /* {{{ */
+{
+ if (!strcasecmp(new_value, "standard")) {
+ MEMCACHE_G(hash_strategy) = MMC_STANDARD_HASH;
+ }
+ else if (!strcasecmp(new_value, "consistent")) {
+ MEMCACHE_G(hash_strategy) = MMC_CONSISTENT_HASH;
+ }
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.hash_strategy must be in set {standard, consistent} ('%s' given)", new_value);
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateHashFunction) /* {{{ */
+{
+ if (!strcasecmp(new_value, "crc32")) {
+ MEMCACHE_G(hash_function) = MMC_HASH_CRC32;
+ }
+ else if (!strcasecmp(new_value, "fnv")) {
+ MEMCACHE_G(hash_function) = MMC_HASH_FNV1A;
+ }
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.hash_function must be in set {crc32, fnv} ('%s' given)", new_value);
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+static PHP_INI_MH(OnUpdateDefaultTimeout) /* {{{ */
+{
+ long int lval;
+
+ lval = strtol(new_value, NULL, 10);
+ if (lval <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcache.default_timeout must be a positive number greater than or equal to 1 ('%s' given)", new_value);
+ return FAILURE;
+ }
+ MEMCACHE_G(default_timeout_ms) = lval;
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_INI */
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("memcache.allow_failover", "1", PHP_INI_ALL, OnUpdateLong, allow_failover, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.max_failover_attempts", "20", PHP_INI_ALL, OnUpdateFailoverAttempts, max_failover_attempts, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.default_port", "11211", PHP_INI_ALL, OnUpdateLong, default_port, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.chunk_size", "8192", PHP_INI_ALL, OnUpdateChunkSize, chunk_size, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.hash_strategy", "standard", PHP_INI_ALL, OnUpdateHashStrategy, hash_strategy, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.hash_function", "crc32", PHP_INI_ALL, OnUpdateHashFunction, hash_function, zend_memcache_globals, memcache_globals)
+ STD_PHP_INI_ENTRY("memcache.default_timeout_ms", "1000", PHP_INI_ALL, OnUpdateDefaultTimeout, default_timeout_ms, zend_memcache_globals, memcache_globals)
+PHP_INI_END()
+/* }}} */
+
+/* {{{ internal function protos */
+static void _mmc_pool_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
+static void _mmc_pserver_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
+
+static void mmc_server_free(mmc_t * TSRMLS_DC);
+static void mmc_server_disconnect(mmc_t * TSRMLS_DC);
+static int mmc_server_store(mmc_t *, const char *, int TSRMLS_DC);
+
+static int mmc_compress(char **, unsigned long *, const char *, int TSRMLS_DC);
+static int mmc_uncompress(char **, unsigned long *, const char *, int);
+static int mmc_get_pool(zval *, mmc_pool_t ** TSRMLS_DC);
+static int mmc_readline(mmc_t * TSRMLS_DC);
+static char * mmc_get_version(mmc_t * TSRMLS_DC);
+static int mmc_str_left(char *, char *, int, int);
+static int mmc_sendcmd(mmc_t *, const char *, int TSRMLS_DC);
+static int mmc_parse_response(mmc_t *mmc, char *, int, char **, int *, int *, int *);
+static int mmc_exec_retrieval_cmd_multi(mmc_pool_t *, zval *, zval **, zval * TSRMLS_DC);
+static int mmc_read_value(mmc_t *, char **, int *, char **, int *, int * TSRMLS_DC);
+static int mmc_flush(mmc_t *, int TSRMLS_DC);
+static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, char *, int);
+static int mmc_get_stats(mmc_t *, char *, int, int, zval * TSRMLS_DC);
+static int mmc_incr_decr(mmc_t *, int, char *, int, int, long * TSRMLS_DC);
+static void php_mmc_incr_decr(INTERNAL_FUNCTION_PARAMETERS, int);
+static void php_mmc_connect(INTERNAL_FUNCTION_PARAMETERS, int);
+/* }}} */
+
+/* {{{ hash strategies */
+extern mmc_hash_t mmc_standard_hash;
+extern mmc_hash_t mmc_consistent_hash;
+/* }}} */
+
+/* {{{ php_memcache_init_globals()
+*/
+static void php_memcache_init_globals(zend_memcache_globals *memcache_globals_p TSRMLS_DC)
+{
+ MEMCACHE_G(debug_mode) = 0;
+ MEMCACHE_G(num_persistent) = 0;
+ MEMCACHE_G(compression_level) = Z_DEFAULT_COMPRESSION;
+ MEMCACHE_G(hash_strategy) = MMC_STANDARD_HASH;
+ MEMCACHE_G(hash_function) = MMC_HASH_CRC32;
+ MEMCACHE_G(default_timeout_ms)= (MMC_DEFAULT_TIMEOUT) * 1000;
+}
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(memcache)
+{
+ zend_class_entry memcache_class_entry;
+ INIT_CLASS_ENTRY(memcache_class_entry, "Memcache", php_memcache_class_functions);
+ memcache_class_entry_ptr = zend_register_internal_class(&memcache_class_entry TSRMLS_CC);
+
+ le_memcache_pool = zend_register_list_destructors_ex(_mmc_pool_list_dtor, NULL, "memcache connection", module_number);
+ le_pmemcache = zend_register_list_destructors_ex(NULL, _mmc_pserver_list_dtor, "persistent memcache connection", module_number);
+
+#ifdef ZTS
+ ts_allocate_id(&memcache_globals_id, sizeof(zend_memcache_globals), (ts_allocate_ctor) php_memcache_init_globals, NULL);
+#else
+ php_memcache_init_globals(&memcache_globals TSRMLS_CC);
+#endif
+
+ REGISTER_LONG_CONSTANT("MEMCACHE_COMPRESSED", MMC_COMPRESSED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_INI_ENTRIES();
+
+#if HAVE_MEMCACHE_SESSION
+ REGISTER_LONG_CONSTANT("MEMCACHE_HAVE_SESSION", 1, CONST_CS | CONST_PERSISTENT);
+ php_session_register_module(ps_memcache_ptr);
+#else
+ REGISTER_LONG_CONSTANT("MEMCACHE_HAVE_SESSION", 0, CONST_CS | CONST_PERSISTENT);
+#endif
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(memcache)
+{
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(memcache)
+{
+ MEMCACHE_G(debug_mode) = 0;
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(memcache)
+{
+ char buf[MAX_LENGTH_OF_LONG + 1];
+
+ sprintf(buf, "%ld", MEMCACHE_G(num_persistent));
+
+ php_info_print_table_start();
+ php_info_print_table_header(2, "memcache support", "enabled");
+ php_info_print_table_row(2, "Active persistent connections", buf);
+ php_info_print_table_row(2, "Version", PHP_MEMCACHE_VERSION);
+ php_info_print_table_row(2, "Revision", "$Revision: 303962 $");
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+/* ------------------
+ internal functions
+ ------------------ */
+
+#if ZEND_DEBUG
+void mmc_debug(const char *format, ...) /* {{{ */
+{
+ TSRMLS_FETCH();
+
+ if (MEMCACHE_G(debug_mode)) {
+ char buffer[1024];
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf(buffer, sizeof(buffer)-1, format, args);
+ va_end(args);
+ buffer[sizeof(buffer)-1] = '\0';
+ php_printf("%s<br />\n", buffer);
+ }
+}
+/* }}} */
+#endif
+
+static struct timeval _convert_timeoutms_to_ts(long msecs) /* {{{ */
+{
+ struct timeval tv;
+ int secs = 0;
+
+ secs = msecs / 1000;
+ tv.tv_sec = secs;
+ tv.tv_usec = ((msecs - (secs * 1000)) * 1000) % 1000000;
+ return tv;
+}
+/* }}} */
+
+static void _mmc_pool_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+{
+ mmc_pool_free((mmc_pool_t *)rsrc->ptr TSRMLS_CC);
+}
+/* }}} */
+
+static void _mmc_pserver_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+{
+ mmc_server_free((mmc_t *)rsrc->ptr TSRMLS_CC);
+}
+/* }}} */
+
+mmc_t *mmc_server_new(char *host, int host_len, unsigned short port, int persistent, int timeout, int retry_interval TSRMLS_DC) /* {{{ */
+{
+ mmc_t *mmc = pemalloc(sizeof(mmc_t), persistent);
+ memset(mmc, 0, sizeof(*mmc));
+
+ mmc->host = pemalloc(host_len + 1, persistent);
+ memcpy(mmc->host, host, host_len);
+ mmc->host[host_len] = '\0';
+
+ mmc->port = port;
+ mmc->status = MMC_STATUS_DISCONNECTED;
+
+ mmc->persistent = persistent;
+ if (persistent) {
+ MEMCACHE_G(num_persistent)++;
+ }
+
+ mmc->timeout = timeout;
+ mmc->retry_interval = retry_interval;
+
+ return mmc;
+}
+/* }}} */
+
+static void mmc_server_callback_dtor(zval **callback TSRMLS_DC) /* {{{ */
+{
+ zval **this_obj;
+
+ if (!callback || !*callback) return;
+
+ if (Z_TYPE_PP(callback) == IS_ARRAY &&
+ zend_hash_index_find(Z_ARRVAL_PP(callback), 0, (void **)&this_obj) == SUCCESS &&
+ Z_TYPE_PP(this_obj) == IS_OBJECT) {
+ zval_ptr_dtor(this_obj);
+ }
+ zval_ptr_dtor(callback);
+}
+/* }}} */
+
+static void mmc_server_callback_ctor(zval **callback TSRMLS_DC) /* {{{ */
+{
+ zval **this_obj;
+
+ if (!callback || !*callback) return;
+
+ if (Z_TYPE_PP(callback) == IS_ARRAY &&
+ zend_hash_index_find(Z_ARRVAL_PP(callback), 0, (void **)&this_obj) == SUCCESS &&
+ Z_TYPE_PP(this_obj) == IS_OBJECT) {
+ zval_add_ref(this_obj);
+ }
+ zval_add_ref(callback);
+}
+/* }}} */
+
+static void mmc_server_sleep(mmc_t *mmc TSRMLS_DC) /*
+ prepare server struct for persistent sleep {{{ */
+{
+ mmc_server_callback_dtor(&mmc->failure_callback TSRMLS_CC);
+ mmc->failure_callback = NULL;
+
+ if (mmc->error != NULL) {
+ pefree(mmc->error, mmc->persistent);
+ mmc->error = NULL;
+ }
+}
+/* }}} */
+
+static void mmc_server_free(mmc_t *mmc TSRMLS_DC) /* {{{ */
+{
+ if (mmc->in_free) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Recursive reference detected, bailing out");
+ return;
+ }
+ mmc->in_free = 1;
+
+ mmc_server_sleep(mmc TSRMLS_CC);
+
+ if (mmc->persistent) {
+ free(mmc->host);
+ free(mmc);
+ MEMCACHE_G(num_persistent)--;
+ }
+ else {
+ if (mmc->stream != NULL) {
+ php_stream_close(mmc->stream);
+ }
+ efree(mmc->host);
+ efree(mmc);
+ }
+}
+/* }}} */
+
+static void mmc_server_seterror(mmc_t *mmc, const char *error, int errnum) /* {{{ */
+{
+ if (error != NULL) {
+ if (mmc->error != NULL) {
+ pefree(mmc->error, mmc->persistent);
+ }
+
+ mmc->error = pestrdup(error, mmc->persistent);
+ mmc->errnum = errnum;
+ }
+}
+/* }}} */
+
+static void mmc_server_received_error(mmc_t *mmc, int response_len) /* {{{ */
+{
+ if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1))
+ {
+ mmc->inbuf[response_len < MMC_BUF_SIZE - 1 ? response_len : MMC_BUF_SIZE - 1] = '\0';
+ mmc_server_seterror(mmc, mmc->inbuf, 0);
+ }
+ else {
+ mmc_server_seterror(mmc, "Received malformed response", 0);
+ }
+}
+/* }}} */
+
+int mmc_server_failure(mmc_t *mmc TSRMLS_DC) /*determines if a request should be retried or is a hard network failure {{{ */
+{
+ switch (mmc->status) {
+ case MMC_STATUS_DISCONNECTED:
+ return 0;
+
+ /* attempt reconnect of sockets in unknown state */
+ case MMC_STATUS_UNKNOWN:
+ mmc->status = MMC_STATUS_DISCONNECTED;
+ return 0;
+ }
+
+ mmc_server_deactivate(mmc TSRMLS_CC);
+ return 1;
+}
+/* }}} */
+
+static int mmc_server_store(mmc_t *mmc, const char *request, int request_len TSRMLS_DC) /* {{{ */
+{
+ int response_len;
+ php_netstream_data_t *sock = (php_netstream_data_t*)mmc->stream->abstract;
+
+ if (mmc->timeoutms > 1) {
+ sock->timeout = _convert_timeoutms_to_ts(mmc->timeoutms);
+ }
+
+ if (php_stream_write(mmc->stream, request, request_len) != request_len) {
+ mmc_server_seterror(mmc, "Failed sending command and value to stream", 0);
+ return -1;
+ }
+
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
+ return -1;
+ }
+
+ if(mmc_str_left(mmc->inbuf, "STORED", response_len, sizeof("STORED") - 1)) {
+ return 1;
+ }
+
+ /* return FALSE */
+ if(mmc_str_left(mmc->inbuf, "NOT_STORED", response_len, sizeof("NOT_STORED") - 1)) {
+ return 0;
+ }
+
+ /* return FALSE without failover */
+ if (mmc_str_left(mmc->inbuf, "SERVER_ERROR out of memory", response_len, sizeof("SERVER_ERROR out of memory") - 1) ||
+ mmc_str_left(mmc->inbuf, "SERVER_ERROR object too large", response_len, sizeof("SERVER_ERROR object too large")-1)) {
+ return 0;
+ }
+
+ mmc_server_received_error(mmc, response_len);
+ return -1;
+}
+/* }}} */
+
+int mmc_prepare_key_ex(const char *key, unsigned int key_len, char *result, unsigned int *result_len TSRMLS_DC) /* {{{ */
+{
+ unsigned int i;
+ if (key_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key cannot be empty");
+ return MMC_REQUEST_FAILURE;
+ }
+
+ *result_len = key_len < MMC_KEY_MAX_SIZE ? key_len : MMC_KEY_MAX_SIZE;
+ result[*result_len] = '\0';
+
+ for (i=0; i<*result_len; i++) {
+ result[i] = ((unsigned char)key[i]) > ' ' ? key[i] : '_';
+ }
+
+ return MMC_OK;
+}
+/* }}} */
+
+int mmc_prepare_key(zval *key, char *result, unsigned int *result_len TSRMLS_DC) /* {{{ */
+{
+ if (Z_TYPE_P(key) == IS_STRING) {
+ return mmc_prepare_key_ex(Z_STRVAL_P(key), Z_STRLEN_P(key), result, result_len TSRMLS_CC);
+ } else {
+ int res;
+ zval *keytmp;
+ ALLOC_ZVAL(keytmp);
+
+ *keytmp = *key;
+ zval_copy_ctor(keytmp);
+ convert_to_string(keytmp);
+
+ res = mmc_prepare_key_ex(Z_STRVAL_P(keytmp), Z_STRLEN_P(keytmp), result, result_len TSRMLS_CC);
+
+ zval_dtor(keytmp);
+ FREE_ZVAL(keytmp);
+
+ return res;
+ }
+}
+/* }}} */
+
+static unsigned int mmc_hash_crc32(const char *key, int key_len) /* CRC32 hash {{{ */
+{
+ unsigned int crc = ~0;
+ int i;
+
+ for (i=0; i<key_len; i++) {
+ CRC32(crc, key[i]);
+ }
+
+ return ~crc;
+}
+/* }}} */
+
+static unsigned int mmc_hash_fnv1a(const char *key, int key_len) /* FNV-1a hash {{{ */
+{
+ unsigned int hval = FNV_32_INIT;
+ int i;
+
+ for (i=0; i<key_len; i++) {
+ hval ^= (unsigned int)key[i];
+ hval *= FNV_32_PRIME;
+ }
+
+ return hval;
+}
+/* }}} */
+
+static void mmc_pool_init_hash(mmc_pool_t *pool TSRMLS_DC) /* {{{ */
+{
+ mmc_hash_function hash;
+
+ switch (MEMCACHE_G(hash_strategy)) {
+ case MMC_CONSISTENT_HASH:
+ pool->hash = &mmc_consistent_hash;
+ break;
+ default:
+ pool->hash = &mmc_standard_hash;
+ }
+
+ switch (MEMCACHE_G(hash_function)) {
+ case MMC_HASH_FNV1A:
+ hash = &mmc_hash_fnv1a;
+ break;
+ default:
+ hash = &mmc_hash_crc32;
+ }
+
+ pool->hash_state = pool->hash->create_state(hash);
+}
+/* }}} */
+
+mmc_pool_t *mmc_pool_new(TSRMLS_D) /* {{{ */
+{
+ mmc_pool_t *pool = emalloc(sizeof(mmc_pool_t));
+ pool->num_servers = 0;
+ pool->compress_threshold = 0;
+ pool->in_free = 0;
+ pool->min_compress_savings = MMC_DEFAULT_SAVINGS;
+
+ mmc_pool_init_hash(pool TSRMLS_CC);
+
+ return pool;
+}
+/* }}} */
+
+void mmc_pool_free(mmc_pool_t *pool TSRMLS_DC) /* {{{ */
+{
+ int i;
+
+ if (pool->in_free) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Recursive reference detected, bailing out");
+ return;
+ }
+ pool->in_free = 1;
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (!pool->servers[i]) {
+ continue;
+ }
+ if (pool->servers[i]->persistent == 0 && pool->servers[i]->host != NULL) {
+ mmc_server_free(pool->servers[i] TSRMLS_CC);
+ } else {
+ mmc_server_sleep(pool->servers[i] TSRMLS_CC);
+ }
+ pool->servers[i] = NULL;
+ }
+
+ if (pool->num_servers) {
+ efree(pool->servers);
+ efree(pool->requests);
+ }
+
+ pool->hash->free_state(pool->hash_state);
+ efree(pool);
+}
+/* }}} */
+
+void mmc_pool_add(mmc_pool_t *pool, mmc_t *mmc, unsigned int weight) /* {{{ */
+{
+ /* add server and a preallocated request pointer */
+ if (pool->num_servers) {
+ pool->servers = erealloc(pool->servers, sizeof(mmc_t *) * (pool->num_servers + 1));
+ pool->requests = erealloc(pool->requests, sizeof(mmc_t *) * (pool->num_servers + 1));
+ }
+ else {
+ pool->servers = emalloc(sizeof(mmc_t *));
+ pool->requests = emalloc(sizeof(mmc_t *));
+ }
+
+ pool->servers[pool->num_servers] = mmc;
+ pool->num_servers++;
+
+ pool->hash->add_server(pool->hash_state, mmc, weight);
+}
+/* }}} */
+
+static int mmc_pool_close(mmc_pool_t *pool TSRMLS_DC) /* disconnects and removes all servers in the pool {{{ */
+{
+ if (pool->num_servers) {
+ int i;
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (pool->servers[i]->persistent == 0 && pool->servers[i]->host != NULL) {
+ mmc_server_free(pool->servers[i] TSRMLS_CC);
+ } else {
+ mmc_server_sleep(pool->servers[i] TSRMLS_CC);
+ }
+ }
+
+ efree(pool->servers);
+ pool->servers = NULL;
+ pool->num_servers = 0;
+
+ efree(pool->requests);
+ pool->requests = NULL;
+
+ /* reallocate the hash strategy state */
+ pool->hash->free_state(pool->hash_state);
+ mmc_pool_init_hash(pool TSRMLS_CC);
+ }
+
+ return 1;
+}
+/* }}} */
+
+int mmc_pool_store(mmc_pool_t *pool, const char *command, int command_len, const char *key, int key_len, int flags, int expire, const char *value, int value_len TSRMLS_DC) /* {{{ */
+{
+ mmc_t *mmc;
+ char *request;
+ int request_len, result = -1;
+ char *key_copy = NULL, *data = NULL;
+
+ if (key_len > MMC_KEY_MAX_SIZE) {
+ key = key_copy = estrndup(key, MMC_KEY_MAX_SIZE);
+ key_len = MMC_KEY_MAX_SIZE;
+ }
+
+ /* autocompress large values */
+ if (pool->compress_threshold && value_len >= pool->compress_threshold) {
+ flags |= MMC_COMPRESSED;
+ }
+
+ if (flags & MMC_COMPRESSED) {
+ unsigned long data_len;
+
+ if (!mmc_compress(&data, &data_len, value, value_len TSRMLS_CC)) {
+ /* mmc_server_seterror(mmc, "Failed to compress data", 0); */
+ return -1;
+ }
+
+ /* was enough space saved to motivate uncompress processing on get */
+ if (data_len < value_len * (1 - pool->min_compress_savings)) {
+ value = data;
+ value_len = data_len;
+ }
+ else {
+ flags &= ~MMC_COMPRESSED;
+ efree(data);
+ data = NULL;
+ }
+ }
+
+ request = emalloc(
+ command_len
+ + 1 /* space */
+ + key_len
+ + 1 /* space */
+ + MAX_LENGTH_OF_LONG
+ + 1 /* space */
+ + MAX_LENGTH_OF_LONG
+ + 1 /* space */
+ + MAX_LENGTH_OF_LONG
+ + sizeof("\r\n") - 1
+ + value_len
+ + sizeof("\r\n") - 1
+ + 1
+ );
+
+ request_len = sprintf(request, "%s %s %d %d %d\r\n", command, key, flags, expire, value_len);
+
+ memcpy(request + request_len, value, value_len);
+ request_len += value_len;
+
+ memcpy(request + request_len, "\r\n", sizeof("\r\n") - 1);
+ request_len += sizeof("\r\n") - 1;
+
+ request[request_len] = '\0';
+
+ while (result < 0 && (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
+ if ((result = mmc_server_store(mmc, request, request_len TSRMLS_CC)) < 0) {
+ mmc_server_failure(mmc TSRMLS_CC);
+ }
+ }
+
+ if (key_copy != NULL) {
+ efree(key_copy);
+ }
+
+ if (data != NULL) {
+ efree(data);
+ }
+
+ efree(request);
+
+ return result;
+}
+/* }}} */
+
+static int mmc_compress(char **result, unsigned long *result_len, const char *data, int data_len TSRMLS_DC) /* {{{ */
+{
+ int status, level = MEMCACHE_G(compression_level);
+
+ *result_len = data_len + (data_len / 1000) + 25 + 1; /* some magic from zlib.c */
+ *result = (char *) emalloc(*result_len);
+
+ if (!*result) {
+ return 0;
+ }
+
+ if (level >= 0) {
+ status = compress2((unsigned char *) *result, result_len, (unsigned const char *) data, data_len, level);
+ } else {
+ status = compress((unsigned char *) *result, result_len, (unsigned const char *) data, data_len);
+ }
+
+ if (status == Z_OK) {
+ *result = erealloc(*result, *result_len + 1);
+ (*result)[*result_len] = '\0';
+ return 1;
+ }
+
+ switch (status) {
+ case Z_MEM_ERROR:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough memory to perform compression");
+ break;
+ case Z_BUF_ERROR:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough room in the output buffer to perform compression");
+ break;
+ case Z_STREAM_ERROR:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid compression level");
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error during compression");
+ break;
+ }
+
+ efree(*result);
+ return 0;
+}
+/* }}}*/
+
+static int mmc_uncompress(char **result, unsigned long *result_len, const char *data, int data_len) /* {{{ */
+{
+ int status;
+ unsigned int factor = 1, maxfactor = 16;
+ char *tmp1 = NULL;
+
+ do {
+ *result_len = (unsigned long)data_len * (1 << factor++);
+ *result = (char *) erealloc(tmp1, *result_len);
+ status = uncompress((unsigned char *) *result, result_len, (unsigned const char *) data, data_len);
+ tmp1 = *result;
+ } while (status == Z_BUF_ERROR && factor < maxfactor);
+
+ if (status == Z_OK) {
+ *result = erealloc(*result, *result_len + 1);
+ (*result)[*result_len] = '\0';
+ return 1;
+ }
+
+ efree(*result);
+ return 0;
+}
+/* }}}*/
+
+static int mmc_get_pool(zval *id, mmc_pool_t **pool TSRMLS_DC) /* {{{ */
+{
+ zval **connection;
+ int resource_type;
+
+ if (Z_TYPE_P(id) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(id), "connection", sizeof("connection"), (void **) &connection) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No servers added to memcache connection");
+ return 0;
+ }
+
+ *pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
+
+ if (!*pool || resource_type != le_memcache_pool) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Memcache->connection member variable");
+ return 0;
+ }
+
+ return Z_LVAL_PP(connection);
+}
+/* }}} */
+
+static int _mmc_open(mmc_t *mmc, char **error_string, int *errnum TSRMLS_DC) /* {{{ */
+{
+ struct timeval tv;
+ char *hostname = NULL, *hash_key = NULL, *errstr = NULL;
+ int hostname_len, err = 0;
+
+ /* close open stream */
+ if (mmc->stream != NULL) {
+ mmc_server_disconnect(mmc TSRMLS_CC);
+ }
+
+ if (mmc->connect_timeoutms > 0) {
+ tv = _convert_timeoutms_to_ts(mmc->connect_timeoutms);
+ } else {
+ tv.tv_sec = mmc->timeout;
+ tv.tv_usec = 0;
+ }
+
+ if (mmc->port) {
+ hostname_len = spprintf(&hostname, 0, "%s:%d", mmc->host, mmc->port);
+ }
+ else {
+ hostname_len = spprintf(&hostname, 0, "%s", mmc->host);
+ }
+
+ if (mmc->persistent) {
+ spprintf(&hash_key, 0, "memcache:%s", hostname);
+ }
+
+#if PHP_API_VERSION > 20020918
+ mmc->stream = php_stream_xport_create( hostname, hostname_len,
+ ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
+ hash_key, &tv, NULL, &errstr, &err);
+#else
+ if (mmc->persistent) {
+ switch(php_stream_from_persistent_id(hash_key, &(mmc->stream) TSRMLS_CC)) {
+ case PHP_STREAM_PERSISTENT_SUCCESS:
+ if (php_stream_eof(mmc->stream)) {
+ php_stream_pclose(mmc->stream);
+ mmc->stream = NULL;
+ break;
+ }
+ case PHP_STREAM_PERSISTENT_FAILURE:
+ break;
+ }
+ }
+
+ if (!mmc->stream) {
+ int socktype = SOCK_STREAM;
+ mmc->stream = php_stream_sock_open_host(mmc->host, mmc->port, socktype, &tv, hash_key);
+ }
+
+#endif
+
+ efree(hostname);
+ if (mmc->persistent) {
+ efree(hash_key);
+ }
+
+ if (!mmc->stream) {
+ MMC_DEBUG(("_mmc_open: can't open socket to host"));
+ mmc_server_seterror(mmc, errstr != NULL ? errstr : "Connection failed", err);
+ mmc_server_deactivate(mmc TSRMLS_CC);
+
+ if (errstr) {
+ if (error_string) {
+ *error_string = errstr;
+ }
+ else {
+ efree(errstr);
+ }
+ }
+ if (errnum) {
+ *errnum = err;
+ }
+
+ return 0;
+ }
+
+ php_stream_auto_cleanup(mmc->stream);
+ php_stream_set_option(mmc->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
+ php_stream_set_option(mmc->stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
+ php_stream_set_chunk_size(mmc->stream, MEMCACHE_G(chunk_size));
+
+ mmc->status = MMC_STATUS_CONNECTED;
+
+ if (mmc->error != NULL) {
+ pefree(mmc->error, mmc->persistent);
+ mmc->error = NULL;
+ }
+
+ return 1;
+}
+/* }}} */
+
+int mmc_open(mmc_t *mmc, int force_connect, char **error_string, int *errnum TSRMLS_DC) /* {{{ */
+{
+ switch (mmc->status) {
+ case MMC_STATUS_DISCONNECTED:
+ return _mmc_open(mmc, error_string, errnum TSRMLS_CC);
+
+ case MMC_STATUS_CONNECTED:
+ return 1;
+
+ case MMC_STATUS_UNKNOWN:
+ /* check connection if needed */
+ if (force_connect) {
+ char *version;
+ if ((version = mmc_get_version(mmc TSRMLS_CC)) == NULL && !_mmc_open(mmc, error_string, errnum TSRMLS_CC)) {
+ break;
+ }
+ if (version) {
+ efree(version);
+ }
+ mmc->status = MMC_STATUS_CONNECTED;
+ }
+ return 1;
+
+ case MMC_STATUS_FAILED:
+ if (mmc->retry_interval >= 0 && (long)time(NULL) >= mmc->failed + mmc->retry_interval) {
+ if (_mmc_open(mmc, error_string, errnum TSRMLS_CC) /*&& mmc_flush(mmc, 0 TSRMLS_CC) > 0*/) {
+ return 1;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+/* }}} */
+
+static void mmc_server_disconnect(mmc_t *mmc TSRMLS_DC) /* {{{ */
+{
+ if (mmc->stream != NULL) {
+ if (mmc->persistent) {
+ php_stream_pclose(mmc->stream);
+ }
+ else {
+ php_stream_close(mmc->stream);
+ }
+ mmc->stream = NULL;
+ }
+ mmc->status = MMC_STATUS_DISCONNECTED;
+}
+/* }}} */
+
+void mmc_server_deactivate(mmc_t *mmc TSRMLS_DC) /* disconnect and marks the server as down {{{ */
+{
+ mmc_server_disconnect(mmc TSRMLS_CC);
+ mmc->status = MMC_STATUS_FAILED;
+ mmc->failed = (long)time(NULL);
+
+ if (mmc->failure_callback != NULL) {
+ zval *retval = NULL;
+ zval *host, *tcp_port, *udp_port, *error, *errnum;
+ zval **params[5];
+
+ params[0] = &host;
+ params[1] = &tcp_port;
+ params[2] = &udp_port;
+ params[3] = &error;
+ params[4] = &errnum;
+
+ MAKE_STD_ZVAL(host);
+ MAKE_STD_ZVAL(tcp_port); MAKE_STD_ZVAL(udp_port);
+ MAKE_STD_ZVAL(error); MAKE_STD_ZVAL(errnum);
+
+ ZVAL_STRING(host, mmc->host, 1);
+ ZVAL_LONG(tcp_port, mmc->port); ZVAL_LONG(udp_port, 0);
+
+ if (mmc->error != NULL) {
+ ZVAL_STRING(error, mmc->error, 1);
+ }
+ else {
+ ZVAL_NULL(error);
+ }
+ ZVAL_LONG(errnum, mmc->errnum);
+
+ call_user_function_ex(EG(function_table), NULL, mmc->failure_callback, &retval, 5, params, 0, NULL TSRMLS_CC);
+
+ zval_ptr_dtor(&host);
+ zval_ptr_dtor(&tcp_port); zval_ptr_dtor(&udp_port);
+ zval_ptr_dtor(&error); zval_ptr_dtor(&errnum);
+
+ if (retval != NULL) {
+ zval_ptr_dtor(&retval);
+ }
+ }
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Server %s (tcp %d) failed with: %s (%d)",
+ mmc->host, mmc->port, mmc->error, mmc->errnum);
+ }
+}
+/* }}} */
+
+static int mmc_readline(mmc_t *mmc TSRMLS_DC) /* {{{ */
+{
+ char *response;
+ size_t response_len;
+
+ if (mmc->stream == NULL) {
+ mmc_server_seterror(mmc, "Socket is closed", 0);
+ return -1;
+ }
+
+ response = php_stream_get_line(mmc->stream, ZSTR(mmc->inbuf), MMC_BUF_SIZE, &response_len);
+ if (response) {
+ MMC_DEBUG(("mmc_readline: read data:"));
+ MMC_DEBUG(("mmc_readline:---"));
+ MMC_DEBUG(("%s", response));
+ MMC_DEBUG(("mmc_readline:---"));
+ return response_len;
+ }
+
+ mmc_server_seterror(mmc, "Failed reading line from stream", 0);
+ return -1;
+}
+/* }}} */
+
+static char *mmc_get_version(mmc_t *mmc TSRMLS_DC) /* {{{ */
+{
+ char *version_str;
+ int response_len;
+
+ if (mmc_sendcmd(mmc, "version", sizeof("version") - 1 TSRMLS_CC) < 0) {
+ return NULL;
+ }
+
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
+ return NULL;
+ }
+
+ if (mmc_str_left(mmc->inbuf, "VERSION ", response_len, sizeof("VERSION ") - 1)) {
+ version_str = estrndup(mmc->inbuf + sizeof("VERSION ") - 1, response_len - (sizeof("VERSION ") - 1) - (sizeof("\r\n") - 1) );
+ return version_str;
+ }
+
+ mmc_server_seterror(mmc, "Malformed version string", 0);
+ return NULL;
+}
+/* }}} */
+
+static int mmc_str_left(char *haystack, char *needle, int haystack_len, int needle_len) /* {{{ */
+{
+ char *found;
+
+ found = php_memnstr(haystack, needle, needle_len, haystack + haystack_len);
+ if ((found - haystack) == 0) {
+ return 1;
+ }
+ return 0;
+}
+/* }}} */
+
+static int mmc_sendcmd(mmc_t *mmc, const char *cmd, int cmdlen TSRMLS_DC) /* {{{ */
+{
+ char *command;
+ int command_len;
+ php_netstream_data_t *sock = (php_netstream_data_t*)mmc->stream->abstract;
+
+ if (!mmc || !cmd) {
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_sendcmd: sending command '%s'", cmd));
+
+ command = emalloc(cmdlen + sizeof("\r\n"));
+ memcpy(command, cmd, cmdlen);
+ memcpy(command + cmdlen, "\r\n", sizeof("\r\n") - 1);
+ command_len = cmdlen + sizeof("\r\n") - 1;
+ command[command_len] = '\0';
+
+ if (mmc->timeoutms > 1) {
+ sock->timeout = _convert_timeoutms_to_ts(mmc->timeoutms);
+ }
+
+ if (php_stream_write(mmc->stream, command, command_len) != command_len) {
+ mmc_server_seterror(mmc, "Failed writing command to stream", 0);
+ efree(command);
+ return -1;
+ }
+ efree(command);
+
+ return 1;
+}
+/* }}}*/
+
+static int mmc_parse_response(mmc_t *mmc, char *response, int response_len, char **key, int *key_len, int *flags, int *value_len) /* {{{ */
+{
+ int i=0, n=0;
+ int spaces[3];
+
+ if (!response || response_len <= 0) {
+ mmc_server_seterror(mmc, "Empty response", 0);
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_parse_response: got response '%s'", response));
+
+ for (i=0, n=0; i < response_len && n < 3; i++) {
+ if (response[i] == ' ') {
+ spaces[n++] = i;
+ }
+ }
+
+ MMC_DEBUG(("mmc_parse_response: found %d spaces", n));
+
+ if (n < 3) {
+ mmc_server_seterror(mmc, "Malformed VALUE header", 0);
+ return -1;
+ }
+
+ if (key != NULL) {
+ int len = spaces[1] - spaces[0] - 1;
+
+ *key = emalloc(len + 1);
+ *key_len = len;
+
+ memcpy(*key, response + spaces[0] + 1, len);
+ (*key)[len] = '\0';
+ }
+
+ *flags = atoi(response + spaces[1]);
+ *value_len = atoi(response + spaces[2]);
+
+ if (*flags < 0 || *value_len < 0) {
+ mmc_server_seterror(mmc, "Malformed VALUE header", 0);
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_parse_response: 1st space is at %d position", spaces[1]));
+ MMC_DEBUG(("mmc_parse_response: 2nd space is at %d position", spaces[2]));
+ MMC_DEBUG(("mmc_parse_response: flags = %d", *flags));
+ MMC_DEBUG(("mmc_parse_response: value_len = %d ", *value_len));
+
+ return 1;
+}
+/* }}} */
+
+static int mmc_postprocess_value(zval **return_value, char *value, int value_len TSRMLS_DC) /*
+ post-process a value into a result zval struct, value will be free()'ed during process {{{ */
+{
+ const char *value_tmp = value;
+ php_unserialize_data_t var_hash;
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+
+ if (!php_var_unserialize(return_value, (const unsigned char **)&value_tmp, (const unsigned char *)(value_tmp + value_len), &var_hash TSRMLS_CC)) {
+ ZVAL_FALSE(*return_value);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ efree(value);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "unable to unserialize data");
+ return 0;
+ }
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ efree(value);
+ return 1;
+}
+/* }}} */
+
+int mmc_exec_retrieval_cmd(mmc_pool_t *pool, const char *key, int key_len, zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */
+{
+ mmc_t *mmc;
+ char *command, *value;
+ int result = -1, command_len, response_len, value_len, flags = 0;
+
+ MMC_DEBUG(("mmc_exec_retrieval_cmd: key '%s'", key));
+
+ command_len = spprintf(&command, 0, "get %s", key);
+
+ while (result < 0 && (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
+ MMC_DEBUG(("mmc_exec_retrieval_cmd: found server '%s:%d' for key '%s'", mmc->host, mmc->port, key));
+
+ /* send command and read value */
+ if ((result = mmc_sendcmd(mmc, command, command_len TSRMLS_CC)) > 0 &&
+ (result = mmc_read_value(mmc, NULL, NULL, &value, &value_len, &flags TSRMLS_CC)) >= 0) {
+
+ /* not found */
+ if (result == 0) {
+ ZVAL_FALSE(*return_value);
+ }
+ /* read "END" */
+ else if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0 || !mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END")-1)) {
+ mmc_server_seterror(mmc, "Malformed END line", 0);
+ result = -1;
+ }
+ else if (flags & MMC_SERIALIZED ) {
+ result = mmc_postprocess_value(return_value, value, value_len TSRMLS_CC);
+ }
+ else {
+ ZVAL_STRINGL(*return_value, value, value_len, 0);
+ }
+ }
+
+ if (result < 0) {
+ mmc_server_failure(mmc TSRMLS_CC);
+ }
+ }
+
+ if (return_flags != NULL) {
+ zval_dtor(return_flags);
+ ZVAL_LONG(return_flags, flags);
+ }
+
+ efree(command);
+ return result;
+}
+/* }}} */
+
+static int mmc_exec_retrieval_cmd_multi(mmc_pool_t *pool, zval *keys, zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */
+{
+ mmc_t *mmc;
+ HashPosition pos;
+ zval **zkey;
+ char *result_key, *value;
+ char key[MMC_KEY_MAX_SIZE];
+ unsigned int key_len;
+
+ int i = 0, j, num_requests, result, result_status, result_key_len, value_len, flags;
+ mmc_queue_t serialized = {0}; /* mmc_queue_t<zval *>, pointers to zvals which need unserializing */
+
+ array_init(*return_value);
+
+ if (return_flags != NULL) {
+ zval_dtor(return_flags);
+ array_init(return_flags);
+ }
+
+ /* until no retrival errors or all servers have failed */
+ do {
+ result_status = num_requests = 0;
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
+
+ /* first pass to build requests for each server */
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&zkey, &pos) == SUCCESS) {
+ if (mmc_prepare_key(*zkey, key, &key_len TSRMLS_CC) == MMC_OK) {
+ /* schedule key if first round or if missing from result */
+ if ((!i || !zend_hash_exists(Z_ARRVAL_PP(return_value), key, key_len)) &&
+ (mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC)) != NULL) {
+ if (!(mmc->outbuf.len)) {
+ smart_str_appendl(&(mmc->outbuf), "get", sizeof("get")-1);
+ pool->requests[num_requests++] = mmc;
+ }
+
+ smart_str_appendl(&(mmc->outbuf), " ", 1);
+ smart_str_appendl(&(mmc->outbuf), key, key_len);
+ MMC_DEBUG(("mmc_exec_retrieval_cmd_multi: scheduled key '%s' for '%s:%d' request length '%d'", key, mmc->host, mmc->port, mmc->outbuf.len));
+ }
+ }
+
+ zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
+ }
+
+ /* second pass to send requests in parallel */
+ for (j=0; j<num_requests; j++) {
+ smart_str_0(&(pool->requests[j]->outbuf));
+
+ if ((result = mmc_sendcmd(pool->requests[j], pool->requests[j]->outbuf.c, pool->requests[j]->outbuf.len TSRMLS_CC)) < 0) {
+ mmc_server_failure(pool->requests[j] TSRMLS_CC);
+ result_status = result;
+ }
+ }
+
+ /* third pass to read responses */
+ for (j=0; j<num_requests; j++) {
+ if (pool->requests[j]->status != MMC_STATUS_FAILED) {
+ for (value = NULL; (result = mmc_read_value(pool->requests[j], &result_key, &result_key_len, &value, &value_len, &flags TSRMLS_CC)) > 0; value = NULL) {
+ if (flags & MMC_SERIALIZED) {
+ zval *result;
+ MAKE_STD_ZVAL(result);
+ ZVAL_STRINGL(result, value, value_len, 0);
+
+ /* don't store duplicate values */
+ if (zend_hash_add(Z_ARRVAL_PP(return_value), result_key, result_key_len + 1, &result, sizeof(result), NULL) == SUCCESS) {
+ mmc_queue_push(&serialized, result);
+ }
+ else {
+ zval_ptr_dtor(&result);
+ }
+ }
+ else {
+ add_assoc_stringl_ex(*return_value, result_key, result_key_len + 1, value, value_len, 0);
+ }
+
+ if (return_flags != NULL) {
+ add_assoc_long_ex(return_flags, result_key, result_key_len + 1, flags);
+ }
+
+ efree(result_key);
+ }
+
+ /* check for server failure */
+ if (result < 0) {
+ mmc_server_failure(pool->requests[j] TSRMLS_CC);
+ result_status = result;
+ }
+ }
+
+ smart_str_free(&(pool->requests[j]->outbuf));
+ }
+ } while (result_status < 0 && MEMCACHE_G(allow_failover) && i++ < MEMCACHE_G(max_failover_attempts));
+
+ /* post-process serialized values */
+ if (serialized.len) {
+ zval *value;
+
+ while ((value = (zval *)mmc_queue_pop(&serialized)) != NULL) {
+ mmc_postprocess_value(&value, Z_STRVAL_P(value), Z_STRLEN_P(value) TSRMLS_CC);
+ }
+
+ mmc_queue_free(&serialized);
+ }
+
+ return result_status;
+}
+/* }}} */
+
+static int mmc_read_value(mmc_t *mmc, char **key, int *key_len, char **value, int *value_len, int *flags TSRMLS_DC) /* {{{ */
+{
+ char *data;
+ int response_len, data_len, i, size;
+
+ /* read "VALUE <key> <flags> <bytes>\r\n" header line */
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
+ MMC_DEBUG(("failed to read the server's response"));
+ return -1;
+ }
+
+ /* reached the end of the data */
+ if (mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END") - 1)) {
+ return 0;
+ }
+
+ if (mmc_parse_response(mmc, mmc->inbuf, response_len, key, key_len, flags, &data_len) < 0) {
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_read_value: data len is %d bytes", data_len));
+
+ /* data_len + \r\n + \0 */
+ data = emalloc(data_len + 3);
+
+ for (i=0; i<data_len+2; i+=size) {
+ if ((size = php_stream_read(mmc->stream, data + i, data_len + 2 - i)) == 0) {
+ mmc_server_seterror(mmc, "Failed reading value response body", 0);
+ if (key) {
+ efree(*key);
+ }
+ efree(data);
+ return -1;
+ }
+ }
+
+ data[data_len] = '\0';
+
+ if ((*flags & MMC_COMPRESSED) && data_len > 0) {
+ char *result_data;
+ unsigned long result_len = 0;
+
+ if (!mmc_uncompress(&result_data, &result_len, data, data_len)) {
+ mmc_server_seterror(mmc, "Failed to uncompress data", 0);
+ if (key) {
+ efree(*key);
+ }
+ efree(data);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "unable to uncompress data");
+ return 0;
+ }
+
+ efree(data);
+ data = result_data;
+ data_len = result_len;
+ }
+
+ *value = data;
+ *value_len = data_len;
+ return 1;
+}
+/* }}} */
+
+int mmc_delete(mmc_t *mmc, const char *key, int key_len, int time TSRMLS_DC) /* {{{ */
+{
+ char *command;
+ int command_len, response_len;
+
+ command_len = spprintf(&command, 0, "delete %s %d", key, time);
+
+ MMC_DEBUG(("mmc_delete: trying to delete '%s'", key));
+
+ if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
+ efree(command);
+ return -1;
+ }
+ efree(command);
+
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0){
+ MMC_DEBUG(("failed to read the server's response"));
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_delete: server's response is '%s'", mmc->inbuf));
+
+ if(mmc_str_left(mmc->inbuf,"DELETED", response_len, sizeof("DELETED") - 1)) {
+ return 1;
+ }
+
+ if(mmc_str_left(mmc->inbuf,"NOT_FOUND", response_len, sizeof("NOT_FOUND") - 1)) {
+ return 0;
+ }
+
+ mmc_server_received_error(mmc, response_len);
+ return -1;
+}
+/* }}} */
+
+static int mmc_flush(mmc_t *mmc, int timestamp TSRMLS_DC) /* {{{ */
+{
+ char *command;
+ int command_len, response_len;
+
+ MMC_DEBUG(("mmc_flush: flushing the cache"));
+
+ if (timestamp) {
+ command_len = spprintf(&command, 0, "flush_all %d", timestamp);
+ }
+ else {
+ command_len = spprintf(&command, 0, "flush_all");
+ }
+
+ if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
+ efree(command);
+ return -1;
+ }
+ efree(command);
+
+ /* get server's response */
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0){
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_flush: server's response is '%s'", mmc->inbuf));
+
+ if(mmc_str_left(mmc->inbuf, "OK", response_len, sizeof("OK") - 1)) {
+ return 1;
+ }
+
+ mmc_server_received_error(mmc, response_len);
+ return -1;
+}
+/* }}} */
+
+/*
+ * STAT 6:chunk_size 64
+ */
+static int mmc_stats_parse_stat(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
+{
+ char *space, *colon, *key;
+ long index = 0;
+
+ /* find space delimiting key and value */
+ if ((space = php_memnstr(start, " ", 1, end)) == NULL) {
+ return 0;
+ }
+
+ /* find colon delimiting subkeys */
+ if ((colon = php_memnstr(start, ":", 1, space - 1)) != NULL) {
+ zval *element, **elem;
+ key = estrndup(start, colon - start);
+
+ /* find existing or create subkey array in result */
+ if ((is_numeric_string(key, colon - start, &index, NULL, 0) &&
+ zend_hash_index_find(Z_ARRVAL_P(result), index, (void **) &elem) != FAILURE) ||
+ zend_hash_find(Z_ARRVAL_P(result), key, colon - start + 1, (void **) &elem) != FAILURE) {
+ element = *elem;
+ }
+ else {
+ MAKE_STD_ZVAL(element);
+ array_init(element);
+ add_assoc_zval_ex(result, key, colon - start + 1, element);
+ }
+
+ efree(key);
+ return mmc_stats_parse_stat(colon + 1, end, element TSRMLS_CC);
+ }
+
+ /* no more subkeys, add value under last subkey */
+ key = estrndup(start, space - start);
+ add_assoc_stringl_ex(result, key, space - start + 1, space + 1, end - space, 1);
+ efree(key);
+
+ return 1;
+}
+/* }}} */
+
+/*
+ * ITEM test_key [3 b; 1157099416 s]
+ */
+static int mmc_stats_parse_item(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
+{
+ char *space, *value, *value_end, *key;
+ zval *element;
+
+ /* find space delimiting key and value */
+ if ((space = php_memnstr(start, " ", 1, end)) == NULL) {
+ return 0;
+ }
+
+ MAKE_STD_ZVAL(element);
+ array_init(element);
+
+ /* parse each contained value */
+ for (value = php_memnstr(space, "[", 1, end); value != NULL && value <= end; value = php_memnstr(value + 1, ";", 1, end)) {
+ do {
+ value++;
+ } while (*value == ' ' && value <= end);
+
+ if (value <= end && (value_end = php_memnstr(value, " ", 1, end)) != NULL && value_end <= end) {
+ add_next_index_stringl(element, value, value_end - value, 1);
+ }
+ }
+
+ /* add parsed values under key */
+ key = estrndup(start, space - start);
+ add_assoc_zval_ex(result, key, space - start + 1, element);
+ efree(key);
+
+ return 1;
+}
+/* }}} */
+
+static int mmc_stats_parse_generic(char *start, char *end, zval *result TSRMLS_DC) /* {{{ */
+{
+ char *space, *key;
+
+ /* "stats maps" returns "\n" delimited lines, other commands uses "\r\n" */
+ if (*end == '\r') {
+ end--;
+ }
+
+ if (start <= end) {
+ if ((space = php_memnstr(start, " ", 1, end)) != NULL) {
+ key = estrndup(start, space - start);
+ add_assoc_stringl_ex(result, key, space - start + 1, space + 1, end - space, 1);
+ efree(key);
+ }
+ else {
+ add_next_index_stringl(result, start, end - start, 1);
+ }
+ }
+
+ return 1;
+}
+/* }}} */
+
+static int mmc_get_stats(mmc_t *mmc, char *type, int slabid, int limit, zval *result TSRMLS_DC) /* {{{ */
+{
+ char *command;
+ int command_len, response_len;
+
+ if (slabid) {
+ command_len = spprintf(&command, 0, "stats %s %d %d", type, slabid, limit);
+ }
+ else if (type) {
+ command_len = spprintf(&command, 0, "stats %s", type);
+ }
+ else {
+ command_len = spprintf(&command, 0, "stats");
+ }
+
+ if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
+ efree(command);
+ return -1;
+ }
+
+ efree(command);
+ array_init(result);
+
+ while ((response_len = mmc_readline(mmc TSRMLS_CC)) >= 0) {
+ if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1)) {
+
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+
+ ZVAL_FALSE(result);
+ return 0;
+ }
+ else if (mmc_str_left(mmc->inbuf, "RESET", response_len, sizeof("RESET") - 1)) {
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+
+ ZVAL_TRUE(result);
+ return 1;
+ }
+ else if (mmc_str_left(mmc->inbuf, "ITEM ", response_len, sizeof("ITEM ") - 1)) {
+ if (!mmc_stats_parse_item(mmc->inbuf + (sizeof("ITEM ") - 1), mmc->inbuf + response_len - sizeof("\r\n"), result TSRMLS_CC)) {
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+ return -1;
+ }
+ }
+ else if (mmc_str_left(mmc->inbuf, "STAT ", response_len, sizeof("STAT ") - 1)) {
+ if (!mmc_stats_parse_stat(mmc->inbuf + (sizeof("STAT ") - 1), mmc->inbuf + response_len - sizeof("\r\n"), result TSRMLS_CC)) {
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+ return -1;
+ }
+ }
+ else if (mmc_str_left(mmc->inbuf, "END", response_len, sizeof("END") - 1)) {
+ break;
+ }
+ else if (!mmc_stats_parse_generic(mmc->inbuf, mmc->inbuf + response_len - sizeof("\n"), result TSRMLS_CC)) {
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+ return -1;
+ }
+ }
+
+ if (response_len < 0) {
+ zend_hash_destroy(Z_ARRVAL_P(result));
+ FREE_HASHTABLE(Z_ARRVAL_P(result));
+ return -1;
+ }
+
+ return 1;
+}
+/* }}} */
+
+static int mmc_incr_decr(mmc_t *mmc, int cmd, char *key, int key_len, int value, long *number TSRMLS_DC) /* {{{ */
+{
+ char *command;
+ int command_len, response_len;
+
+ if (cmd > 0) {
+ command_len = spprintf(&command, 0, "incr %s %d", key, value);
+ }
+ else {
+ command_len = spprintf(&command, 0, "decr %s %d", key, value);
+ }
+
+ if (mmc_sendcmd(mmc, command, command_len TSRMLS_CC) < 0) {
+ efree(command);
+ return -1;
+ }
+ efree(command);
+
+ if ((response_len = mmc_readline(mmc TSRMLS_CC)) < 0) {
+ MMC_DEBUG(("failed to read the server's response"));
+ return -1;
+ }
+
+ MMC_DEBUG(("mmc_incr_decr: server's answer is: '%s'", mmc->inbuf));
+ if (mmc_str_left(mmc->inbuf, "NOT_FOUND", response_len, sizeof("NOT_FOUND") - 1)) {
+ MMC_DEBUG(("failed to %sement variable - item with such key not found", cmd > 0 ? "incr" : "decr"));
+ return 0;
+ }
+ else if (mmc_str_left(mmc->inbuf, "ERROR", response_len, sizeof("ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "CLIENT_ERROR", response_len, sizeof("CLIENT_ERROR") - 1) ||
+ mmc_str_left(mmc->inbuf, "SERVER_ERROR", response_len, sizeof("SERVER_ERROR") - 1)) {
+ mmc_server_received_error(mmc, response_len);
+ return -1;
+ }
+
+ *number = (long)atol(mmc->inbuf);
+ return 1;
+}
+/* }}} */
+
+static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, char *command, int command_len) /* {{{ */
+{
+ mmc_pool_t *pool;
+ zval *value, *mmc_object = getThis();
+
+ int result, key_len;
+ char *key;
+ long flags = 0, expire = 0;
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ php_serialize_data_t value_hash;
+ smart_str buf = {0};
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Osz|ll", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &value, &flags, &expire) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, &value, &flags, &expire) == FAILURE) {
+ return;
+ }
+ }
+
+ if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ RETURN_FALSE;
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
+ RETURN_FALSE;
+ }
+
+ switch (Z_TYPE_P(value)) {
+ case IS_STRING:
+ result = mmc_pool_store(
+ pool, command, command_len, key_tmp, key_tmp_len, flags, expire,
+ Z_STRVAL_P(value), Z_STRLEN_P(value) TSRMLS_CC);
+ break;
+
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL: {
+ zval value_copy;
+
+ /* FIXME: we should be using 'Z' instead of this, but unfortunately it's PHP5-only */
+ value_copy = *value;
+ zval_copy_ctor(&value_copy);
+ convert_to_string(&value_copy);
+
+ result = mmc_pool_store(
+ pool, command, command_len, key_tmp, key_tmp_len, flags, expire,
+ Z_STRVAL(value_copy), Z_STRLEN(value_copy) TSRMLS_CC);
+
+ zval_dtor(&value_copy);
+ break;
+ }
+
+ default: {
+ zval value_copy, *value_copy_ptr;
+
+ /* FIXME: we should be using 'Z' instead of this, but unfortunately it's PHP5-only */
+ value_copy = *value;
+ zval_copy_ctor(&value_copy);
+ value_copy_ptr = &value_copy;
+
+ PHP_VAR_SERIALIZE_INIT(value_hash);
+ php_var_serialize(&buf, &value_copy_ptr, &value_hash TSRMLS_CC);
+ PHP_VAR_SERIALIZE_DESTROY(value_hash);
+
+ if (!buf.c) {
+ /* something went really wrong */
+ zval_dtor(&value_copy);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to serialize value");
+ RETURN_FALSE;
+ }
+
+ flags |= MMC_SERIALIZED;
+ zval_dtor(&value_copy);
+
+ result = mmc_pool_store(
+ pool, command, command_len, key_tmp, key_tmp_len, flags, expire,
+ buf.c, buf.len TSRMLS_CC);
+ }
+ }
+
+ if (flags & MMC_SERIALIZED) {
+ smart_str_free(&buf);
+ }
+
+ if (result > 0) {
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+static void php_mmc_incr_decr(INTERNAL_FUNCTION_PARAMETERS, int cmd) /* {{{ */
+{
+ mmc_t *mmc;
+ mmc_pool_t *pool;
+ int result = -1, key_len;
+ long value = 1, number;
+ char *key;
+ zval *mmc_object = getThis();
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &value) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &value) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
+ RETURN_FALSE;
+ }
+
+ if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ RETURN_FALSE;
+ }
+
+ while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
+ if ((result = mmc_incr_decr(mmc, cmd, key_tmp, key_tmp_len, value, &number TSRMLS_CC)) < 0) {
+ mmc_server_failure(mmc TSRMLS_CC);
+ }
+ }
+
+ if (result > 0) {
+ RETURN_LONG(number);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+static void php_mmc_connect (INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
+{
+ zval **connection, *mmc_object = getThis();
+ mmc_t *mmc = NULL;
+ mmc_pool_t *pool;
+ int resource_type, host_len, errnum = 0, list_id;
+ char *host, *error_string = NULL;
+ long port = MEMCACHE_G(default_port), timeout = MMC_DEFAULT_TIMEOUT, timeoutms = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lll", &host, &host_len, &port, &timeout, &timeoutms) == FAILURE) {
+ return;
+ }
+
+ if (timeoutms < 1) {
+ timeoutms = MEMCACHE_G(default_timeout_ms);
+ }
+
+ /* initialize and connect server struct */
+ if (persistent) {
+ mmc = mmc_find_persistent(host, host_len, port, timeout, MMC_DEFAULT_RETRY TSRMLS_CC);
+ }
+ else {
+ MMC_DEBUG(("php_mmc_connect: creating regular connection"));
+ mmc = mmc_server_new(host, host_len, port, 0, timeout, MMC_DEFAULT_RETRY TSRMLS_CC);
+ }
+
+ mmc->timeout = timeout;
+ mmc->connect_timeoutms = timeoutms;
+
+ if (!mmc_open(mmc, 1, &error_string, &errnum TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't connect to %s:%ld, %s (%d)", host, port, error_string ? error_string : "Unknown error", errnum);
+ if (!persistent) {
+ mmc_server_free(mmc TSRMLS_CC);
+ }
+ if (error_string) {
+ efree(error_string);
+ }
+ RETURN_FALSE;
+ }
+
+ /* initialize pool and object if need be */
+ if (!mmc_object) {
+ pool = mmc_pool_new(TSRMLS_C);
+ mmc_pool_add(pool, mmc, 1);
+
+ object_init_ex(return_value, memcache_class_entry_ptr);
+ list_id = zend_list_insert(pool, le_memcache_pool);
+ add_property_resource(return_value, "connection", list_id);
+ }
+ else if (zend_hash_find(Z_OBJPROP_P(mmc_object), "connection", sizeof("connection"), (void **) &connection) != FAILURE) {
+ pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
+ if (!pool || resource_type != le_memcache_pool) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown connection identifier");
+ RETURN_FALSE;
+ }
+
+ mmc_pool_add(pool, mmc, 1);
+ RETURN_TRUE;
+ }
+ else {
+ pool = mmc_pool_new(TSRMLS_C);
+ mmc_pool_add(pool, mmc, 1);
+
+ list_id = zend_list_insert(pool, le_memcache_pool);
+ add_property_resource(mmc_object, "connection", list_id);
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* ----------------
+ module functions
+ ---------------- */
+
+/* {{{ proto object memcache_connect( string host [, int port [, int timeout ] ])
+ Connects to server and returns a Memcache object */
+PHP_FUNCTION(memcache_connect)
+{
+ php_mmc_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto object memcache_pconnect( string host [, int port [, int timeout ] ])
+ Connects to server and returns a Memcache object */
+PHP_FUNCTION(memcache_pconnect)
+{
+ php_mmc_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto bool memcache_add_server( string host [, int port [, bool persistent [, int weight [, int timeout [, int retry_interval [, bool status [, callback failure_callback ] ] ] ] ] ] ])
+ Adds a connection to the pool. The order in which this function is called is significant */
+PHP_FUNCTION(memcache_add_server)
+{
+ zval **connection, *mmc_object = getThis(), *failure_callback = NULL;
+ mmc_pool_t *pool;
+ mmc_t *mmc;
+ long port = MEMCACHE_G(default_port), weight = 1, timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY, timeoutms = 0;
+ zend_bool persistent = 1, status = 1;
+ int resource_type, host_len, list_id;
+ char *host;
+
+ if (mmc_object) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lblllbzl", &host, &host_len, &port, &persistent, &weight, &timeout, &retry_interval, &status, &failure_callback, &timeoutms) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lblllbzl", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port, &persistent, &weight, &timeout, &retry_interval, &status, &failure_callback, &timeoutms) == FAILURE) {
+ return;
+ }
+ }
+
+ if (timeoutms < 1) {
+ timeoutms = MEMCACHE_G(default_timeout_ms);
+ }
+
+ if (weight < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "weight must be a positive integer");
+ RETURN_FALSE;
+ }
+
+ if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
+ if (!IS_CALLABLE(failure_callback, 0, NULL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid failure callback");
+ RETURN_FALSE;
+ }
+ }
+
+ /* lazy initialization of server struct */
+ if (persistent) {
+ mmc = mmc_find_persistent(host, host_len, port, timeout, retry_interval TSRMLS_CC);
+ }
+ else {
+ MMC_DEBUG(("memcache_add_server: initializing regular struct"));
+ mmc = mmc_server_new(host, host_len, port, 0, timeout, retry_interval TSRMLS_CC);
+ }
+
+ mmc->connect_timeoutms = timeoutms;
+
+ /* add server in failed mode */
+ if (!status) {
+ mmc->status = MMC_STATUS_FAILED;
+ }
+
+ if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
+ mmc->failure_callback = failure_callback;
+ mmc_server_callback_ctor(&mmc->failure_callback TSRMLS_CC);
+ }
+
+ /* initialize pool if need be */
+ if (zend_hash_find(Z_OBJPROP_P(mmc_object), "connection", sizeof("connection"), (void **) &connection) == FAILURE) {
+ pool = mmc_pool_new(TSRMLS_C);
+ list_id = zend_list_insert(pool, le_memcache_pool);
+ add_property_resource(mmc_object, "connection", list_id);
+ }
+ else {
+ pool = (mmc_pool_t *) zend_list_find(Z_LVAL_PP(connection), &resource_type);
+ if (!pool || resource_type != le_memcache_pool) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to extract 'connection' variable from object");
+ RETURN_FALSE;
+ }
+ }
+
+ mmc_pool_add(pool, mmc, weight);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool memcache_set_server_params( string host [, int port [, int timeout [, int retry_interval [, bool status [, callback failure_callback ] ] ] ] ])
+ Changes server parameters at runtime */
+PHP_FUNCTION(memcache_set_server_params)
+{
+ zval *mmc_object = getThis(), *failure_callback = NULL;
+ mmc_pool_t *pool;
+ mmc_t *mmc = NULL;
+ long port = MEMCACHE_G(default_port), timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY;
+ zend_bool status = 1;
+ int host_len, i;
+ char *host;
+
+ if (mmc_object) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lllbz", &host, &host_len, &port, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lllbz", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port, &timeout, &retry_interval, &status, &failure_callback) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (!strcmp(pool->servers[i]->host, host) && pool->servers[i]->port == port) {
+ mmc = pool->servers[i];
+ break;
+ }
+ }
+
+ if (!mmc) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server not found in pool");
+ RETURN_FALSE;
+ }
+
+ if (failure_callback != NULL && Z_TYPE_P(failure_callback) != IS_NULL) {
+ if (!IS_CALLABLE(failure_callback, 0, NULL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid failure callback");
+ RETURN_FALSE;
+ }
+ }
+
+ mmc->timeout = timeout;
+ mmc->retry_interval = retry_interval;
+
+ if (!status) {
+ mmc->status = MMC_STATUS_FAILED;
+ }
+ else if (mmc->status == MMC_STATUS_FAILED) {
+ mmc->status = MMC_STATUS_DISCONNECTED;
+ }
+
+ if (failure_callback != NULL) {
+ if (mmc->failure_callback != NULL) {
+ mmc_server_callback_dtor(&mmc->failure_callback TSRMLS_CC);
+ }
+
+ if (Z_TYPE_P(failure_callback) != IS_NULL) {
+ mmc->failure_callback = failure_callback;
+ mmc_server_callback_ctor(&mmc->failure_callback TSRMLS_CC);
+ }
+ else {
+ mmc->failure_callback = NULL;
+ }
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int memcache_get_server_status( string host [, int port ])
+ Returns server status (0 if server is failed, otherwise non-zero) */
+PHP_FUNCTION(memcache_get_server_status)
+{
+ zval *mmc_object = getThis();
+ mmc_pool_t *pool;
+ mmc_t *mmc = NULL;
+ long port = MEMCACHE_G(default_port);
+ int host_len, i;
+ char *host;
+
+ if (mmc_object) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &host, &host_len, &port) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &host, &host_len, &port) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (!strcmp(pool->servers[i]->host, host) && pool->servers[i]->port == port) {
+ mmc = pool->servers[i];
+ break;
+ }
+ }
+
+ if (!mmc) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server not found in pool");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(mmc->status);
+}
+/* }}} */
+
+mmc_t *mmc_find_persistent(char *host, int host_len, int port, int timeout, int retry_interval TSRMLS_DC) /* {{{ */
+{
+ mmc_t *mmc;
+ zend_rsrc_list_entry *le;
+ char *hash_key;
+ int hash_key_len;
+
+ MMC_DEBUG(("mmc_find_persistent: seeking for persistent connection"));
+ hash_key_len = spprintf(&hash_key, 0, "mmc_connect___%s:%d", host, port);
+
+ if (zend_hash_find(&EG(persistent_list), hash_key, hash_key_len+1, (void **) &le) == FAILURE) {
+ zend_rsrc_list_entry new_le;
+ MMC_DEBUG(("mmc_find_persistent: connection wasn't found in the hash"));
+
+ mmc = mmc_server_new(host, host_len, port, 1, timeout, retry_interval TSRMLS_CC);
+ new_le.type = le_pmemcache;
+ new_le.ptr = mmc;
+
+ /* register new persistent connection */
+ if (zend_hash_update(&EG(persistent_list), hash_key, hash_key_len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
+ mmc_server_free(mmc TSRMLS_CC);
+ mmc = NULL;
+ } else {
+ zend_list_insert(mmc, le_pmemcache);
+ }
+ }
+ else if (le->type != le_pmemcache || le->ptr == NULL) {
+ zend_rsrc_list_entry new_le;
+ MMC_DEBUG(("mmc_find_persistent: something was wrong, reconnecting.."));
+ zend_hash_del(&EG(persistent_list), hash_key, hash_key_len+1);
+
+ mmc = mmc_server_new(host, host_len, port, 1, timeout, retry_interval TSRMLS_CC);
+ new_le.type = le_pmemcache;
+ new_le.ptr = mmc;
+
+ /* register new persistent connection */
+ if (zend_hash_update(&EG(persistent_list), hash_key, hash_key_len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
+ mmc_server_free(mmc TSRMLS_CC);
+ mmc = NULL;
+ }
+ else {
+ zend_list_insert(mmc, le_pmemcache);
+ }
+ }
+ else {
+ MMC_DEBUG(("mmc_find_persistent: connection found in the hash"));
+ mmc = (mmc_t *)le->ptr;
+ mmc->timeout = timeout;
+ mmc->retry_interval = retry_interval;
+
+ /* attempt to reconnect this node before failover in case connection has gone away */
+ if (mmc->status == MMC_STATUS_CONNECTED) {
+ mmc->status = MMC_STATUS_UNKNOWN;
+ }
+ }
+
+ efree(hash_key);
+ return mmc;
+}
+/* }}} */
+
+/* {{{ proto string memcache_get_version( object memcache )
+ Returns server's version */
+PHP_FUNCTION(memcache_get_version)
+{
+ mmc_pool_t *pool;
+ char *version;
+ int i;
+ zval *mmc_object = getThis();
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &mmc_object, memcache_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
+ if ((version = mmc_get_version(pool->servers[i] TSRMLS_CC)) != NULL) {
+ RETURN_STRING(version, 0);
+ }
+ else {
+ mmc_server_failure(pool->servers[i] TSRMLS_CC);
+ }
+ }
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool memcache_add( object memcache, string key, mixed var [, int flag [, int expire ] ] )
+ Adds new item. Item with such key should not exist. */
+PHP_FUNCTION(memcache_add)
+{
+ php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "add", sizeof("add") - 1);
+}
+/* }}} */
+
+/* {{{ proto bool memcache_set( object memcache, string key, mixed var [, int flag [, int expire ] ] )
+ Sets the value of an item. Item may exist or not */
+PHP_FUNCTION(memcache_set)
+{
+ php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "set", sizeof("set") - 1);
+}
+/* }}} */
+
+/* {{{ proto bool memcache_replace( object memcache, string key, mixed var [, int flag [, int expire ] ] )
+ Replaces existing item. Returns false if item doesn't exist */
+PHP_FUNCTION(memcache_replace)
+{
+ php_mmc_store(INTERNAL_FUNCTION_PARAM_PASSTHRU, "replace", sizeof("replace") - 1);
+}
+/* }}} */
+
+/* {{{ proto mixed memcache_get( object memcache, mixed key [, mixed &flags ] )
+ Returns value of existing item or false */
+PHP_FUNCTION(memcache_get)
+{
+ mmc_pool_t *pool;
+ zval *zkey, *mmc_object = getThis(), *flags = NULL;
+ char key[MMC_KEY_MAX_SIZE];
+ unsigned int key_len;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|z", &mmc_object, memcache_class_entry_ptr, &zkey, &flags) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &zkey, &flags) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
+ RETURN_FALSE;
+ }
+
+ if (Z_TYPE_P(zkey) != IS_ARRAY) {
+ if (mmc_prepare_key(zkey, key, &key_len TSRMLS_CC) == MMC_OK) {
+ if (mmc_exec_retrieval_cmd(pool, key, key_len, &return_value, flags TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETVAL_FALSE;
+ }
+ }
+ else {
+ RETVAL_FALSE;
+ }
+ } else if (zend_hash_num_elements(Z_ARRVAL_P(zkey))){
+ if (mmc_exec_retrieval_cmd_multi(pool, zkey, &return_value, flags TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETVAL_FALSE;
+ }
+ } else {
+ RETVAL_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool memcache_delete( object memcache, string key [, int expire ])
+ Deletes existing item */
+PHP_FUNCTION(memcache_delete)
+{
+ mmc_t *mmc;
+ mmc_pool_t *pool;
+ int result = -1, key_len;
+ zval *mmc_object = getThis();
+ char *key;
+ long time = 0;
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &time) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &time) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) {
+ RETURN_FALSE;
+ }
+
+ if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ RETURN_FALSE;
+ }
+
+ while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
+ if ((result = mmc_delete(mmc, key_tmp, key_tmp_len, time TSRMLS_CC)) < 0) {
+ mmc_server_failure(mmc TSRMLS_CC);
+ }
+ }
+
+ if (result > 0) {
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool memcache_debug( bool onoff )
+ Turns on/off internal debugging */
+PHP_FUNCTION(memcache_debug)
+{
+#if ZEND_DEBUG
+ zend_bool onoff;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &onoff) == FAILURE) {
+ return;
+ }
+
+ MEMCACHE_G(debug_mode) = onoff ? 1 : 0;
+
+ RETURN_TRUE;
+#else
+ RETURN_FALSE;
+#endif
+
+}
+/* }}} */
+
+/* {{{ proto array memcache_get_stats( object memcache [, string type [, int slabid [, int limit ] ] ])
+ Returns server's statistics */
+PHP_FUNCTION(memcache_get_stats)
+{
+ mmc_pool_t *pool;
+ int i, failures = 0;
+ zval *mmc_object = getThis();
+
+ char *type = NULL;
+ int type_len = 0;
+ long slabid = 0, limit = MMC_DEFAULT_CACHEDUMP_LIMIT;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|sll", &mmc_object, memcache_class_entry_ptr, &type, &type_len, &slabid, &limit) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sll", &type, &type_len, &slabid, &limit) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
+ if (mmc_get_stats(pool->servers[i], type, slabid, limit, return_value TSRMLS_CC) < 0) {
+ mmc_server_failure(pool->servers[i] TSRMLS_CC);
+ failures++;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ failures++;
+ }
+ }
+
+ if (failures >= pool->num_servers) {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto array memcache_get_extended_stats( object memcache [, string type [, int slabid [, int limit ] ] ])
+ Returns statistics for each server in the pool */
+PHP_FUNCTION(memcache_get_extended_stats)
+{
+ mmc_pool_t *pool;
+ char *hostname;
+ int i, hostname_len;
+ zval *mmc_object = getThis(), *stats;
+
+ char *type = NULL;
+ int type_len = 0;
+ long slabid = 0, limit = MMC_DEFAULT_CACHEDUMP_LIMIT;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|sll", &mmc_object, memcache_class_entry_ptr, &type, &type_len, &slabid, &limit) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sll", &type, &type_len, &slabid, &limit) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i=0; i<pool->num_servers; i++) {
+ MAKE_STD_ZVAL(stats);
+
+ hostname_len = spprintf(&hostname, 0, "%s:%d", pool->servers[i]->host, pool->servers[i]->port);
+
+ if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
+ if (mmc_get_stats(pool->servers[i], type, slabid, limit, stats TSRMLS_CC) < 0) {
+ mmc_server_failure(pool->servers[i] TSRMLS_CC);
+ ZVAL_FALSE(stats);
+ }
+ }
+ else {
+ ZVAL_FALSE(stats);
+ }
+
+ add_assoc_zval_ex(return_value, hostname, hostname_len + 1, stats);
+ efree(hostname);
+ }
+}
+/* }}} */
+
+/* {{{ proto array memcache_set_compress_threshold( object memcache, int threshold [, float min_savings ] )
+ Set automatic compress threshold */
+PHP_FUNCTION(memcache_set_compress_threshold)
+{
+ mmc_pool_t *pool;
+ zval *mmc_object = getThis();
+ long threshold;
+ double min_savings = MMC_DEFAULT_SAVINGS;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|d", &mmc_object, memcache_class_entry_ptr, &threshold, &min_savings) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|d", &threshold, &min_savings) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (threshold < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "threshold must be a positive integer");
+ RETURN_FALSE;
+ }
+ pool->compress_threshold = threshold;
+
+ if (min_savings != MMC_DEFAULT_SAVINGS) {
+ if (min_savings < 0 || min_savings > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "min_savings must be a float in the 0..1 range");
+ RETURN_FALSE;
+ }
+ pool->min_compress_savings = min_savings;
+ }
+ else {
+ pool->min_compress_savings = MMC_DEFAULT_SAVINGS;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int memcache_increment( object memcache, string key [, int value ] )
+ Increments existing variable */
+PHP_FUNCTION(memcache_increment)
+{
+ php_mmc_incr_decr(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto int memcache_decrement( object memcache, string key [, int value ] )
+ Decrements existing variable */
+PHP_FUNCTION(memcache_decrement)
+{
+ php_mmc_incr_decr(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto bool memcache_close( object memcache )
+ Closes connection to memcached */
+PHP_FUNCTION(memcache_close)
+{
+ mmc_pool_t *pool;
+ zval *mmc_object = getThis();
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &mmc_object, memcache_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (!mmc_pool_close(pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool memcache_flush( object memcache [, int timestamp ] )
+ Flushes cache, optionally at the specified time */
+PHP_FUNCTION(memcache_flush)
+{
+ mmc_pool_t *pool;
+ int i, failures = 0;
+ zval *mmc_object = getThis();
+ long timestamp = 0;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &mmc_object, memcache_class_entry_ptr, ×tamp) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", ×tamp) == FAILURE) {
+ return;
+ }
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<pool->num_servers; i++) {
+ if (mmc_open(pool->servers[i], 1, NULL, NULL TSRMLS_CC)) {
+ if (mmc_flush(pool->servers[i], timestamp TSRMLS_CC) < 0) {
+ mmc_server_failure(pool->servers[i] TSRMLS_CC);
+ failures++;
+ }
+ }
+ else {
+ failures++;
+ }
+ }
+
+ if (failures && failures >= pool->num_servers) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool memcache_setoptimeout( object memcache , int timeoutms )
+ Set the timeout, in milliseconds, for subsequent operations on all open connections */
+PHP_FUNCTION(memcache_setoptimeout)
+{
+ mmc_pool_t *pool;
+ mmc_t *mmc;
+ int i;
+ zval *mmc_object = getThis();
+ long timeoutms = 0;
+
+ if (mmc_object == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &mmc_object, memcache_class_entry_ptr, &timeoutms) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &timeoutms) == FAILURE) {
+ return;
+ }
+ }
+
+ if (timeoutms < 1) {
+ timeoutms = MEMCACHE_G(default_timeout_ms);
+ }
+
+ if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < pool->num_servers; i++) {
+ mmc = pool->servers[i];
+ mmc->timeoutms = timeoutms;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/memcache.dsp
^
|
(renamed from memcache-2.2.3/memcache.dsp)
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/memcache-2.2.6/memcache.dsp
^
|
(renamed from memcache-2.2.3/memcache.dsp)
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache.php
^
|
@@ -0,0 +1,881 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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. |
+ +----------------------------------------------------------------------+
+ | Author: Harun Yayli <harunyayli at gmail.com> |
+ +----------------------------------------------------------------------+
+*/
+
+$VERSION='$Id: memcache.php 303962 2010-10-03 15:48:23Z hradtke $';
+
+define('ADMIN_USERNAME','memcache'); // Admin Username
+define('ADMIN_PASSWORD','password'); // Admin Password
+define('DATE_FORMAT','Y/m/d H:i:s');
+define('GRAPH_SIZE',200);
+define('MAX_ITEM_DUMP',50);
+
+$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array
+$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
+
+
+////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
+
+///////////////// Password protect ////////////////////////////////////////////////////////////////
+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=\"Memcache Login\"");
+ Header("HTTP/1.0 401 Unauthorized");
+
+ echo <<<EOB
+ <html><body>
+ <h1>Rejected!</h1>
+ <big>Wrong Username or Password!</big>
+ </body></html>
+EOB;
+ exit;
+}
+
+///////////MEMCACHE FUNCTIONS /////////////////////////////////////////////////////////////////////
+
+function sendMemcacheCommands($command){
+ global $MEMCACHE_SERVERS;
+ $result = array();
+
+ foreach($MEMCACHE_SERVERS as $server){
+ $strs = explode(':',$server);
+ $host = $strs[0];
+ $port = $strs[1];
+ $result[$server] = sendMemcacheCommand($host,$port,$command);
+ }
+ return $result;
+}
+function sendMemcacheCommand($server,$port,$command){
+
+ $s = @fsockopen($server,$port);
+ if (!$s){
+ die("Cant connect to:".$server.':'.$port);
+ }
+
+ fwrite($s, $command."\r\n");
+
+ $buf='';
+ while ((!feof($s))) {
+ $buf .= fgets($s, 256);
+ if (strpos($buf,"END\r\n")!==false){ // stat says end
+ break;
+ }
+ if (strpos($buf,"DELETED\r\n")!==false || strpos($buf,"NOT_FOUND\r\n")!==false){ // delete says these
+ break;
+ }
+ if (strpos($buf,"OK\r\n")!==false){ // flush_all says ok
+ break;
+ }
+ }
+ fclose($s);
+ return parseMemcacheResults($buf);
+}
+function parseMemcacheResults($str){
+
+ $res = array();
+ $lines = explode("\r\n",$str);
+ $cnt = count($lines);
+ for($i=0; $i< $cnt; $i++){
+ $line = $lines[$i];
+ $l = explode(' ',$line,3);
+ if (count($l)==3){
+ $res[$l[0]][$l[1]]=$l[2];
+ if ($l[0]=='VALUE'){ // next line is the value
+ $res[$l[0]][$l[1]] = array();
+ list ($flag,$size)=explode(' ',$l[2]);
+ $res[$l[0]][$l[1]]['stat']=array('flag'=>$flag,'size'=>$size);
+ $res[$l[0]][$l[1]]['value']=$lines[++$i];
+ }
+ }elseif($line=='DELETED' || $line=='NOT_FOUND' || $line=='OK'){
+ return $line;
+ }
+ }
+ return $res;
+
+}
+
+function dumpCacheSlab($server,$slabId,$limit){
+ list($host,$port) = explode(':',$server);
+ $resp = sendMemcacheCommand($host,$port,'stats cachedump '.$slabId.' '.$limit);
+
+ return $resp;
+
+}
+
+function flushServer($server){
+ list($host,$port) = explode(':',$server);
+ $resp = sendMemcacheCommand($host,$port,'flush_all');
+ return $resp;
+}
+function getCacheItems(){
+ $items = sendMemcacheCommands('stats items');
+ $serverItems = array();
+ $totalItems = array();
+ foreach ($items as $server=>$itemlist){
+ $serverItems[$server] = array();
+ $totalItems[$server]=0;
+ if (!isset($itemlist['STAT'])){
+ continue;
+ }
+
+ $iteminfo = $itemlist['STAT'];
+
+ foreach($iteminfo as $keyinfo=>$value){
+ if (preg_match('/items\:(\d+?)\:(.+?)$/',$keyinfo,$matches)){
+ $serverItems[$server][$matches[1]][$matches[2]] = $value;
+ if ($matches[2]=='number'){
+ $totalItems[$server] +=$value;
+ }
+ }
+ }
+ }
+ return array('items'=>$serverItems,'counts'=>$totalItems);
+}
+function getMemcacheStats($total=true){
+ $resp = sendMemcacheCommands('stats');
+ if ($total){
+ $res = array();
+ foreach($resp as $server=>$r){
+ foreach($r['STAT'] as $key=>$row){
+ if (!isset($res[$key])){
+ $res[$key]=null;
+ }
+ switch ($key){
+ case 'pid':
+ $res['pid'][$server]=$row;
+ break;
+ case 'uptime':
+ $res['uptime'][$server]=$row;
+ break;
+ case 'time':
+ $res['time'][$server]=$row;
+ break;
+ case 'version':
+ $res['version'][$server]=$row;
+ break;
+ case 'pointer_size':
+ $res['pointer_size'][$server]=$row;
+ break;
+ case 'rusage_user':
+ $res['rusage_user'][$server]=$row;
+ break;
+ case 'rusage_system':
+ $res['rusage_system'][$server]=$row;
+ break;
+ case 'curr_items':
+ $res['curr_items']+=$row;
+ break;
+ case 'total_items':
+ $res['total_items']+=$row;
+ break;
+ case 'bytes':
+ $res['bytes']+=$row;
+ break;
+ case 'curr_connections':
+ $res['curr_connections']+=$row;
+ break;
+ case 'total_connections':
+ $res['total_connections']+=$row;
+ break;
+ case 'connection_structures':
+ $res['connection_structures']+=$row;
+ break;
+ case 'cmd_get':
+ $res['cmd_get']+=$row;
+ break;
+ case 'cmd_set':
+ $res['cmd_set']+=$row;
+ break;
+ case 'get_hits':
+ $res['get_hits']+=$row;
+ break;
+ case 'get_misses':
+ $res['get_misses']+=$row;
+ break;
+ case 'evictions':
+ $res['evictions']+=$row;
+ break;
+ case 'bytes_read':
+ $res['bytes_read']+=$row;
+ break;
+ case 'bytes_written':
+ $res['bytes_written']+=$row;
+ break;
+ case 'limit_maxbytes':
+ $res['limit_maxbytes']+=$row;
+ break;
+ case 'threads':
+ $res['rusage_system'][$server]=$row;
+ break;
+ }
+ }
+ }
+ return $res;
+ }
+ return $resp;
+}
+
+//////////////////////////////////////////////////////
+
+//
+// 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');
+}
+
+function bsize($s) {
+ foreach (array('','K','M','G') as $i => $k) {
+ if ($s < 1024) break;
+ $s/=1024;
+ }
+ return sprintf("%5.1f %sBytes",$s,$k);
+}
+
+// create menu entry
+function menu_entry($ob,$title) {
+ global $PHP_SELF;
+ if ($ob==$_GET['op']){
+ return "<li><a class=\"child_active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>";
+ }
+ return "<li><a class=\"active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>";
+}
+
+function getHeader(){
+ $header = <<<EOB
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head><title>MEMCACHE INFO</title>
+<style type="text/css"><!--
+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; }
+
+h1.memcache { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
+* html h1.memcache { margin-bottom:-7px; }
+h1.memcache a:hover { text-decoration:none; color:rgb(90,90,90); }
+h1.memcache 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;
+ display:block;
+ width:130px;
+ }
+h1.memcache span.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
+h1.memcache span.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
+h1.memcache div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
+hr.memcache {
+ 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;
+ }
+.td-0 a , .td-n a, .tr-0 a , tr-1 a {
+ text-decoration:underline;
+}
+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="memcache">
+ <span class="logo"><a href="http://pecl.php.net/package/memcache">memcache</a></span>
+ <span class="nameinfo">memcache.php by <a href="http://livebookmark.net">Harun Yayli</a></span>
+ </h1>
+ <hr class="memcache">
+</div>
+<div class=content>
+EOB;
+
+ return $header;
+}
+function getFooter(){
+ global $VERSION;
+ $footer = '</div><!-- Based on apc.php '.$VERSION.'--></body>
+</html>
+';
+
+ return $footer;
+
+}
+function getMenu(){
+ global $PHP_SELF;
+echo "<ol class=menu>";
+if ($_GET['op']!=4){
+echo <<<EOB
+ <li><a href="$PHP_SELF&op={$_GET['op']}">Refresh Data</a></li>
+EOB;
+}
+else {
+echo <<<EOB
+ <li><a href="$PHP_SELF&op=2}">Back</a></li>
+EOB;
+}
+echo
+ menu_entry(1,'View Host Stats'),
+ menu_entry(2,'Variables');
+
+echo <<<EOB
+ </ol>
+ <br/>
+EOB;
+}
+
+// TODO, AUTH
+
+$_GET['op'] = !isset($_GET['op'])? '1':$_GET['op'];
+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : '';
+
+$PHP_SELF=$PHP_SELF.'?';
+$time = time();
+// sanitize _GET
+
+foreach($_GET as $key=>$g){
+ $_GET[$key]=htmlentities($g);
+}
+
+
+// singleout
+// when singleout is set, it only gives details for that server.
+if (isset($_GET['singleout']) && $_GET['singleout']>=0 && $_GET['singleout'] <count($MEMCACHE_SERVERS)){
+ $MEMCACHE_SERVERS = array($MEMCACHE_SERVERS[$_GET['singleout']]);
+}
+
+// display images
+if (isset($_GET['IMG'])){
+ $memcacheStats = getMemcacheStats();
+ $memcacheStatsSingle = getMemcacheStats(false);
+
+ if (!graphics_avail()) {
+ exit(0);
+ }
+
+ 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);
+ }
+ }
+ }
+
+
+ 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);
+ }
+ }
+ }
+ $size = GRAPH_SIZE; // image size
+ $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 ($_GET['IMG']){
+ case 1: // pie chart
+ $tsize=$memcacheStats['limit_maxbytes'];
+ $avail=$tsize-$memcacheStats['bytes'];
+ $x=$y=$size/2;
+ $angle_from = 0;
+ $fuzz = 0.000001;
+
+ foreach($memcacheStatsSingle as $serv=>$mcs) {
+ $free = $mcs['STAT']['limit_maxbytes']-$mcs['STAT']['bytes'];
+ $used = $mcs['STAT']['bytes'];
+
+
+ if ($free>0){
+ // draw free
+ $angle_to = ($free*360)/$tsize;
+ $perc =sprintf("%.2f%%", ($free *100) / $tsize) ;
+
+ fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_green,$perc);
+ $angle_from = $angle_from + $angle_to ;
+ }
+ if ($used>0){
+ // draw used
+ $angle_to = ($used*360)/$tsize;
+ $perc =sprintf("%.2f%%", ($used *100) / $tsize) ;
+ fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_red, '('.$perc.')' );
+ $angle_from = $angle_from+ $angle_to ;
+ }
+ }
+
+ break;
+
+ case 2: // hit miss
+
+ $hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits'];
+ $misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses'];
+ $total = $hits + $misses ;
+
+ fill_box($image, 30,$size,50,-$hits*($size-21)/$total,$col_black,$col_green,sprintf("%.1f%%",$hits*100/$total));
+ fill_box($image,130,$size,50,-max(4,($total-$hits)*($size-21)/$total),$col_black,$col_red,sprintf("%.1f%%",$misses*100/$total));
+ break;
+
+ }
+ header("Content-type: image/png");
+ imagepng($image);
+ exit;
+}
+
+echo getHeader();
+echo getMenu();
+
+switch ($_GET['op']) {
+
+ case 1: // host stats
+ $phpversion = phpversion();
+ $memcacheStats = getMemcacheStats();
+ $memcacheStatsSingle = getMemcacheStats(false);
+
+ $mem_size = $memcacheStats['limit_maxbytes'];
+ $mem_used = $memcacheStats['bytes'];
+ $mem_avail= $mem_size-$mem_used;
+ $startTime = time()-array_sum($memcacheStats['uptime']);
+
+ $curr_items = $memcacheStats['curr_items'];
+ $total_items = $memcacheStats['total_items'];
+ $hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits'];
+ $misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses'];
+ $sets = $memcacheStats['cmd_set'];
+
+ $req_rate = sprintf("%.2f",($hits+$misses)/($time-$startTime));
+ $hit_rate = sprintf("%.2f",($hits)/($time-$startTime));
+ $miss_rate = sprintf("%.2f",($misses)/($time-$startTime));
+ $set_rate = sprintf("%.2f",($sets)/($time-$startTime));
+
+ echo <<< EOB
+ <div class="info div1"><h2>General Cache Information</h2>
+ <table cellspacing=0><tbody>
+ <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
+EOB;
+ echo "<tr class=tr-0><td class=td-0>Memcached Host". ((count($MEMCACHE_SERVERS)>1) ? 's':'')."</td><td>";
+ $i=0;
+ if (!isset($_GET['singleout']) && count($MEMCACHE_SERVERS)>1){
+ foreach($MEMCACHE_SERVERS as $server){
+ echo ($i+1).'. <a href="'.$PHP_SELF.'&singleout='.$i++.'">'.$server.'</a><br/>';
+ }
+ }
+ else{
+ echo '1.'.$MEMCACHE_SERVERS[0];
+ }
+ if (isset($_GET['singleout'])){
+ echo '<a href="'.$PHP_SELF.'">(all servers)</a><br/>';
+ }
+ echo "</td></tr>\n";
+ echo "<tr class=tr-1><td class=td-0>Total Memcache Cache</td><td>".bsize($memcacheStats['limit_maxbytes'])."</td></tr>\n";
+
+ echo <<<EOB
+ </tbody></table>
+ </div>
+
+ <div class="info div1"><h2>Memcache Server Information</h2>
+EOB;
+ foreach($MEMCACHE_SERVERS as $server){
+ echo '<table cellspacing=0><tbody>';
+ echo '<tr class=tr-1><td class=td-1>'.$server.'</td><td><a href="'.$PHP_SELF.'&server='.array_search($server,$MEMCACHE_SERVERS).'&op=6">[<b>Flush this server</b>]</a></td></tr>';
+ echo '<tr class=tr-0><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>';
+ echo '<tr class=tr-1><td class=td-0>Uptime</td><td>',duration($memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>';
+ echo '<tr class=tr-0><td class=td-0>Memcached Server Version</td><td>'.$memcacheStatsSingle[$server]['STAT']['version'].'</td></tr>';
+ echo '<tr class=tr-1><td class=td-0>Used Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['bytes']),'</td></tr>';
+ echo '<tr class=tr-0><td class=td-0>Total Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['limit_maxbytes']),'</td></tr>';
+ echo '</tbody></table>';
+ }
+ echo <<<EOB
+
+ </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>Cache Usage</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&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$time\"></td>".
+ "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF&IMG=2&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$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: ',$hits.sprintf(" (%.1f%%)",$hits*100/($hits+$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: ',$misses.sprintf(" (%.1f%%)",$misses*100/($hits+$misses)),"</td>\n";
+ echo <<< EOB
+ </tr>
+ </tbody></table>
+<br/>
+ <div class="info"><h2>Cache Information</h2>
+ <table cellspacing=0><tbody>
+ <tr class=tr-0><td class=td-0>Current Items(total)</td><td>$curr_items ($total_items)</td></tr>
+ <tr class=tr-1><td class=td-0>Hits</td><td>{$hits}</td></tr>
+ <tr class=tr-0><td class=td-0>Misses</td><td>{$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>Set Rate</td><td>$set_rate cache requests/second</td></tr>
+ </tbody></table>
+ </div>
+
+EOB;
+
+ break;
+
+ case 2: // variables
+
+ $m=0;
+ $cacheItems= getCacheItems();
+ $items = $cacheItems['items'];
+ $totals = $cacheItems['counts'];
+ $maxDump = MAX_ITEM_DUMP;
+ foreach($items as $server => $entries) {
+
+ echo <<< EOB
+
+ <div class="info"><table cellspacing=0><tbody>
+ <tr><th colspan="2">$server</th></tr>
+ <tr><th>Slab Id</th><th>Info</th></tr>
+EOB;
+
+ foreach($entries as $slabId => $slab) {
+ $dumpUrl = $PHP_SELF.'&op=2&server='.(array_search($server,$MEMCACHE_SERVERS)).'&dumpslab='.$slabId;
+ echo
+ "<tr class=tr-$m>",
+ "<td class=td-0><center>",'<a href="',$dumpUrl,'">',$slabId,'</a>',"</center></td>",
+ "<td class=td-last><b>Item count:</b> ",$slab['number'],'<br/><b>Age:</b>',duration($time-$slab['age']),'<br/> <b>Evicted:</b>',((isset($slab['evicted']) && $slab['evicted']==1)? 'Yes':'No');
+ if ((isset($_GET['dumpslab']) && $_GET['dumpslab']==$slabId) && (isset($_GET['server']) && $_GET['server']==array_search($server,$MEMCACHE_SERVERS))){
+ echo "<br/><b>Items: item</b><br/>";
+ $items = dumpCacheSlab($server,$slabId,$slab['number']);
+ // maybe someone likes to do a pagination here :)
+ $i=1;
+ foreach($items['ITEM'] as $itemKey=>$itemInfo){
+ $itemInfo = trim($itemInfo,'[ ]');
+
+
+ echo '<a href="',$PHP_SELF,'&op=4&server=',(array_search($server,$MEMCACHE_SERVERS)),'&key=',base64_encode($itemKey).'">',$itemKey,'</a>';
+ if ($i++ % 10 == 0) {
+ echo '<br/>';
+ }
+ elseif ($i!=$slab['number']+1){
+ echo ',';
+ }
+ }
+ }
+
+ echo "</td></tr>";
+ $m=1-$m;
+ }
+ echo <<<EOB
+ </tbody></table>
+ </div><hr/>
+EOB;
+}
+ break;
+
+ break;
+
+ case 4: //item dump
+ if (!isset($_GET['key']) || !isset($_GET['server'])){
+ echo "No key set!";
+ break;
+ }
+ // I'm not doing anything to check the validity of the key string.
+ // probably an exploit can be written to delete all the files in key=base64_encode("\n\r delete all").
+ // somebody has to do a fix to this.
+ $theKey = htmlentities(base64_decode($_GET['key']));
+
+ $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
+ list($h,$p) = explode(':',$theserver);
+ $r = sendMemcacheCommand($h,$p,'get '.$theKey);
+ echo <<<EOB
+ <div class="info"><table cellspacing=0><tbody>
+ <tr><th>Server<th>Key</th><th>Value</th><th>Delete</th></tr>
+EOB;
+ echo "<tr><td class=td-0>",$theserver,"</td><td class=td-0>",$theKey,
+ " <br/>flag:",$r['VALUE'][$theKey]['stat']['flag'],
+ " <br/>Size:",bsize($r['VALUE'][$theKey]['stat']['size']),
+ "</td><td>",chunk_split($r['VALUE'][$theKey]['value'],40),"</td>",
+ '<td><a href="',$PHP_SELF,'&op=5&server=',(int)$_GET['server'],'&key=',base64_encode($theKey),"\">Delete</a></td>","</tr>";
+ echo <<<EOB
+ </tbody></table>
+ </div><hr/>
+EOB;
+ break;
+ case 5: // item delete
+ if (!isset($_GET['key']) || !isset($_GET['server'])){
+ echo "No key set!";
+ break;
+ }
+ $theKey = htmlentities(base64_decode($_GET['key']));
+ $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
+ list($h,$p) = explode(':',$theserver);
+ $r = sendMemcacheCommand($h,$p,'delete '.$theKey);
+ echo 'Deleting '.$theKey.':'.$r;
+ break;
+
+ case 6: // flush server
+ $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
+ $r = flushServer($theserver);
+ echo 'Flush '.$theserver.":".$r;
+ break;
+}
+echo getFooter();
+
+?>
\ No newline at end of file
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache_consistent_hash.c
^
|
@@ -0,0 +1,198 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache_consistent_hash.c 303962 2010-10-03 15:48:23Z hradtke $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include "php.h"
+#include "php_memcache.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(memcache)
+
+typedef struct mmc_consistent_point {
+ mmc_t *server;
+ unsigned int point;
+} mmc_consistent_point_t;
+
+typedef struct mmc_consistent_state {
+ int num_servers;
+ mmc_consistent_point_t *points;
+ int num_points;
+ mmc_t *buckets[MMC_CONSISTENT_BUCKETS];
+ int buckets_populated;
+ mmc_hash_function hash;
+} mmc_consistent_state_t;
+
+void *mmc_consistent_create_state(mmc_hash_function hash) /* {{{ */
+{
+ mmc_consistent_state_t *state = emalloc(sizeof(mmc_consistent_state_t));
+ memset(state, 0, sizeof(mmc_consistent_state_t));
+ state->hash = hash;
+ return state;
+}
+/* }}} */
+
+void mmc_consistent_free_state(void *s) /* {{{ */
+{
+ mmc_consistent_state_t *state = s;
+ if (state != NULL) {
+ if (state->points != NULL) {
+ efree(state->points);
+ }
+ efree(state);
+ }
+}
+/* }}} */
+
+static int mmc_consistent_compare(const void *a, const void *b) /* {{{ */
+{
+ if (((mmc_consistent_point_t *)a)->point < ((mmc_consistent_point_t *)b)->point) {
+ return -1;
+ }
+ if (((mmc_consistent_point_t *)a)->point > ((mmc_consistent_point_t *)b)->point) {
+ return 1;
+ }
+ return 0;
+}
+/* }}} */
+
+static mmc_t *mmc_consistent_find(mmc_consistent_state_t *state, unsigned int point) /* {{{ */
+{
+ int lo = 0, hi = state->num_points - 1, mid;
+
+ while (1) {
+ /* point is outside interval or lo >= hi, wrap-around */
+ if (point <= state->points[lo].point || point > state->points[hi].point) {
+ return state->points[lo].server;
+ }
+
+ /* test middle point */
+ mid = lo + (hi - lo) / 2;
+ MMC_DEBUG(("mmc_consistent_find: lo %d, hi %d, mid %d, point %u, midpoint %u", lo, hi, mid, point, state->points[mid].point));
+
+ /* perfect match */
+ if (point <= state->points[mid].point && point > (mid ? state->points[mid-1].point : 0)) {
+ return state->points[mid].server;
+ }
+
+ /* too low, go up */
+ if (state->points[mid].point < point) {
+ lo = mid + 1;
+ }
+ else {
+ hi = mid - 1;
+ }
+ }
+}
+/* }}} */
+
+static void mmc_consistent_populate_buckets(mmc_consistent_state_t *state) /* {{{ */
+{
+ unsigned int i, step = 0xffffffff / MMC_CONSISTENT_BUCKETS;
+
+ qsort((void *)state->points, state->num_points, sizeof(mmc_consistent_point_t), mmc_consistent_compare);
+ for (i=0; i<MMC_CONSISTENT_BUCKETS; i++) {
+ state->buckets[i] = mmc_consistent_find(state, step * i);
+ }
+
+ state->buckets_populated = 1;
+}
+/* }}} */
+
+mmc_t *mmc_consistent_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */
+{
+ mmc_consistent_state_t *state = s;
+ mmc_t *mmc;
+
+ if (state->num_servers > 1) {
+ unsigned int i, hash = state->hash(key, key_len);
+
+ if (!state->buckets_populated) {
+ mmc_consistent_populate_buckets(state);
+ }
+
+ mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS];
+
+ /* perform failover if needed */
+ for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) {
+ char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1);
+ int next_len = sprintf(next_key, "%s-%d", key, i);
+ MMC_DEBUG(("mmc_consistent_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status));
+
+ hash = state->hash(next_key, next_len);
+ mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS];
+
+ efree(next_key);
+ }
+ }
+ else {
+ mmc = state->points[0].server;
+ mmc_open(mmc, 0, NULL, NULL TSRMLS_CC);
+ }
+
+ return mmc->status != MMC_STATUS_FAILED ? mmc : NULL;
+}
+/* }}} */
+
+void mmc_consistent_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */
+{
+ mmc_consistent_state_t *state = s;
+ int i, key_len, points = weight * MMC_CONSISTENT_POINTS;
+
+ /* buffer for "host:port-i\0" */
+ char *key = emalloc(strlen(mmc->host) + MAX_LENGTH_OF_LONG * 2 + 3);
+
+ /* add weight * MMC_CONSISTENT_POINTS number of points for this server */
+ state->points = erealloc(state->points, sizeof(mmc_consistent_point_t) * (state->num_points + points));
+
+ for (i=0; i<points; i++) {
+ key_len = sprintf(key, "%s:%d-%d", mmc->host, mmc->port, i);
+ state->points[state->num_points + i].server = mmc;
+ state->points[state->num_points + i].point = state->hash(key, key_len);
+ MMC_DEBUG(("mmc_consistent_add_server: key %s, point %lu", key, state->points[state->num_points + i].point));
+ }
+
+ state->num_points += points;
+ state->num_servers++;
+ state->buckets_populated = 0;
+
+ efree(key);
+}
+/* }}} */
+
+mmc_hash_t mmc_consistent_hash = {
+ mmc_consistent_create_state,
+ mmc_consistent_free_state,
+ mmc_consistent_find_server,
+ mmc_consistent_add_server
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache_queue.c
^
|
@@ -0,0 +1,130 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache_queue.c 303965 2010-10-03 20:40:19Z hradtke $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "memcache_queue.h"
+
+void mmc_queue_push(mmc_queue_t *queue, void *ptr) {
+ if (mmc_queue_contains(queue, ptr)) return;
+
+ if (queue->len >= queue->alloc) {
+ int increase = 1 + MMC_QUEUE_PREALLOC;
+ queue->alloc += increase;
+ queue->items = erealloc(queue->items, sizeof(*queue->items) * queue->alloc);
+
+ /* move tail segment downwards */
+ if (queue->head < queue->tail) {
+ memmove(queue->items + queue->tail + increase, queue->items + queue->tail, (queue->alloc - queue->tail - increase) * sizeof(*queue->items));
+ queue->tail += increase;
+ }
+ }
+
+ if (queue->len) {
+ queue->head++;
+
+ if (queue->head >= queue->alloc) {
+ queue->head = 0;
+ }
+ }
+
+ queue->items[queue->head] = ptr;
+ queue->len++;
+}
+
+void *mmc_queue_pop(mmc_queue_t *queue) {
+ if (queue->len) {
+ void *ptr;
+
+ ptr = queue->items[queue->tail];
+ queue->len--;
+
+ if (queue->len) {
+ queue->tail++;
+
+ if (queue->tail >= queue->alloc) {
+ queue->tail = 0;
+ }
+ }
+
+ return ptr;
+ }
+ return NULL;
+}
+
+int mmc_queue_contains(mmc_queue_t *queue, void *ptr) {
+ if (queue != NULL) {
+ int i;
+
+ for (i=0; i < queue->len; i++) {
+ if (mmc_queue_item(queue, i) == ptr) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void mmc_queue_free(mmc_queue_t *queue) {
+ if (queue->items != NULL) {
+ efree(queue->items);
+ }
+ memset(queue, 0, sizeof(*queue));
+}
+
+void mmc_queue_copy(mmc_queue_t *source, mmc_queue_t *target) {
+ if (target->alloc != source->alloc) {
+ target->alloc = source->alloc;
+ erealloc(target->items, sizeof(*target->items) * target->alloc);
+ }
+
+ memcpy(target->items, source->items, sizeof(*source->items) * source->alloc);
+ target->head = source->head;
+ target->tail = source->tail;
+ target->len = source->len;
+}
+
+void mmc_queue_remove(mmc_queue_t *queue, void *ptr) {
+ void *item;
+ mmc_queue_t original = *queue;
+ mmc_queue_release(queue);
+
+ while ((item = mmc_queue_pop(&original)) != NULL) {
+ if (item != ptr) {
+ mmc_queue_push(queue, item);
+ }
+ }
+
+ mmc_queue_free(&original);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache_queue.h
^
|
@@ -0,0 +1,56 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache_queue.h 303962 2010-10-03 15:48:23Z hradtke $ */
+
+#ifndef MEMCACHE_QUEUE_H_
+#define MEMCACHE_QUEUE_H_
+
+/* request / server stack */
+#define MMC_QUEUE_PREALLOC 25
+
+typedef struct mmc_queue {
+ void **items; /* items on queue */
+ int alloc; /* allocated size */
+ int head; /* head index in ring buffer */
+ int tail; /* tail index in ring buffer */
+ int len;
+} mmc_queue_t;
+
+#define mmc_queue_release(q) memset((q), 0, sizeof(*(q)))
+#define mmc_queue_reset(q) (q)->len = (q)->head = (q)->tail = 0
+#define mmc_queue_item(q, i) ((q)->tail + (i) < (q)->alloc ? (q)->items[(q)->tail + (i)] : (q)->items[(i) - ((q)->alloc - (q)->tail)])
+
+void mmc_queue_push(mmc_queue_t *, void *);
+void *mmc_queue_pop(mmc_queue_t *);
+int mmc_queue_contains(mmc_queue_t *, void *);
+void mmc_queue_free(mmc_queue_t *);
+void mmc_queue_copy(mmc_queue_t *, mmc_queue_t *);
+void mmc_queue_remove(mmc_queue_t *, void *);
+
+#endif /*MEMCACHE_QUEUE_H_*/
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache_session.c
^
|
@@ -0,0 +1,290 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache_session.c 303962 2010-10-03 15:48:23Z hradtke $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include "php.h"
+#include "php_ini.h"
+#include "php_variables.h"
+
+#include "SAPI.h"
+#include "ext/standard/url.h"
+#include "php_memcache.h"
+
+#if HAVE_MEMCACHE_SESSION
+#include "ext/session/php_session.h"
+#endif
+
+ps_module ps_mod_memcache = {
+ PS_MOD(memcache)
+};
+
+/* {{{ PS_OPEN_FUNC
+ */
+PS_OPEN_FUNC(memcache)
+{
+ mmc_pool_t *pool;
+ mmc_t *mmc;
+
+ php_url *url;
+ zval *params, **param;
+ int i, j, path_len;
+
+ pool = mmc_pool_new(TSRMLS_C);
+
+ for (i=0,j=0,path_len=strlen(save_path); i<path_len; i=j+1) {
+ /* find beginning of url */
+ while (i<path_len && (isspace(save_path[i]) || save_path[i] == ','))
+ i++;
+
+ /* find end of url */
+ j = i;
+ while (j<path_len && !isspace(save_path[j]) && save_path[j] != ',')
+ j++;
+
+ if (i < j) {
+ int persistent = 0, weight = 1, timeout = MMC_DEFAULT_TIMEOUT, retry_interval = MMC_DEFAULT_RETRY;
+
+ /* translate unix: into file: */
+ if (!strncmp(save_path+i, "unix:", sizeof("unix:")-1)) {
+ int len = j-i;
+ char *path = estrndup(save_path+i, len);
+ memcpy(path, "file:", sizeof("file:")-1);
+ url = php_url_parse_ex(path, len);
+ efree(path);
+ }
+ else {
+ url = php_url_parse_ex(save_path+i, j-i);
+ }
+
+ if (!url) {
+ char *path = estrndup(save_path+i, j-i);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Failed to parse session.save_path (error at offset %d, url was '%s')", i, path);
+ efree(path);
+
+ mmc_pool_free(pool TSRMLS_CC);
+ PS_SET_MOD_DATA(NULL);
+ return FAILURE;
+ }
+
+ /* parse parameters */
+ if (url->query != NULL) {
+ MAKE_STD_ZVAL(params);
+ array_init(params);
+
+ sapi_module.treat_data(PARSE_STRING, estrdup(url->query), params TSRMLS_CC);
+
+ if (zend_hash_find(Z_ARRVAL_P(params), "persistent", sizeof("persistent"), (void **) ¶m) != FAILURE) {
+ convert_to_boolean_ex(param);
+ persistent = Z_BVAL_PP(param);
+ }
+
+ if (zend_hash_find(Z_ARRVAL_P(params), "weight", sizeof("weight"), (void **) ¶m) != FAILURE) {
+ convert_to_long_ex(param);
+ weight = Z_LVAL_PP(param);
+ }
+
+ if (zend_hash_find(Z_ARRVAL_P(params), "timeout", sizeof("timeout"), (void **) ¶m) != FAILURE) {
+ convert_to_long_ex(param);
+ timeout = Z_LVAL_PP(param);
+ }
+
+ if (zend_hash_find(Z_ARRVAL_P(params), "retry_interval", sizeof("retry_interval"), (void **) ¶m) != FAILURE) {
+ convert_to_long_ex(param);
+ retry_interval = Z_LVAL_PP(param);
+ }
+
+ zval_ptr_dtor(¶ms);
+ }
+
+ if (url->scheme && url->path && !strcmp(url->scheme, "file")) {
+ char *host;
+ int host_len = spprintf(&host, 0, "unix://%s", url->path);
+
+ /* chop off trailing :0 port specifier */
+ if (!strcmp(host + host_len - 2, ":0")) {
+ host_len -= 2;
+ }
+
+ if (persistent) {
+ mmc = mmc_find_persistent(host, host_len, 0, timeout, retry_interval TSRMLS_CC);
+ }
+ else {
+ mmc = mmc_server_new(host, host_len, 0, 0, timeout, retry_interval TSRMLS_CC);
+ }
+
+ efree(host);
+ }
+ else {
+ if (url->host == NULL || weight <= 0 || timeout <= 0) {
+ php_url_free(url);
+ mmc_pool_free(pool TSRMLS_CC);
+ PS_SET_MOD_DATA(NULL);
+ return FAILURE;
+ }
+
+ if (persistent) {
+ mmc = mmc_find_persistent(url->host, strlen(url->host), url->port, timeout, retry_interval TSRMLS_CC);
+ }
+ else {
+ mmc = mmc_server_new(url->host, strlen(url->host), url->port, 0, timeout, retry_interval TSRMLS_CC);
+ }
+ }
+
+ mmc_pool_add(pool, mmc, weight);
+ php_url_free(url);
+ }
+ }
+
+ if (pool->num_servers) {
+ PS_SET_MOD_DATA(pool);
+ return SUCCESS;
+ }
+
+ mmc_pool_free(pool TSRMLS_CC);
+ PS_SET_MOD_DATA(NULL);
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ PS_CLOSE_FUNC
+ */
+PS_CLOSE_FUNC(memcache)
+{
+ mmc_pool_t *pool = PS_GET_MOD_DATA();
+
+ if (pool) {
+ mmc_pool_free(pool TSRMLS_CC);
+ PS_SET_MOD_DATA(NULL);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PS_READ_FUNC
+ */
+PS_READ_FUNC(memcache)
+{
+ mmc_pool_t *pool = PS_GET_MOD_DATA();
+ zval *result;
+
+ if (pool) {
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ return FAILURE;
+ }
+
+ MAKE_STD_ZVAL(result);
+ ZVAL_NULL(result);
+
+ if (mmc_exec_retrieval_cmd(pool, key_tmp, key_tmp_len, &result, NULL TSRMLS_CC) <= 0 || Z_TYPE_P(result) != IS_STRING) {
+ zval_ptr_dtor(&result);
+ return FAILURE;
+ }
+
+ *val = Z_STRVAL_P(result);
+ *vallen = Z_STRLEN_P(result);
+ FREE_ZVAL(result);
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ PS_WRITE_FUNC
+ */
+PS_WRITE_FUNC(memcache)
+{
+ mmc_pool_t *pool = PS_GET_MOD_DATA();
+
+ if (pool) {
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ return FAILURE;
+ }
+
+ if (mmc_pool_store(pool, "set", sizeof("set")-1, key_tmp, key_tmp_len, 0, INI_INT("session.gc_maxlifetime"), val, vallen TSRMLS_CC)) {
+ return SUCCESS;
+ }
+ }
+
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ PS_DESTROY_FUNC
+ */
+PS_DESTROY_FUNC(memcache)
+{
+ mmc_pool_t *pool = PS_GET_MOD_DATA();
+ mmc_t *mmc;
+
+ int result = -1;
+
+ if (pool) {
+ char key_tmp[MMC_KEY_MAX_SIZE];
+ unsigned int key_tmp_len;
+
+ if (mmc_prepare_key_ex(key, strlen(key), key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) {
+ return FAILURE;
+ }
+
+ while (result < 0 && (mmc = mmc_pool_find(pool, key_tmp, key_tmp_len TSRMLS_CC)) != NULL) {
+ if ((result = mmc_delete(mmc, key_tmp, key_tmp_len, 0 TSRMLS_CC)) < 0) {
+ mmc_server_failure(mmc TSRMLS_CC);
+ }
+ }
+
+ if (result >= 0) {
+ return SUCCESS;
+ }
+ }
+
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ PS_GC_FUNC
+ */
+PS_GC_FUNC(memcache)
+{
+ return SUCCESS;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/memcache_standard_hash.c
^
|
@@ -0,0 +1,132 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: memcache_standard_hash.c 303962 2010-10-03 15:48:23Z hradtke $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_memcache.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(memcache)
+
+typedef struct mmc_standard_state {
+ int num_servers;
+ mmc_t **buckets;
+ int num_buckets;
+ mmc_hash_function hash;
+} mmc_standard_state_t;
+
+void *mmc_standard_create_state(mmc_hash_function hash) /* {{{ */
+{
+ mmc_standard_state_t *state = emalloc(sizeof(mmc_standard_state_t));
+ memset(state, 0, sizeof(mmc_standard_state_t));
+ state->hash = hash;
+ return state;
+}
+/* }}} */
+
+void mmc_standard_free_state(void *s) /* {{{ */
+{
+ mmc_standard_state_t *state = s;
+ if (state != NULL) {
+ if (state->buckets != NULL) {
+ efree(state->buckets);
+ }
+ efree(state);
+ }
+}
+/* }}} */
+
+static unsigned int mmc_hash(mmc_standard_state_t *state, const char *key, int key_len) /* {{{ */
+{
+ unsigned int hash = (state->hash(key, key_len) >> 16) & 0x7fff;
+ return hash ? hash : 1;
+}
+/* }}} */
+
+mmc_t *mmc_standard_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */
+{
+ mmc_standard_state_t *state = s;
+ mmc_t *mmc;
+
+ if (state->num_servers > 1) {
+ unsigned int hash = mmc_hash(state, key, key_len), i;
+ mmc = state->buckets[hash % state->num_buckets];
+
+ /* perform failover if needed */
+ for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) {
+ char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1);
+ int next_len = sprintf(next_key, "%d%s", i+1, key);
+ MMC_DEBUG(("mmc_standard_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status));
+
+ hash += mmc_hash(state, next_key, next_len);
+ mmc = state->buckets[hash % state->num_buckets];
+
+ efree(next_key);
+ }
+ }
+ else {
+ mmc = state->buckets[0];
+ mmc_open(mmc, 0, NULL, NULL TSRMLS_CC);
+ }
+
+ return mmc->status != MMC_STATUS_FAILED ? mmc : NULL;
+}
+/* }}} */
+
+void mmc_standard_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */
+{
+ mmc_standard_state_t *state = s;
+ int i;
+
+ /* add weight number of buckets for this server */
+ if (state->num_buckets) {
+ state->buckets = erealloc(state->buckets, sizeof(mmc_t *) * (state->num_buckets + weight));
+ }
+ else {
+ state->buckets = emalloc(sizeof(mmc_t *) * (weight));
+ }
+
+ for (i=0; i<weight; i++) {
+ state->buckets[state->num_buckets + i] = mmc;
+ }
+
+ state->num_buckets += weight;
+ state->num_servers++;
+}
+/* }}} */
+
+mmc_hash_t mmc_standard_hash = {
+ mmc_standard_create_state,
+ mmc_standard_free_state,
+ mmc_standard_find_server,
+ mmc_standard_add_server
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
memcache-2.2.6.tgz/memcache-2.2.6/php_memcache.h
^
|
@@ -0,0 +1,229 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 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_0.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: Antony Dovgal <tony@daylessday.org> |
+ | Mikael Johansson <mikael AT synd DOT info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: php_memcache.h 303967 2010-10-03 20:57:13Z hradtke $ */
+
+#ifndef PHP_MEMCACHE_H
+#define PHP_MEMCACHE_H
+
+extern zend_module_entry memcache_module_entry;
+#define phpext_memcache_ptr &memcache_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_MEMCACHE_API __declspec(dllexport)
+#else
+#define PHP_MEMCACHE_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#include "ext/standard/php_smart_str_public.h"
+
+PHP_MINIT_FUNCTION(memcache);
+PHP_MSHUTDOWN_FUNCTION(memcache);
+PHP_RINIT_FUNCTION(memcache);
+PHP_MINFO_FUNCTION(memcache);
+
+PHP_FUNCTION(memcache_connect);
+PHP_FUNCTION(memcache_pconnect);
+PHP_FUNCTION(memcache_add_server);
+PHP_FUNCTION(memcache_set_server_params);
+PHP_FUNCTION(memcache_get_server_status);
+PHP_FUNCTION(memcache_get_version);
+PHP_FUNCTION(memcache_add);
+PHP_FUNCTION(memcache_set);
+PHP_FUNCTION(memcache_replace);
+PHP_FUNCTION(memcache_get);
+PHP_FUNCTION(memcache_delete);
+PHP_FUNCTION(memcache_debug);
+PHP_FUNCTION(memcache_get_stats);
+PHP_FUNCTION(memcache_get_extended_stats);
+PHP_FUNCTION(memcache_set_compress_threshold);
+PHP_FUNCTION(memcache_increment);
+PHP_FUNCTION(memcache_decrement);
+PHP_FUNCTION(memcache_close);
+PHP_FUNCTION(memcache_flush);
+PHP_FUNCTION(memcache_setoptimeout);
+
+#define PHP_MEMCACHE_VERSION "2.2.6"
+
+#define MMC_BUF_SIZE 4096
+#define MMC_SERIALIZED 1
+#define MMC_COMPRESSED 2
+#define MMC_DEFAULT_TIMEOUT 1 /* seconds */
+#define MMC_KEY_MAX_SIZE 250 /* stoled from memcached sources =) */
+#define MMC_DEFAULT_RETRY 15 /* retry failed server after x seconds */
+#define MMC_DEFAULT_SAVINGS 0.2 /* minimum 20% savings for compression to be used */
+#define MMC_DEFAULT_CACHEDUMP_LIMIT 100 /* number of entries */
+
+#define MMC_STATUS_FAILED 0
+#define MMC_STATUS_DISCONNECTED 1
+#define MMC_STATUS_UNKNOWN 2
+#define MMC_STATUS_CONNECTED 3
+
+#define MMC_OK 0
+#define MMC_REQUEST_FAILURE -1
+
+#define MMC_STANDARD_HASH 1
+#define MMC_CONSISTENT_HASH 2
+#define MMC_HASH_CRC32 1 /* CRC32 hash function */
+#define MMC_HASH_FNV1A 2 /* FNV-1a hash function */
+
+#define MMC_CONSISTENT_POINTS 160 /* points per server */
+#define MMC_CONSISTENT_BUCKETS 1024 /* number of precomputed buckets, should be power of 2 */
+
+typedef struct mmc {
+ php_stream *stream;
+ char inbuf[MMC_BUF_SIZE];
+ smart_str outbuf;
+ char *host;
+ unsigned short port;
+ long timeout;
+ long timeoutms; /* takes precedence over timeout */
+ long connect_timeoutms; /* takes precedence over timeout */
+ long failed;
+ long retry_interval;
+ int persistent;
+ int status;
+ char *error; /* last error message */
+ int errnum; /* last error code */
+ zval *failure_callback;
+ zend_bool in_free;
+} mmc_t;
+
+/* hashing strategy */
+typedef unsigned int (*mmc_hash_function)(const char *, int);
+typedef void * (*mmc_hash_create_state)(mmc_hash_function);
+typedef void (*mmc_hash_free_state)(void *);
+typedef mmc_t * (*mmc_hash_find_server)(void *, const char *, int TSRMLS_DC);
+typedef void (*mmc_hash_add_server)(void *, mmc_t *, unsigned int);
+
+#define mmc_pool_find(pool, key, key_len) \
+ pool->hash->find_server(pool->hash_state, key, key_len)
+
+typedef struct mmc_hash {
+ mmc_hash_create_state create_state;
+ mmc_hash_free_state free_state;
+ mmc_hash_find_server find_server;
+ mmc_hash_add_server add_server;
+} mmc_hash_t;
+
+/* 32 bit magic FNV-1a prime and init */
+#define FNV_32_PRIME 0x01000193
+#define FNV_32_INIT 0x811c9dc5
+
+typedef struct mmc_pool {
+ mmc_t **servers;
+ int num_servers;
+ mmc_t **requests;
+ int compress_threshold;
+ double min_compress_savings;
+ zend_bool in_free;
+ mmc_hash_t *hash;
+ void *hash_state;
+} mmc_pool_t;
+
+/* our globals */
+ZEND_BEGIN_MODULE_GLOBALS(memcache)
+ long debug_mode;
+ long default_port;
+ long num_persistent;
+ long compression_level;
+ long allow_failover;
+ long chunk_size;
+ long max_failover_attempts;
+ long hash_strategy;
+ long hash_function;
+ long default_timeout_ms;
+ZEND_END_MODULE_GLOBALS(memcache)
+
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
+# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC)
+#else
+# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp))
+#endif
+
+/* internal functions */
+mmc_t *mmc_server_new(char *, int, unsigned short, int, int, int TSRMLS_DC);
+mmc_t *mmc_find_persistent(char *, int, int, int, int TSRMLS_DC);
+int mmc_server_failure(mmc_t * TSRMLS_DC);
+void mmc_server_deactivate(mmc_t * TSRMLS_DC);
+
+int mmc_prepare_key(zval *, char *, unsigned int * TSRMLS_DC);
+int mmc_prepare_key_ex(const char *, unsigned int, char *, unsigned int * TSRMLS_DC);
+
+mmc_pool_t *mmc_pool_new(TSRMLS_D);
+void mmc_pool_free(mmc_pool_t * TSRMLS_DC);
+void mmc_pool_add(mmc_pool_t *, mmc_t *, unsigned int);
+int mmc_pool_store(mmc_pool_t *, const char *, int, const char *, int, int, int, const char *, int TSRMLS_DC);
+int mmc_open(mmc_t *, int, char **, int * TSRMLS_DC);
+int mmc_exec_retrieval_cmd(mmc_pool_t *, const char *, int, zval **, zval * TSRMLS_DC);
+int mmc_delete(mmc_t *, const char *, int, int TSRMLS_DC);
+
+/* session handler struct */
+#if HAVE_MEMCACHE_SESSION
+#include "ext/session/php_session.h"
+
+extern ps_module ps_mod_memcache;
+#define ps_memcache_ptr &ps_mod_memcache
+
+PS_FUNCS(memcache);
+#endif
+
+/* {{{ macros */
+#if ZEND_DEBUG
+
+void mmc_debug(const char *format, ...);
+
+#define MMC_DEBUG(info) \
+{\
+ mmc_debug info; \
+}\
+
+#else
+
+#define MMC_DEBUG(info) \
+{\
+}\
+
+#endif
+/* }}} */
+
+#ifdef ZTS
+#define MEMCACHE_G(v) TSRMG(memcache_globals_id, zend_memcache_globals *, v)
+#else
+#define MEMCACHE_G(v) (memcache_globals.v)
+#endif
+
+#ifndef ZSTR
+#define ZSTR
+#endif
+
+#endif /* PHP_MEMCACHE_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Changed |
memcache-2.2.6.tgz/package.xml
^
|
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.6.2" 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">
+<package packagerversion="1.9.1" 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>memcache</name>
<channel>pecl.php.net</channel>
<summary>memcached extension</summary>
@@ -11,8 +11,8 @@
<lead>
<name>Antony Dovgal</name>
<user>tony2001</user>
- <email>tony2001@phpclub.net</email>
- <active>yes</active>
+ <email>tony@daylessday.org</email>
+ <active>no</active>
</lead>
<lead>
<name>Mikael Johansson</name>
@@ -20,38 +20,45 @@
<email>mikael@synd.info</email>
<active>yes</active>
</lead>
- <date>2008-02-05</date>
- <time>20:46:51</time>
+ <lead>
+ <name>Herman Radtke</name>
+ <user>hradtke</user>
+ <email>hradtke@php.net</email>
+ <active>yes</active>
+ </lead>
+ <date>2010-10-03</date>
+ <time>13:57:47</time>
<version>
- <release>2.2.3</release>
- <api>2.2.3</api>
+ <release>2.2.6</release>
+ <api>2.2.6</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Fixed PECL bug #12883 (Breaks UTF-8 in keys)
-- Fixed PECL bug #13060 (make problems, due to role="doc" instead of role="src")
-- Added package version to phpinfo()</notes>
+ <notes>
+- Fixed pecl bug #16536 (Weight of 0 causes SegFault on memcache_add_server)
+- Fixed pecl bug #17130 (Uninitialized tv.tv_usec causing PHP to loop endlessly)
+- Fixed pecl bug #13623 (Memcache-client makes php segfault in semi-related code)
+ </notes>
<contents>
<dir name="/">
- <file md5sum="a35c3d4407a9f946e6ea8f26e75ef72b" name="config.m4" role="src" />
- <file md5sum="2775fadca560939d9c7fd23d2e7c879c" name="config9.m4" role="src" />
- <file md5sum="c682769a4b07803f4aa1b720f9405dc0" name="config.w32" role="src" />
+ <file md5sum="7cf485250442fb33fb95d3a15f324158" name="config.m4" role="src" />
+ <file md5sum="d4fe6714821f067f9325141ef53c0dde" name="config9.m4" role="src" />
+ <file md5sum="b8e420711ef22bb16ef123dc75999d03" name="config.w32" role="src" />
<file md5sum="f818c8af5b84d8c936eca307b63aafec" name="CREDITS" role="doc" />
<file md5sum="5b6b03aebb60f141416489a527b2c9be" name="example.php" role="doc" />
- <file md5sum="91791aa8bc13ae1de5d3c569c7f318b9" name="memcache.c" role="src" />
- <file md5sum="e28ec589f5b44ba5456a5950fe4631ee" name="memcache_queue.c" role="src" />
- <file md5sum="7f87146516c5d4b315eb702bd217df94" name="memcache_session.c" role="src" />
- <file md5sum="aa706ccc970730f34a55cba72555698f" name="memcache_standard_hash.c" role="src" />
- <file md5sum="c62db6e6399b3a87282ea401ce29d310" name="memcache_consistent_hash.c" role="src" />
+ <file md5sum="b5822470d1a28c86f9e01b1bb18fab43" name="memcache.c" role="src" />
+ <file md5sum="7758ddd159ee9a41dac38b11a1e559c3" name="memcache_queue.c" role="src" />
+ <file md5sum="79d1fb6a64af9ce0f6c08fdbb5a79a88" name="memcache_session.c" role="src" />
+ <file md5sum="085400cb62fd618ae3b4ae4927bc828b" name="memcache_standard_hash.c" role="src" />
+ <file md5sum="57944943fdd444deb3e642a60110fa5c" name="memcache_consistent_hash.c" role="src" />
<file md5sum="a0904f003d7ae14ff22c15fd0c417ceb" name="memcache.dsp" role="src" />
- <file md5sum="0e5c024a5d214d6f45f5de5c1af8304b" name="php_memcache.h" role="src">
- <tasks:replace from="@PACKAGE-VERSION@" to="version" type="package-info" />
- </file>
- <file md5sum="d0fe0181d0a9c3559b7a3efbbaa3a58a" name="memcache_queue.h" role="src" />
- <file md5sum="3a5a10c91e4dafd7bc46f346bd37c26c" name="README" role="doc" />
+ <file md5sum="b791fddd518a79b1faff92cdaa4a3817" name="php_memcache.h" role="src" />
+ <file md5sum="86f30f355dde9981512af22045323e4d" name="memcache_queue.h" role="src" />
+ <file md5sum="9b003fbed1a7f05c96154fb7b13fce2d" name="README" role="doc" />
+ <file md5sum="924ee99155f4bee0640053d73fbf2595" name="memcache.php" role="doc" />
</dir>
</contents>
<dependencies>
@@ -70,6 +77,60 @@
</extsrcrelease>
<changelog>
<release>
+ <date>2009-02-27</date>
+ <version>
+ <release>2.2.5</release>
+ <api>2.2.5</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Improved performance of consistent hash strategy
+- Fixed PECL request #13758 (Failed to extract 'connection' variable from object)
+ </notes>
+ </release>
+ <release>
+ <date>2008-09-11</date>
+ <version>
+ <release>2.2.4</release>
+ <api>2.2.4</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Added memcached stats script from Harun Yayli (http://livebookmark.net/memcachephp)
+- Fixed server weight not being used in the session handler
+- Fixed PECL bug #13343 (compilation breaks with CodeWarrior compiler)
+- Fixed PECL bug #13546 (Session handler through unix socket)
+- Fixed PECL bug #14239 (Memcache::set() modifies value parameter)
+- Fixed PECL request #13725 (unnecessary allocations in mmc_consistent_add_server)
+- Changed behaviour when unserialize/uncompress fail to return false instead of failing the server
+ </notes>
+ </release>
+ <release>
+ <date>2008-02-05</date>
+ <version>
+ <release>2.2.3</release>
+ <api>2.2.3</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Fixed PECL bug #12883 (Breaks UTF-8 in keys)
+- Fixed PECL bug #13060 (make problems, due to role="doc" instead of role="src")
+- Added package version to phpinfo()
+ </notes>
+ </release>
+ <release>
<date>2008-01-10</date>
<version>
<release>2.2.2</release>
@@ -80,10 +141,12 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Fixed PECL bug 12494 (Segmentation fault when Exception thrown in the callback function)
+ <notes>
+- Fixed PECL bug 12494 (Segmentation fault when Exception thrown in the callback function)
- Fixed PECL bug #12834 (segfault when getting duplicate array values on 64-bit system)
- Changed behaviour of close() to actually remove all servers from pool (PECL bug #12555)
-- Added configure option for PEAR installer to disable session handler support</notes>
+- Added configure option for PEAR installer to disable session handler support
+ </notes>
</release>
<release>
<date>2007-11-01</date>
@@ -96,10 +159,12 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Added argument to Memcache::get() that receives the flags for retrieved value(s)
+ <notes>
+- Added argument to Memcache::get() that receives the flags for retrieved value(s)
- Fixed PECL bug 11369 ("nested" get calls in __wakeup() functions breaks)
- Fixed problem with keys being modified in-place and empty keys (PECL Bug #11236)
-- Fixed incompatibility with standard hash strategy in previous versions</notes>
+- Fixed incompatibility with standard hash strategy in previous versions
+ </notes>
</release>
<release>
<date>2007-09-21</date>
@@ -112,7 +177,8 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Added support for consistent hash strategy
+ <notes>
+- Added support for consistent hash strategy
- New INI directives
"memcache.hash_strategy" = {standard, consistent}
"memcache.hash_function" = {crc32, fnv}
@@ -120,7 +186,8 @@
- Fixed PECL bug #11221 (Double free when returning cached object with __sleep)
- Fixed PECL bug #10607 (Segfault on array key retrieval when array key is not IS_STRING)
- Don't failover on "object to large" errors
-- Use $phpincludedir for finding php_session.h</notes>
+- Use $phpincludedir for finding php_session.h
+ </notes>
</release>
<release>
<date>2007-03-27</date>
@@ -133,7 +200,9 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Added missing files to the package.</notes>
+ <notes>
+- Added missing files to the package.
+ </notes>
</release>
<release>
<date>2007-03-27</date>
@@ -146,9 +215,11 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Added experimental session storage support. You can use memcached as session storage.
+ <notes>
+- Added experimental session storage support. You can use memcached as session storage.
- Fixed PECL bug #9486 (empty keys should not be allowed in memcache_set/add())
-- Fixed PECL bug #9854 (get() changes the datatype of variable of given as key)</notes>
+- Fixed PECL bug #9854 (get() changes the datatype of variable of given as key)
+ </notes>
</release>
<release>
<date>2006-10-09</date>
@@ -161,13 +232,15 @@
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Servers may be flagged up/down and the user may specify a error callback
+ <notes>
+- Servers may be flagged up/down and the user may specify a error callback
- Individual server params and up/down status may be changed at runtime
- New methods: setServerParams(), getServerStatus()
- Statistics methods support fetching other kinds of stats (slabs, items, cachedump, ...)
- Fixed PECL bugs #7631, #8117 (erroneous line feeds in config.m4)
- Added memcache.max_failover_attempts ini directive, which can be used to configure max number of
- servers to try when setting and getting data.</notes>
+ servers to try when setting and getting data.
+ </notes>
</release>
<release>
<version>
@@ -180,8 +253,10 @@
</stability>
<date>2006-05-16</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Redefined retry_interval as long to fix no-automatic-reconnect behaviour
- - Fixed PECL bugs #7635, #7637 (OnUpdateInt: referenced symbol not found)</notes>
+ <notes>
+- Redefined retry_interval as long to fix no-automatic-reconnect behaviour
+ - Fixed PECL bugs #7635, #7637 (OnUpdateInt: referenced symbol not found)
+ </notes>
</release>
<release>
<version>
@@ -194,8 +269,10 @@
</stability>
<date>2006-05-15</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Display ini entries in phpinfo() output
- - Fixed Zend2 compat</notes>
+ <notes>
+- Display ini entries in phpinfo() output
+ - Fixed Zend2 compat
+ </notes>
</release>
<release>
<version>
@@ -208,11 +285,13 @@
</stability>
<date>2006-05-14</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Added "memcache.default_port" ini directive (default 11211)
+ <notes>
+- Added "memcache.default_port" ini directive (default 11211)
- Added "memcache.allow_failover" ini directive (default On)
- Added "memcache.chunk_size" ini directive (default 8192 bytes)
- Setting retry_interval parameter to -1 disables automatic reconnect
-- Fixed PECL bug #7331 (NULL pointer freeing causes memcache to segfault)</notes>
+- Fixed PECL bug #7331 (NULL pointer freeing causes memcache to segfault)
+ </notes>
</release>
<release>
<version>
@@ -225,11 +304,13 @@
</stability>
<date>2006-02-01</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Fixed PECL bug #6595 (segfault in addServer())
+ <notes>
+- Fixed PECL bug #6595 (segfault in addServer())
- Fixed PECL bug #6512 (buffer overrun in getVersion())
- Fixed PECL bug #6460 (lacking include of php_smart_str_public.h)
- Fixed PECL bug #6370 (incorrect failover on out-of-memory server errors)
-- Improved zlib detection</notes>
+- Improved zlib detection
+ </notes>
</release>
<release>
<version>
@@ -242,9 +323,11 @@
</stability>
<date>2005-12-21</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Multiple servers with loadbalancing and failover
+ <notes>
+- Multiple servers with loadbalancing and failover
- Automatic compress threshold setting
-- New methods: addServer(), getExtendedStats(), setCompressThreshold()</notes>
+- New methods: addServer(), getExtendedStats(), setCompressThreshold()
+ </notes>
</release>
<release>
<version>
@@ -257,8 +340,10 @@
</stability>
<date>2005-10-12</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>- Fixed minor leak appeared when connect fails.
-- Fixed PECL bug #5626 (segfault when trying to use previously closed connection).</notes>
+ <notes>
+- Fixed minor leak appeared when connect fails.
+- Fixed PECL bug #5626 (segfault when trying to use previously closed connection).
+ </notes>
</release>
<release>
<version>
@@ -271,8 +356,10 @@
</stability>
<date>2005-08-05</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Fixed minor leak.
-2) Class Memcache made inheritable.</notes>
+ <notes>
+1) Fixed minor leak.
+2) Class Memcache made inheritable.
+ </notes>
</release>
<release>
<version>
@@ -285,8 +372,10 @@
</stability>
<date>2004-12-02</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Added multi get support (i.e. you're now able to get multiple items with one get() call,
-just pass array of keys to get() and it will return associative array of found items).</notes>
+ <notes>
+1) Added multi get support (i.e. you're now able to get multiple items with one get() call,
+just pass array of keys to get() and it will return associative array of found items).
+ </notes>
</release>
<release>
<version>
@@ -299,8 +388,10 @@
</stability>
<date>2004-08-29</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Fixed potential problem with empty datasets (yet another patch from Andrey Nigmatulin [anight at monamour dot ru]).
-2) Fixed bug #2167 (thanks to [pbnadeau at gmail dot com] for noticing, testing and patching).</notes>
+ <notes>
+1) Fixed potential problem with empty datasets (yet another patch from Andrey Nigmatulin [anight at monamour dot ru]).
+2) Fixed bug #2167 (thanks to [pbnadeau at gmail dot com] for noticing, testing and patching).
+ </notes>
</release>
<release>
<version>
@@ -313,10 +404,12 @@
</stability>
<date>2004-07-20</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Fixed typo, preventing to use set() with flags and expire in the same time (thanks to Troy Hakala [troy at recipezaar dot com] for noticing).
+ <notes>
+1) Fixed typo, preventing to use set() with flags and expire in the same time (thanks to Troy Hakala [troy at recipezaar dot com] for noticing).
2) Added possibility to store objects and arrays compressed.
3) Hopefully fixed all possible problems with persistent connections (thanks to [anight at monamour dot ru]).
-4) Some uncritical impovements.</notes>
+4) Some uncritical impovements.
+ </notes>
</release>
<release>
<version>
@@ -329,8 +422,10 @@
</stability>
<date>2004-06-08</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Fixed couple of possible segfaults and one error (many thanks to Anight).
-2) Minor improvements.</notes>
+ <notes>
+1) Fixed couple of possible segfaults and one error (many thanks to Anight).
+2) Minor improvements.
+ </notes>
</release>
<release>
<version>
@@ -343,9 +438,11 @@
</stability>
<date>2004-05-21</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Ifdef'ed debug routines, so they are available only in debug mode.
+ <notes>
+1) Ifdef'ed debug routines, so they are available only in debug mode.
This should add more speed to extension.
-2) Minor code decorations.</notes>
+2) Minor code decorations.
+ </notes>
</release>
<release>
<version>
@@ -358,9 +455,11 @@
</stability>
<date>2004-xx-xx</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>1) Added on-the-fly data (de)compression support.
+ <notes>
+1) Added on-the-fly data (de)compression support.
2) Added procedural API.
-3) Extension was fairly refactored and accelerated.</notes>
+3) Extension was fairly refactored and accelerated.
+ </notes>
</release>
<release>
<version>
@@ -373,8 +472,10 @@
</stability>
<date>2004-02-26</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>New methods: getStats(), increment(), decrement().
-Extension should be rather stable.</notes>
+ <notes>
+New methods: getStats(), increment(), decrement().
+Extension should be rather stable.
+ </notes>
</release>
<release>
<version>
@@ -387,7 +488,9 @@
</stability>
<date>2004-02-08</date>
<license uri="http://www.php.net/license">PHP License</license>
- <notes>Initial release in PECL</notes>
+ <notes>
+Initial release in PECL
+ </notes>
</release>
</changelog>
</package>
|