[-]
[+]
|
Changed |
php5-memcached.spec
|
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/CREDITS
^
|
@@ -1,2 +0,0 @@
-memcached
-Andrei Zmievski
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/EXPERIMENTAL
^
|
@@ -1,5 +0,0 @@
-this extension is experimental,
-its functions may change their names
-or move to extension all together
-so do not rely to much on them
-you have been warned!
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/LICENSE
^
|
@@ -1,68 +0,0 @@
---------------------------------------------------------------------
- The PHP License, Version 3.0
-Copyright (c) 1999 - 2003 The PHP Group. All rights reserved.
---------------------------------------------------------------------
-
-Redistribution and use in source and binary forms, with or without
-modification, is permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- 3. The name "PHP" must not be used to endorse or promote products
- derived from this software without prior written permission. For
- written permission, please contact group@php.net.
-
- 4. Products derived from this software may not be called "PHP", nor
- may "PHP" appear in their name, without prior written permission
- from group@php.net. You may indicate that your software works in
- conjunction with PHP by saying "Foo for PHP" instead of calling
- it "PHP Foo" or "phpfoo"
-
- 5. The PHP Group may publish revised and/or new versions of the
- license from time to time. Each version will be given a
- distinguishing version number.
- Once covered code has been published under a particular version
- of the license, you may always continue to use it under the terms
- of that version. You may also choose to use such covered code
- under the terms of any subsequent version of the license
- published by the PHP Group. No one other than the PHP Group has
- the right to modify the terms applicable to covered code created
- under this License.
-
- 6. Redistributions of any form whatsoever must retain the following
- acknowledgment:
- "This product includes PHP, freely available from
- <http://www.php.net/>".
-
-THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
-ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
-DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE.
-
---------------------------------------------------------------------
-
-This software consists of voluntary contributions made by many
-individuals on behalf of the PHP Group.
-
-The PHP Group can be contacted via Email at group@php.net.
-
-For more information on the PHP Group and the PHP project,
-please see <http://www.php.net>.
-
-This product includes the Zend Engine, freely available at
-<http://www.zend.com>.
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/README
^
|
@@ -1,11 +0,0 @@
-This is a PHP extension for interfacing with memcached via libmemcached library.
-
-
-Resources
----------
-
- libmemcached:
- http://tangent.org/552/libmemcached.html
-
- memcached:
- http://www.danga.com/memcached/
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/config.m4
^
|
@@ -1,136 +0,0 @@
-dnl
-dnl $ Id: $
-dnl vim:se ts=2 sw=2 et:
-
-PHP_ARG_ENABLE(memcached, whether to enable memcached support,
-[ --enable-memcached Enable memcached support])
-
-PHP_ARG_WITH(libmemcached-dir, for libmemcached,
-[ --with-libmemcached-dir[=DIR] Set the path to libmemcached install prefix.], yes)
-
-PHP_ARG_ENABLE(memcached-session, whether to enable memcached session handler support,
-[ --disable-memcached-session Disable memcached session handler support], yes, no)
-
-if test -z "$PHP_ZLIB_DIR"; then
-PHP_ARG_WITH(zlib-dir, for ZLIB,
-[ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], 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_MEMCACHED" != "no"; then
-
- dnl # zlib
- 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
-
- AC_MSG_CHECKING([for zlib location])
- if test "$PHP_ZLIB_DIR" = "no"; then
- AC_MSG_ERROR([memcached support requires ZLIB. Use --with-zlib-dir=<DIR> to specify the prefix where ZLIB headers and library are located])
- else
- AC_MSG_RESULT([$PHP_ZLIB_DIR])
- PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHE_SHARED_LIBADD)
- PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR)
- fi
-
- if test "$PHP_MEMCACHED_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 memcached session support])
- if test "$PHP_MEMCACHED_SESSION" != "no"; then
- AC_MSG_RESULT([enabled])
- AC_DEFINE(HAVE_MEMCACHED_SESSION,1,[Whether memcache session handler is enabled])
- SESSION_INCLUDES="-I$session_inc_path"
- ifdef([PHP_ADD_EXTENSION_DEP],
- [
- PHP_ADD_EXTENSION_DEP(memcached, session)
- ])
- else
- SESSION_INCLUDES=""
- AC_MSG_RESULT([disabled])
- fi
-
- if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then
- if test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached/memcached.h"; then
- PHP_LIBMEMCACHED_DIR="$PHP_LIBMEMCACHED_DIR"
- else
- AC_MSG_ERROR([Can't find libmemcached headers under "$PHP_LIBMEMCACHED_DIR"])
- fi
- else
- PHP_LIBMEMCACHED_DIR="no"
- for i in /usr /usr/local; do
- if test -r "$i/include/libmemcached/memcached.h"; then
- PHP_LIBMEMCACHED_DIR=$i
- break
- fi
- done
- fi
-
- AC_MSG_CHECKING([for libmemcached location])
- if test "$PHP_LIBMEMCACHED_DIR" = "no"; then
- AC_MSG_ERROR([memcached support requires libmemcached. Use --with-libmemcached-dir=<DIR> to specify the prefix where libmemcached headers and library are located])
- else
- AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR])
- PHP_LIBMEMCACHED_INCDIR="$PHP_LIBMEMCACHED_DIR/include"
- PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR)
- PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/lib, MEMCACHED_SHARED_LIBADD)
-
- PHP_SUBST(MEMCACHED_SHARED_LIBADD)
- PHP_NEW_EXTENSION(memcached, php_memcached.c , $ext_shared,,$SESSION_INCLUDES)
-
- ifdef([PHP_ADD_EXTENSION_DEP],
- [
- PHP_ADD_EXTENSION_DEP(memcached, spl, true)
- ])
-
- fi
-
-fi
-
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/memcached-api.php
^
|
@@ -1,148 +0,0 @@
-<?php
-
-/**
- * Collator class.
- */
-
-class Memcached {
-
- /**
- * Libmemcached behavior options.
- */
-
- const OPT_HASH;
-
- const OPT_HASH_DEFAULT;
-
- const OPT_HASH_MD5;
-
- const OPT_HASH_CRC;
-
- const OPT_HASH_FNV1_64;
-
- const OPT_HASH_FNV1A_64;
-
- const OPT_HASH_FNV1_32;
-
- const OPT_HASH_FNV1A_32;
-
- const OPT_HASH_HSIEH;
-
- const OPT_HASH_MURMUR;
-
- const OPT_DISTRIBUTION;
-
- const OPT_DISTRIBUTION_MODULA;
-
- const OPT_DISTRIBUTION_CONSISTENT;
-
- const OPT_BUFER_REQUESTS;
-
- const OPT_BINARY_PROTOCOL;
-
- const OPT_NO_BLOCK;
-
- const OPT_TCP_NODELAY;
-
- const OPT_SOCKET_SEND_SIZE;
-
- const OPT_SOCKET_RECV_SIZE;
-
- const OPT_CONNECT_TIMEOUT;
-
- const OPT_RETRY_TIMEOUT;
-
- const OPT_SND_TIMEOUT;
-
- const OPT_RCV_TIMEOUT;
-
- const OPT_POLL_TIMEOUT;
-
- const OPT_SERVER_FAILURE_LIMIT;
-
- const OPT_CACHE_LOOKUPS;
-
-
- /**
- * Class options.
- */
- const OPT_COMPRESSION;
-
- const OPT_PREFIX_KEY;
-
-
- public function __construct( $persistent_id = '' ) {}
-
- public function get( $key, &$cas_token = null, $cache_cb = null ) {}
-
- public function getByKey( $server_key, $key, $cache_cb = null ) {}
-
- public function getMulti( array $keys, &$cas_tokens = null ) {}
-
- public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null ) {}
-
- public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {}
-
- public function getDelayedByKey( $server_key, array $keys, $with_cas = null, $value_cb = null ) {}
-
- public function fetch( ) {}
-
- public function fetchAll( ) {}
-
- public function set( $key, $value, $expiration = 0 ) {}
-
- public function setByKey( $server_key, $key, $value, $expiration = 0 ) {}
-
- public function setMulti( $array, $expiration = 0 ) {}
-
- public function setMultiByKey( $server_key, $array, $expiration = 0 ) {}
-
- public function cas( $token, $key, $value, $expiration = 0 ) {}
-
- public function casByKey( $token, $server_key, $key, $value, $expiration = 0 ) {}
-
- public function add( $key, $value, $expiration = 0 ) {}
-
- public function addByKey( $server_key, $key, $value, $expiration = 0 ) {}
-
- public function append( $key, $value, $expiration = 0 ) {}
-
- public function appendByKey( $server_ke, $key, $value, $expiration = 0 ) {}
-
- public function prepend( $key, $value, $expiration = 0 ) {}
-
- public function prependByKey( $server_key, $key, $value, $expiration = 0 ) {}
-
- public function replace( $key, $value, $expiration = 0 ) {}
-
- public function replaceByKey( $serve_key, $key, $value, $expiration = 0 ) {}
-
- public function delete( $key, $expiration = 0 ) {}
-
- public function deleteByKey( $key, $expiration = 0 ) {}
-
- public function increment( $key, $offset = 1) {}
-
- public function decrement( $key, $offset = 1) {}
-
- public function getOption( $option ) {}
-
- public function setOption( $option, $value ) {}
-
- public function addServer( $host, $port, $weight = 0 );
-
- public function getServerList( ) {}
-
- public function getServerByKey( $server_key ) {}
-
- public function flush( ) {}
-
- public function getResultCode( ) {}
-
-}
-
-class MemcachedException extends Exception {
-
- function __construct( $errmsg = "", $errcode = 0 ) {}
-
-}
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/php_memcached.c
^
|
@@ -1,2602 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | Copyright (c) 2008 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: Andrei Zmievski <andrei@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $ Id: $ */
-
-/* TODO
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-#include <php_ini.h>
-#include <SAPI.h>
-#include <ext/standard/info.h>
-#include <zend_extensions.h>
-#include <zend_exceptions.h>
-#include <ext/standard/php_smart_str.h>
-#include <ext/standard/php_var.h>
-#include <libmemcached/memcached.h>
-
-#include <zlib.h>
-
-#include "php_memcached.h"
-
-/****************************************
- Custom options
-****************************************/
-#define MEMC_OPT_COMPRESSION -1001
-#define MEMC_OPT_PREFIX_KEY -1002
-
-/****************************************
- Custom result codes
-****************************************/
-#define MEMC_RES_PAYLOAD_FAILURE -1001
-
-/****************************************
- Payload value flags
-****************************************/
-#define MEMC_VAL_COMPRESSED (1<<0)
-#define MEMC_VAL_SERIALIZED (1<<1)
-#define MEMC_VAL_IS_LONG (1<<2)
-#define MEMC_VAL_IS_DOUBLE (1<<3)
-
-#define MEMC_COMPRESS_THRESHOLD 100
-
-/****************************************
- Helper macros
-****************************************/
-#define MEMC_METHOD_INIT_VARS \
- zval* object = getThis(); \
- php_memc_t* i_obj = NULL; \
-
-#define MEMC_METHOD_FETCH_OBJECT \
- i_obj = (php_memc_t *) zend_object_store_get_object( object TSRMLS_CC ); \
-
-#ifndef DVAL_TO_LVAL
-#ifdef _WIN64
-# define DVAL_TO_LVAL(d, l) \
- if ((d) > LONG_MAX) { \
- (l) = (long)(unsigned long)(__int64) (d); \
- } else { \
- (l) = (long) (d); \
- }
-#else
-# define DVAL_TO_LVAL(d, l) \
- if ((d) > LONG_MAX) { \
- (l) = (unsigned long) (d); \
- } else { \
- (l) = (long) (d); \
- }
-#endif
-#endif
-
-/****************************************
- Structures and definitions
-****************************************/
-typedef struct {
- zend_object zo;
-
- memcached_st *memc;
-
- unsigned is_persistent:1;
- const char *plist_key;
- int plist_key_len;
-
- unsigned compression:1;
-} php_memc_t;
-
-enum {
- MEMC_OP_SET,
- MEMC_OP_ADD,
- MEMC_OP_REPLACE,
- MEMC_OP_APPEND,
- MEMC_OP_PREPEND
-};
-
-static int le_memc;
-
-static zend_class_entry *memcached_ce = NULL;
-static zend_class_entry *memcached_exception_ce = NULL;
-static zend_class_entry *spl_ce_RuntimeException = NULL;
-
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
-const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
-#endif
-
-ZEND_DECLARE_MODULE_GLOBALS(php_memcached)
-
-#ifdef COMPILE_DL_MEMCACHED
-ZEND_GET_MODULE(memcached)
-#endif
-
-/****************************************
- Forward declarations
-****************************************/
-static int php_memc_list_entry(void);
-static int php_memc_handle_error(memcached_return status TSRMLS_DC);
-static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags TSRMLS_DC);
-static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags TSRMLS_DC);
-static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key);
-static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr);
-static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
-static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC);
-static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC);
-
-
-/****************************************
- Method implementations
-****************************************/
-
-/* {{{ Memcached::__construct([string persisten_id]))
- Creates a Memcached object, optionally using persistent memcache connection */
-static PHP_METHOD(Memcached, __construct)
-{
- zval *object = getThis();
- php_memc_t *i_obj;
- memcached_st *memc = NULL;
- char *persistent_id = NULL;
- int persistent_id_len;
- zend_bool skip_ctor = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &persistent_id,
- &persistent_id_len) == FAILURE) {
- ZVAL_NULL(object);
- return;
- }
-
- i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC);
-
- if (persistent_id) {
- char *plist_key = NULL;
- int plist_key_len = 0;
- zend_rsrc_list_entry *le;
- php_memc_t *pi_obj = NULL;
-
- plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id);
- if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len+1, (void *)&le) == SUCCESS) {
- if (le->type == php_memc_list_entry()) {
- pi_obj = (php_memc_t *) le->ptr;
- }
- }
-
- /*
- * If persistent memcache object is found under the given ID, skip constructor.
- * Otherwise, create a new persistent object.
- */
- if (pi_obj) {
- skip_ctor = 1;
- } else {
- pi_obj = pecalloc(1, sizeof(*pi_obj), 1);
-
- if (pi_obj == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle");
- /* not reached */
- }
-
- pi_obj->is_persistent = 1;
- if ((pi_obj->plist_key = pemalloc(plist_key_len + 1, 1)) == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle");
- /* not reached */
- }
- memcpy((char *)pi_obj->plist_key, plist_key, plist_key_len + 1);
- pi_obj->plist_key_len = plist_key_len + 1;
-
- /*
- * Copy state bits because we've just constructed a new persistent object.
- */
- pi_obj->compression = i_obj->compression;
- }
-
- /*
- * Copy emalloc'ed bits.
- */
- pi_obj->zo = i_obj->zo;
-
- /*
- * Replace non-persistent object with the persistent one.
- */
- efree(i_obj);
- i_obj = pi_obj;
- zend_object_store_set_object(object, i_obj TSRMLS_CC);
-
- if (plist_key) {
- efree(plist_key);
- }
- }
-
- if (skip_ctor) {
- return;
- }
-
- memc = memcached_create(NULL);
- if (memc == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure");
- /* not reached */
- }
- i_obj->memc = memc;
-
- if (persistent_id) {
- zend_rsrc_list_entry le;
-
- le.type = php_memc_list_entry();
- le.ptr = i_obj;
- if (zend_hash_update(&EG(persistent_list), (char *)i_obj->plist_key,
- i_obj->plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry");
- /* not reached */
- }
- }
-}
-/* }}} */
-
-/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ])
- Returns a value for the given key or false */
-PHP_METHOD(Memcached, get)
-{
- php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ])
- Returns a value for key from the server identified by the server key or false */
-PHP_METHOD(Memcached, getByKey)
-{
- php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_get_impl */
-static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- char *key = NULL;
- size_t key_len = 0;
- char *server_key = NULL;
- int server_key_len = 0;
- char *payload = NULL;
- size_t payload_len = 0;
- uint32_t flags = 0;
- uint64_t cas = 0;
- zval *cas_token = NULL;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fcc = empty_fcall_info_cache;
- memcached_result_st result;
- memcached_return status = MEMCACHED_SUCCESS;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|fz", &server_key,
- &server_key_len, &key, &key_len, &fci, &fcc, &cas_token) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|fz", &key, &key_len,
- &fci, &fcc, &cas_token) == FAILURE) {
- return;
- }
- }
-
- if (key_len == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- RETURN_FALSE;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- if (cas_token) {
-
- uint64_t orig_cas_flag;
-
- /*
- * Enable CAS support, but only if it is currently disabled.
- */
- orig_cas_flag = memcached_behavior_get(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
- }
-
- status = memcached_mget_by_key(i_obj->memc, server_key, server_key_len, &key, &key_len, 1);
-
- if (php_memc_handle_error(status) < 0) {
- RETURN_FALSE;
- }
-
- status = MEMCACHED_SUCCESS;
- memcached_result_create(i_obj->memc, &result);
-
- if (memcached_fetch_result(i_obj->memc, &result, &status) == NULL) {
-
- /*
- * If the result wasn't found, and we have the read-through callback, invoke
- * it to get the value. The CAS token will be 0, because we cannot generate it
- * ourselves.
- */
- if ((status == MEMCACHED_END || status == MEMCACHED_NOTFOUND) && fci.size != 0) {
- status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len,
- return_value TSRMLS_DC);
- ZVAL_DOUBLE(cas_token, 0);
- }
-
- if (php_memc_handle_error(status) < 0) {
- memcached_result_free(&result);
- RETURN_FALSE;
- }
-
- /* if we have a callback, all processing is done */
- if (fci.size != 0) {
- return;
- }
- }
-
- payload = memcached_result_value(&result);
- payload_len = memcached_result_length(&result);
- flags = memcached_result_flags(&result);
- cas = memcached_result_cas(&result);
-
- if (php_memc_zval_from_payload(return_value, payload, payload_len, flags TSRMLS_CC) < 0) {
- memcached_result_free(&result);
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- zval_dtor(cas_token);
- ZVAL_DOUBLE(cas_token, (double)cas);
-
- memcached_result_free(&result);
-
- /*
- * Restore the CAS support flag, but only if we had to turn it on.
- */
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
- }
- return;
-
- } else {
-
- size_t dummy_length;
- uint32_t dummy_flags;
- int rc;
- memcached_return dummy_status;
-
- status = memcached_mget_by_key(i_obj->memc, server_key, server_key_len, &key, &key_len, 1);
- payload = memcached_fetch(i_obj->memc, NULL, NULL, &payload_len, &flags, &status);
- /* This is for historical reasons */
- if (status == MEMCACHED_END)
- status = MEMCACHED_NOTFOUND;
-
- /*
- * If payload wasn't found and we have a read-through callback, invoke it to get
- * the value. The callback will take care of storing the value back into memcache.
- */
- if (payload == NULL && status == MEMCACHED_NOTFOUND && fci.size != 0) {
- status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len,
- return_value TSRMLS_DC);
- }
-
- (void)memcached_fetch(i_obj->memc, NULL, NULL, &dummy_length, &dummy_flags, &dummy_status);
-
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- if (payload) {
- free(payload);
- }
- RETURN_FALSE;
- }
-
- /* payload will be NULL if the callback was invoked */
- if (payload != NULL) {
- rc = php_memc_zval_from_payload(return_value, payload, payload_len, flags TSRMLS_CC);
- free(payload);
- if (rc < 0) {
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
- }
-
- }
-}
-/* }}} */
-
-/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ])
- Returns values for the given keys or false */
-PHP_METHOD(Memcached, getMulti)
-{
- php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ])
- Returns values for the given keys from the server identified by the server key or false */
-PHP_METHOD(Memcached, getMultiByKey)
-{
- php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_getMulti_impl */
-static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- zval *keys = NULL;
- char *server_key = NULL;
- int server_key_len = 0;
- size_t num_keys = 0;
- zval **entry = NULL;
- char *payload = NULL;
- size_t payload_len = 0;
- char **mkeys = NULL;
- size_t *mkeys_len = NULL;
- char *res_key = NULL;
- size_t res_key_len = 0;
- uint32_t flags;
- uint64_t cas = 0;
- zval *cas_tokens = NULL;
- uint64_t orig_cas_flag;
- zval *value;
- int i = 0;
- memcached_result_st result;
- memcached_return status = MEMCACHED_SUCCESS;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|z", &server_key,
- &server_key_len, &keys, &cas_tokens) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &keys, &cas_tokens) == FAILURE) {
- return;
- }
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
- mkeys = safe_emalloc(num_keys, sizeof(char *), 0);
- mkeys_len = safe_emalloc(num_keys, sizeof(size_t), 0);
-
- /*
- * Create the array of keys for libmemcached. If none of the keys were valid
- * (strings), set bad key result code and return.
- */
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys));
- zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(keys))) {
-
- if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) {
- mkeys[i] = Z_STRVAL_PP(entry);
- mkeys_len[i] = Z_STRLEN_PP(entry);
- i++;
- }
- }
-
- if (i == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- efree(mkeys);
- efree(mkeys_len);
- RETURN_FALSE;
- }
-
- /*
- * Enable CAS support, but only if it is currently disabled.
- */
- if (cas_tokens) {
- orig_cas_flag = memcached_behavior_get(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
- }
- }
-
- status = memcached_mget_by_key(i_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i);
-
- /*
- * Restore the CAS support flag, but only if we had to turn it on.
- */
- if (cas_tokens) {
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
- }
- }
-
- efree(mkeys);
- efree(mkeys_len);
- if (php_memc_handle_error(status) < 0) {
- RETURN_FALSE;
- }
-
- /*
- * Iterate through the result set and create the result array. The CAS tokens are
- * returned as doubles, because we cannot store potential 64-bit values in longs.
- */
- if (cas_tokens) {
- zval_dtor(cas_tokens);
- array_init(cas_tokens);
- }
- array_init(return_value);
- status = MEMCACHED_SUCCESS;
- memcached_result_create(i_obj->memc, &result);
- while ((memcached_fetch_result(i_obj->memc, &result, &status)) != NULL) {
-
- payload = memcached_result_value(&result);
- payload_len = memcached_result_length(&result);
- flags = memcached_result_flags(&result);
- res_key = memcached_result_key_value(&result);
- res_key_len = memcached_result_key_length(&result);
-
- MAKE_STD_ZVAL(value);
-
- if (php_memc_zval_from_payload(value, payload, payload_len, flags TSRMLS_CC) < 0) {
- zval_ptr_dtor(&value);
- zval_dtor(return_value);
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- add_assoc_zval_ex(return_value, res_key, res_key_len+1, value);
- if (cas_tokens) {
- cas = memcached_result_cas(&result);
- add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas);
- }
- }
-
- memcached_result_free(&result);
-
- if (status != MEMCACHED_END && php_memc_handle_error(status) < 0) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ])
- Sends a request for the given keys and returns immediately */
-PHP_METHOD(Memcached, getDelayed)
-{
- php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ])
- Sends a request for the given keys from the server identified by the server key and returns immediately */
-PHP_METHOD(Memcached, getDelayedByKey)
-{
- php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_getDelayed_impl */
-static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- zval *keys = NULL;
- char *server_key = NULL;
- int server_key_len = 0;
- zend_bool with_cas = 0;
- size_t num_keys = 0;
- zval **entry = NULL;
- char **mkeys = NULL;
- size_t *mkeys_len = NULL;
- uint64_t orig_cas_flag;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fcc = empty_fcall_info_cache;
- int i = 0;
- memcached_return status = MEMCACHED_SUCCESS;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|bf", &server_key,
- &server_key_len, &keys, &with_cas, &fci, &fcc) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|bf", &keys, &with_cas,
- &fci, &fcc) == FAILURE) {
- return;
- }
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- /*
- * Create the array of keys for libmemcached. If none of the keys were valid
- * (strings), set bad key result code and return.
- */
- num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
- mkeys = safe_emalloc(num_keys, sizeof(char *), 0);
- mkeys_len = safe_emalloc(num_keys, sizeof(size_t), 0);
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys));
- zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(keys))) {
-
- if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) {
- mkeys[i] = Z_STRVAL_PP(entry);
- mkeys_len[i] = Z_STRLEN_PP(entry);
- i++;
- }
- }
-
- if (i == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- efree(mkeys);
- efree(mkeys_len);
- RETURN_FALSE;
- }
-
- /*
- * Enable CAS support, but only if it is currently disabled.
- */
- if (with_cas) {
- orig_cas_flag = memcached_behavior_get(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
- }
- }
-
- /*
- * Issue the request, but collect results only if the result callback is provided.
- */
- status = memcached_mget_by_key(i_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i);
-
- /*
- * Restore the CAS support flag, but only if we had to turn it on.
- */
- if (with_cas) {
- if (orig_cas_flag == 0) {
- memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
- }
- }
-
- efree(mkeys);
- efree(mkeys_len);
- if (php_memc_handle_error(status) < 0) {
- RETURN_FALSE;
- }
-
- if (fci.size != 0) {
- /*
- * We have a result callback. Iterate through the result set and invoke the
- * callback for each one.
- */
- memcached_result_st result;
-
- memcached_result_create(i_obj->memc, &result);
- while ((memcached_fetch_result(i_obj->memc, &result, &status)) != NULL) {
- if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result TSRMLS_CC) < 0) {
- status = MEMCACHED_FAILURE;
- break;
- }
- }
- memcached_result_free(&result);
-
- /* we successfully retrieved all rows */
- if (status == MEMCACHED_END) {
- status = MEMCACHED_SUCCESS;
- }
- if (php_memc_handle_error(status) < 0) {
- RETURN_FALSE;
- }
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::fetch()
- Returns the next result from a previous delayed request */
-PHP_METHOD(Memcached, fetch)
-{
- char *res_key = NULL;
- size_t res_key_len = 0;
- char *payload = NULL;
- size_t payload_len = 0;
- zval *value;
- uint32_t flags = 0;
- uint64_t cas = 0;
- memcached_result_st result;
- memcached_return status = MEMCACHED_SUCCESS;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- memcached_result_create(i_obj->memc, &result);
- if ((memcached_fetch_result(i_obj->memc, &result, &status)) == NULL) {
- php_memc_handle_error(status TSRMLS_CC);
- memcached_result_free(&result);
- RETURN_FALSE;
- }
-
- payload = memcached_result_value(&result);
- payload_len = memcached_result_length(&result);
- flags = memcached_result_flags(&result);
- res_key = memcached_result_key_value(&result);
- res_key_len = memcached_result_key_length(&result);
- cas = memcached_result_cas(&result);
-
- MAKE_STD_ZVAL(value);
-
- if (php_memc_zval_from_payload(value, payload, payload_len, flags TSRMLS_CC) < 0) {
- zval_ptr_dtor(&value);
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- array_init(return_value);
- add_assoc_stringl_ex(return_value, ZEND_STRS("key"), res_key, res_key_len, 1);
- add_assoc_zval_ex(return_value, ZEND_STRS("value"), value);
- add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas);
-
- memcached_result_free(&result);
-}
-/* }}} */
-
-/* {{{ Memcached::fetchAll()
- Returns all the results from a previous delayed request */
-PHP_METHOD(Memcached, fetchAll)
-{
- char *res_key = NULL;
- size_t res_key_len = 0;
- char *payload = NULL;
- size_t payload_len = 0;
- zval *value, *entry;
- uint32_t flags;
- uint64_t cas = 0;
- memcached_result_st result;
- memcached_return status = MEMCACHED_SUCCESS;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- array_init(return_value);
- memcached_result_create(i_obj->memc, &result);
-
- while ((memcached_fetch_result(i_obj->memc, &result, &status)) != NULL) {
-
- payload = memcached_result_value(&result);
- payload_len = memcached_result_length(&result);
- flags = memcached_result_flags(&result);
- res_key = memcached_result_key_value(&result);
- res_key_len = memcached_result_key_length(&result);
- cas = memcached_result_cas(&result);
-
- MAKE_STD_ZVAL(value);
-
- if (php_memc_zval_from_payload(value, payload, payload_len, flags TSRMLS_CC) < 0) {
- zval_ptr_dtor(&value);
- zval_dtor(return_value);
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- MAKE_STD_ZVAL(entry);
- array_init(entry);
- add_assoc_stringl_ex(entry, ZEND_STRS("key"), res_key, res_key_len, 1);
- add_assoc_zval_ex(entry, ZEND_STRS("value"), value);
- add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas);
- add_next_index_zval(return_value, entry);
- }
-
- memcached_result_free(&result);
-
- if (status != MEMCACHED_END && php_memc_handle_error(status) < 0) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ Memcached::set(string key, mixed value [, int expiration ])
- Sets the value for the given key */
-PHP_METHOD(Memcached, set)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ])
- Sets the value for the given key on the server identified by the server key */
-PHP_METHOD(Memcached, setByKey)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1);
-}
-/* }}} */
-
-/* {{{ Memcached::setMulti(array entries [, int expiration ])
- Sets the keys/values specified in the entries array */
-PHP_METHOD(Memcached, setMulti)
-{
- php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::setMultiByKey(string server_key, array entries [, int expiration ])
- Sets the keys/values specified in the entries array on the server identified by the given server key */
-PHP_METHOD(Memcached, setMultiByKey)
-{
- php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_setMulti_impl */
-static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- zval *entries;
- char *server_key = NULL;
- int server_key_len = 0;
- time_t expiration = 0;
- zval **entry;
- char *str_key;
- uint str_key_len;
- ulong num_key;
- char *payload;
- size_t payload_len;
- uint32_t flags = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &server_key,
- &server_key_len, &entries, &expiration) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &entries, &expiration) == FAILURE) {
- return;
- }
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries));
- zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(entries))) {
-
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(entries), &str_key, &str_key_len, &num_key, 0, NULL) != HASH_KEY_IS_STRING) {
- continue;
- }
-
- flags = 0;
- if (i_obj->compression) {
- flags |= MEMC_VAL_COMPRESSED;
- }
-
- payload = php_memc_zval_to_payload(*entry, &payload_len, &flags TSRMLS_CC);
- if (payload == NULL) {
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- if (!by_key) {
- server_key = str_key;
- server_key_len = str_key_len;
- }
- status = memcached_set_by_key(i_obj->memc, server_key, server_key_len, str_key,
- str_key_len, payload, payload_len, expiration, flags);
- efree(payload);
-
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::add(string key, mixed value [, int expiration ])
- Sets the value for the given key, failing if the key already exists */
-PHP_METHOD(Memcached, add)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ])
- Sets the value for the given key on the server identified by the sever key, failing if the key already exists */
-PHP_METHOD(Memcached, addByKey)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1);
-}
-/* }}} */
-
-/* {{{ Memcached::append(string key, mixed value)
- Appends the value to existing one for the key */
-PHP_METHOD(Memcached, append)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::appendByKey(string server_key, string key, mixed value)
- Appends the value to existing one for the key on the server identified by the server key */
-PHP_METHOD(Memcached, appendByKey)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1);
-}
-/* }}} */
-
-/* {{{ Memcached::prepend(string key, mixed value)
- Prepends the value to existing one for the key */
-PHP_METHOD(Memcached, prepend)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::prependByKey(string server_key, string key, mixed value)
- Prepends the value to existing one for the key on the server identified by the server key */
-PHP_METHOD(Memcached, prependByKey)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1);
-}
-/* }}} */
-
-/* {{{ Memcached::replace(string key, mixed value [, int expiration ])
- Replaces the value for the given key, failing if the key doesn't exist */
-PHP_METHOD(Memcached, replace)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ])
- Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */
-PHP_METHOD(Memcached, replaceByKey)
-{
- php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_store_impl */
-static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key)
-{
- char *key = NULL;
- int key_len = 0;
- char *server_key = NULL;
- int server_key_len = 0;
- zval *value;
- time_t expiration = 0;
- char *payload;
- size_t payload_len;
- uint32_t flags = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|l", &server_key,
- &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &key, &key_len,
- &value, &expiration) == FAILURE) {
- return;
- }
- server_key = key;
- server_key_len = key_len;
- }
-
- if (key_len == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- RETURN_FALSE;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- if (i_obj->compression) {
- /*
- * When compression is enabled, we cannot do appends/prepends because that would
- * corrupt the compressed values. It is up to the user to fetch the value,
- * append/prepend new data, and store it again.
- */
- if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on");
- return;
- }
- flags |= MEMC_VAL_COMPRESSED;
- }
-
- payload = php_memc_zval_to_payload(value, &payload_len, &flags TSRMLS_CC);
- if (payload == NULL) {
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
-
- switch (op) {
- case MEMC_OP_SET:
- status = memcached_set_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, payload, payload_len, expiration, flags);
- break;
-
- case MEMC_OP_ADD:
- status = memcached_add_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, payload, payload_len, expiration, flags);
- break;
-
- case MEMC_OP_REPLACE:
- status = memcached_replace_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, payload, payload_len, expiration, flags);
- break;
-
- case MEMC_OP_APPEND:
- status = memcached_append_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, payload, payload_len, expiration, flags);
- break;
-
- case MEMC_OP_PREPEND:
- status = memcached_prepend_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, payload, payload_len, expiration, flags);
- break;
-
- default:
- /* not reached */
- assert(0);
- break;
- }
-
- efree(payload);
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ])
- Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */
-PHP_METHOD(Memcached, cas)
-{
- php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ])
- Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */
-PHP_METHOD(Memcached, casByKey)
-{
- php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_cas_impl */
-static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- double cas_d;
- uint64_t cas;
- char *key = NULL;
- int key_len = 0;
- char *server_key = NULL;
- int server_key_len = 0;
- zval *value;
- time_t expiration = 0;
- char *payload;
- size_t payload_len;
- uint32_t flags = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|l", &cas_d, &server_key,
- &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|l", &cas_d, &key, &key_len,
- &value, &expiration) == FAILURE) {
- return;
- }
- server_key = key;
- server_key_len = key_len;
- }
-
- if (key_len == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- RETURN_FALSE;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- DVAL_TO_LVAL(cas_d, cas);
-
- if (i_obj->compression) {
- flags |= MEMC_VAL_COMPRESSED;
- }
-
- payload = php_memc_zval_to_payload(value, &payload_len, &flags TSRMLS_CC);
- if (payload == NULL) {
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- RETURN_FALSE;
- }
- status = memcached_cas_by_key(i_obj->memc, server_key, server_key_len, key, key_len,
- payload, payload_len, expiration, flags, cas);
- efree(payload);
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::delete(string key [, int expiration ])
- Deletes the given key */
-PHP_METHOD(Memcached, delete)
-{
- php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ Memcached::deleteByKey(string server_key, string key [, int expiration ])
- Deletes the given key from the server identified by the server key */
-PHP_METHOD(Memcached, deleteByKey)
-{
- php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ -- php_memc_delete_impl */
-static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
-{
- char *key = NULL;
- int key_len = 0;
- char *server_key = NULL;
- int server_key_len = 0;
- time_t expiration = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (by_key) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key,
- &server_key_len, &key, &key_len, &expiration) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len,
- &expiration) == FAILURE) {
- return;
- }
- server_key = key;
- server_key_len = key_len;
- }
-
- if (key_len == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- RETURN_FALSE;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- status = memcached_delete_by_key(i_obj->memc, server_key, server_key_len, key,
- key_len, expiration);
-
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::increment(string key [, int delta ])
- Increments the value for the given key by delta, defaulting to 1 */
-PHP_METHOD(Memcached, increment)
-{
- php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-/* {{{ Memcached::decrement(string key [, int delta ])
- Decrements the value for the given key by delta, defaulting to 1 */
-PHP_METHOD(Memcached, decrement)
-{
- php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ -- php_memc_incdec_impl */
-static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr)
-{
- char *key = NULL;
- int key_len = 0;
- long offset = 1;
- uint64_t value;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &offset) == FAILURE) {
- return;
- }
-
- if (key_len == 0) {
- MEMC_G(rescode) = MEMCACHED_BAD_KEY_PROVIDED;
- RETURN_FALSE;
- }
-
- if (offset < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset has to be > 0");
- RETURN_FALSE;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- if (incr) {
- status = memcached_increment(i_obj->memc, key, key_len, (unsigned int)offset, &value);
- } else {
- status = memcached_decrement(i_obj->memc, key, key_len, (unsigned int)offset, &value);
- }
-
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_LONG((long)value);
-}
-/* }}} */
-
-/* {{{ Memcached::addServer(string hostname, int port [, int weight ])
- Adds the given memcache server to the list */
-PHP_METHOD(Memcached, addServer)
-{
- char *host;
- int host_len;
- long port, weight = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &host, &host_len,
- &port, &weight) == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- status = memcached_server_add_with_weight(i_obj->memc, host, port, weight);
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::getServerList()
- Returns the list of the memcache servers in use */
-PHP_METHOD(Memcached, getServerList)
-{
- memcached_server_st *servers;
- unsigned int i, servers_count;
- zval *array;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
-
- array_init(return_value);
- servers = memcached_server_list(i_obj->memc);
- servers_count = memcached_server_count(i_obj->memc);
- if (servers == NULL) {
- return;
- }
-
- for (i = 0; i < servers_count; i++) {
- MAKE_STD_ZVAL(array);
- array_init(array);
- add_assoc_string(array, "host", servers[i].hostname, 1);
- add_assoc_long(array, "port", servers[i].port);
- add_assoc_long(array, "weight", servers[i].weight);
- add_next_index_zval(return_value, array);
- }
-}
-/* }}} */
-
-/* {{{ Memcached::getServerByKey(string server_key)
- Returns the server identified by the given server key */
-PHP_METHOD(Memcached, getServerByKey)
-{
- char *server_key;
- int server_key_len;
- memcached_server_st *server;
- memcached_return error;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_key, &server_key_len) == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- server = memcached_server_by_key(i_obj->memc, server_key, server_key_len, &error);
- if (server == NULL) {
- php_memc_handle_error(error TSRMLS_CC);
- RETURN_FALSE;
- }
-
- array_init(return_value);
- add_assoc_string(return_value, "host", server->hostname, 1);
- add_assoc_long(return_value, "port", server->port);
- add_assoc_long(return_value, "weight", server->weight);
- memcached_server_free(server);
-}
-/* }}} */
-
-/* {{{ Memcached::getStats()
- Returns statistics for the memcache servers */
-PHP_METHOD(Memcached, getStats)
-{
- memcached_stat_st *stats;
- memcached_server_st *servers;
- unsigned int i, servers_count;
- memcached_return status;
- char *hostport = NULL;
- int hostport_len;
- zval *entry;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
-
- stats = memcached_stat(i_obj->memc, NULL, &status);
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- array_init(return_value);
- servers = memcached_server_list(i_obj->memc);
- servers_count = memcached_server_count(i_obj->memc);
- if (servers == NULL) {
- return;
- }
-
- for (i = 0; i < servers_count; i++) {
- hostport_len = spprintf(&hostport, 0, "%s:%d", servers[i].hostname, servers[i].port);
-
- MAKE_STD_ZVAL(entry);
- array_init(entry);
-
- add_assoc_long(entry, "pid", stats[i].pid);
- add_assoc_long(entry, "uptime", stats[i].uptime);
- add_assoc_long(entry, "threads", stats[i].threads);
- add_assoc_long(entry, "time", stats[i].time);
- add_assoc_long(entry, "pointer_size", stats[i].pointer_size);
- add_assoc_long(entry, "rusage_user_seconds", stats[i].rusage_user_seconds);
- add_assoc_long(entry, "rusage_user_microseconds", stats[i].rusage_user_microseconds);
- add_assoc_long(entry, "rusage_system_seconds", stats[i].rusage_system_seconds);
- add_assoc_long(entry, "rusage_system_microseconds", stats[i].rusage_system_microseconds);
- add_assoc_long(entry, "curr_items", stats[i].curr_items);
- add_assoc_long(entry, "total_items", stats[i].total_items);
- add_assoc_long(entry, "limit_maxbytes", stats[i].limit_maxbytes);
- add_assoc_long(entry, "curr_connections", stats[i].curr_connections);
- add_assoc_long(entry, "total_connections", stats[i].total_connections);
- add_assoc_long(entry, "connection_structures", stats[i].connection_structures);
- add_assoc_long(entry, "bytes", stats[i].bytes);
- add_assoc_long(entry, "cmd_get", stats[i].cmd_get);
- add_assoc_long(entry, "cmd_set", stats[i].cmd_set);
- add_assoc_long(entry, "get_hits", stats[i].get_hits);
- add_assoc_long(entry, "get_misses", stats[i].get_misses);
- add_assoc_long(entry, "evictions", stats[i].evictions);
- add_assoc_long(entry, "bytes_read", stats[i].bytes_read);
- add_assoc_long(entry, "bytes_written", stats[i].bytes_written);
- add_assoc_stringl(entry, "version", stats[i].version, strlen(stats[i].version), 1);
-
- add_assoc_zval_ex(return_value, hostport, hostport_len+1, entry);
- efree(hostport);
- }
-
- memcached_stat_free(i_obj->memc, stats);
-}
-/* }}} */
-
-/* {{{ Memcached::flush([ int expiration ])
- Flushes the data on all the servers */
-static PHP_METHOD(Memcached, flush)
-{
- time_t expiration = 0;
- memcached_return status;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &expiration) == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-
- status = memcached_flush(i_obj->memc, expiration);
- if (php_memc_handle_error(status TSRMLS_CC) < 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::getOption(int option)
- Returns the value for the given option constant */
-static PHP_METHOD(Memcached, getOption)
-{
- long option;
- uint64_t result;
- memcached_behavior flag;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &option) == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
-
- switch (option) {
- case MEMC_OPT_COMPRESSION:
- RETURN_BOOL(i_obj->compression);
-
- case MEMC_OPT_PREFIX_KEY:
- {
- memcached_return retval;
- char *result;
-
- result = memcached_callback_get(i_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval);
- if (retval == MEMCACHED_SUCCESS) {
- RETURN_STRING(result, 1);
- } else {
- RETURN_EMPTY_STRING();
- }
- }
-
- case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
- case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
- if (memcached_server_count(i_obj->memc) == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "no servers defined");
- return;
- }
-
- default:
- /*
- * Assume that it's a libmemcached behavior option.
- */
- flag = (memcached_behavior) option;
- result = memcached_behavior_get(i_obj->memc, flag);
- RETURN_LONG((long)result);
- }
-}
-/* }}} */
-
-/* {{{ Memcached::setOption(int option, mixed value)
- Sets the value for the given option constant */
-static PHP_METHOD(Memcached, setOption)
-{
- long option;
- memcached_behavior flag;
- zval *value;
- MEMC_METHOD_INIT_VARS;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &option, &value) == FAILURE) {
- return;
- }
-
- MEMC_METHOD_FETCH_OBJECT;
-
- switch (option) {
- case MEMC_OPT_COMPRESSION:
- convert_to_boolean(value);
- i_obj->compression = Z_BVAL_P(value);
- break;
-
- case MEMC_OPT_PREFIX_KEY:
- {
- char *key;
- convert_to_string(value);
- if (Z_STRLEN_P(value) == 0) {
- key = NULL;
- } else {
- key = Z_STRVAL_P(value);
- }
- if (memcached_callback_set(i_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) ==
- MEMCACHED_BAD_KEY_PROVIDED) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided");
- RETURN_FALSE;
- }
- break;
- }
-
- default:
- /*
- * Assume that it's a libmemcached behavior option.
- */
- flag = (memcached_behavior) option;
- convert_to_long(value);
- if (memcached_behavior_set(i_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) == MEMCACHED_FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option");
- RETURN_FALSE;
- }
- break;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Memcached::getResultCode()
- Returns the result code from the last operation */
-static PHP_METHOD(Memcached, getResultCode)
-{
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
- return;
- }
-
- RETURN_LONG(MEMC_G(rescode));
-}
-/* }}} */
-
-
-/****************************************
- Internal support code
-****************************************/
-
-/* {{{ constructor/destructor */
-static void php_memc_destroy(php_memc_t *i_obj TSRMLS_DC)
-{
- memcached_free(i_obj->memc);
-
- pefree(i_obj, i_obj->is_persistent);
-}
-
-static void php_memc_free_storage(php_memc_t *i_obj TSRMLS_DC)
-{
- zend_object_std_dtor(&i_obj->zo TSRMLS_CC);
-
- if (!i_obj->is_persistent) {
- php_memc_destroy(i_obj TSRMLS_CC);
- }
-}
-
-zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC)
-{
- zend_object_value retval;
- php_memc_t *i_obj;
- zval *tmp;
-
- i_obj = ecalloc(1, sizeof(*i_obj));
- zend_object_std_init( &i_obj->zo, ce TSRMLS_CC );
- zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
- i_obj->compression = 1;
-
- retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC);
- retval.handlers = zend_get_std_object_handlers();
-
- return retval;
-}
-
-ZEND_RSRC_DTOR_FUNC(php_memc_dtor)
-{
- if (rsrc->ptr) {
- php_memc_t *i_obj = (php_memc_t *)rsrc->ptr;
- php_memc_destroy(i_obj TSRMLS_CC);
- rsrc->ptr = NULL;
- }
-}
-/* }}} */
-
-/* {{{ internal API functions */
-static int php_memc_handle_error(memcached_return status TSRMLS_DC)
-{
- int result = 0;
-
- switch (status) {
- case MEMCACHED_SUCCESS:
- case MEMCACHED_STORED:
- case MEMCACHED_DELETED:
- case MEMCACHED_STAT:
- result = 0;
- break;
-
- case MEMCACHED_END:
- case MEMCACHED_BUFFERED:
- MEMC_G(rescode) = status;
- result = 0;
- break;
-
- default:
- MEMC_G(rescode) = status;
- result = -1;
- break;
- }
-
- return result;
-}
-
-static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags TSRMLS_DC)
-{
- char *payload;
- smart_str buf = {0};
-
- switch (Z_TYPE_P(value)) {
-
- case IS_STRING:
- smart_str_appendl(&buf, Z_STRVAL_P(value), Z_STRLEN_P(value));
- break;
-
- case IS_LONG:
- case IS_DOUBLE:
- case IS_BOOL:
- {
- zval value_copy;
-
- value_copy = *value;
- zval_copy_ctor(&value_copy);
- convert_to_string(&value_copy);
- smart_str_appendl(&buf, Z_STRVAL(value_copy), Z_STRLEN(value_copy));
- zval_dtor(&value_copy);
-
- *flags &= ~MEMC_VAL_COMPRESSED;
- if (Z_TYPE_P(value) == IS_LONG) {
- *flags |= MEMC_VAL_IS_LONG;
- } else if (Z_TYPE_P(value) == IS_DOUBLE) {
- *flags |= MEMC_VAL_IS_DOUBLE;
- }
- break;
- }
-
- default:
- {
- php_serialize_data_t var_hash;
-
- PHP_VAR_SERIALIZE_INIT(var_hash);
- php_var_serialize(&buf, &value, &var_hash TSRMLS_CC);
- PHP_VAR_SERIALIZE_DESTROY(var_hash);
-
- if (!buf.c) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value");
- smart_str_free(&buf);
- return NULL;
- }
-
- *flags |= MEMC_VAL_SERIALIZED;
- break;
- }
- }
-
- /* turn off compression for values below the threshold */
- if (buf.len < MEMC_COMPRESS_THRESHOLD) {
- *flags &= ~MEMC_VAL_COMPRESSED;
- }
-
- if (*flags & MEMC_VAL_COMPRESSED) {
- unsigned long payload_comp_len = buf.len + (buf.len / 500) + 25 + 1;
- char *payload_comp = emalloc(payload_comp_len);
-
- if (compress(payload_comp, &payload_comp_len, buf.c, buf.len) != Z_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value");
- free(payload_comp);
- smart_str_free(&buf);
- return NULL;
- }
- payload = payload_comp;
- *payload_len = payload_comp_len;
- payload[*payload_len] = 0;
- } else {
- payload = emalloc(buf.len + 1);
- *payload_len = buf.len;
- memcpy(payload, buf.c, buf.len);
- payload[buf.len] = 0;
- }
-
- smart_str_free(&buf);
- return payload;
-}
-
-static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags TSRMLS_DC)
-{
- if (payload == NULL) {
- return -1;
- }
-
- if (flags & MEMC_VAL_COMPRESSED) {
- /*
- From gzuncompress().
-
- zlib::uncompress() wants to know the output data length
- if none was given as a parameter
- we try from input length * 2 up to input length * 2^15
- doubling it whenever it wasn't big enough
- that should be eneugh for all real life cases
- */
- unsigned int factor = 1, maxfactor = 16;
- unsigned long length;
- int status;
- char *buf = NULL;
- do {
- length = (unsigned long)payload_len * (1 << factor++);
- buf = erealloc(buf, length + 1);
- memset(buf, 0, length + 1);
- status = uncompress(buf, &length, payload, payload_len);
- } while ((status==Z_BUF_ERROR) && (factor < maxfactor));
-
- payload = emalloc(length + 1);
- memcpy(payload, buf, length);
- payload_len = length;
- payload[payload_len] = 0;
- efree(buf);
- if (status != Z_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not uncompress value");
- efree(payload);
- return -1;
- }
- }
-
- if (flags & MEMC_VAL_SERIALIZED) {
- const char *payload_tmp = payload;
- php_unserialize_data_t var_hash;
-
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, payload_tmp + payload_len, &var_hash TSRMLS_CC)) {
- ZVAL_FALSE(value);
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- if (flags & MEMC_VAL_COMPRESSED) {
- efree(payload);
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value");
- return -1;
- }
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
- } else {
- payload[payload_len] = 0;
- if (flags & MEMC_VAL_IS_LONG) {
- long lval = strtol(payload, NULL, 10);
- ZVAL_LONG(value, lval);
- } else if (flags & MEMC_VAL_IS_DOUBLE) {
- double dval = zend_strtod(payload, NULL);
- ZVAL_DOUBLE(value, dval);
- } else {
- ZVAL_STRINGL(value, payload, payload_len, 1);
- }
- }
-
- if (flags & MEMC_VAL_COMPRESSED) {
- efree(payload);
- }
-
- return 0;
-}
-
-static int php_memc_list_entry(void)
-{
- return le_memc;
-}
-
-static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC)
-{
- MEMC_G(rescode) = MEMCACHED_SUCCESS;
-#if HAVE_MEMCACHED_SESSION
- MEMC_G(sess_locked) = 0;
- MEMC_G(sess_lock_key) = NULL;
- MEMC_G(sess_lock_key_len) = 0;
-#endif
-}
-
-static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC)
-{
-}
-
-PHP_MEMCACHED_API
-zend_class_entry *php_memc_get_ce(void)
-{
- return memcached_ce;
-}
-
-PHP_MEMCACHED_API
-zend_class_entry *php_memc_get_exception(void)
-{
- return memcached_exception_ce;
-}
-
-PHP_MEMCACHED_API
-zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC)
-{
-#if HAVE_SPL
- if (!root) {
- if (!spl_ce_RuntimeException) {
- zend_class_entry **pce;
-
- if (zend_hash_find(CG(class_table), "runtimeexception",
- sizeof("RuntimeException"), (void **) &pce) == SUCCESS) {
- spl_ce_RuntimeException = *pce;
- return *pce;
- }
- } else {
- return spl_ce_RuntimeException;
- }
- }
-#endif
-#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
- return zend_exception_get_default();
-#else
- return zend_exception_get_default(TSRMLS_C);
-#endif
-}
-
-static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci,
- zend_fcall_info_cache *fcc, char *key,
- size_t key_len, zval *value TSRMLS_DC)
-{
- char *payload = NULL;
- size_t payload_len = 0;
- zval **params[3];
- zval *retval;
- zval *z_key;
- uint32_t flags = 0;
- memcached_return rc;
- php_memc_t* i_obj;
- memcached_return status = MEMCACHED_SUCCESS;
-
- MAKE_STD_ZVAL(z_key);
- ZVAL_STRINGL(z_key, key, key_len, 1);
- ZVAL_NULL(value);
-
- params[0] = &memc_obj;
- params[1] = &z_key;
- params[2] = &value;
-
- fci->retval_ptr_ptr = &retval;
- fci->params = params;
- fci->param_count = 3;
-
- if (zend_call_function(fci, fcc TSRMLS_CC) == SUCCESS && retval) {
- i_obj = (php_memc_t *) zend_object_store_get_object(memc_obj TSRMLS_CC);
-
- convert_to_boolean(retval);
- if (Z_BVAL_P(retval) == 1) {
- payload = php_memc_zval_to_payload(value, &payload_len, &flags TSRMLS_CC);
- if (payload == NULL) {
- status = MEMC_RES_PAYLOAD_FAILURE;
- } else {
- rc = memcached_set(i_obj->memc, key, key_len, payload, payload_len, 0, flags);
- if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) {
- status = rc;
- }
- efree(payload);
- }
- } else {
- status = MEMCACHED_NOTFOUND;
- }
-
- zval_ptr_dtor(&retval);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke cache callback");
- status = MEMCACHED_FAILURE;
- }
-
- zval_ptr_dtor(&z_key);
-
- return status;
-}
-
-static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci,
- zend_fcall_info_cache *fcc,
- memcached_result_st *result TSRMLS_DC)
-{
- char *res_key = NULL;
- size_t res_key_len = 0;
- char *payload = NULL;
- size_t payload_len = 0;
- zval *value, *retval = NULL;
- uint64_t cas = 0;
- zval **params[2];
- zval *z_result;
- uint32_t flags = 0;
- int rc = 0;
-
- params[0] = &memc_obj;
- params[1] = &z_result;
-
- fci->retval_ptr_ptr = &retval;
- fci->params = params;
- fci->param_count = 2;
-
- payload = memcached_result_value(result);
- payload_len = memcached_result_length(result);
- flags = memcached_result_flags(result);
- res_key = memcached_result_key_value(result);
- res_key_len = memcached_result_key_length(result);
- cas = memcached_result_cas(result);
-
- MAKE_STD_ZVAL(value);
-
- if (php_memc_zval_from_payload(value, payload, payload_len, flags TSRMLS_CC) < 0) {
- zval_ptr_dtor(&value);
- MEMC_G(rescode) = MEMC_RES_PAYLOAD_FAILURE;
- return -1;
- }
-
- MAKE_STD_ZVAL(z_result);
- array_init(z_result);
- add_assoc_stringl_ex(z_result, ZEND_STRS("key"), res_key, res_key_len, 1);
- add_assoc_zval_ex(z_result, ZEND_STRS("value"), value);
- add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas);
-
- if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback");
- rc = -1;
- }
-
- if (retval) {
- zval_ptr_dtor(&retval);
- }
- zval_ptr_dtor(&z_result);
-
- return rc;
-}
-
-/* }}} */
-
-/* {{{ session support */
-#if HAVE_MEMCACHED_SESSION
-
-#define MEMC_SESS_LOCK_ATTEMPTS 30
-#define MEMC_SESS_LOCK_WAIT 100000
-#define MEMC_SESS_LOCK_EXPIRATION 30
-
-ps_module ps_mod_memcached = {
- PS_MOD(memcached)
-};
-
-
-static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
-{
- char *lock_key = NULL;
- int lock_key_len = 0;
- int attempts = MEMC_SESS_LOCK_ATTEMPTS;
- time_t expiration = time(NULL) + MEMC_SESS_LOCK_EXPIRATION;
- memcached_return status;
-
- lock_key_len = spprintf(&lock_key, 0, "memc.sess.lock_key.%s", key);
- while (attempts--) {
- status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
- if (status == MEMCACHED_SUCCESS) {
- MEMC_G(sess_locked) = 1;
- MEMC_G(sess_lock_key) = lock_key;
- MEMC_G(sess_lock_key_len) = lock_key_len;
- return 0;
- }
- usleep(MEMC_SESS_LOCK_WAIT);
- }
-
- efree(lock_key);
- return -1;
-}
-
-static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC)
-{
- if (MEMC_G(sess_locked)) {
- memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0);
- MEMC_G(sess_locked) = 0;
- efree(MEMC_G(sess_lock_key));
- MEMC_G(sess_lock_key_len) = 0;
- }
-}
-
-PS_OPEN_FUNC(memcached)
-{
- memcached_st *memc_sess = PS_GET_MOD_DATA();
- memcached_server_st *servers;
- memcached_return status;
-
- servers = memcached_servers_parse((char *)save_path);
- if (servers) {
- memc_sess = memcached_create(NULL);
- if (memc_sess) {
- status = memcached_server_push(memc_sess, servers);
- if (status == MEMCACHED_SUCCESS) {
- PS_SET_MOD_DATA(memc_sess);
- return SUCCESS;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure");
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path");
- }
-
- PS_SET_MOD_DATA(NULL);
- return FAILURE;
-}
-
-PS_CLOSE_FUNC(memcached)
-{
- memcached_st *memc_sess = PS_GET_MOD_DATA();
-
- php_memc_sess_unlock(memc_sess TSRMLS_CC);
- if (memc_sess) {
- memcached_free(memc_sess);
- PS_SET_MOD_DATA(NULL);
- }
-
- return SUCCESS;
-}
-
-PS_READ_FUNC(memcached)
-{
- char *payload = NULL;
- size_t payload_len = 0;
- char *sess_key = NULL;
- int sess_key_len = 0;
- uint32_t flags = 0;
- memcached_return status;
- memcached_st *memc_sess = PS_GET_MOD_DATA();
-
- if (php_memc_sess_lock(memc_sess, key TSRMLS_CC) < 0) {
- return FAILURE;
- }
-
- sess_key_len = spprintf(&sess_key, 0, "memc.sess.key.%s", key);
- payload = memcached_get(memc_sess, sess_key, sess_key_len, &payload_len, &flags, &status);
- efree(sess_key);
-
- if (status == MEMCACHED_SUCCESS) {
- *val = estrndup(payload, payload_len);
- *vallen = payload_len;
- free(payload);
- return SUCCESS;
- } else {
- return FAILURE;
- }
-}
-
-PS_WRITE_FUNC(memcached)
-{
- char *sess_key = NULL;
- int sess_key_len = 0;
- time_t expiration;
- int sess_lifetime;
- memcached_return status;
- memcached_st *memc_sess = PS_GET_MOD_DATA();
-
- sess_key_len = spprintf(&sess_key, 0, "memc.sess.key.%s", key);
- sess_lifetime = zend_ini_long(ZEND_STRL("session.gc_maxlifetime"), 0);
- if (sess_lifetime > 0) {
- expiration = time(NULL) + sess_lifetime;
- } else {
- expiration = 0;
- }
- status = memcached_set(memc_sess, sess_key, sess_key_len, val, vallen, expiration, 0);
- efree(sess_key);
-
- if (status == MEMCACHED_SUCCESS) {
- return SUCCESS;
- } else {
- return FAILURE;
- }
-}
-
-PS_DESTROY_FUNC(memcached)
-{
- char *sess_key = NULL;
- int sess_key_len = 0;
- memcached_st *memc_sess = PS_GET_MOD_DATA();
-
- sess_key_len = spprintf(&sess_key, 0, "memc.sess.key.%s", key);
- memcached_delete(memc_sess, sess_key, sess_key_len, 0);
- efree(sess_key);
- php_memc_sess_unlock(memc_sess TSRMLS_CC);
-
- return SUCCESS;
-}
-
-PS_GC_FUNC(memcached)
-{
- return SUCCESS;
-}
-
-#endif
-/* }}} */
-
-/* {{{ methods arginfo */
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
- ZEND_ARG_INFO(0, persistent_id)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_getResultCode, 0)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, cache_cb)
- ZEND_ARG_INFO(1, cas_token)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, cache_cb)
- ZEND_ARG_INFO(1, cas_token)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, keys, 0)
- ZEND_ARG_INFO(1, cas_tokens)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_ARRAY_INFO(0, keys, 0)
- ZEND_ARG_INFO(1, cas_tokens)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, keys, 0)
- ZEND_ARG_INFO(0, with_cas)
- ZEND_ARG_INFO(0, value_cb)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayedByKey, 0, 0, 2)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_ARRAY_INFO(0, keys, 0)
- ZEND_ARG_INFO(0, with_cas)
- ZEND_ARG_INFO(0, value_cb)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_fetch, 0)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_fetchAll, 0)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1)
- ZEND_ARG_ARRAY_INFO(0, entries, 0)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_ARRAY_INFO(0, entries, 0)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3)
- ZEND_ARG_INFO(0, cas_token)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4)
- ZEND_ARG_INFO(0, cas_token)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteByKey, 0, 0, 2)
- ZEND_ARG_INFO(0, server_key)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, offset)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_INFO(0, offset)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0)
- ZEND_ARG_INFO(0, expiration)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2)
- ZEND_ARG_INFO(0, host)
- ZEND_ARG_INFO(0, port)
- ZEND_ARG_INFO(0, weight)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_getServerList, 0)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0)
- ZEND_ARG_INFO(0, server_key)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0)
- ZEND_ARG_INFO(0, option)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0)
- ZEND_ARG_INFO(0, option)
- ZEND_ARG_INFO(0, value)
-ZEND_END_ARG_INFO()
-
-static
-ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0)
-ZEND_END_ARG_INFO()
-/* }}} */
-
-/* {{{ memcached_class_methods */
-#define MEMC_ME(name, args) PHP_ME(Memcached, name, args, ZEND_ACC_PUBLIC)
-static zend_function_entry memcached_class_methods[] = {
- MEMC_ME(__construct, arginfo___construct)
-
- MEMC_ME(getResultCode, arginfo_getResultCode)
-
- MEMC_ME(get, arginfo_get)
- MEMC_ME(getByKey, arginfo_getByKey)
- MEMC_ME(getMulti, arginfo_getMulti)
- MEMC_ME(getMultiByKey, arginfo_getMultiByKey)
- MEMC_ME(getDelayed, arginfo_getDelayed)
- MEMC_ME(getDelayedByKey, arginfo_getDelayedByKey)
- MEMC_ME(fetch, arginfo_fetch)
- MEMC_ME(fetchAll, arginfo_fetchAll)
-
- MEMC_ME(set, arginfo_set)
- MEMC_ME(setByKey, arginfo_setByKey)
- MEMC_ME(setMulti, arginfo_setMulti)
- MEMC_ME(setMultiByKey, arginfo_setMultiByKey)
-
- MEMC_ME(cas, arginfo_cas)
- MEMC_ME(casByKey, arginfo_casByKey)
- MEMC_ME(add, arginfo_add)
- MEMC_ME(addByKey, arginfo_addByKey)
- MEMC_ME(append, arginfo_append)
- MEMC_ME(appendByKey, arginfo_appendByKey)
- MEMC_ME(prepend, arginfo_prepend)
- MEMC_ME(prependByKey, arginfo_prependByKey)
- MEMC_ME(replace, arginfo_replace)
- MEMC_ME(replaceByKey, arginfo_replaceByKey)
- MEMC_ME(delete, arginfo_delete)
- MEMC_ME(deleteByKey, arginfo_deleteByKey)
-
- MEMC_ME(increment, arginfo_increment)
- MEMC_ME(decrement, arginfo_decrement)
-
- MEMC_ME(addServer, arginfo_addServer)
- MEMC_ME(getServerList, arginfo_getServerList)
- MEMC_ME(getServerByKey, arginfo_getServerByKey)
-
- MEMC_ME(getStats, arginfo_getStats)
-
- MEMC_ME(flush, arginfo_flush)
-
- MEMC_ME(getOption, arginfo_getOption)
- MEMC_ME(setOption, arginfo_setOption)
- { NULL, NULL, NULL }
-};
-#undef MEMC_ME
-/* }}} */
-
-/* {{{ memcached_module_entry
- */
-
-#if ZEND_MODULE_API_NO >= 20050922
-static const zend_module_dep memcached_deps[] = {
-#ifdef HAVE_MEMCACHED_SESSION
- ZEND_MOD_REQUIRED("session")
-#endif
-#ifdef HAVE_SPL
- ZEND_MOD_REQUIRED("spl")
-#endif
- {NULL, NULL, NULL}
-};
-#endif
-
-zend_module_entry memcached_module_entry = {
-#if ZEND_MODULE_API_NO >= 20050922
- STANDARD_MODULE_HEADER_EX, NULL,
- (zend_module_dep*)memcached_deps,
-#else
- STANDARD_MODULE_HEADER,
-#endif
- "memcached",
- NULL,
- PHP_MINIT(memcached),
- PHP_MSHUTDOWN(memcached),
- NULL,
- NULL,
- PHP_MINFO(memcached),
- PHP_MEMCACHED_VERSION,
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-/* {{{ php_memc_register_constants */
-static void php_memc_register_constants(INIT_FUNC_ARGS)
-{
- #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC)
-
- /*
- * Class options
- */
-
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY);
-
- /*
- * libmemcached behavior options
- */
-
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_HASH, MEMCACHED_BEHAVIOR_HASH);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_DEFAULT, MEMCACHED_HASH_DEFAULT);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_MD5, MEMCACHED_HASH_MD5);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_CRC, MEMCACHED_HASH_CRC);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_64, MEMCACHED_HASH_FNV1_64);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_64, MEMCACHED_HASH_FNV1A_64);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_32, MEMCACHED_HASH_FNV1_32);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_32, MEMCACHED_HASH_FNV1A_32);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_HSIEH, MEMCACHED_HASH_HSIEH);
- REGISTER_MEMC_CLASS_CONST_LONG(HASH_MURMUR, MEMCACHED_HASH_MURMUR);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION);
- REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA);
- REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_BUFFER_WRITES, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_BINARY_PROTOCOL, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_NO_BLOCK, MEMCACHED_BEHAVIOR_NO_BLOCK);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_NODELAY, MEMCACHED_BEHAVIOR_TCP_NODELAY);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_SEND_SIZE, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_RECV_SIZE, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_CONNECT_TIMEOUT, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_RETRY_TIMEOUT, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_SEND_TIMEOUT, MEMCACHED_BEHAVIOR_SND_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_RECV_TIMEOUT, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_POLL_TIMEOUT, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_CACHE_LOOKUPS, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS);
- REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_FAILURE_LIMIT, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT);
-
- /*
- * libmemcached result codes
- */
-
- REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED);
- REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE);
-
- /*
- * Our result codes.
- */
-
- REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE);
-
-
- #undef REGISTER_MEMC_CLASS_CONST_LONG
-}
-/* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION */
-PHP_MINIT_FUNCTION(memcached)
-{
- zend_class_entry ce;
-
- le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number);
-
- INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods);
- memcached_ce = zend_register_internal_class(&ce TSRMLS_CC);
- memcached_ce->create_object = php_memc_new;
-
- INIT_CLASS_ENTRY(ce, "MemcachedException", NULL);
- memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC);
- /* TODO
- * possibly declare custom exception property here
- */
-
- php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU);
-
-#ifdef ZTS
- ts_allocate_id(&php_memcached_globals_id, sizeof(zend_php_memcached_globals),
- (ts_allocate_ctor) php_memc_init_globals, (ts_allocate_dtor) php_memc_destroy_globals);
-#else
- php_memc_init_globals(&php_memcached_globals TSRMLS_CC);
-#endif
-
-#if HAVE_MEMCACHED_SESSION
- php_session_register_module(ps_memcached_ptr);
-#endif
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MSHUTDOWN_FUNCTION */
-PHP_MSHUTDOWN_FUNCTION(memcached)
-{
-#ifdef ZTS
- ts_free_id(php_memcached_globals_id);
-#else
- php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC);
-#endif
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION */
-PHP_MINFO_FUNCTION(memcached)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "memcached support", "enabled");
- php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION);
- php_info_print_table_row(2, "Revision", "$Revision: 1.1 $");
- php_info_print_table_row(2, "libmemcached version", memcached_lib_version());
- php_info_print_table_end();
-}
-/* }}} */
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim: noet sw=4 ts=4 fdm=marker:
- */
|
[-]
[+]
|
Deleted |
memcached-0.1.0.tgz/memcached-0.1.0/php_memcached.h
^
|
@@ -1,78 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | Copyright (c) 2008 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: Andrei Zmievski <andrei@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $ Id: $ */
-
-#ifndef PHP_MEMCACHED_H
-#define PHP_MEMCACHED_H
-
-extern zend_module_entry memcached_module_entry;
-#define phpext_memcached_ptr &memcached_module_entry
-
-#ifdef PHP_WIN32
-#define PHP_MEMCACHED_API __declspec(dllexport)
-#else
-#define PHP_MEMCACHED_API
-#endif
-
-ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
- memcached_return rescode;
-#if HAVE_MEMCACHED_SESSION
- short sess_locked:1;
- char* sess_lock_key;
- int sess_lock_key_len;
-#endif
-ZEND_END_MODULE_GLOBALS(php_memcached)
-
-PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void);
-PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void);
-PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC);
-
-PHP_MINIT_FUNCTION(memcached);
-PHP_MSHUTDOWN_FUNCTION(memcached);
-PHP_RINIT_FUNCTION(memcached);
-PHP_RSHUTDOWN_FUNCTION(memcached);
-PHP_MINFO_FUNCTION(memcached);
-
-#define PHP_MEMCACHED_VERSION "0.1.0"
-
-#ifdef ZTS
-#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_memcache_globals *, v)
-#else
-#define MEMC_G(v) (php_memcached_globals.v)
-#endif
-
-/* session handler struct */
-#if HAVE_MEMCACHED_SESSION
-#include "ext/session/php_session.h"
-
-extern ps_module ps_mod_memcached;
-#define ps_memcached_ptr &ps_mod_memcached
-
-PS_FUNCS(memcached);
-#endif
-
-#endif /* PHP_MEMCACHED_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 |
memcached-0.1.1.tgz
^
|
|
Deleted |
memcached-0.1.2.tgz
^
|
|
Deleted |
memcached-0.1.3.tgz
^
|
|
Deleted |
memcached-0.1.4.tgz
^
|
|
Deleted |
memcached-0.1.5.tgz
^
|
|
Deleted |
memcached-0.2.0.tgz
^
|
|
Deleted |
memcached-1.0.0.tgz
^
|
|
Deleted |
memcached-1.0.1.tgz
^
|
|
Deleted |
memcached-1.0.2.tgz
^
|
|
Deleted |
memcached-2.0.0.tgz
^
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/CREDITS
^
|
@@ -0,0 +1,2 @@
+memcached
+Andrei Zmievski, Oleg Grenrus (igbinary support)
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/ChangeLog
^
|
@@ -0,0 +1,132 @@
+memcached extension changelog
+
+Version 2.1.0
+-------------
+ * Drop support for libmemcached 0.x series, now 1.0.x is required
+ * Add support for virtual bucket distribution
+ * Fix compilation against PHP 5.2
+
+Version 2.0.1
+-------------
+ * Fix embedded version number to be not -dev
+
+Version 2.0.0
+-------------
+ * Add touch() and touchByKey() methods
+ * Add resetServerList() and quit() methods
+ * Support binary protocol in sessions
+ * Make it work with libmemcached up to 1.0.4
+ * Test against PHP 5.4.0
+
+Version 2.0.0b2
+---------------
+ * Add OPT_REMOVE_FAILED_SERVERS option.
+ * Make it work with libmemcached up to 0.49.
+ * Fix a case where invalid session ID could lock the script.
+ * Improve session support:
+ - Add support for libmemcached config string
+ - Add persistence support via PERSISTENT=persistent_id prefix
+ of the save_path
+ * Add 3rd parameter to the __construct() that allows specification
+ of libmemcached configuration string
+ * Fix a possible crash in __construct() when using persistent
+ connections
+ * Add work-around a bug in libmemcached < 0.50 that causes truncation
+ of last character of server key prefix
+ * When using multiple servers implement transparent fail-over
+ * Fix php_memc_cas_impl() implementation when server_key is not being used
+ * Add support for incrementByKey() and decrementByKey()
+ * Make increment/decrement initialize value when it is not available (when
+ using binary protocol)
+
+Version 2.0.0b1
+---------------
+ * Change the return value for non-existing keys to be NULL rather than
+ 'false', affects simple get only
+ * Add fastlz library that provides better/faster payload compression
+ * Add configure switch to enable/disable JSON serialization support
+ * Add getAllKeys() method
+ * Add deleteMulti() and deleteMultiByKey() methods
+ * Add isPristine() and isPersistent() methods
+ * Add setOptions() method to set multiple options at once
+ * Add SERIALIZER_JSON_ARRAY type that decodes JSON payloads as arrays
+ instead of objects
+ * Add support for Unix domain socket connections
+ * Add memcached.compression_threshold INI setting
+ * Add memcached.compression_factor INI setting
+ * Add memcached.compression_type INI setting
+ * Implement a few speed optimizations
+ * Many bug fixes and memory leaks plugged
+ * Add several more tests
+ * Add constants for libmemcached 0.37+:
+ - Memcached::OPT_NUMBER_OF_REPLICAS
+ - Memcached::OPT_RANDOMIZE_REPLICA_READ
+ * Add 'on_new' callback to constructor
+ * Add SASL support
+
+Version 1.0.1
+-------------
+ * Fix JSON API handling to account for PHP 5.2/5.3 version differences.
+ * Add memcached.sess_locking, memcached.sess_lock_wait, and
+ memcached.sess_prefix INI entries.
+ * Add OPT_AUTO_EJECT_HOSTS option.
+
+Version 1.0.0
+-------------
+ * First stable release.
+ * Add getResultMessage() method.
+ * Fix OPT_RECV_TIMEOUT definition.
+ * Initialize Session lock wait to max execution time (if max execution
+ time is unlimited, default to 30 seconds).
+
+Version 0.2.0
+-------------
+ * Add JSON serializer support, requires PHP 5.2.10+.
+ * Add HAVE_JSON and HAVE_IGBINARY class constants that indicate
+ whether the respective serializers are available.
+ * Add 'flags' parameter to getMulti() and getMultiByKey().
+ * Add GET_PRESERVE_ORDER class constant that can be used with
+ abovementioned flags parameter to make the order of the keys in the
+ response match the request.
+ * Fix an issue with retrieving 0-length payloads (FALSE boolean value).
+ * Refactor the way payload types are stored in memcached flags to optimize
+ the structure and allow for future expansion. WARNING! You have to flush
+ the cache when upgrading to this version.
+ * Add several tests.
+
+Version 0.1.5
+-------------
+ * Implement getVersion().
+ * Add support for preserving boolean value types.
+ * Fix crash when child class does not call constructor.
+ * Fix bug #16084 (Crash when addServers is called with an associative array).
+ * ZTS compilation fixes.
+
+Version 0.1.4
+-------------
+ * Fix compilation against PHP 5.3.
+ * Add support for 'igbinary' serializer (Oleg Grenrus)
+
+Version 0.1.3
+-------------
+ * Bludgeon bug #15896 (Memcached setMulti error) into submission.
+
+Version 0.1.2
+-------------
+ * Fix bug #15896 (Memcached setMulti error).
+ * Check for empty key in getServerByKey().
+ * Allow passing 'null' for callbacks.
+ * get() with cas token fetching wasn't erroring out properly.
+ * Rename certain parameters in the API to be more clear.
+ * Allow only strings as the append/prepend value.
+ * Remove expiration parameter from append/prepend.
+
+Version 0.1.1
+-------------
+ * Add OPT_LIBKETAMA_COMPATIBLE option.
+ * Implement addServers() method.
+ * Swap internal compressed and serialized flags to be compatible with other clients.
+
+Version 0.1.0
+-------------
+ * Initial release
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/LICENSE
^
|
@@ -0,0 +1,68 @@
+--------------------------------------------------------------------
+ The PHP License, version 3.01
+Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
+--------------------------------------------------------------------
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project,
+please see <http://www.php.net>.
+
+PHP includes the Zend Engine, freely available at
+<http://www.zend.com>.
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/README.markdown
^
|
@@ -0,0 +1,14 @@
+Description
+-----------
+This extension uses libmemcached library to provide API for communicating with
+memcached servers.
+
+memcached is a high-performance, distributed memory object caching system,
+generic in nature, but intended for use in speeding up dynamic web applications
+by alleviating database load.
+
+Resources
+---------
+ * [libmemcached](http://tangent.org/552/libmemcached.html)
+ * [memcached](http://www.danga.com/memcached/)
+ * [igbinary](http://opensource.dynamoid.com/)
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/config.m4
^
|
@@ -0,0 +1,268 @@
+dnl
+dnl $ Id: $
+dnl vim:se ts=2 sw=2 et:
+
+PHP_ARG_ENABLE(memcached, whether to enable memcached support,
+[ --enable-memcached Enable memcached support])
+
+PHP_ARG_WITH(libmemcached-dir, for libmemcached,
+[ --with-libmemcached-dir[=DIR] Set the path to libmemcached install prefix.], yes)
+
+PHP_ARG_ENABLE(memcached-session, whether to enable memcached session handler support,
+[ --disable-memcached-session Disable memcached session handler support], yes, no)
+
+PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializer support,
+[ --enable-memcached-igbinary Enable memcached igbinary serializer support], no, no)
+
+PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support,
+[ --enable-memcached-json Enable memcached json serializer support], no, no)
+
+PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support,
+[ --disable-memcached-sasl Disable memcached sasl support], no, no)
+
+if test -z "$PHP_ZLIB_DIR"; then
+PHP_ARG_WITH(zlib-dir, for ZLIB,
+[ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], 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_MEMCACHED" != "no"; then
+
+
+ dnl # zlib
+ 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
+
+ AC_MSG_CHECKING([for zlib location])
+ if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then
+ AC_MSG_RESULT([$PHP_ZLIB_DIR])
+ PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD)
+ PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR)
+ else
+ AC_MSG_ERROR([memcached support requires ZLIB. Use --with-zlib-dir=<DIR> to specify the prefix where ZLIB headers and library are located])
+ fi
+
+ if test "$PHP_MEMCACHED_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
+
+ if test "$PHP_MEMCACHED_JSON" != "no"; then
+ AC_MSG_CHECKING([for json includes])
+ json_inc_path=""
+
+ tmp_version=$PHP_VERSION
+ if test -z "$tmp_version"; then
+ if test -z "$PHP_CONFIG"; then
+ AC_MSG_ERROR([php-config not found])
+ fi
+ PHP_MEMCACHED_VERSION_ORIG=`$PHP_CONFIG --version`;
+ else
+ PHP_MEMCACHED_VERSION_ORIG=$tmp_version
+ fi
+
+ if test -z $PHP_MEMCACHED_VERSION_ORIG; then
+ AC_MSG_ERROR([failed to detect PHP version, please report])
+ fi
+
+ PHP_MEMCACHED_VERSION_MASK=`echo ${PHP_MEMCACHED_VERSION_ORIG} | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+
+ if test $PHP_MEMCACHED_VERSION_MASK -ge 5003000; then
+ if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then
+ json_inc_path="$abs_srcdir/include/php"
+ elif test -f "$abs_srcdir/ext/json/php_json.h"; then
+ json_inc_path="$abs_srcdir"
+ elif test -f "$phpincludedir/ext/json/php_json.h"; then
+ json_inc_path="$phpincludedir"
+ else
+ for i in php php4 php5 php6; do
+ if test -f "$prefix/include/$i/ext/json/php_json.h"; then
+ json_inc_path="$prefix/include/$i"
+ fi
+ done
+ fi
+ if test "$json_inc_path" = ""; then
+ AC_MSG_ERROR([Cannot find php_json.h])
+ else
+ AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available])
+ AC_DEFINE(HAVE_JSON_API_5_3,1,[Whether JSON API for PHP 5.3 is available])
+ AC_MSG_RESULT([$json_inc_path])
+ fi
+ elif test $PHP_MEMCACHED_VERSION_MASK -ge 5002009; then
+ dnl Check JSON for PHP 5.2.9+
+ if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then
+ json_inc_path="$abs_srcdir/include/php"
+ elif test -f "$abs_srcdir/ext/json/php_json.h"; then
+ json_inc_path="$abs_srcdir"
+ elif test -f "$phpincludedir/ext/json/php_json.h"; then
+ json_inc_path="$phpincludedir"
+ else
+ for i in php php4 php5 php6; do
+ if test -f "$prefix/include/$i/ext/json/php_json.h"; then
+ json_inc_path="$prefix/include/$i"
+ fi
+ done
+ fi
+ if test "$json_inc_path" = ""; then
+ AC_MSG_ERROR([Cannot find php_json.h])
+ else
+ AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available])
+ AC_DEFINE(HAVE_JSON_API_5_2,1,[Whether JSON API for PHP 5.2 is available])
+ AC_MSG_RESULT([$json_inc_path])
+ fi
+ else
+ AC_MSG_RESULT([the PHP version does not support JSON serialization API])
+ fi
+ fi
+
+ if test "$PHP_MEMCACHED_IGBINARY" != "no"; then
+ AC_MSG_CHECKING([for igbinary includes])
+ igbinary_inc_path=""
+
+ if test -f "$abs_srcdir/include/php/ext/igbinary/igbinary.h"; then
+ igbinary_inc_path="$abs_srcdir/include/php"
+ elif test -f "$abs_srcdir/ext/igbinary/igbinary.h"; then
+ igbinary_inc_path="$abs_srcdir"
+ elif test -f "$phpincludedir/ext/session/igbinary.h"; then
+ igbinary_inc_path="$phpincludedir"
+ elif test -f "$phpincludedir/ext/igbinary/igbinary.h"; then
+ igbinary_inc_path="$phpincludedir"
+ else
+ for i in php php4 php5 php6; do
+ if test -f "$prefix/include/$i/ext/igbinary/igbinary.h"; then
+ igbinary_inc_path="$prefix/include/$i"
+ fi
+ done
+ fi
+
+ if test "$igbinary_inc_path" = ""; then
+ AC_MSG_ERROR([Cannot find igbinary.h])
+ else
+ AC_MSG_RESULT([$igbinary_inc_path])
+ fi
+ fi
+
+ AC_MSG_CHECKING([for memcached session support])
+ if test "$PHP_MEMCACHED_SESSION" != "no"; then
+ AC_MSG_RESULT([enabled])
+ AC_DEFINE(HAVE_MEMCACHED_SESSION,1,[Whether memcache session handler is enabled])
+ SESSION_INCLUDES="-I$session_inc_path"
+ ifdef([PHP_ADD_EXTENSION_DEP],
+ [
+ PHP_ADD_EXTENSION_DEP(memcached, session)
+ ])
+ else
+ SESSION_INCLUDES=""
+ AC_MSG_RESULT([disabled])
+ fi
+
+ AC_MSG_CHECKING([for memcached igbinary support])
+ if test "$PHP_MEMCACHED_IGBINARY" != "no"; then
+ AC_MSG_RESULT([enabled])
+ AC_DEFINE(HAVE_MEMCACHED_IGBINARY,1,[Whether memcache igbinary serializer is enabled])
+ IGBINARY_INCLUDES="-I$igbinary_inc_path"
+ ifdef([PHP_ADD_EXTENSION_DEP],
+ [
+ PHP_ADD_EXTENSION_DEP(memcached, igbinary)
+ ])
+ else
+ IGBINARY_INCLUDES=""
+ AC_MSG_RESULT([disabled])
+ fi
+
+ if test "$PHP_MEMCACHED_SASL" != "no"; then
+ AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"])
+ AC_MSG_CHECKING([whether to enable sasl support])
+ AC_MSG_RESULT([$memcached_enable_sasl])
+ fi
+
+ AC_MSG_CHECKING([for libmemcached location])
+ if test "$PHP_LIBMEMCACHED_DIR" != "no" && test "$PHP_LIBMEMCACHED_DIR" != "yes"; then
+ if ! test -r "$PHP_LIBMEMCACHED_DIR/include/libmemcached-1.0/memcached.h"; then
+ AC_MSG_ERROR([Can't find libmemcached 1.0.x headers under "$PHP_LIBMEMCACHED_DIR"])
+ fi
+ else
+ PHP_LIBMEMCACHED_DIR="no"
+ for i in /usr /usr/local; do
+ if test -r "$i/include/libmemcached/memcached.h"; then
+ PHP_LIBMEMCACHED_DIR=$i
+ break
+ fi
+ done
+ fi
+
+ if test "$PHP_LIBMEMCACHED_DIR" = "no"; then
+ AC_MSG_ERROR([memcached support requires libmemcached 1.0.x. Use --with-libmemcached-dir=<DIR> to specify the prefix where libmemcached headers and library are located])
+ else
+ AC_MSG_RESULT([$PHP_LIBMEMCACHED_DIR])
+
+ PHP_LIBMEMCACHED_INCDIR="$PHP_LIBMEMCACHED_DIR/include"
+ PHP_ADD_INCLUDE($PHP_LIBMEMCACHED_INCDIR)
+ PHP_ADD_LIBRARY_WITH_PATH(memcached, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD)
+
+ PHP_SUBST(MEMCACHED_SHARED_LIBADD)
+
+ PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c g_fmt.c"
+
+ if test "$PHP_MEMCACHED_SESSION" != "no"; then
+ PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c"
+ fi
+
+ PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES)
+ PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1)
+
+ ifdef([PHP_ADD_EXTENSION_DEP],
+ [
+ PHP_ADD_EXTENSION_DEP(memcached, spl, true)
+ ])
+
+ fi
+
+fi
+
|
[-]
[+]
|
Changed |
memcached-2.1.0.tgz/memcached-2.1.0/config.w32
^
|
(renamed from memcached-0.1.0/config.w32)
|
[-]
[+]
|
Changed |
memcached-2.1.0.tgz/memcached-2.1.0/config.w32
^
|
(renamed from memcached-0.1.0/config.w32)
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/fastlz/LICENSE
^
|
@@ -0,0 +1,24 @@
+FastLZ - lightning-fast lossless compression library
+
+Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/fastlz/fastlz.c
^
|
@@ -0,0 +1,551 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define FASTLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#else
+#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define FASTLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define FASTLZ_INLINE __inline
+#else
+#define FASTLZ_INLINE
+#endif
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_STRICT_ALIGN
+#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef FASTLZ_STRICT_ALIGN
+#endif
+#endif
+
+/*
+ * FIXME: use preprocessor magic to set this on different platforms!
+ */
+typedef unsigned char flzuint8;
+typedef unsigned short flzuint16;
+typedef unsigned int flzuint32;
+
+/* prototypes */
+int fastlz_compress(const void* input, int length, void* output);
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_DISTANCE 8192
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_READU16(p) *((const flzuint16*)(p))
+#else
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
+#endif
+
+#define HASH_LOG 13
+#define HASH_SIZE (1<< HASH_LOG)
+#define HASH_MASK (HASH_SIZE-1)
+#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 1
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz1_compress
+#define FASTLZ_DECOMPRESSOR fastlz1_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "fastlz.c"
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 2
+
+#undef MAX_DISTANCE
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz2_compress
+#define FASTLZ_DECOMPRESSOR fastlz2_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "fastlz.c"
+
+int fastlz_compress(const void* input, int length, void* output)
+{
+ /* for short block, choose fastlz1 */
+ if(length < 65536)
+ return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout)
+{
+ /* magic identifier for compression level */
+ int level = ((*(const flzuint8*)input) >> 5) + 1;
+
+ if(level == 1)
+ return fastlz1_decompress(input, length, output, maxout);
+ if(level == 2)
+ return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void* input, int length, void* output)
+{
+ if(level == 1)
+ return fastlz1_compress(input, length, output);
+ if(level == 2)
+ return fastlz2_compress(input, length, output);
+
+ return 0;
+}
+
+#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_bound = ip + length - 2;
+ const flzuint8* ip_limit = ip + length - 12;
+ flzuint8* op = (flzuint8*) output;
+
+ const flzuint8* htab[HASH_SIZE];
+ const flzuint8** hslot;
+ flzuint32 hval;
+
+ flzuint32 copy;
+
+ /* sanity check */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
+ {
+ if(length)
+ {
+ /* create literal copy only */
+ *op++ = length-1;
+ ip_bound++;
+ while(ip <= ip_bound)
+ *op++ = *ip++;
+ return length+1;
+ }
+ else
+ return 0;
+ }
+
+ /* initializes hash table */
+ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
+ *hslot = ip;
+
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY-1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ {
+ const flzuint8* ref;
+ flzuint32 distance;
+
+ /* minimum match length */
+ flzuint32 len = 3;
+
+ /* comparison starting-point */
+ const flzuint8* anchor = ip;
+
+ /* check for a run */
+#if FASTLZ_LEVEL==2
+ if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
+ {
+ distance = 1;
+ ip += 3;
+ ref = anchor - 1 + 3;
+ goto match;
+ }
+#endif
+
+ /* find potential match */
+ HASH_FUNCTION(hval,ip);
+ hslot = htab + hval;
+ ref = htab[hval];
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* update hash table */
+ *hslot = anchor;
+
+ /* is this a match? check the first 3 bytes */
+ if(distance==0 ||
+#if FASTLZ_LEVEL==1
+ (distance >= MAX_DISTANCE) ||
+#else
+ (distance >= MAX_FARDISTANCE) ||
+#endif
+ *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+ goto literal;
+
+#if FASTLZ_LEVEL==2
+ /* far, needs at least 5-byte match */
+ if(distance >= MAX_DISTANCE)
+ {
+ if(*ip++ != *ref++ || *ip++!= *ref++)
+ goto literal;
+ len += 2;
+ }
+
+ match:
+#endif
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if(!distance)
+ {
+ /* zero distance means a run */
+ flzuint8 x = ip[-1];
+ while(ip < ip_bound)
+ if(*ref++ != x) break; else ip++;
+ }
+ else
+ for(;;)
+ {
+ /* safe because the outer check against ip limit */
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ while(ip < ip_bound)
+ if(*ref++ != *ip++) break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if(copy)
+ /* copy is biased, '0' means 1 byte copy */
+ *(op-copy-1) = copy-1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+#if FASTLZ_LEVEL==2
+ if(distance < MAX_DISTANCE)
+ {
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = (distance & 255);
+ }
+ }
+ else
+ {
+ /* far away, but not yet in the another galaxy... */
+ if(len < 7)
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (len << 5) + 31;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ else
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (7 << 5) + 31;
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ }
+#else
+
+ if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
+ while(len > MAX_LEN-2)
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 -2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN-2;
+ }
+
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+#endif
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY-1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while(ip <= ip_bound)
+ {
+ *op++ = *ip++;
+ copy++;
+ if(copy == MAX_COPY)
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if(copy)
+ *(op-copy-1) = copy-1;
+ else
+ op--;
+
+#if FASTLZ_LEVEL==2
+ /* marker for fastlz2 */
+ *(flzuint8*)output |= (1 << 5);
+#endif
+
+ return op - (flzuint8*)output;
+}
+
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_limit = ip + length;
+ flzuint8* op = (flzuint8*) output;
+ flzuint8* op_limit = op + maxout;
+ flzuint32 ctrl = (*ip++) & 31;
+ int loop = 1;
+
+ do
+ {
+ const flzuint8* ref = op;
+ flzuint32 len = ctrl >> 5;
+ flzuint32 ofs = (ctrl & 31) << 8;
+
+ if(ctrl >= 32)
+ {
+#if FASTLZ_LEVEL==2
+ flzuint8 code;
+#endif
+ len--;
+ ref -= ofs;
+ if (len == 7-1)
+#if FASTLZ_LEVEL==1
+ len += *ip++;
+ ref -= *ip++;
+#else
+ do
+ {
+ code = *ip++;
+ len += code;
+ } while (code==255);
+ code = *ip++;
+ ref -= code;
+
+ /* match from 16-bit distance */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
+ if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
+ {
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_DISTANCE;
+ }
+#endif
+
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
+ return 0;
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
+ return 0;
+#endif
+
+ if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ ctrl = *ip++;
+ else
+ loop = 0;
+
+ if(ref == op)
+ {
+ /* optimize copy for a run */
+ flzuint8 b = ref[-1];
+ *op++ = b;
+ *op++ = b;
+ *op++ = b;
+ for(; len; --len)
+ *op++ = b;
+ }
+ else
+ {
+#if !defined(FASTLZ_STRICT_ALIGN)
+ const flzuint16* p;
+ flzuint16* q;
+#endif
+ /* copy from reference */
+ ref--;
+ *op++ = *ref++;
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+ /* copy a byte, so that now it's word aligned */
+ if(len & 1)
+ {
+ *op++ = *ref++;
+ len--;
+ }
+
+ /* copy 16-bit at once */
+ q = (flzuint16*) op;
+ op += len;
+ p = (const flzuint16*) ref;
+ for(len>>=1; len > 4; len-=4)
+ {
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ }
+ for(; len; --len)
+ *q++ = *p++;
+#else
+ for(; len; --len)
+ *op++ = *ref++;
+#endif
+ }
+ }
+ else
+ {
+ ctrl++;
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
+ return 0;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
+ return 0;
+#endif
+
+ *op++ = *ip++;
+ for(--ctrl; ctrl; ctrl--)
+ *op++ = *ip++;
+
+ loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+ if(loop)
+ ctrl = *ip++;
+ }
+ }
+ while(FASTLZ_EXPECT_CONDITIONAL(loop));
+
+ return op - (flzuint8*)output;
+}
+
+#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/fastlz/fastlz.h
^
|
@@ -0,0 +1,100 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef FASTLZ_H
+#define FASTLZ_H
+
+#define FASTLZ_VERSION 0x000100
+
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 0
+#define FASTLZ_VERSION_REVISION 0
+
+#define FASTLZ_VERSION_STRING "0.1.0"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+*/
+
+int fastlz_compress(const void* input, int length, void* output);
+
+/**
+ Decompress a block of compressed data and returns the size of the
+ decompressed block. If error occurs, e.g. the compressed data is
+ corrupted or the output buffer is not large enough, then 0 (zero)
+ will be returned instead.
+
+ The input buffer and the output buffer can not overlap.
+
+ Decompression is memory safe and guaranteed not to write the output buffer
+ more than what is specified in maxout.
+ */
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress above.
+*/
+
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* FASTLZ_H */
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/g_fmt.c
^
|
@@ -0,0 +1,99 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 1996 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
+ * it suffices to declare buf
+ * char buf[32];
+ */
+
+/* Modified for use with php in the memcached client extension.
+ *
+ * // Teddy Grenman <teddy.grenman@iki.fi>, 2010-05-18.
+ */
+
+#include <zend_operators.h>
+
+char *php_memcached_g_fmt(register char *b, double x) {
+ register int i, k;
+ register char *s;
+ int decpt, j, sign;
+ char *b0, *s0, *se;
+
+ b0 = b;
+#ifdef IGNORE_ZERO_SIGN
+ if (!x) {
+ *b++ = '0';
+ *b = 0;
+ goto done;
+ }
+#endif
+
+ s = s0 = zend_dtoa(x, 0, 0, &decpt, &sign, &se);
+ if (sign)
+ *b++ = '-';
+ if (decpt == 9999) /* Infinity or Nan */ {
+ while(*b++ = *s++);
+ goto done0;
+ }
+ if (decpt <= -4 || decpt > se - s + 5) {
+ *b++ = *s++;
+ if (*s) {
+ *b++ = '.';
+ while(*b = *s++)
+ b++;
+ }
+ *b++ = 'e';
+ /* sprintf(b, "%+.2d", decpt - 1); */
+ if (--decpt < 0) {
+ *b++ = '-';
+ decpt = -decpt;
+ }
+ else
+ *b++ = '+';
+ for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
+ for(;;) {
+ i = decpt / k;
+ *b++ = i + '0';
+ if (--j <= 0)
+ break;
+ decpt -= i*k;
+ decpt *= 10;
+ }
+ *b = 0;
+ } else if (decpt <= 0) {
+ *b++ = '.';
+ for(; decpt < 0; decpt++)
+ *b++ = '0';
+ while(*b++ = *s++);
+ } else {
+ while(*b = *s++) {
+ b++;
+ if (--decpt == 0 && *s)
+ *b++ = '.';
+ }
+ for(; decpt > 0; decpt--)
+ *b++ = '0';
+ *b = 0;
+ }
+
+ done0:
+ zend_freedtoa(s0);
+ done:
+ return b0;
+}
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/g_fmt.h
^
|
@@ -0,0 +1,34 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 1996 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
+ * it suffices to declare buf
+ * char buf[32];
+ */
+
+/* Modified for use with php in the memcached client
+ * extension by Teddy Grenman, 2010.
+ */
+
+#ifndef MEMC_G_FMT_H
+#define MEMC_G_FMT_H
+
+char *php_memcached_g_fmt(register char *b, double x);
+
+#endif
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/memcached-api.php
^
|
@@ -0,0 +1,280 @@
+<?php
+
+/**
+ * Memcached class.
+ */
+
+class Memcached {
+ /**
+ * Libmemcached behavior options.
+ */
+
+ const OPT_HASH;
+
+ const OPT_HASH_DEFAULT;
+
+ const HASH_MD5;
+
+ const HASH_CRC;
+
+ const HASH_FNV1_64;
+
+ const HASH_FNV1A_64;
+
+ const HASH_FNV1_32;
+
+ const HASH_FNV1A_32;
+
+ const HASH_HSIEH;
+
+ const HASH_MURMUR;
+
+ const OPT_DISTRIBUTION;
+
+ const DISTRIBUTION_MODULA;
+
+ const DISTRIBUTION_CONSISTENT;
+
+ const LIBKETAMA_COMPATIBLE;
+
+ const OPT_BUFFER_REQUESTS;
+
+ const OPT_BINARY_PROTOCOL;
+
+ const OPT_NO_BLOCK;
+
+ const OPT_TCP_NODELAY;
+
+ const OPT_SOCKET_SEND_SIZE;
+
+ const OPT_SOCKET_RECV_SIZE;
+
+ const OPT_CONNECT_TIMEOUT;
+
+ const OPT_RETRY_TIMEOUT;
+
+ const OPT_SND_TIMEOUT;
+
+ const OPT_RCV_TIMEOUT;
+
+ const OPT_POLL_TIMEOUT;
+
+ const OPT_SERVER_FAILURE_LIMIT;
+
+ const OPT_CACHE_LOOKUPS;
+
+ const OPT_AUTO_EJECT_HOSTS;
+
+ const OPT_NUMBER_OF_REPLICAS;
+
+ const OPT_NOREPLY;
+
+ const OPT_VERIFY_KEY;
+
+ const OPT_RANDOMIZE_REPLICA_READS;
+
+
+ /**
+ * Class parameters
+ */
+ const HAVE_JSON;
+
+ const HAVE_IGBINARY;
+
+ /**
+ * Class options.
+ */
+ const OPT_COMPRESSION;
+
+ const OPT_COMPRESSION_TYPE;
+
+ const OPT_PREFIX_KEY;
+
+ /**
+ * Serializer constants
+ */
+ const SERIALIZER_PHP;
+
+ const SERIALIZER_IGBINARY;
+
+ const SERIALIZER_JSON;
+
+ const SERIALIZER_JSON_ARRAY;
+
+ /**
+ * Compression types
+ */
+ const COMPRESSION_TYPE_FASTLZ;
+
+ const COMPRESSION_TYPE_ZLIB;
+
+ /**
+ * Flags
+ */
+ const GET_PRESERVE_ORDER;
+
+ /**
+ * Return values
+ */
+ const GET_ERROR_RETURN_VALUE;
+
+ const RES_PAYLOAD_FAILURE;
+
+ const RES_SUCCESS;
+
+ const RES_FAILURE;
+
+ const RES_HOST_LOOKUP_FAILURE;
+
+ const RES_UNKNOWN_READ_FAILURE;
+
+ const RES_PROTOCOL_ERROR;
+
+ const RES_CLIENT_ERROR;
+
+ const RES_SERVER_ERROR;
+
+ const RES_WRITE_FAILURE;
+
+ const RES_DATA_EXISTS;
+
+ const RES_NOTSTORED;
+
+ const RES_NOTFOUND;
+
+ const RES_PARTIAL_READ;
+
+ const RES_SOME_ERRORS;
+
+ const RES_NO_SERVERS;
+
+ const RES_END;
+
+ const RES_ERRNO;
+
+ const RES_BUFFERED;
+
+ const RES_TIMEOUT;
+
+ const RES_BAD_KEY_PROVIDED;
+
+ const RES_STORED;
+
+ const RES_DELETED;
+
+ const RES_STAT;
+
+ const RES_ITEM;
+
+ const RES_NOT_SUPPORTED;
+
+ const RES_FETCH_NOTFINISHED;
+
+ const RES_SERVER_MARKED_DEAD;
+
+ const RES_UNKNOWN_STAT_KEY;
+
+ const RES_INVALID_HOST_PROTOCOL;
+
+ const RES_MEMORY_ALLOCATION_FAILURE;
+
+ const RES_CONNECTION_SOCKET_CREATE_FAILURE;
+
+
+ public function __construct( $persistent_id = '', $on_new_object_cb = null ) {}
+
+ public function get( $key, $cache_cb = null, &$cas_token = null ) {}
+
+ public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null ) {}
+
+ public function getMulti( array $keys, &$cas_tokens = null, $flags = 0 ) {}
+
+ public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0 ) {}
+
+ public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {}
+
+ public function getDelayedByKey( $server_key, array $keys, $with_cas = null, $value_cb = null ) {}
+
+ public function fetch( ) {}
+
+ public function fetchAll( ) {}
+
+ public function set( $key, $value, $expiration = 0 ) {}
+
+ public function touch( $key, $expiration = 0 ) {}
+
+ public function touchbyKey( $key, $expiration = 0 ) {}
+
+ public function setByKey( $server_key, $key, $value, $expiration = 0 ) {}
+
+ public function setMulti( array $items, $expiration = 0 ) {}
+
+ public function setMultiByKey( $server_key, array $items, $expiration = 0 ) {}
+
+ public function cas( $token, $key, $value, $expiration = 0 ) {}
+
+ public function casByKey( $token, $server_key, $key, $value, $expiration = 0 ) {}
+
+ public function add( $key, $value, $expiration = 0 ) {}
+
+ public function addByKey( $server_key, $key, $value, $expiration = 0 ) {}
+
+ public function append( $key, $value ) {}
+
+ public function appendByKey( $server_key, $key, $value ) {}
+
+ public function prepend( $key, $value ) {}
+
+ public function prependByKey( $server_key, $key, $value ) {}
+
+ public function replace( $key, $value, $expiration = 0 ) {}
+
+ public function replaceByKey( $server_key, $key, $value, $expiration = 0 ) {}
+
+ public function delete( $key, $time = 0 ) {}
+
+ public function deleteByKey( $server_key, $key, $time = 0 ) {}
+
+ public function deleteMulti( array $keys, $expiration = 0 ) {}
+
+ public function deleteMultiByKey( $server_key, array $keys, $expiration = 0 ) {}
+
+ public function increment( $key, $offset = 1) {}
+
+ public function decrement( $key, $offset = 1) {}
+
+ public function getOption( $option ) {}
+
+ public function setOption( $option, $value ) {}
+
+ public function setOptions( array $options ) {}
+
+ public function addServer( $host, $port, $weight = 0 ) {}
+
+ public function addServers( array $servers ) {}
+
+ public function getServerList( ) {}
+
+ public function getServerByKey( $server_key ) {}
+
+ public function flush( $delay = 0 ) {}
+
+ public function getStats( ) {}
+
+ public function getVersion( ) {}
+
+ public function getResultCode( ) {}
+
+ public function getResultMessage( ) {}
+
+ public function isPersistent( ) {}
+
+ public function isPristine( ) {}
+
+}
+
+class MemcachedException extends Exception {
+
+ function __construct( $errmsg = "", $errcode = 0 ) {}
+
+}
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/memcached.ini
^
|
@@ -0,0 +1,57 @@
+[memcached]
+; Use session locking
+; valid values: On, Off
+; the default is On
+memcached.sess_locking = On
+
+; Session spin lock retry wait time in microseconds.
+; Be carefull when setting this value.
+; Valid values are integers, where 0 is interpreted as
+; the default value. Negative values result in a reduces
+; locking to a try lock.
+; the default is 150000
+memcached.sess_lock_wait = 150000
+
+; memcached session key prefix
+; valid values are strings less than 219 bytes long
+; the default value is "memc.sess.key."
+memcached.sess_prefix = "memc.sess.key."
+
+; memcached session binary mode
+memcached.sess_binary = Off
+
+; Set the compression type
+; valid values are: fastlz, zlib
+; the default is fastlz
+memcached.compression_type = "fastlz"
+
+; Compression factor
+; Store compressed value only if the compression
+; factor (saving) exceeds the set limit.
+;
+; store compressed if:
+; plain_len > comp_len * factor
+;
+; the default value is 1.3 (23% space saving)
+memcached.compression_factor = "1.3"
+
+; The compression threshold
+;
+; Do not compress serialized values below this threshold.
+; the default is 2000 bytes
+memcached.compression_threshold = 2000
+
+; Set the default serializer for new memcached objects.
+; valid values are: php, igbinary, json, json_array
+;
+; json - standard php JSON encoding. This serializer
+; is fast and compact but only works on UTF-8
+; encoded data and does not fully implement
+; serializing. See the JSON extension.
+; json_array - as json, but decodes into arrays
+; php - the standard php serializer
+; igbinary - a binary serializer
+;
+; The default is igbinary if available and php otherwise.
+memcached.serializer = "igbinary"
+
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/php_libmemcached_compat.h
^
|
@@ -0,0 +1,7 @@
+#ifndef PHP_LIBMEMCACHED_COMPAT
+#define PHP_LIBMEMCACHED_COMPAT
+
+/* this is the version(s) we support */
+#include <libmemcached-1.0/memcached.h>
+
+#endif
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/php_memcached.c
^
|
@@ -0,0 +1,3903 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2009-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $ Id: $ */
+
+/* TODO
+ * - set LIBKETAMA_COMPATIBLE as the default?
+ * - fix unserialize(serialize($memc))
+ * - ability to set binary protocol for sessions
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <php.h>
+#include <php_main.h>
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#include <php_ini.h>
+#include <SAPI.h>
+#include <ext/standard/info.h>
+#include <zend_extensions.h>
+#include <zend_exceptions.h>
+#include <ext/standard/php_smart_str.h>
+#include <ext/standard/php_var.h>
+#include <ext/standard/basic_functions.h>
+
+#include "php_memcached.h"
+#include "g_fmt.h"
+
+#ifdef HAVE_MEMCACHED_SESSION
+# include "php_memcached_session.h"
+#endif
+
+#include "fastlz/fastlz.h"
+#include <zlib.h>
+
+/* Used to store the size of the block */
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#ifdef PHP_WIN32
+# include "win32/php_stdint.h"
+#else
+# ifndef HAVE_INT32_T
+# if SIZEOF_INT == 4
+typedef int int32_t;
+# elif SIZEOF_LONG == 4
+typedef long int int32_t;
+# endif
+# endif
+
+# ifndef HAVE_UINT32_T
+# if SIZEOF_INT == 4
+typedef unsigned int uint32_t;
+# elif SIZEOF_LONG == 4
+typedef unsigned long int uint32_t;
+# endif
+# endif
+#endif
+
+#ifdef HAVE_JSON_API
+# include "ext/json/php_json.h"
+#endif
+
+#ifdef HAVE_MEMCACHED_IGBINARY
+# include "ext/igbinary/igbinary.h"
+#endif
+
+/*
+ * This is needed because PHP 5.3.[01] does not install JSON_parser.h by default. This
+ * constant will move into php_json.h in the future anyway.
+ */
+#ifndef JSON_PARSER_DEFAULT_DEPTH
+#define JSON_PARSER_DEFAULT_DEPTH 512
+#endif
+
+/****************************************
+ Custom options
+****************************************/
+#define MEMC_OPT_COMPRESSION -1001
+#define MEMC_OPT_PREFIX_KEY -1002
+#define MEMC_OPT_SERIALIZER -1003
+#define MEMC_OPT_COMPRESSION_TYPE -1004
+
+/****************************************
+ Custom result codes
+****************************************/
+#define MEMC_RES_PAYLOAD_FAILURE -1001
+
+/****************************************
+ Payload value flags
+****************************************/
+#define MEMC_VAL_TYPE_MASK 0xf
+#define MEMC_VAL_GET_TYPE(flags) ((flags) & MEMC_VAL_TYPE_MASK)
+#define MEMC_VAL_SET_TYPE(flags, type) ((flags) |= ((type) & MEMC_VAL_TYPE_MASK))
+
+#define MEMC_VAL_IS_STRING 0
+#define MEMC_VAL_IS_LONG 1
+#define MEMC_VAL_IS_DOUBLE 2
+#define MEMC_VAL_IS_BOOL 3
+#define MEMC_VAL_IS_SERIALIZED 4
+#define MEMC_VAL_IS_IGBINARY 5
+#define MEMC_VAL_IS_JSON 6
+
+#define MEMC_VAL_COMPRESSED (1<<4)
+#define MEMC_VAL_COMPRESSION_ZLIB (1<<5)
+#define MEMC_VAL_COMPRESSION_FASTLZ (1<<6)
+
+/****************************************
+ "get" operation flags
+****************************************/
+#define MEMC_GET_PRESERVE_ORDER (1<<0)
+
+/****************************************
+ Helper macros
+****************************************/
+#define MEMC_METHOD_INIT_VARS \
+ zval* object = getThis(); \
+ php_memc_t* i_obj = NULL; \
+ struct memc_obj* m_obj = NULL;
+
+#define MEMC_METHOD_FETCH_OBJECT \
+ i_obj = (php_memc_t *) zend_object_store_get_object( object TSRMLS_CC ); \
+ m_obj = i_obj->obj; \
+ if (!m_obj) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memcached constructor was not called"); \
+ return; \
+ }
+
+#ifndef DVAL_TO_LVAL
+#ifdef _WIN64
+# define DVAL_TO_LVAL(d, l) \
+ if ((d) > LONG_MAX) { \
+ (l) = (long)(unsigned long)(__int64) (d); \
+ } else { \
+ (l) = (long) (d); \
+ }
+#else
+# define DVAL_TO_LVAL(d, l) \
+ if ((d) > LONG_MAX) { \
+ (l) = (unsigned long) (d); \
+ } else { \
+ (l) = (long) (d); \
+ }
+#endif
+#endif
+
+#define RETURN_FROM_GET RETURN_FALSE
+
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3)
+#define zend_parse_parameters_none() \
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
+#endif
+
+
+/****************************************
+ Structures and definitions
+****************************************/
+enum memcached_compression_type {
+ COMPRESSION_TYPE_ZLIB = 1,
+ COMPRESSION_TYPE_FASTLZ = 2,
+};
+
+typedef struct {
+ zend_object zo;
+
+ struct memc_obj {
+ memcached_st *memc;
+ zend_bool compression;
+ enum memcached_serializer serializer;
+ enum memcached_compression_type compression_type;
+#if HAVE_MEMCACHED_SASL
+ zend_bool has_sasl_data;
+#endif
+ } *obj;
+
+ zend_bool is_persistent;
+ zend_bool is_pristine;
+ int rescode;
+ int memc_errno;
+} php_memc_t;
+
+enum {
+ MEMC_OP_SET,
+ MEMC_OP_TOUCH,
+ MEMC_OP_ADD,
+ MEMC_OP_REPLACE,
+ MEMC_OP_APPEND,
+ MEMC_OP_PREPEND
+};
+
+static zend_class_entry *memcached_ce = NULL;
+static zend_class_entry *memcached_exception_ce = NULL;
+
+static zend_object_handlers memcached_object_handlers;
+
+struct callbackContext
+{
+ zval *array;
+ zval *entry;
+ memcached_stat_st *stats; /* for use with functions that need stats */
+ void *return_value;
+ unsigned int i; /* for use with structures mapped against servers */
+};
+
+#if HAVE_SPL
+static zend_class_entry *spl_ce_RuntimeException = NULL;
+#endif
+
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
+const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
+#undef ZEND_BEGIN_ARG_INFO_EX
+#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
+ static zend_arg_info name[] = { \
+ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
+#endif
+
+ZEND_DECLARE_MODULE_GLOBALS(php_memcached)
+
+#ifdef COMPILE_DL_MEMCACHED
+ZEND_GET_MODULE(memcached)
+#endif
+
+static PHP_INI_MH(OnUpdateCompressionType)
+{
+ if (!new_value) {
+ MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ;
+ } else if (!strcmp(new_value, "fastlz")) {
+ MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ;
+ } else if (!strcmp(new_value, "zlib")) {
+ MEMC_G(compression_type_real) = COMPRESSION_TYPE_ZLIB;
+ } else {
+ return FAILURE;
+ }
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+
+static PHP_INI_MH(OnUpdateSerializer)
+{
+ if (!new_value) {
+ MEMC_G(serializer) = SERIALIZER_DEFAULT;
+ } else if (!strcmp(new_value, "php")) {
+ MEMC_G(serializer) = SERIALIZER_PHP;
+#ifdef HAVE_MEMCACHE_IGBINARY
+ } else if (!strcmp(new_value, "igbinary")) {
+ MEMC_G(serializer) = SERIALIZER_IGBINARY;
+#endif // IGBINARY
+#ifdef HAVE_JSON_API
+ } else if (!strcmp(new_value, "json")) {
+ MEMC_G(serializer) = SERIALIZER_JSON;
+ } else if (!strcmp(new_value, "json_array")) {
+ MEMC_G(serializer) = SERIALIZER_JSON_ARRAY;
+#endif // JSON
+ } else {
+ return FAILURE;
+ }
+
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+
+/* {{{ INI entries */
+PHP_INI_BEGIN()
+#ifdef HAVE_MEMCACHED_SESSION
+ STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals)
+ STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals)
+ STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals)
+ STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals)
+#endif
+ STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals)
+ STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals)
+ STD_PHP_INI_ENTRY("memcached.compression_threshold", "2000", PHP_INI_ALL, OnUpdateLong, compression_threshold, zend_php_memcached_globals, php_memcached_globals)
+
+ STD_PHP_INI_ENTRY("memcached.serializer", SERIALIZER_DEFAULT_NAME, PHP_INI_ALL, OnUpdateSerializer, serializer_name, zend_php_memcached_globals, php_memcached_globals)
+#if HAVE_MEMCACHED_SASL
+ STD_PHP_INI_ENTRY("memcached.use_sasl", "0", PHP_INI_SYSTEM, OnUpdateBool, use_sasl, zend_php_memcached_globals, php_memcached_globals)
+#endif
+PHP_INI_END()
+/* }}} */
+
+/****************************************
+ Forward declarations
+****************************************/
+static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC);
+static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC);
+static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC);
+static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key);
+static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
+static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC);
+static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC);
+static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
+static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
+static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
+static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC);
+
+/****************************************
+ Method implementations
+****************************************/
+
+static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len TSRMLS_DC)
+{
+ zval pid_z;
+ zval *retval_ptr, *pid_z_ptr = &pid_z;
+ zval **params[2];
+
+ INIT_ZVAL(pid_z);
+ if (persistent_id) {
+ ZVAL_STRINGL(pid_z_ptr, persistent_id, persistent_id_len, 1);
+ }
+
+ /* Call the cb */
+ params[0] = &object;
+ params[1] = &pid_z_ptr;
+
+ fci->params = params;
+ fci->param_count = 2;
+ fci->retval_ptr_ptr = &retval_ptr;
+ fci->no_separation = 1;
+
+ if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", Z_STRVAL_P(fci->function_name));
+ return 0;
+ }
+ zval_dtor(pid_z_ptr);
+
+ if (retval_ptr) {
+ zval_ptr_dtor(&retval_ptr);
+ }
+ return 1;
+}
+
+static int le_memc, le_memc_sess;
+
+static int php_memc_list_entry(void)
+{
+ return le_memc;
+}
+
+/* {{{ Memcached::__construct([string persistent_id[, callback on_new[, string connection_str]]]))
+ Creates a Memcached object, optionally using persistent memcache connection */
+static PHP_METHOD(Memcached, __construct)
+{
+ zval *object = getThis();
+ php_memc_t *i_obj;
+ struct memc_obj *m_obj = NULL;
+ char *persistent_id = NULL, *conn_str = NULL;
+ int persistent_id_len, conn_str_len;
+ zend_bool is_persistent = 0;
+
+ char *plist_key = NULL;
+ int plist_key_len = 0;
+
+ zend_fcall_info fci = {0};
+ zend_fcall_info_cache fci_cache;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f!s", &persistent_id, &persistent_id_len, &fci, &fci_cache, &conn_str, &conn_str_len) == FAILURE) {
+ ZVAL_NULL(object);
+ return;
+ }
+
+ i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC);
+ i_obj->is_pristine = 0;
+
+ if (persistent_id && *persistent_id) {
+ zend_rsrc_list_entry *le = NULL;
+
+ is_persistent = 1;
+ plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id);
+ plist_key_len += 1;
+
+ if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) {
+ if (le->type == php_memc_list_entry()) {
+ m_obj = (struct memc_obj *) le->ptr;
+ }
+ }
+ i_obj->obj = m_obj;
+ }
+
+ i_obj->is_persistent = is_persistent;
+
+ if (!m_obj) {
+ m_obj = pecalloc(1, sizeof(*m_obj), is_persistent);
+ if (m_obj == NULL) {
+ if (plist_key) {
+ efree(plist_key);
+ }
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle");
+ /* not reached */
+ }
+
+ if (conn_str) {
+ m_obj->memc = memcached(conn_str, conn_str_len);
+ if (!m_obj->memc) {
+ char error_buffer[1024];
+ if (plist_key) {
+ efree(plist_key);
+ }
+ if (libmemcached_check_configuration(conn_str, conn_str_len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "configuration error %s", error_buffer);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure");
+ }
+ /* not reached */
+ }
+ } else {
+ m_obj->memc = memcached_create(NULL);
+ if (m_obj->memc == NULL) {
+ if (plist_key) {
+ efree(plist_key);
+ }
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure");
+ /* not reached */
+ }
+ }
+
+ m_obj->serializer = MEMC_G(serializer);
+ m_obj->compression_type = MEMC_G(compression_type_real);
+ m_obj->compression = 1;
+
+ i_obj->obj = m_obj;
+ i_obj->is_pristine = 1;
+
+ if (fci.size) { /* will be 0 when not available */
+ if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len TSRMLS_CC) || EG(exception)) {
+ /* error calling or exception thrown from callback */
+ if (plist_key) {
+ efree(plist_key);
+ }
+
+ i_obj->obj = NULL;
+ if (is_persistent) {
+ php_memc_destroy(m_obj, is_persistent TSRMLS_CC);
+ }
+
+ return;
+ }
+ }
+
+ if (is_persistent) {
+ zend_rsrc_list_entry le;
+
+ le.type = php_memc_list_entry();
+ le.ptr = m_obj;
+ if (zend_hash_update(&EG(persistent_list), (char *)plist_key,
+ plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) {
+ if (plist_key) {
+ efree(plist_key);
+ }
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry");
+ /* not reached */
+ }
+ }
+ }
+
+ if (plist_key) {
+ efree(plist_key);
+ }
+}
+/* }}} */
+
+/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ])
+ Returns a value for the given key or false */
+PHP_METHOD(Memcached, get)
+{
+ php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ])
+ Returns a value for key from the server identified by the server key or false */
+PHP_METHOD(Memcached, getByKey)
+{
+ php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ -- php_memc_get_impl */
+static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ char *key = NULL;
+ int key_len = 0;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ char *payload = NULL;
+ size_t payload_len = 0;
+ uint32_t flags = 0;
+ uint64_t cas = 0;
+ const char* keys[1] = { NULL };
+ size_t key_lens[1] = { 0 };
+ zval *cas_token = NULL;
+ zend_fcall_info fci = empty_fcall_info;
+ zend_fcall_info_cache fcc = empty_fcall_info_cache;
+ memcached_result_st result;
+ memcached_return status = MEMCACHED_SUCCESS;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|f!z", &server_key,
+ &server_key_len, &key, &key_len, &fci, &fcc, &cas_token) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!z", &key, &key_len,
+ &fci, &fcc, &cas_token) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FROM_GET;
+ }
+
+ keys[0] = key;
+ key_lens[0] = key_len;
+
+ if (cas_token) {
+ uint64_t orig_cas_flag;
+
+ /*
+ * Enable CAS support, but only if it is currently disabled.
+ */
+ orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
+ if (orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
+ }
+
+ status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1);
+
+ if (orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FROM_GET;
+ }
+
+ status = MEMCACHED_SUCCESS;
+ memcached_result_create(m_obj->memc, &result);
+
+ if (memcached_fetch_result(m_obj->memc, &result, &status) == NULL) {
+ /* This is for historical reasons */
+ if (status == MEMCACHED_END)
+ status = MEMCACHED_NOTFOUND;
+
+ /*
+ * If the result wasn't found, and we have the read-through callback, invoke
+ * it to get the value. The CAS token will be 0, because we cannot generate it
+ * ourselves.
+ */
+ if (status == MEMCACHED_NOTFOUND && fci.size != 0) {
+ status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len,
+ return_value TSRMLS_CC);
+ ZVAL_DOUBLE(cas_token, 0);
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ memcached_result_free(&result);
+ RETURN_FROM_GET;
+ }
+
+ /* if we have a callback, all processing is done */
+ if (fci.size != 0) {
+ memcached_result_free(&result);
+ return;
+ }
+ }
+
+ payload = memcached_result_value(&result);
+ payload_len = memcached_result_length(&result);
+ flags = memcached_result_flags(&result);
+ cas = memcached_result_cas(&result);
+
+ if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) {
+ memcached_result_free(&result);
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FROM_GET;
+ }
+
+ zval_dtor(cas_token);
+ ZVAL_DOUBLE(cas_token, (double)cas);
+
+ memcached_result_free(&result);
+
+ } else {
+ int rc;
+ zend_bool return_value_set = 0;
+
+ status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1);
+ payload = memcached_fetch(m_obj->memc, NULL, NULL, &payload_len, &flags, &status);
+
+ /* This is for historical reasons */
+ if (status == MEMCACHED_END)
+ status = MEMCACHED_NOTFOUND;
+
+ /*
+ * If payload wasn't found and we have a read-through callback, invoke it to get
+ * the value. The callback will take care of storing the value back into memcache.
+ * The callback will set the return value.
+ */
+ if (payload == NULL && status == MEMCACHED_NOTFOUND && fci.size != 0) {
+ size_t dummy_length;
+ uint32_t dummy_flags;
+ memcached_return dummy_status;
+
+ status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len,
+ return_value TSRMLS_CC);
+ return_value_set = 1;
+
+ (void)memcached_fetch(m_obj->memc, NULL, NULL, &dummy_length, &dummy_flags, &dummy_status);
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ if (payload) {
+ free(payload);
+ }
+ RETURN_FROM_GET;
+ }
+
+ /* if memcached gave a value and there was no callback, payload may be NULL */
+ if (!return_value_set) {
+ rc = php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC);
+ free(payload);
+ if (rc < 0) {
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FROM_GET;
+ }
+ }
+
+ }
+}
+/* }}} */
+
+/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ])
+ Returns values for the given keys or false */
+PHP_METHOD(Memcached, getMulti)
+{
+ php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ])
+ Returns values for the given keys from the server identified by the server key or false */
+PHP_METHOD(Memcached, getMultiByKey)
+{
+ php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ -- php_memc_getMulti_impl */
+static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ zval *keys = NULL;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ size_t num_keys = 0;
+ zval **entry = NULL;
+ char *payload = NULL;
+ size_t payload_len = 0;
+ const char **mkeys = NULL;
+ size_t *mkeys_len = NULL;
+ char *res_key = NULL;
+ size_t res_key_len = 0;
+ uint32_t flags;
+ uint64_t cas = 0;
+ zval *cas_tokens = NULL;
+ uint64_t orig_cas_flag;
+ zval *value;
+ long get_flags = 0;
+ int i = 0;
+ zend_bool preserve_order;
+ memcached_result_st result;
+ memcached_return status = MEMCACHED_SUCCESS;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zl", &server_key,
+ &server_key_len, &keys, &cas_tokens, &get_flags) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER);
+ num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
+ mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0);
+ mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0);
+ array_init(return_value);
+
+ /*
+ * Create the array of keys for libmemcached. If none of the keys were valid
+ * (strings), set bad key result code and return.
+ */
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys));
+ zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(keys))) {
+
+ if (Z_TYPE_PP(entry) != IS_STRING) {
+ convert_to_string_ex(entry);
+ }
+
+ if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) {
+ mkeys[i] = Z_STRVAL_PP(entry);
+ mkeys_len[i] = Z_STRLEN_PP(entry);
+
+ if (preserve_order) {
+ add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i] + 1);
+ }
+ i++;
+ }
+ }
+
+ if (i == 0) {
+ i_obj->rescode = MEMCACHED_NOTFOUND;
+ efree(mkeys);
+ efree(mkeys_len);
+ return;
+ }
+
+ /*
+ * Enable CAS support, but only if it is currently disabled.
+ */
+ if (cas_tokens) {
+ orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
+ if (orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
+ }
+ }
+
+ status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i);
+ /* Handle error, but ignore, there might still be some result */
+ php_memc_handle_error(i_obj, status TSRMLS_CC);
+
+ /*
+ * Restore the CAS support flag, but only if we had to turn it on.
+ */
+ if (cas_tokens && orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
+ }
+
+ efree(mkeys);
+ efree(mkeys_len);
+
+ /*
+ * Iterate through the result set and create the result array. The CAS tokens are
+ * returned as doubles, because we cannot store potential 64-bit values in longs.
+ */
+ if (cas_tokens) {
+ zval_dtor(cas_tokens);
+ array_init(cas_tokens);
+ }
+
+ memcached_result_create(m_obj->memc, &result);
+ while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) {
+ if (status != MEMCACHED_SUCCESS) {
+ status = MEMCACHED_SOME_ERRORS;
+ php_memc_handle_error(i_obj, status TSRMLS_CC);
+ continue;
+ }
+
+ payload = memcached_result_value(&result);
+ payload_len = memcached_result_length(&result);
+ flags = memcached_result_flags(&result);
+ res_key = memcached_result_key_value(&result);
+ res_key_len = memcached_result_key_length(&result);
+
+ /*
+ * This may be a bug in libmemcached, the key is not null terminated
+ * whe using the binary protocol.
+ */
+ res_key[res_key_len] = 0;
+
+ MAKE_STD_ZVAL(value);
+
+ if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) {
+ zval_ptr_dtor(&value);
+ if (EG(exception)) {
+ status = MEMC_RES_PAYLOAD_FAILURE;
+ php_memc_handle_error(i_obj, status TSRMLS_CC);
+ memcached_quit(m_obj->memc);
+
+ break;
+ }
+ status = MEMCACHED_SOME_ERRORS;
+ i_obj->rescode = MEMCACHED_SOME_ERRORS;
+
+ continue;
+ }
+
+ add_assoc_zval_ex(return_value, res_key, res_key_len+1, value);
+ if (cas_tokens) {
+ cas = memcached_result_cas(&result);
+ add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas);
+ }
+ }
+
+ memcached_result_free(&result);
+
+ if (EG(exception)) {
+ /* XXX: cas_tokens should only be set on success, currently we're destructive */
+ if (cas_tokens) {
+ zval_dtor(cas_tokens);
+ ZVAL_NULL(cas_tokens);
+ }
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ])
+ Sends a request for the given keys and returns immediately */
+PHP_METHOD(Memcached, getDelayed)
+{
+ php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ])
+ Sends a request for the given keys from the server identified by the server key and returns immediately */
+PHP_METHOD(Memcached, getDelayedByKey)
+{
+ php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ -- php_memc_getDelayed_impl */
+static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ zval *keys = NULL;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ zend_bool with_cas = 0;
+ size_t num_keys = 0;
+ zval **entry = NULL;
+ const char **mkeys = NULL;
+ size_t *mkeys_len = NULL;
+ uint64_t orig_cas_flag;
+ zend_fcall_info fci = empty_fcall_info;
+ zend_fcall_info_cache fcc = empty_fcall_info_cache;
+ int i = 0;
+ memcached_return status = MEMCACHED_SUCCESS;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|bf!", &server_key,
+ &server_key_len, &keys, &with_cas, &fci, &fcc) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|bf!", &keys, &with_cas,
+ &fci, &fcc) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ /*
+ * Create the array of keys for libmemcached. If none of the keys were valid
+ * (strings), set bad key result code and return.
+ */
+ num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
+ mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0);
+ mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0);
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys));
+ zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(keys))) {
+
+ if (Z_TYPE_PP(entry) != IS_STRING) {
+ convert_to_string_ex(entry);
+ }
+
+ if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) {
+ mkeys[i] = Z_STRVAL_PP(entry);
+ mkeys_len[i] = Z_STRLEN_PP(entry);
+ i++;
+ }
+ }
+
+ if (i == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ efree(mkeys);
+ efree(mkeys_len);
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+
+ /*
+ * Enable CAS support, but only if it is currently disabled.
+ */
+ if (with_cas) {
+ orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
+ if (orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
+ }
+ }
+
+ /*
+ * Issue the request, but collect results only if the result callback is provided.
+ */
+ status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i);
+
+ /*
+ * Restore the CAS support flag, but only if we had to turn it on.
+ */
+ if (with_cas && orig_cas_flag == 0) {
+ memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
+ }
+
+ efree(mkeys);
+ efree(mkeys_len);
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+
+ if (fci.size != 0) {
+ /*
+ * We have a result callback. Iterate through the result set and invoke the
+ * callback for each one.
+ */
+ memcached_result_st result;
+
+ memcached_result_create(m_obj->memc, &result);
+ while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) {
+ if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result TSRMLS_CC) < 0) {
+ status = MEMCACHED_FAILURE;
+ break;
+ }
+ }
+ memcached_result_free(&result);
+
+ /* we successfully retrieved all rows */
+ if (status == MEMCACHED_END) {
+ status = MEMCACHED_SUCCESS;
+ }
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::fetch()
+ Returns the next result from a previous delayed request */
+PHP_METHOD(Memcached, fetch)
+{
+ char *res_key = NULL;
+ size_t res_key_len = 0;
+ char *payload = NULL;
+ size_t payload_len = 0;
+ zval *value;
+ uint32_t flags = 0;
+ uint64_t cas = 0;
+ memcached_result_st result;
+ memcached_return status = MEMCACHED_SUCCESS;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ memcached_result_create(m_obj->memc, &result);
+ if ((memcached_fetch_result(m_obj->memc, &result, &status)) == NULL) {
+ php_memc_handle_error(i_obj, status TSRMLS_CC);
+ memcached_result_free(&result);
+ RETURN_FALSE;
+ }
+
+ payload = memcached_result_value(&result);
+ payload_len = memcached_result_length(&result);
+ flags = memcached_result_flags(&result);
+ res_key = memcached_result_key_value(&result);
+ res_key_len = memcached_result_key_length(&result);
+ cas = memcached_result_cas(&result);
+
+ MAKE_STD_ZVAL(value);
+
+ if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) {
+ memcached_result_free(&result);
+ zval_ptr_dtor(&value);
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ add_assoc_stringl_ex(return_value, ZEND_STRS("key"), res_key, res_key_len, 1);
+ add_assoc_zval_ex(return_value, ZEND_STRS("value"), value);
+ if (cas != 0) {
+ /* XXX: also check against ULLONG_MAX or memc_behavior */
+ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas);
+ }
+
+ memcached_result_free(&result);
+}
+/* }}} */
+
+/* {{{ Memcached::fetchAll()
+ Returns all the results from a previous delayed request */
+PHP_METHOD(Memcached, fetchAll)
+{
+ char *res_key = NULL;
+ size_t res_key_len = 0;
+ char *payload = NULL;
+ size_t payload_len = 0;
+ zval *value, *entry;
+ uint32_t flags;
+ uint64_t cas = 0;
+ memcached_result_st result;
+ memcached_return status = MEMCACHED_SUCCESS;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ array_init(return_value);
+ memcached_result_create(m_obj->memc, &result);
+
+ while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) {
+ payload = memcached_result_value(&result);
+ payload_len = memcached_result_length(&result);
+ flags = memcached_result_flags(&result);
+ res_key = memcached_result_key_value(&result);
+ res_key_len = memcached_result_key_length(&result);
+ cas = memcached_result_cas(&result);
+
+ MAKE_STD_ZVAL(value);
+
+ if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) {
+ memcached_result_free(&result);
+ zval_ptr_dtor(&value);
+ zval_dtor(return_value);
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FALSE;
+ }
+
+ MAKE_STD_ZVAL(entry);
+ array_init(entry);
+ add_assoc_stringl_ex(entry, ZEND_STRS("key"), res_key, res_key_len, 1);
+ add_assoc_zval_ex(entry, ZEND_STRS("value"), value);
+ if (cas != 0) {
+ /* XXX: also check against ULLONG_MAX or memc_behavior */
+ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas);
+ }
+ add_next_index_zval(return_value, entry);
+ }
+
+ memcached_result_free(&result);
+
+ if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ Memcached::set(string key, mixed value [, int expiration ])
+ Sets the value for the given key */
+PHP_METHOD(Memcached, set)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ])
+ Sets the value for the given key on the server identified by the server key */
+PHP_METHOD(Memcached, setByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1);
+}
+/* }}} */
+
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002
+/* {{{ Memcached::touch(string key, [, int expiration ])
+ Sets a new expiration for the given key */
+PHP_METHOD(Memcached, touch)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::touchbyKey(string key, [, int expiration ])
+ Sets a new expiration for the given key */
+PHP_METHOD(Memcached, touchByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1);
+}
+/* }}} */
+#endif
+
+
+/* {{{ Memcached::setMulti(array items [, int expiration ])
+ Sets the keys/values specified in the items array */
+PHP_METHOD(Memcached, setMulti)
+{
+ php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ])
+ Sets the keys/values specified in the items array on the server identified by the given server key */
+PHP_METHOD(Memcached, setMultiByKey)
+{
+ php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+#define PHP_MEMC_FAILOVER_RETRY \
+ if (!by_key && retry < 2) { \
+ switch (i_obj->rescode) { \
+ case MEMCACHED_HOST_LOOKUP_FAILURE: \
+ case MEMCACHED_CONNECTION_FAILURE: \
+ case MEMCACHED_CONNECTION_BIND_FAILURE: \
+ case MEMCACHED_WRITE_FAILURE: \
+ case MEMCACHED_READ_FAILURE: \
+ case MEMCACHED_UNKNOWN_READ_FAILURE: \
+ case MEMCACHED_PROTOCOL_ERROR: \
+ case MEMCACHED_SERVER_ERROR: \
+ case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: \
+ case MEMCACHED_TIMEOUT: \
+ case MEMCACHED_FAIL_UNIX_SOCKET: \
+ case MEMCACHED_SERVER_MARKED_DEAD: \
+ if (memcached_server_count(m_obj->memc) > 0) { \
+ retry++; \
+ goto retry; \
+ } \
+ break; \
+ } \
+ } \
+
+/* {{{ -- php_memc_setMulti_impl */
+static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ zval *entries;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ time_t expiration = 0;
+ zval **entry;
+ char *str_key;
+ uint str_key_len;
+ ulong num_key;
+ char *payload;
+ size_t payload_len;
+ uint32_t flags = 0;
+ uint32_t retry = 0;
+ memcached_return status;
+ char tmp_key[MEMCACHED_MAX_KEY];
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &server_key,
+ &server_key_len, &entries, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &entries, &expiration) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries));
+ zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(entries))) {
+ int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(entries), &str_key, &str_key_len, &num_key, 0, NULL);
+
+ if (key_type == HASH_KEY_IS_LONG) {
+ /* Array keys are unsigned, but php integers are signed.
+ * Keys must be converted to signed strings that match
+ * php integers. */
+ assert(sizeof(tmp_key) >= sizeof(ZEND_TOSTR(LONG_MIN)));
+
+ str_key_len = sprintf(tmp_key, "%ld", (long)num_key) + 1;
+ str_key = (char *)tmp_key;
+ } else if (key_type != HASH_KEY_IS_STRING) {
+ continue;
+ }
+
+ flags = 0;
+ if (m_obj->compression) {
+ flags |= MEMC_VAL_COMPRESSED;
+ }
+
+ payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC);
+ if (payload == NULL) {
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FALSE;
+ }
+
+retry:
+ if (!by_key) {
+ status = memcached_set(m_obj->memc, str_key, str_key_len-1, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags);
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ PHP_MEMC_FAILOVER_RETRY
+ efree(payload);
+ RETURN_FALSE;
+ }
+ efree(payload);
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::add(string key, mixed value [, int expiration ])
+ Sets the value for the given key, failing if the key already exists */
+PHP_METHOD(Memcached, add)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ])
+ Sets the value for the given key on the server identified by the sever key, failing if the key already exists */
+PHP_METHOD(Memcached, addByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::append(string key, mixed value)
+ Appends the value to existing one for the key */
+PHP_METHOD(Memcached, append)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::appendByKey(string server_key, string key, mixed value)
+ Appends the value to existing one for the key on the server identified by the server key */
+PHP_METHOD(Memcached, appendByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::prepend(string key, mixed value)
+ Prepends the value to existing one for the key */
+PHP_METHOD(Memcached, prepend)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::prependByKey(string server_key, string key, mixed value)
+ Prepends the value to existing one for the key on the server identified by the server key */
+PHP_METHOD(Memcached, prependByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::replace(string key, mixed value [, int expiration ])
+ Replaces the value for the given key, failing if the key doesn't exist */
+PHP_METHOD(Memcached, replace)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ])
+ Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */
+PHP_METHOD(Memcached, replaceByKey)
+{
+ php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1);
+}
+/* }}} */
+
+
+/* {{{ -- php_memc_store_impl */
+static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key)
+{
+ char *key = NULL;
+ int key_len = 0;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ char *s_value = NULL;
+ int s_value_len = 0;
+ zval s_zvalue;
+ zval *value;
+ time_t expiration = 0;
+ char *payload;
+ size_t payload_len;
+ uint32_t flags = 0;
+ uint32_t retry = 0;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &server_key,
+ &server_key_len, &key, &key_len, &s_value, &s_value_len) == FAILURE) {
+ return;
+ }
+ INIT_ZVAL(s_zvalue);
+ value = &s_zvalue;
+ ZVAL_STRINGL(value, s_value, s_value_len, 0);
+ } else if (op == MEMC_OP_TOUCH) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key,
+ &server_key_len, &key, &key_len, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|l", &server_key,
+ &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) {
+ return;
+ }
+ }
+ } else {
+ if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len,
+ &s_value, &s_value_len) == FAILURE) {
+ return;
+ }
+ INIT_ZVAL(s_zvalue);
+ value = &s_zvalue;
+ ZVAL_STRINGL(value, s_value, s_value_len, 0);
+ } else if (op == MEMC_OP_TOUCH) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key,
+ &key_len, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &key, &key_len,
+ &value, &expiration) == FAILURE) {
+ return;
+ }
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FALSE;
+ }
+
+ if (m_obj->compression) {
+ /*
+ * When compression is enabled, we cannot do appends/prepends because that would
+ * corrupt the compressed values. It is up to the user to fetch the value,
+ * append/prepend new data, and store it again.
+ */
+ if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on");
+ return;
+ }
+ flags |= MEMC_VAL_COMPRESSED;
+ }
+
+ if (op == MEMC_OP_TOUCH) {
+ if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol");
+ RETURN_FALSE;
+ }
+ } else {
+ payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC);
+ if (payload == NULL) {
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FALSE;
+ }
+ }
+retry:
+ switch (op) {
+ case MEMC_OP_SET:
+ if (!server_key) {
+ status = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, payload, payload_len, expiration, flags);
+ }
+ break;
+
+ case MEMC_OP_TOUCH:
+ if (!server_key) {
+ status = memcached_touch(m_obj->memc, key, key_len, expiration);
+ } else {
+ status = memcached_touch_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, expiration);
+ }
+ break;
+
+
+ case MEMC_OP_ADD:
+ if (!server_key) {
+ status = memcached_add(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_add_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, payload, payload_len, expiration, flags);
+ }
+ break;
+
+ case MEMC_OP_REPLACE:
+ if (!server_key) {
+ status = memcached_replace(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_replace_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, payload, payload_len, expiration, flags);
+ }
+ break;
+
+ case MEMC_OP_APPEND:
+ if (!server_key) {
+ status = memcached_append(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_append_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, payload, payload_len, expiration, flags);
+ }
+ break;
+
+ case MEMC_OP_PREPEND:
+ if (!server_key) {
+ status = memcached_prepend(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ } else {
+ status = memcached_prepend_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, payload, payload_len, expiration, flags);
+ }
+ break;
+
+ default:
+ /* not reached */
+ assert(0);
+ break;
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ PHP_MEMC_FAILOVER_RETRY
+ RETVAL_FALSE;
+ } else {
+ RETVAL_TRUE;
+ }
+
+ if (op != MEMC_OP_TOUCH) {
+ efree(payload);
+ }
+}
+/* }}} */
+
+/* {{{ -- php_memc_cas_impl */
+static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ double cas_d;
+ uint64_t cas;
+ char *key = NULL;
+ int key_len = 0;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ zval *value;
+ time_t expiration = 0;
+ char *payload;
+ size_t payload_len;
+ uint32_t flags = 0;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|l", &cas_d, &server_key,
+ &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|l", &cas_d, &key, &key_len,
+ &value, &expiration) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FALSE;
+ }
+
+ DVAL_TO_LVAL(cas_d, cas);
+
+ if (m_obj->compression) {
+ flags |= MEMC_VAL_COMPRESSED;
+ }
+
+ payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC);
+ if (payload == NULL) {
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ RETURN_FALSE;
+ }
+
+ if (by_key) {
+ status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, payload, payload_len, expiration, flags, cas);
+ } else {
+ status = memcached_cas(m_obj->memc, key, key_len, payload, payload_len, expiration, flags, cas);
+ }
+ efree(payload);
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ])
+ Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */
+PHP_METHOD(Memcached, cas)
+{
+ php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ])
+ Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */
+PHP_METHOD(Memcached, casByKey)
+{
+ php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::delete(string key [, int time ])
+ Deletes the given key */
+PHP_METHOD(Memcached, delete)
+{
+ php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::deleteMulti(array keys [, int time ])
+ Deletes the given keys */
+PHP_METHOD(Memcached, deleteMulti)
+{
+ php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::deleteByKey(string server_key, string key [, int time ])
+ Deletes the given key from the server identified by the server key */
+PHP_METHOD(Memcached, deleteByKey)
+{
+ php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::deleteMultiByKey(array keys [, int time ])
+ Deletes the given key from the server identified by the server key */
+PHP_METHOD(Memcached, deleteMultiByKey)
+{
+ php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ -- php_memc_delete_impl */
+static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ char *key = NULL;
+ int key_len = 0;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ time_t expiration = 0;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key,
+ &server_key_len, &key, &key_len, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len,
+ &expiration) == FAILURE) {
+ return;
+ }
+ server_key = key;
+ server_key_len = key_len;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FALSE;
+ }
+
+ status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, key,
+ key_len, expiration);
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ -- php_memc_deleteMulti_impl */
+static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
+{
+ zval *entries;
+ char *server_key = NULL;
+ int server_key_len = 0;
+ time_t expiration = 0;
+ zval **entry;
+
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (by_key) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|l", &server_key,
+ &server_key_len, &entries, &expiration) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|l", &entries, &expiration) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ array_init(return_value);
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries));
+ zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(entries))) {
+
+ if (Z_TYPE_PP(entry) != IS_STRING) {
+ convert_to_string_ex(entry);
+ }
+
+ if (Z_STRLEN_PP(entry) == 0) {
+ continue;
+ }
+
+ if (!by_key) {
+ server_key = Z_STRVAL_PP(entry);
+ server_key_len = Z_STRLEN_PP(entry);
+ }
+
+ status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), expiration);
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ add_assoc_long(return_value, Z_STRVAL_PP(entry), status);
+ } else {
+ add_assoc_bool(return_value, Z_STRVAL_PP(entry), 1);
+ }
+ }
+
+ return;
+}
+/* }}} */
+
+/* {{{ -- php_memc_incdec_impl */
+static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr)
+{
+ char *key, *server_key;
+ int key_len, server_key_len;
+ long offset = 1;
+ uint64_t value, initial = 0;
+ time_t expiry = 0;
+ memcached_return status;
+ int n_args = ZEND_NUM_ARGS();
+ uint32_t retry = 0;
+
+ MEMC_METHOD_INIT_VARS;
+
+ if (!by_key) {
+ if (zend_parse_parameters(n_args TSRMLS_CC, "s|lll", &key, &key_len, &offset, &initial, &expiry) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(n_args TSRMLS_CC, "ss|lll", &server_key, &server_key_len, &key, &key_len, &offset, &initial, &expiry) == FAILURE) {
+ return;
+ }
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FALSE;
+ }
+
+ if (offset < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset has to be > 0");
+ RETURN_FALSE;
+ }
+
+retry:
+ if ((!by_key && n_args < 3) || (by_key && n_args < 4)) {
+ if (by_key) {
+ if (incr) {
+ status = memcached_increment_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value);
+ } else {
+ status = memcached_decrement_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value);
+ }
+ } else {
+ if (incr) {
+ status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value);
+ } else {
+ status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value);
+ }
+ }
+ } else {
+ if (by_key) {
+ if (incr) {
+ status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value);
+ } else {
+ status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value);
+ }
+ } else {
+ if (incr) {
+ status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value);
+ } else {
+ status = memcached_decrement_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value);
+ }
+ }
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ PHP_MEMC_FAILOVER_RETRY
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG((long)value);
+}
+/* }}} */
+
+/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ])
+ Increments the value for the given key by delta, defaulting to 1 */
+PHP_METHOD(Memcached, increment)
+{
+ php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ])
+ Decrements the value for the given key by delta, defaulting to 1 */
+PHP_METHOD(Memcached, decrement)
+{
+ php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ])
+ Decrements by server the value for the given key by delta, defaulting to 1 */
+PHP_METHOD(Memcached, decrementByKey)
+{
+ php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
+}
+/* }}} */
+
+/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ])
+ Increments by server the value for the given key by delta, defaulting to 1 */
+PHP_METHOD(Memcached, incrementByKey)
+{
+ php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::addServer(string hostname, int port [, int weight ])
+ Adds the given memcache server to the list */
+PHP_METHOD(Memcached, addServer)
+{
+ char *host;
+ int host_len;
+ long port, weight = 0;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &host, &host_len,
+ &port, &weight) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (host[0] == '/') { /* unix domain socket */
+ status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight);
+ } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) {
+ status = memcached_server_add_udp_with_weight(m_obj->memc, host, port, weight);
+ } else {
+ status = memcached_server_add_with_weight(m_obj->memc, host, port, weight);
+ }
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::addServers(array servers)
+ Adds the given memcache servers to the server list */
+PHP_METHOD(Memcached, addServers)
+{
+ zval *servers;
+ zval **entry;
+ zval **z_host, **z_port, **z_weight = NULL;
+ uint32_t weight = 0;
+ int entry_size, i = 0;
+ memcached_server_st *list = NULL;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &servers) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(servers)), i = 0;
+ zend_hash_get_current_data(Z_ARRVAL_P(servers), (void **)&entry) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(servers)), i++) {
+
+ if (Z_TYPE_PP(entry) != IS_ARRAY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "server list entry #%d is not an array", i+1);
+ continue;
+ }
+
+ entry_size = zend_hash_num_elements(Z_ARRVAL_PP(entry));
+
+ if (entry_size > 1) {
+ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
+
+ /* Check that we have a host */
+ if (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_host) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server host for entry #%d", i+1);
+ continue;
+ }
+
+ /* Check that we have a port */
+ if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE ||
+ zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_port) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server port for entry #%d", i+1);
+ continue;
+ }
+
+ convert_to_string_ex(z_host);
+ convert_to_long_ex(z_port);
+
+ weight = 0;
+ if (entry_size > 2) {
+ /* Try to get weight */
+ if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE ||
+ zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_weight) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server weight for entry #%d", i+1);
+ }
+
+ convert_to_long_ex(z_weight);
+ weight = Z_LVAL_PP(z_weight);
+ }
+
+ list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host),
+ Z_LVAL_PP(z_port), weight, &status);
+
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) == 0) {
+ continue;
+ }
+ }
+
+ /* catch-all for all errors */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not add entry #%d to the server list", i+1);
+ }
+
+ status = memcached_server_push(m_obj->memc, list);
+ memcached_server_list_free(list);
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+/* {{{ Memcached::getServerList()
+ Returns the list of the memcache servers in use */
+PHP_METHOD(Memcached, getServerList)
+{
+ struct callbackContext context = {0};
+ memcached_server_function callbacks[1];
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ callbacks[0] = php_memc_do_serverlist_callback;
+ array_init(return_value);
+ context.return_value = return_value;
+ memcached_server_cursor(m_obj->memc, callbacks, &context, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::getServerByKey(string server_key)
+ Returns the server identified by the given server key */
+PHP_METHOD(Memcached, getServerByKey)
+{
+ char *server_key;
+ int server_key_len;
+ memcached_server_st *server;
+ memcached_return error;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_key, &server_key_len) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ if (server_key_len == 0) {
+ i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED;
+ RETURN_FALSE;
+ }
+
+ server = memcached_server_by_key(m_obj->memc, server_key, server_key_len, &error);
+ if (server == NULL) {
+ php_memc_handle_error(i_obj, error TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ add_assoc_string(return_value, "host", server->hostname, 1);
+ add_assoc_long(return_value, "port", server->port);
+ add_assoc_long(return_value, "weight", server->weight);
+}
+/* }}} */
+
+/* {{{ Memcached::resetServerList()
+ Reset the server list in use */
+PHP_METHOD(Memcached, resetServerList)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ memcached_servers_reset(m_obj->memc);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::quit()
+ Close any open connections */
+PHP_METHOD(Memcached, quit)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ memcached_quit(m_obj->memc);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::getStats()
+ Returns statistics for the memcache servers */
+PHP_METHOD(Memcached, getStats)
+{
+ memcached_stat_st *stats;
+ memcached_return status;
+ struct callbackContext context = {0};
+ memcached_server_function callbacks[1];
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ if (memcached_server_count(m_obj->memc) == 0) {
+ array_init(return_value);
+ return;
+ }
+
+ stats = memcached_stat(m_obj->memc, NULL, &status);
+ php_memc_handle_error(i_obj, status TSRMLS_CC);
+ if (stats == NULL) {
+ RETURN_FALSE;
+ } else if (status != MEMCACHED_SUCCESS && status != MEMCACHED_SOME_ERRORS) {
+ memcached_stat_free(m_obj->memc, stats);
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ callbacks[0] = php_memc_do_stats_callback;
+ context.i = 0;
+ context.stats = stats;
+ context.return_value = return_value;
+ memcached_server_cursor(m_obj->memc, callbacks, &context, 1);
+
+ memcached_stat_free(m_obj->memc, stats);
+}
+/* }}} */
+
+/* {{{ Memcached::getVersion()
+ Returns the version of each memcached server in the pool */
+PHP_METHOD(Memcached, getVersion)
+{
+ memcached_return status = MEMCACHED_SUCCESS;
+ struct callbackContext context = {0};
+ memcached_server_function callbacks[1];
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ array_init(return_value);
+
+ status = memcached_version(m_obj->memc);
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+
+ callbacks[0] = php_memc_do_version_callback;
+ context.return_value = return_value;
+
+ memcached_server_cursor(m_obj->memc, callbacks, &context, 1);
+}
+/* }}} */
+
+/* {{{ Memcached::getAllKeys()
+ Returns the keys stored on all the servers */
+static memcached_return php_memc_dump_func_callback(const memcached_st *ptr __attribute__((unused)), \
+ const char *key, size_t key_length, void *context)
+{
+ zval *ctx = (zval*) context;
+ add_next_index_string(ctx, (char*) key, 1);
+
+ return MEMCACHED_SUCCESS;
+}
+
+PHP_METHOD(Memcached, getAllKeys)
+{
+ memcached_return rc;
+ memcached_dump_func callback[1];
+ MEMC_METHOD_INIT_VARS;
+
+ callback[0] = php_memc_dump_func_callback;
+ MEMC_METHOD_FETCH_OBJECT;
+
+ array_init(return_value);
+ rc = memcached_dump(m_obj->memc, callback, return_value, 1);
+ if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ Memcached::flush([ int delay ])
+ Flushes the data on all the servers */
+static PHP_METHOD(Memcached, flush)
+{
+ time_t delay = 0;
+ memcached_return status;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &delay) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+ i_obj->rescode = MEMCACHED_SUCCESS;
+
+ status = memcached_flush(m_obj->memc, delay);
+ if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ Memcached::getOption(int option)
+ Returns the value for the given option constant */
+static PHP_METHOD(Memcached, getOption)
+{
+ long option;
+ uint64_t result;
+ memcached_behavior flag;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &option) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ switch (option) {
+ case MEMC_OPT_COMPRESSION_TYPE:
+ RETURN_LONG(m_obj->compression_type);
+
+ case MEMC_OPT_COMPRESSION:
+ RETURN_BOOL(m_obj->compression);
+
+ case MEMC_OPT_PREFIX_KEY:
+ {
+ memcached_return retval;
+ char *result;
+
+ result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval);
+ if (retval == MEMCACHED_SUCCESS && result) {
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000
+ RETURN_STRINGL(result, strlen(result) - 1, 1);
+#else
+ RETURN_STRING(result, 1);
+#endif
+ } else {
+ RETURN_EMPTY_STRING();
+ }
+ }
+
+ case MEMC_OPT_SERIALIZER:
+ RETURN_LONG((long)m_obj->serializer);
+ break;
+
+ case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
+ case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
+ if (memcached_server_count(m_obj->memc) == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "no servers defined");
+ return;
+ }
+
+ default:
+ /*
+ * Assume that it's a libmemcached behavior option.
+ */
+ flag = (memcached_behavior) option;
+ result = memcached_behavior_get(m_obj->memc, flag);
+ RETURN_LONG((long)result);
+ }
+}
+/* }}} */
+
+static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRMLS_DC)
+{
+ memcached_behavior flag;
+ struct memc_obj *m_obj = i_obj->obj;
+
+ switch (option) {
+ case MEMC_OPT_COMPRESSION:
+ convert_to_long(value);
+ m_obj->compression = Z_LVAL_P(value) ? 1 : 0;
+ break;
+
+ case MEMC_OPT_COMPRESSION_TYPE:
+ convert_to_long(value);
+ if (Z_LVAL_P(value) == COMPRESSION_TYPE_FASTLZ ||
+ Z_LVAL_P(value) == COMPRESSION_TYPE_ZLIB) {
+ m_obj->compression_type = Z_LVAL_P(value);
+ } else {
+ /* invalid compression type */
+ return 0;
+ }
+ break;
+
+ case MEMC_OPT_PREFIX_KEY:
+ {
+ char *key;
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000
+ char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1];
+#endif
+ convert_to_string(value);
+ if (Z_STRLEN_P(value) == 0) {
+ key = NULL;
+ } else {
+ /*
+ work-around a bug in libmemcached prior to version 0.50 that truncates the trailing
+ character of the key prefix, to avoid the issue we pad it with a '0'
+ */
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00050000
+ snprintf(tmp, sizeof(tmp), "%s0", Z_STRVAL_P(value));
+ key = tmp;
+#else
+ key = Z_STRVAL_P(value);
+#endif
+ }
+ if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided");
+ return 0;
+ }
+ break;
+ }
+
+ case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
+ flag = (memcached_behavior) option;
+
+ convert_to_long(value);
+ if (memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) == MEMCACHED_FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option");
+ return 0;
+ }
+
+ /*
+ * This is necessary because libmemcached does not reset hash/distribution
+ * options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA
+ * (non-weighted) case. We have to clean up ourselves.
+ */
+ if (!Z_LVAL_P(value)) {
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000
+ (void)memcached_behavior_set_key_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT);
+ (void)memcached_behavior_set_distribution_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT);
+ (void)memcached_behavior_set_distribution(m_obj->memc, MEMCACHED_DISTRIBUTION_MODULA);
+#else
+ m_obj->memc->hash = 0;
+ m_obj->memc->distribution = 0;
+#endif
+ }
+ break;
+
+ case MEMC_OPT_SERIALIZER:
+ {
+ convert_to_long(value);
+ /* igbinary serializer */
+#ifdef HAVE_MEMCACHED_IGBINARY
+ if (Z_LVAL_P(value) == SERIALIZER_IGBINARY) {
+ m_obj->serializer = SERIALIZER_IGBINARY;
+ } else
+#endif
+#ifdef HAVE_JSON_API
+ if (Z_LVAL_P(value) == SERIALIZER_JSON) {
+ m_obj->serializer = SERIALIZER_JSON;
+ } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) {
+ m_obj->serializer = SERIALIZER_JSON_ARRAY;
+ } else
+#endif
+ /* php serializer */
+ if (Z_LVAL_P(value) == SERIALIZER_PHP) {
+ m_obj->serializer = SERIALIZER_PHP;
+ } else {
+ m_obj->serializer = SERIALIZER_PHP;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid serializer provided");
+ return 0;
+ }
+ break;
+ }
+
+ default:
+ /*
+ * Assume that it's a libmemcached behavior option.
+ */
+ flag = (memcached_behavior) option;
+ convert_to_long(value);
+ if (flag < 0 ||
+/* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000
+ flag >= MEMCACHED_BEHAVIOR_MAX ||
+#endif
+ memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option");
+ return 0;
+ }
+ break;
+ }
+
+ return 1;
+}
+
+/* {{{ Memcached::setOptions(array options)
+ Sets the value for the given option constant */
+static PHP_METHOD(Memcached, setOptions)
+{
+ zval *options;
+ zend_bool ok = 1;
+ uint key_len;
+ char *key;
+ ulong key_index;
+ zval **value;
+
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &options) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(options));
+ zend_hash_get_current_data(Z_ARRVAL_P(options), (void *) &value) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(options))) {
+
+ if (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) {
+ zval copy = **value;
+ zval_copy_ctor(©);
+ INIT_PZVAL(©);
+
+ if (!php_memc_set_option(i_obj, (long) key_index, © TSRMLS_CC)) {
+ ok = 0;
+ }
+
+ zval_dtor(©);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option");
+ ok = 0;
+ }
+ }
+
+ RETURN_BOOL(ok);
+}
+/* }}} */
+
+/* {{{ Memcached::setOption(int option, mixed value)
+ Sets the value for the given option constant */
+static PHP_METHOD(Memcached, setOption)
+{
+ long option;
+ zval *value;
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &option, &value) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ RETURN_BOOL(php_memc_set_option(i_obj, option, value TSRMLS_CC));
+}
+/* }}} */
+
+#ifdef HAVE_MEMCACHED_SASL
+/* {{{ Memcached::setSaslAuthData(string user, string pass)
+ Sets sasl credentials */
+static PHP_METHOD(Memcached, setSaslAuthData)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ char *user, *pass;
+ int user_len, pass_len, rc;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &user, &user_len, &pass, &pass_len) == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL is only supported with binary protocol");
+ RETURN_FALSE;
+ }
+ RETURN_BOOL(memcached_set_sasl_auth_data(m_obj->memc, user, pass));
+}
+/* }}} */
+#endif /* HAVE_MEMCACHED_SASL */
+
+/* {{{ Memcached::getResultCode()
+ Returns the result code from the last operation */
+static PHP_METHOD(Memcached, getResultCode)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ RETURN_LONG(i_obj->rescode);
+}
+/* }}} */
+
+/* {{{ Memcached::getResultMessage()
+ Returns the result message from the last operation */
+static PHP_METHOD(Memcached, getResultMessage)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ switch (i_obj->rescode) {
+ case MEMC_RES_PAYLOAD_FAILURE:
+ RETURN_STRING("PAYLOAD FAILURE", 1);
+ break;
+
+ case MEMCACHED_ERRNO:
+ case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE:
+ case MEMCACHED_UNKNOWN_READ_FAILURE:
+ if (i_obj->memc_errno) {
+ char *str;
+ int str_len;
+ str_len = spprintf(&str, 0, "%s: %s", memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode),
+ strerror(i_obj->memc_errno));
+ RETURN_STRINGL(str, str_len, 0);
+ }
+ /* Fall through */
+ default:
+ RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), 1);
+ break;
+ }
+
+}
+/* }}} */
+
+/* {{{ Memcached::isPersistent()
+ Returns the true if instance uses a persistent connection */
+static PHP_METHOD(Memcached, isPersistent)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ RETURN_BOOL(i_obj->is_persistent);
+}
+/* }}} */
+
+/* {{{ Memcached::isPristine()
+ Returns the true if instance is recently created */
+static PHP_METHOD(Memcached, isPristine)
+{
+ MEMC_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ MEMC_METHOD_FETCH_OBJECT;
+
+ RETURN_BOOL(i_obj->is_pristine);
+}
+/* }}} */
+
+/****************************************
+ Internal support code
+****************************************/
+
+/* {{{ constructor/destructor */
+static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC)
+{
+#if HAVE_MEMCACHED_SASL
+ if (m_obj->has_sasl_data) {
+ memcached_destroy_sasl_auth_data(m_obj->memc);
+ }
+#endif
+ if (m_obj->memc) {
+ memcached_free(m_obj->memc);
+ }
+
+ pefree(m_obj, persistent);
+}
+
+static void php_memc_free_storage(php_memc_t *i_obj TSRMLS_DC)
+{
+ zend_object_std_dtor(&i_obj->zo TSRMLS_CC);
+
+ if (i_obj->obj && !i_obj->is_persistent) {
+ php_memc_destroy(i_obj->obj, 0 TSRMLS_CC);
+ }
+
+ i_obj->obj = NULL;
+ efree(i_obj);
+}
+
+zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ php_memc_t *i_obj;
+ zval *tmp;
+
+ i_obj = ecalloc(1, sizeof(*i_obj));
+ zend_object_std_init( &i_obj->zo, ce TSRMLS_CC );
+#if PHP_VERSION_ID >= 50400
+ object_properties_init( (zend_object *) i_obj, ce);
+#else
+ zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+#endif
+
+ retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC);
+ retval.handlers = &memcached_object_handlers;
+
+ return retval;
+}
+
+ZEND_RSRC_DTOR_FUNC(php_memc_dtor)
+{
+ if (rsrc->ptr) {
+ struct memc_obj *m_obj = (struct memc_obj *)rsrc->ptr;
+ php_memc_destroy(m_obj, 1 TSRMLS_CC);
+ rsrc->ptr = NULL;
+ }
+}
+
+ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor)
+{
+ if (rsrc->ptr) {
+ memcached_sess *memc_sess = (memcached_sess *)rsrc->ptr;
+ memcached_free(memc_sess->memc_sess);
+ pefree(rsrc->ptr, 1);
+ rsrc->ptr = NULL;
+ }
+}
+/* }}} */
+
+/* {{{ internal API functions */
+static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
+{
+ struct callbackContext* context = (struct callbackContext*) in_context;
+ zval *array;
+
+ MAKE_STD_ZVAL(array);
+ array_init(array);
+ add_assoc_string(array, "host", memcached_server_name(instance), 1);
+ add_assoc_long(array, "port", memcached_server_port(instance));
+ /*
+ * API does not allow to get at this field.
+ add_assoc_long(array, "weight", instance->weight);
+ */
+ add_next_index_zval(context->return_value, array);
+ return MEMCACHED_SUCCESS;
+}
+
+static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
+{
+ char *hostport = NULL;
+ int hostport_len;
+ struct callbackContext* context = (struct callbackContext*) in_context;
+ zval *entry;
+ hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance));
+
+ MAKE_STD_ZVAL(entry);
+ array_init(entry);
+
+ add_assoc_long(entry, "pid", context->stats[context->i].pid);
+ add_assoc_long(entry, "uptime", context->stats[context->i].uptime);
+ add_assoc_long(entry, "threads", context->stats[context->i].threads);
+ add_assoc_long(entry, "time", context->stats[context->i].time);
+ add_assoc_long(entry, "pointer_size", context->stats[context->i].pointer_size);
+ add_assoc_long(entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds);
+ add_assoc_long(entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds);
+ add_assoc_long(entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds);
+ add_assoc_long(entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds);
+ add_assoc_long(entry, "curr_items", context->stats[context->i].curr_items);
+ add_assoc_long(entry, "total_items", context->stats[context->i].total_items);
+ add_assoc_long(entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes);
+ add_assoc_long(entry, "curr_connections", context->stats[context->i].curr_connections);
+ add_assoc_long(entry, "total_connections", context->stats[context->i].total_connections);
+ add_assoc_long(entry, "connection_structures", context->stats[context->i].connection_structures);
+ add_assoc_long(entry, "bytes", context->stats[context->i].bytes);
+ add_assoc_long(entry, "cmd_get", context->stats[context->i].cmd_get);
+ add_assoc_long(entry, "cmd_set", context->stats[context->i].cmd_set);
+ add_assoc_long(entry, "get_hits", context->stats[context->i].get_hits);
+ add_assoc_long(entry, "get_misses", context->stats[context->i].get_misses);
+ add_assoc_long(entry, "evictions", context->stats[context->i].evictions);
+ add_assoc_long(entry, "bytes_read", context->stats[context->i].bytes_read);
+ add_assoc_long(entry, "bytes_written", context->stats[context->i].bytes_written);
+ add_assoc_stringl(entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version), 1);
+
+ add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, entry);
+ efree(hostport);
+
+ /* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */
+ context->i++;
+ return MEMCACHED_SUCCESS;
+}
+
+static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
+{
+ char *hostport = NULL;
+ char version[16];
+ int hostport_len, version_len;
+ struct callbackContext* context = (struct callbackContext*) in_context;
+
+ hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance));
+ version_len = snprintf(version, sizeof(version), "%d.%d.%d",
+ memcached_server_major_version(instance),
+ memcached_server_minor_version(instance),
+ memcached_server_micro_version(instance));
+
+ add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1);
+ efree(hostport);
+ return MEMCACHED_SUCCESS;
+}
+
+static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC)
+{
+ int result = 0;
+
+ switch (status) {
+ case MEMCACHED_SUCCESS:
+ case MEMCACHED_STORED:
+ case MEMCACHED_DELETED:
+ case MEMCACHED_STAT:
+ result = 0;
+ i_obj->memc_errno = 0;
+ break;
+
+ case MEMCACHED_END:
+ case MEMCACHED_BUFFERED:
+ i_obj->rescode = status;
+ i_obj->memc_errno = 0;
+ result = 0;
+ break;
+
+ case MEMCACHED_SOME_ERRORS:
+ i_obj->rescode = status;
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
+ i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc);
+#else
+ i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */
+
+#endif
+ result = 0;
+ break;
+
+ default:
+ i_obj->rescode = status;
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
+ i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc);
+#else
+ i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */
+
+#endif
+ result = -1;
+ break;
+ }
+
+ return result;
+}
+
+static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC)
+{
+ char *payload;
+ char *p;
+ int l;
+ zend_bool buf_used = 0;
+ smart_str buf = {0};
+ char tmp[40] = {0};
+
+ switch (Z_TYPE_P(value)) {
+
+ case IS_STRING:
+ p = Z_STRVAL_P(value);
+ l = Z_STRLEN_P(value);
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING);
+ break;
+
+ case IS_LONG:
+ l = sprintf(tmp, "%ld", Z_LVAL_P(value));
+ p = tmp;
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG);
+ break;
+
+ case IS_DOUBLE:
+ php_memcached_g_fmt(tmp, Z_DVAL_P(value));
+ p = tmp;
+ l = strlen(tmp);
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE);
+ break;
+
+ case IS_BOOL:
+ if (Z_BVAL_P(value)) {
+ l = 1;
+ tmp[0] = '1';
+ tmp[1] = '\0';
+ } else {
+ l = 0;
+ tmp[0] = '\0';
+ }
+ p = tmp;
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL);
+ break;
+
+ default:
+ switch (serializer) {
+#ifdef HAVE_MEMCACHED_IGBINARY
+ case SERIALIZER_IGBINARY:
+ if (igbinary_serialize((uint8_t **) &buf.c, &buf.len, value TSRMLS_CC) != 0) {
+ smart_str_free(&buf);
+ return NULL;
+ }
+ p = buf.c;
+ l = buf.len;
+ buf_used = 1;
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY);
+ break;
+#endif
+
+#ifdef HAVE_JSON_API
+ case SERIALIZER_JSON:
+ case SERIALIZER_JSON_ARRAY:
+ {
+#if HAVE_JSON_API_5_2
+ php_json_encode(&buf, value TSRMLS_CC);
+#elif HAVE_JSON_API_5_3
+ php_json_encode(&buf, value, 0 TSRMLS_CC); /* options */
+#endif
+ buf.c[buf.len] = 0;
+ p = buf.c;
+ l = buf.len;
+ buf_used = 1;
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON);
+ break;
+ }
+#endif
+ default:
+ {
+ php_serialize_data_t var_hash;
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+ php_var_serialize(&buf, &value, &var_hash TSRMLS_CC);
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ if (!buf.c) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value");
+ smart_str_free(&buf);
+ return NULL;
+ }
+ p = buf.c;
+ l = buf.len;
+ buf_used = 1;
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ /* Check for exceptions caused by serializers */
+ if (EG(exception) && buf_used) {
+ smart_str_free(&buf);
+ return NULL;
+ }
+
+ /* turn off compression for values below the threshold */
+ if ((*flags & MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) {
+ *flags &= ~MEMC_VAL_COMPRESSED;
+ }
+
+ if (*flags & MEMC_VAL_COMPRESSED) {
+ /* status */
+ zend_bool compress_status = 0;
+
+ /* Additional 5% for the data */
+ unsigned long payload_comp_len = (unsigned long)((l * 1.05) + 1);
+ char *payload_comp = emalloc(payload_comp_len + sizeof(uint32_t));
+ payload = payload_comp;
+ memcpy(payload_comp, &l, sizeof(uint32_t));
+ payload_comp += sizeof(uint32_t);
+
+ if (compression_type == COMPRESSION_TYPE_FASTLZ) {
+ compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0);
+ *flags |= MEMC_VAL_COMPRESSION_FASTLZ;
+ } else if (compression_type == COMPRESSION_TYPE_ZLIB) {
+ compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK);
+ *flags |= MEMC_VAL_COMPRESSION_ZLIB;
+ }
+
+ if (!compress_status) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value");
+ efree(payload);
+ if (buf_used) {
+ smart_str_free(&buf);
+ }
+ return NULL;
+ }
+
+ /* Check that we are above ratio */
+ if (l > (payload_comp_len * MEMC_G(compression_factor))) {
+ *payload_len = payload_comp_len + sizeof(uint32_t);
+ payload[*payload_len] = 0;
+ } else {
+ /* Store plain value */
+ *flags &= ~MEMC_VAL_COMPRESSED;
+ *payload_len = l;
+ memcpy(payload, p, l);
+ payload[l] = 0;
+ }
+ } else {
+ *payload_len = l;
+ payload = estrndup(p, l);
+ }
+
+ if (buf_used) {
+ smart_str_free(&buf);
+ }
+ return payload;
+}
+
+/* The caller MUST free the payload */
+static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC)
+{
+ /*
+ A NULL payload is completely valid if length is 0, it is simply empty.
+ */
+ zend_bool payload_emalloc = 0;
+ char *buffer = NULL;
+
+ if (payload == NULL && payload_len > 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Could not handle non-existing value of length %zu", payload_len);
+ return -1;
+ } else if (payload == NULL) {
+ if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) {
+ ZVAL_FALSE(value);
+ } else {
+ ZVAL_EMPTY_STRING(value);
+ }
+ return 0;
+ }
+
+ if (flags & MEMC_VAL_COMPRESSED) {
+ uint32_t len;
+ unsigned long length;
+ zend_bool decompress_status = 0;
+
+ /* Stored with newer memcached extension? */
+ if (flags & MEMC_VAL_COMPRESSION_FASTLZ || flags & MEMC_VAL_COMPRESSION_ZLIB) {
+ /* This is copied from Ilia's patch */
+ memcpy(&len, payload, sizeof(uint32_t));
+ buffer = emalloc(len + 1);
+ payload_len -= sizeof(uint32_t);
+ payload += sizeof(uint32_t);
+ length = len;
+
+ if (flags & MEMC_VAL_COMPRESSION_FASTLZ) {
+ decompress_status = ((length = fastlz_decompress(payload, payload_len, buffer, len)) > 0);
+ } else if (flags & MEMC_VAL_COMPRESSION_ZLIB) {
+ decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, payload_len) == Z_OK);
+ }
+ }
+
+ /* Fall back to 'old style decompression' */
+ if (!decompress_status) {
+ unsigned int factor = 1, maxfactor = 16;
+ int status;
+
+ do {
+ length = (unsigned long)payload_len * (1 << factor++);
+ buffer = erealloc(buffer, length + 1);
+ memset(buffer, 0, length + 1);
+ status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, payload_len);
+ } while ((status==Z_BUF_ERROR) && (factor < maxfactor));
+
+ if (status == Z_OK) {
+ decompress_status = 1;
+ }
+ }
+
+ if (!decompress_status) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value");
+ efree(buffer);
+ return -1;
+ }
+ payload = buffer;
+ payload_len = length;
+ payload_emalloc = 1;
+ }
+
+ payload[payload_len] = 0;
+
+ switch (MEMC_VAL_GET_TYPE(flags)) {
+ case MEMC_VAL_IS_STRING:
+ if (payload_emalloc) {
+ ZVAL_STRINGL(value, payload, payload_len, 0);
+ payload_emalloc = 0;
+ } else {
+ ZVAL_STRINGL(value, payload, payload_len, 1);
+ }
+ break;
+
+ case MEMC_VAL_IS_LONG:
+ {
+ long lval = strtol(payload, NULL, 10);
+ ZVAL_LONG(value, lval);
+ break;
+ }
+
+ case MEMC_VAL_IS_DOUBLE:
+ if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) {
+ ZVAL_DOUBLE(value, php_get_inf());
+ } else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) {
+ ZVAL_DOUBLE(value, -php_get_inf());
+ } else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) {
+ ZVAL_DOUBLE(value, php_get_nan());
+ } else {
+ ZVAL_DOUBLE(value, zend_strtod(payload, NULL));
+ }
+ break;
+
+ case MEMC_VAL_IS_BOOL:
+ ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1');
+ break;
+
+ case MEMC_VAL_IS_SERIALIZED:
+ {
+ const char *payload_tmp = payload;
+ php_unserialize_data_t var_hash;
+
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash TSRMLS_CC)) {
+ ZVAL_FALSE(value);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value");
+ goto my_error;
+ }
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ break;
+ }
+
+ case MEMC_VAL_IS_IGBINARY:
+#ifdef HAVE_MEMCACHED_IGBINARY
+ if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) {
+ ZVAL_FALSE(value);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary");
+ goto my_error;
+ }
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support");
+ goto my_error;
+#endif
+ break;
+
+ case MEMC_VAL_IS_JSON:
+#ifdef HAVE_JSON_API
+# if HAVE_JSON_API_5_2
+ php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC);
+# elif HAVE_JSON_API_5_3
+ php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC);
+# endif
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support");
+ goto my_error;
+#endif
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type");
+ goto my_error;
+ }
+
+ if (payload_emalloc) {
+ efree(payload);
+ }
+
+ return 0;
+
+my_error:
+ if (payload_emalloc) {
+ efree(payload);
+ }
+ return -1;
+}
+
+static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC)
+{
+#ifdef HAVE_MEMCACHED_SESSION
+ MEMC_G(sess_locking_enabled) = 1;
+ MEMC_G(sess_binary_enabled) = 1;
+ MEMC_G(sess_prefix) = NULL;
+ MEMC_G(sess_lock_wait) = 0;
+ MEMC_G(sess_locked) = 0;
+ MEMC_G(sess_lock_key) = NULL;
+ MEMC_G(sess_lock_key_len) = 0;
+#endif
+ MEMC_G(serializer_name) = NULL;
+ MEMC_G(serializer) = SERIALIZER_DEFAULT;
+ MEMC_G(compression_type) = NULL;
+ MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ;
+ MEMC_G(compression_factor) = 1.30;
+#if HAVE_MEMCACHED_SASL
+ MEMC_G(use_sasl) = 0;
+#endif
+}
+
+static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC)
+{
+}
+
+PHP_MEMCACHED_API
+zend_class_entry *php_memc_get_ce(void)
+{
+ return memcached_ce;
+}
+
+PHP_MEMCACHED_API
+zend_class_entry *php_memc_get_exception(void)
+{
+ return memcached_exception_ce;
+}
+
+PHP_MEMCACHED_API
+zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC)
+{
+#if HAVE_SPL
+ if (!root) {
+ if (!spl_ce_RuntimeException) {
+ zend_class_entry **pce;
+
+ if (zend_hash_find(CG(class_table), "runtimeexception",
+ sizeof("RuntimeException"), (void **) &pce) == SUCCESS) {
+ spl_ce_RuntimeException = *pce;
+ return *pce;
+ }
+ } else {
+ return spl_ce_RuntimeException;
+ }
+ }
+#endif
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
+ return zend_exception_get_default();
+#else
+ return zend_exception_get_default(TSRMLS_C);
+#endif
+}
+
+static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci,
+ zend_fcall_info_cache *fcc, char *key,
+ size_t key_len, zval *value TSRMLS_DC)
+{
+ char *payload = NULL;
+ size_t payload_len = 0;
+ zval **params[4];
+ zval *retval;
+ zval *z_key;
+ zval *z_expiration;
+
+ uint32_t flags = 0;
+ memcached_return rc;
+ php_memc_t* i_obj;
+ memcached_return status = MEMCACHED_SUCCESS;
+ int result;
+
+ MAKE_STD_ZVAL(z_key);
+ MAKE_STD_ZVAL(z_expiration);
+ ZVAL_STRINGL(z_key, key, key_len, 1);
+ ZVAL_NULL(value);
+ ZVAL_LONG(z_expiration, 0);
+
+ params[0] = &zmemc_obj;
+ params[1] = &z_key;
+ params[2] = &value;
+ params[3] = &z_expiration;
+
+ fci->retval_ptr_ptr = &retval;
+ fci->params = params;
+ fci->param_count = sizeof(params) / sizeof(params[0]);
+
+ result = zend_call_function(fci, fcc TSRMLS_CC);
+ if (result == SUCCESS && retval) {
+ i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC);
+ struct memc_obj *m_obj = i_obj->obj;
+
+ if (zend_is_true(retval)) {
+ time_t expiration;
+
+ if (Z_TYPE_P(z_expiration) != IS_LONG) {
+ convert_to_long(z_expiration);
+ }
+
+ expiration = Z_LVAL_P(z_expiration);
+
+ payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC);
+ if (payload == NULL) {
+ status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE;
+ } else {
+ rc = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags);
+ if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) {
+ status = rc;
+ }
+ efree(payload);
+ }
+ } else {
+ status = MEMCACHED_NOTFOUND;
+ zval_dtor(value);
+ ZVAL_NULL(value);
+ }
+
+ } else {
+ if (result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke cache callback");
+ }
+ status = MEMCACHED_FAILURE;
+ zval_dtor(value);
+ ZVAL_NULL(value);
+ }
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+
+ zval_ptr_dtor(&z_key);
+ zval_ptr_dtor(&z_expiration);
+
+ return status;
+}
+
+static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci,
+ zend_fcall_info_cache *fcc,
+ memcached_result_st *result TSRMLS_DC)
+{
+ char *res_key = NULL;
+ size_t res_key_len = 0;
+ char *payload = NULL;
+ size_t payload_len = 0;
+ zval *value, *retval = NULL;
+ uint64_t cas = 0;
+ zval **params[2];
+ zval *z_result;
+ uint32_t flags = 0;
+ int rc = 0;
+ php_memc_t *i_obj = NULL;
+
+ params[0] = &zmemc_obj;
+ params[1] = &z_result;
+
+ fci->retval_ptr_ptr = &retval;
+ fci->params = params;
+ fci->param_count = 2;
+
+ payload = memcached_result_value(result);
+ payload_len = memcached_result_length(result);
+ flags = memcached_result_flags(result);
+ res_key = memcached_result_key_value(result);
+ res_key_len = memcached_result_key_length(result);
+ cas = memcached_result_cas(result);
+
+ MAKE_STD_ZVAL(value);
+
+ i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC);
+
+ if (php_memc_zval_from_payload(value, payload, payload_len, flags, i_obj->obj->serializer TSRMLS_CC) < 0) {
+ zval_ptr_dtor(&value);
+ i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE;
+ return -1;
+ }
+
+ MAKE_STD_ZVAL(z_result);
+ array_init(z_result);
+ add_assoc_stringl_ex(z_result, ZEND_STRS("key"), res_key, res_key_len, 1);
+ add_assoc_zval_ex(z_result, ZEND_STRS("value"), value);
+ if (cas != 0) {
+ add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas);
+ }
+
+ if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback");
+ rc = -1;
+ }
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+ zval_ptr_dtor(&z_result);
+
+ return rc;
+}
+
+/* }}} */
+
+/* {{{ methods arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, persistent_id)
+ ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getResultCode, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getResultMessage, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, cache_cb)
+ ZEND_ARG_INFO(1, cas_token)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, cache_cb)
+ ZEND_ARG_INFO(1, cas_token)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, keys, 0)
+ ZEND_ARG_INFO(1, cas_tokens)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_ARRAY_INFO(0, keys, 0)
+ ZEND_ARG_INFO(1, cas_tokens)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, keys, 0)
+ ZEND_ARG_INFO(0, with_cas)
+ ZEND_ARG_INFO(0, value_cb)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayedByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_ARRAY_INFO(0, keys, 0)
+ ZEND_ARG_INFO(0, with_cas)
+ ZEND_ARG_INFO(0, value_cb)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_fetch, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_fetchAll, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_touchByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, items, 0)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_ARRAY_INFO(0, items, 0)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3)
+ ZEND_ARG_INFO(0, cas_token)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4)
+ ZEND_ARG_INFO(0, cas_token)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, expiration)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, time)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMulti, 0, 0, 1)
+ ZEND_ARG_INFO(0, keys)
+ ZEND_ARG_INFO(0, time)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, time)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMultiByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, keys)
+ ZEND_ARG_INFO(0, time)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, initial_value)
+ ZEND_ARG_INFO(0, expiry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, initial_value)
+ ZEND_ARG_INFO(0, expiry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_incrementByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, initial_value)
+ ZEND_ARG_INFO(0, expiry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_decrementByKey, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_key)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, initial_value)
+ ZEND_ARG_INFO(0, expiry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0)
+ ZEND_ARG_INFO(0, delay)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2)
+ ZEND_ARG_INFO(0, host)
+ ZEND_ARG_INFO(0, port)
+ ZEND_ARG_INFO(0, weight)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_addServers, 0)
+ ZEND_ARG_ARRAY_INFO(0, servers, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getServerList, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_resetServerList, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_quit, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0)
+ ZEND_ARG_INFO(0, server_key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0)
+ ZEND_ARG_INFO(0, option)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, password)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0)
+ ZEND_ARG_INFO(0, option)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_isPersistent, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_isPristine, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_getAllKeys, 0)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ memcached_class_methods */
+#define MEMC_ME(name, args) PHP_ME(Memcached, name, args, ZEND_ACC_PUBLIC)
+static zend_function_entry memcached_class_methods[] = {
+ MEMC_ME(__construct, arginfo___construct)
+
+ MEMC_ME(getResultCode, arginfo_getResultCode)
+ MEMC_ME(getResultMessage, arginfo_getResultMessage)
+
+ MEMC_ME(get, arginfo_get)
+ MEMC_ME(getByKey, arginfo_getByKey)
+ MEMC_ME(getMulti, arginfo_getMulti)
+ MEMC_ME(getMultiByKey, arginfo_getMultiByKey)
+ MEMC_ME(getDelayed, arginfo_getDelayed)
+ MEMC_ME(getDelayedByKey, arginfo_getDelayedByKey)
+ MEMC_ME(fetch, arginfo_fetch)
+ MEMC_ME(fetchAll, arginfo_fetchAll)
+
+ MEMC_ME(set, arginfo_set)
+ MEMC_ME(setByKey, arginfo_setByKey)
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002
+ MEMC_ME(touch, arginfo_touch)
+ MEMC_ME(touchByKey, arginfo_touchByKey)
+#endif
+ MEMC_ME(setMulti, arginfo_setMulti)
+ MEMC_ME(setMultiByKey, arginfo_setMultiByKey)
+
+ MEMC_ME(cas, arginfo_cas)
+ MEMC_ME(casByKey, arginfo_casByKey)
+ MEMC_ME(add, arginfo_add)
+ MEMC_ME(addByKey, arginfo_addByKey)
+ MEMC_ME(append, arginfo_append)
+ MEMC_ME(appendByKey, arginfo_appendByKey)
+ MEMC_ME(prepend, arginfo_prepend)
+ MEMC_ME(prependByKey, arginfo_prependByKey)
+ MEMC_ME(replace, arginfo_replace)
+ MEMC_ME(replaceByKey, arginfo_replaceByKey)
+ MEMC_ME(delete, arginfo_delete)
+ MEMC_ME(deleteMulti, arginfo_deleteMulti)
+ MEMC_ME(deleteByKey, arginfo_deleteByKey)
+ MEMC_ME(deleteMultiByKey, arginfo_deleteMultiByKey)
+
+ MEMC_ME(increment, arginfo_increment)
+ MEMC_ME(decrement, arginfo_decrement)
+ MEMC_ME(incrementByKey, arginfo_incrementByKey)
+ MEMC_ME(decrementByKey, arginfo_decrementByKey)
+
+ MEMC_ME(addServer, arginfo_addServer)
+ MEMC_ME(addServers, arginfo_addServers)
+ MEMC_ME(getServerList, arginfo_getServerList)
+ MEMC_ME(getServerByKey, arginfo_getServerByKey)
+ MEMC_ME(resetServerList, arginfo_resetServerList)
+ MEMC_ME(quit, arginfo_quit)
+
+ MEMC_ME(getStats, arginfo_getStats)
+ MEMC_ME(getVersion, arginfo_getVersion)
+ MEMC_ME(getAllKeys, arginfo_getAllKeys)
+
+ MEMC_ME(flush, arginfo_flush)
+
+ MEMC_ME(getOption, arginfo_getOption)
+ MEMC_ME(setOption, arginfo_setOption)
+ MEMC_ME(setOptions, arginfo_setOptions)
+#ifdef HAVE_MEMCACHED_SASL
+ MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData)
+#endif
+ MEMC_ME(isPersistent, arginfo_isPersistent)
+ MEMC_ME(isPristine, arginfo_isPristine)
+ { NULL, NULL, NULL }
+};
+#undef MEMC_ME
+/* }}} */
+
+/* {{{ memcached_module_entry
+ */
+
+#if ZEND_MODULE_API_NO >= 20050922
+static const zend_module_dep memcached_deps[] = {
+#ifdef HAVE_MEMCACHED_SESSION
+ ZEND_MOD_REQUIRED("session")
+#endif
+#ifdef HAVE_MEMCACHED_IGBINARY
+ ZEND_MOD_REQUIRED("igbinary")
+#endif
+#ifdef HAVE_SPL
+ ZEND_MOD_REQUIRED("spl")
+#endif
+ {NULL, NULL, NULL}
+};
+#endif
+
+zend_module_entry memcached_module_entry = {
+#if ZEND_MODULE_API_NO >= 20050922
+ STANDARD_MODULE_HEADER_EX, NULL,
+ (zend_module_dep*)memcached_deps,
+#else
+ STANDARD_MODULE_HEADER,
+#endif
+ "memcached",
+ NULL,
+ PHP_MINIT(memcached),
+ PHP_MSHUTDOWN(memcached),
+#if HAVE_MEMCACHED_SASL
+ PHP_RINIT(memcached),
+ PHP_RSHUTDOWN(memcached),
+#else
+ NULL,
+ NULL,
+#endif
+ PHP_MINFO(memcached),
+ PHP_MEMCACHED_VERSION,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+/* {{{ php_memc_register_constants */
+static void php_memc_register_constants(INIT_FUNC_ARGS)
+{
+ #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC)
+ #define REGISTER_MEMC_CLASS_CONST_BOOL(name, value) zend_declare_class_constant_bool(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC)
+ #define REGISTER_MEMC_CLASS_CONST_NULL(name) zend_declare_class_constant_null(php_memc_get_ce() , ZEND_STRS( #name ) - 1 TSRMLS_CC)
+
+ /*
+ * Class options
+ */
+
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER);
+
+ /*
+ * Indicate whether igbinary serializer is available
+ */
+#ifdef HAVE_MEMCACHED_IGBINARY
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 1);
+#else
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 0);
+#endif
+
+ /*
+ * Indicate whether json serializer is available
+ */
+#ifdef HAVE_JSON_API
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 1);
+#else
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0);
+#endif
+
+#ifdef HAVE_MEMCACHED_SESSION
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1);
+#else
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 0);
+#endif
+
+#ifdef HAVE_MEMCACHED_SASL
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 1);
+#else
+ REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 0);
+#endif
+
+ /*
+ * libmemcached behavior options
+ */
+
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_HASH, MEMCACHED_BEHAVIOR_HASH);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_DEFAULT, MEMCACHED_HASH_DEFAULT);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_MD5, MEMCACHED_HASH_MD5);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_CRC, MEMCACHED_HASH_CRC);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_64, MEMCACHED_HASH_FNV1_64);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_64, MEMCACHED_HASH_FNV1A_64);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1_32, MEMCACHED_HASH_FNV1_32);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_FNV1A_32, MEMCACHED_HASH_FNV1A_32);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_HSIEH, MEMCACHED_HASH_HSIEH);
+ REGISTER_MEMC_CLASS_CONST_LONG(HASH_MURMUR, MEMCACHED_HASH_MURMUR);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION);
+ REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA);
+ REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT);
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
+ REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET);
+#endif
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_BUFFER_WRITES, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_BINARY_PROTOCOL, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_NO_BLOCK, MEMCACHED_BEHAVIOR_NO_BLOCK);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_NODELAY, MEMCACHED_BEHAVIOR_TCP_NODELAY);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_SEND_SIZE, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SOCKET_RECV_SIZE, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_CONNECT_TIMEOUT, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_RETRY_TIMEOUT, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SEND_TIMEOUT, MEMCACHED_BEHAVIOR_SND_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_RECV_TIMEOUT, MEMCACHED_BEHAVIOR_RCV_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_POLL_TIMEOUT, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_CACHE_LOOKUPS, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_FAILURE_LIMIT, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_AUTO_EJECT_HOSTS, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_HASH_WITH_PREFIX_KEY, MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_NOREPLY, MEMCACHED_BEHAVIOR_NOREPLY);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_SORT_HOSTS, MEMCACHED_BEHAVIOR_SORT_HOSTS);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_VERIFY_KEY, MEMCACHED_BEHAVIOR_VERIFY_KEY);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_USE_UDP, MEMCACHED_BEHAVIOR_USE_UDP);
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ);
+#endif
+#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS);
+#endif
+
+ /*
+ * libmemcached result codes
+ */
+
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_STORED, MEMCACHED_STORED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_DELETED, MEMCACHED_DELETED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_STAT, MEMCACHED_STAT);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_ITEM, MEMCACHED_ITEM);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_NOT_SUPPORTED, MEMCACHED_NOT_SUPPORTED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_FETCH_NOTFINISHED, MEMCACHED_FETCH_NOTFINISHED);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MARKED_DEAD, MEMCACHED_SERVER_MARKED_DEAD);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_STAT_KEY, MEMCACHED_UNKNOWN_STAT_KEY);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE);
+#if HAVE_MEMCACHED_SASL
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE);
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE);
+#endif
+ /*
+ * Our result codes.
+ */
+
+ REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE);
+
+ /*
+ * Serializer types.
+ */
+ REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_PHP, SERIALIZER_PHP);
+ REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY);
+ REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON);
+ REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON_ARRAY, SERIALIZER_JSON_ARRAY);
+
+ /*
+ * Compression types
+ */
+ REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_FASTLZ, COMPRESSION_TYPE_FASTLZ);
+ REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZLIB, COMPRESSION_TYPE_ZLIB);
+
+ /*
+ * Flags.
+ */
+ REGISTER_MEMC_CLASS_CONST_LONG(GET_PRESERVE_ORDER, MEMC_GET_PRESERVE_ORDER);
+
+ #undef REGISTER_MEMC_CLASS_CONST_LONG
+
+ /*
+ * Return value from simple get errors
+ */
+ REGISTER_MEMC_CLASS_CONST_BOOL(GET_ERROR_RETURN_VALUE, 0);
+}
+/* }}} */
+
+#if HAVE_MEMCACHED_SASL
+PHP_RINIT_FUNCTION(memcached)
+{
+ if (MEMC_G(use_sasl)) {
+ if (sasl_client_init(NULL) != SASL_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library");
+ }
+ }
+ return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(memcached)
+{
+ if (MEMC_G(use_sasl)) {
+ sasl_done();
+ }
+
+ return SUCCESS;
+}
+#endif
+
+int php_memc_sess_list_entry(void)
+{
+ return le_memc_sess;
+}
+
+/* {{{ PHP_MINIT_FUNCTION */
+PHP_MINIT_FUNCTION(memcached)
+{
+ zend_class_entry ce;
+
+ memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ memcached_object_handlers.clone_obj = NULL;
+
+ le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number);
+ le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number);
+
+ INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods);
+ memcached_ce = zend_register_internal_class(&ce TSRMLS_CC);
+ memcached_ce->create_object = php_memc_new;
+
+ INIT_CLASS_ENTRY(ce, "MemcachedException", NULL);
+ memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC);
+ /* TODO
+ * possibly declare custom exception property here
+ */
+
+ php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU);
+
+#ifdef ZTS
+ ts_allocate_id(&php_memcached_globals_id, sizeof(zend_php_memcached_globals),
+ (ts_allocate_ctor) php_memc_init_globals, (ts_allocate_dtor) php_memc_destroy_globals);
+#else
+ php_memc_init_globals(&php_memcached_globals TSRMLS_CC);
+#endif
+
+#ifdef HAVE_MEMCACHED_SESSION
+ php_session_register_module(ps_memcached_ptr);
+#endif
+
+ REGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION */
+PHP_MSHUTDOWN_FUNCTION(memcached)
+{
+#ifdef ZTS
+ ts_free_id(php_memcached_globals_id);
+#else
+ php_memc_destroy_globals(&php_memcached_globals TSRMLS_CC);
+#endif
+
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION */
+PHP_MINFO_FUNCTION(memcached)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "memcached support", "enabled");
+ php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION);
+ php_info_print_table_row(2, "libmemcached version", memcached_lib_version());
+
+#ifdef HAVE_MEMCACHED_SESSION
+ php_info_print_table_row(2, "Session support", "yes");
+#else
+ php_info_print_table_row(2, "Session support ", "no");
+#endif
+
+#ifdef HAVE_MEMCACHED_IGBINARY
+ php_info_print_table_row(2, "igbinary support", "yes");
+#else
+ php_info_print_table_row(2, "igbinary support", "no");
+#endif
+
+#ifdef HAVE_JSON_API
+ php_info_print_table_row(2, "json support", "yes");
+#else
+ php_info_print_table_row(2, "json support", "no");
+#endif
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim: noet sw=4 ts=4 fdm=marker:
+ */
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/php_memcached.h
^
|
@@ -0,0 +1,118 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2009 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: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $ Id: $ */
+
+#ifndef PHP_MEMCACHED_H
+#define PHP_MEMCACHED_H
+
+#include "php_libmemcached_compat.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+extern zend_module_entry memcached_module_entry;
+#define phpext_memcached_ptr &memcached_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_MEMCACHED_API __declspec(dllexport)
+#else
+#define PHP_MEMCACHED_API
+#endif
+
+/****************************************
+ Structures and definitions
+****************************************/
+enum memcached_serializer {
+ SERIALIZER_PHP = 1,
+ SERIALIZER_IGBINARY = 2,
+ SERIALIZER_JSON = 3,
+ SERIALIZER_JSON_ARRAY = 4,
+};
+#ifdef HAVE_MEMCACHED_IGBINARY
+#define SERIALIZER_DEFAULT SERIALIZER_IGBINARY
+#define SERIALIZER_DEFAULT_NAME "igbinary"
+#else
+#define SERIALIZER_DEFAULT SERIALIZER_PHP
+#define SERIALIZER_DEFAULT_NAME "php"
+#endif /* HAVE_MEMCACHED_IGBINARY */
+
+#if LIBMEMCACHED_WITH_SASL_SUPPORT
+# if defined(HAVE_SASL_SASL_H)
+# include <sasl/sasl.h>
+# define HAVE_MEMCACHED_SASL 1
+# endif
+#endif
+
+ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
+#ifdef HAVE_MEMCACHED_SESSION
+ zend_bool sess_locking_enabled;
+ long sess_lock_wait;
+ char* sess_prefix;
+ zend_bool sess_locked;
+ char* sess_lock_key;
+ int sess_lock_key_len;
+#endif
+ char *serializer_name;
+ enum memcached_serializer serializer;
+
+ char *compression_type;
+ int compression_type_real;
+ int compression_threshold;
+
+ double compression_factor;
+#if HAVE_MEMCACHED_SASL
+ bool use_sasl;
+#endif
+ zend_bool sess_binary_enabled;
+ZEND_END_MODULE_GLOBALS(php_memcached)
+
+PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void);
+PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void);
+PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC);
+
+PHP_RINIT_FUNCTION(memcached);
+PHP_RSHUTDOWN_FUNCTION(memcached);
+PHP_MINIT_FUNCTION(memcached);
+PHP_MSHUTDOWN_FUNCTION(memcached);
+PHP_MINFO_FUNCTION(memcached);
+
+#define PHP_MEMCACHED_VERSION "2.1.0"
+
+#ifdef ZTS
+#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v)
+#else
+#define MEMC_G(v) (php_memcached_globals.v)
+#endif
+
+typedef struct {
+ memcached_st *memc_sess;
+ zend_bool is_persisent;
+} memcached_sess;
+
+int php_memc_sess_list_entry(void);
+
+#endif /* PHP_MEMCACHED_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 |
memcached-2.1.0.tgz/memcached-2.1.0/php_memcached_session.c
^
|
@@ -0,0 +1,305 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2009-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <php.h>
+#include <php_main.h>
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#include <php_ini.h>
+#include <SAPI.h>
+#include <ext/standard/info.h>
+#include <zend_extensions.h>
+#include <zend_exceptions.h>
+#include <ext/standard/php_smart_str.h>
+#include <ext/standard/php_var.h>
+
+#include "php_memcached.h"
+#include "php_memcached_session.h"
+
+extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached)
+
+#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000
+#define MEMC_SESS_LOCK_EXPIRATION 30
+
+ps_module ps_mod_memcached = {
+ PS_MOD(memcached)
+};
+
+static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
+{
+ char *lock_key = NULL;
+ int lock_key_len = 0;
+ unsigned long attempts;
+ long lock_maxwait;
+ long lock_wait = MEMC_G(sess_lock_wait);
+ time_t expiration;
+ memcached_return status;
+ /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */
+
+ lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0);
+ if (lock_maxwait <= 0) {
+ lock_maxwait = MEMC_SESS_LOCK_EXPIRATION;
+ }
+ if (lock_wait == 0) {
+ lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT;
+ }
+ expiration = time(NULL) + lock_maxwait + 1;
+ attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait);
+
+ lock_key_len = spprintf(&lock_key, 0, "lock.%s", key);
+ do {
+ status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
+ if (status == MEMCACHED_SUCCESS) {
+ MEMC_G(sess_locked) = 1;
+ MEMC_G(sess_lock_key) = lock_key;
+ MEMC_G(sess_lock_key_len) = lock_key_len;
+ return 0;
+ } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) {
+ break;
+ }
+
+ if (lock_wait > 0) {
+ usleep(lock_wait);
+ }
+ } while(--attempts > 0);
+
+ efree(lock_key);
+ return -1;
+}
+
+static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC)
+{
+ if (MEMC_G(sess_locked)) {
+ memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0);
+ MEMC_G(sess_locked) = 0;
+ efree(MEMC_G(sess_lock_key));
+ MEMC_G(sess_lock_key_len) = 0;
+ }
+}
+
+PS_OPEN_FUNC(memcached)
+{
+ memcached_sess *memc_sess = PS_GET_MOD_DATA();
+ memcached_return status;
+ char *p, *plist_key = NULL;
+ int plist_key_len;
+
+ if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) {
+ zend_rsrc_list_entry *le = NULL;
+ char *e;
+
+ p = (char *)save_path + sizeof("PERSISTENT=") - 1;
+ if (!*p) {
+error:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid persistent id for session storage");
+ return FAILURE;
+ }
+ if ((e = strchr(p, ' '))) {
+ plist_key_len = spprintf(&plist_key, 0, "memcached_sessions:id=%.*s", (int)(e - p), p);
+ } else {
+ goto error;
+ }
+ plist_key_len++;
+ if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) {
+ if (le->type == php_memc_sess_list_entry()) {
+ memc_sess = (memcached_sess *) le->ptr;
+ PS_SET_MOD_DATA(memc_sess);
+ return SUCCESS;
+ }
+ }
+ p = e + 1;
+ memc_sess = pecalloc(sizeof(*memc_sess), 1, 1);
+ memc_sess->is_persisent = 1;
+ } else {
+ p = (char *)save_path;
+ memc_sess = ecalloc(sizeof(*memc_sess), 1);
+ memc_sess->is_persisent = 0;
+ }
+
+ if (!strstr(p, "--SERVER")) {
+ memcached_server_st *servers = memcached_servers_parse(p);
+ if (servers) {
+ memc_sess->memc_sess = memcached_create(NULL);
+ if (memc_sess->memc_sess) {
+ status = memcached_server_push(memc_sess->memc_sess, servers);
+ memcached_server_list_free(servers);
+
+ if (memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) {
+ PS_SET_MOD_DATA(NULL);
+ if (plist_key) {
+ efree(plist_key);
+ }
+ memcached_free(memc_sess->memc_sess);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix");
+ return FAILURE;
+ }
+
+ if (status == MEMCACHED_SUCCESS) {
+ goto success;
+ }
+ } else {
+ memcached_server_list_free(servers);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure");
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path");
+ }
+ } else {
+ memc_sess->memc_sess = memcached(p, strlen(p));
+ if (!memc_sess->memc_sess) {
+ char error_buffer[1024];
+ if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage");
+ }
+ } else {
+success:
+ PS_SET_MOD_DATA(memc_sess);
+
+ if (plist_key) {
+ zend_rsrc_list_entry le;
+
+ le.type = php_memc_sess_list_entry();
+ le.ptr = memc_sess;
+
+ if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) {
+ efree(plist_key);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry");
+ }
+ efree(plist_key);
+ }
+
+ if (MEMC_G(sess_binary_enabled)) {
+ if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol");
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+ }
+ }
+
+ if (plist_key) {
+ efree(plist_key);
+ }
+ PS_SET_MOD_DATA(NULL);
+ return FAILURE;
+}
+
+PS_CLOSE_FUNC(memcached)
+{
+ memcached_sess *memc_sess = PS_GET_MOD_DATA();
+
+ if (MEMC_G(sess_locking_enabled)) {
+ php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC);
+ }
+ if (memc_sess->memc_sess) {
+ if (!memc_sess->is_persisent) {
+ memcached_free(memc_sess->memc_sess);
+ efree(memc_sess);
+ }
+ PS_SET_MOD_DATA(NULL);
+ }
+
+ return SUCCESS;
+}
+
+PS_READ_FUNC(memcached)
+{
+ char *payload = NULL;
+ size_t payload_len = 0;
+ int key_len = strlen(key);
+ uint32_t flags = 0;
+ memcached_return status;
+ memcached_sess *memc_sess = PS_GET_MOD_DATA();
+ size_t key_length;
+
+ key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock."
+ if (!key_length || key_length >= MEMCACHED_MAX_KEY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters");
+ PS(invalid_session_id) = 1;
+ return FAILURE;
+ }
+
+ if (MEMC_G(sess_locking_enabled)) {
+ if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) {
+ return FAILURE;
+ }
+ }
+
+ payload = memcached_get(memc_sess->memc_sess, key, key_len, &payload_len, &flags, &status);
+
+ if (status == MEMCACHED_SUCCESS) {
+ *val = estrndup(payload, payload_len);
+ *vallen = payload_len;
+ free(payload);
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+
+PS_WRITE_FUNC(memcached)
+{
+ int key_len = strlen(key);
+ time_t expiration = 0;
+ memcached_return status;
+ memcached_sess *memc_sess = PS_GET_MOD_DATA();
+ size_t key_length;
+
+ key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock."
+ if (!key_length || key_length >= MEMCACHED_MAX_KEY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters");
+ PS(invalid_session_id) = 1;
+ return FAILURE;
+ }
+
+ if (PS(gc_maxlifetime) > 0) {
+ expiration = PS(gc_maxlifetime);
+ }
+ status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0);
+
+ if (status == MEMCACHED_SUCCESS) {
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+
+PS_DESTROY_FUNC(memcached)
+{
+ memcached_sess *memc_sess = PS_GET_MOD_DATA();
+
+ memcached_delete(memc_sess->memc_sess, key, strlen(key), 0);
+ if (MEMC_G(sess_locking_enabled)) {
+ php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC);
+ }
+
+ return SUCCESS;
+}
+
+PS_GC_FUNC(memcached)
+{
+ return SUCCESS;
+}
+/* }}} */
|
[-]
[+]
|
Added |
memcached-2.1.0.tgz/memcached-2.1.0/php_memcached_session.h
^
|
@@ -0,0 +1,36 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2009-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef PHP_MEMCACHED_SESSION_H
+#define PHP_MEMCACHED_SESSION_H
+
+/* session handler struct */
+
+#include "ext/session/php_session.h"
+
+extern ps_module ps_mod_memcached;
+#define ps_memcached_ptr &ps_mod_memcached
+
+PS_FUNCS(memcached);
+
+PS_OPEN_FUNC(memcached);
+PS_CLOSE_FUNC(memcached);
+PS_READ_FUNC(memcached);
+PS_WRITE_FUNC(memcached);
+PS_DESTROY_FUNC(memcached);
+PS_GC_FUNC(memcached);
+
+#endif /* PHP_MEMCACHED_SESSION_H */
|
[-]
[+]
|
Changed |
memcached-2.1.0.tgz/package.xml
^
|
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.7.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">
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<package packagerversion="1.9.4" 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>memcached</name>
<channel>pecl.php.net</channel>
<summary>PHP extension for interfacing with memcached via libmemcached library</summary>
@@ -10,29 +10,42 @@
<email>andrei@php.net</email>
<active>yes</active>
</lead>
- <date>2009-01-29</date>
- <time>11:03:19</time>
+ <date>2012-08-07</date>
+ <time>05:02:46</time>
<version>
- <release>0.1.0</release>
- <api>0.1.0</api>
+ <release>2.1.0</release>
+ <api>2.1.0</api>
</version>
<stability>
- <release>beta</release>
- <api>beta</api>
+ <release>stable</release>
+ <api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
- <notes>Initial PECL release</notes>
+ <notes>
+- Drop support for libmemcached 0.x series, now 1.0.x is required
+- Add support for virtual bucket distribution
+- Fix compilation against PHP 5.2
+ </notes>
<contents>
<dir name="/">
- <file md5sum="7291f1b05a4608bc9223993fd2bea6c2" name="EXPERIMENTAL" role="doc" />
- <file md5sum="f81d550f7ec687531cc74ba65685e2dc" name="README" role="doc" />
- <file md5sum="7a7ca69843a849d18f95a4dfac069516" name="CREDITS" role="doc" />
- <file md5sum="56e7876babee694afcf5aa631bbe2a54" name="LICENSE" role="doc" />
- <file md5sum="c4e7dcc68d8d98d7eab285ff826a8a56" name="memcached-api.php" role="doc" />
- <file md5sum="54b47c575f8d82ca76f528d822243d46" name="config.m4" role="src" />
+ <file md5sum="6c6f0e1acb0d69171f0e7a4f3e42643a" name="README.markdown" role="doc" />
+ <file md5sum="f15b54956edc11e9bf1c995385b433b4" name="CREDITS" role="doc" />
+ <file md5sum="cb564efdf78cce8ea6e4b5a4f7c05d97" name="LICENSE" role="doc" />
+ <file md5sum="fc7ce7c78c402d449f661fc079af7748" name="ChangeLog" role="doc" />
+ <file md5sum="c5fda4446266a77bd5eb2cb95f9d4b8a" name="memcached-api.php" role="doc" />
+ <file md5sum="0cbeff40883a91586a1407ce8526ef7d" name="memcached.ini" role="doc" />
+ <file md5sum="543b3b1b8571c4b9c02eafee4a6f3fa3" name="fastlz/LICENSE" role="doc" />
+ <file md5sum="2f448392e75887d5e4b52637aa61289a" name="config.m4" role="src" />
<file md5sum="e91185048e5901055861ae041a7ad84a" name="config.w32" role="src" />
- <file md5sum="033a8a83491714bbd34949b1349b46aa" name="php_memcached.c" role="src" />
- <file md5sum="39a2edfd8cc457d566314da277d0fe9f" name="php_memcached.h" role="src" />
+ <file md5sum="3fd633c565eb9f8ecc42a39b2f2e2cb1" name="php_memcached.c" role="src" />
+ <file md5sum="5f66d9fea145955a504c5cded44f9bb6" name="php_memcached.h" role="src" />
+ <file md5sum="8047a7f071988600491aa58fd46bca24" name="php_memcached_session.c" role="src" />
+ <file md5sum="c92bc3e2db00fe51b070b3701a898b01" name="php_memcached_session.h" role="src" />
+ <file md5sum="5fec17d9c15eec1e6f60e67fcc10d7eb" name="php_libmemcached_compat.h" role="src" />
+ <file md5sum="85fb511eda2b916c758c23fe5ebaf2a7" name="g_fmt.c" role="src" />
+ <file md5sum="94fb8525d4419947cec4653a302be41a" name="g_fmt.h" role="src" />
+ <file md5sum="89384a08695fc238e9fbc41b0a14b5a7" name="fastlz/fastlz.c" role="src" />
+ <file md5sum="d49275e3dcc1d23d6ce0041648be8e14" name="fastlz/fastlz.h" role="src" />
</dir>
</contents>
<dependencies>
@@ -52,6 +65,273 @@
<changelog>
<release>
<stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>2.1.0</release>
+ <api>2.1.0</api>
+ </version>
+ <date>2012-08-06</date>
+ <notes>
+- Drop support for libmemcached 0.x series, now 1.0.x is required
+- Add support for virtual bucket distribution
+- Fix compilation against PHP 5.2
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>2.0.1</release>
+ <api>2.0.1</api>
+ </version>
+ <date>2012-03-03</date>
+ <notes>
+- Fix embedded version number to be not -dev
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>2.0.0</release>
+ <api>2.0.0</api>
+ </version>
+ <date>2012-03-02</date>
+ <notes>
+- Add touch() and touchByKey() methods
+- Add resetServerList() and quit() methods
+- Support binary protocol in sessions
+- Make it work with libmemcached up to 1.0.4
+- Test against PHP 5.4.0
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>2.0.0b2</release>
+ <api>2.0.0b2</api>
+ </version>
+ <date>2011-06-24</date>
+ <notes>
+- Add OPT_REMOVE_FAILED_SERVERS option.
+- Make it work with libmemcached up to 0.49.
+- Fix a case where invalid session ID could lock the script.
+- Improve session support:
+ * Add support for libmemcached config string
+ * Add persistence support via PERSISTENT=persistent_id prefix
+ of the save_path
+- Add 3rd parameter to the __construct() that allows specification
+ of libmemcached configuration string
+- Fix a possible crash in __construct() when using persistent
+ connections
+- Add work-around a bug in libmemcached < 0.50 that causes truncation
+ of last character of server key prefix
+- When using multiple servers implement transparent fail-over
+- Fix php_memc_cas_impl() implementation when server_key is not being used
+- Add support for incrementByKey() and decrementByKey()
+- Make increment/decrement initialize value when it is not available (when
+ using binary protocol)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>2.0.0b1</release>
+ <api>2.0.0b1</api>
+ </version>
+ <date>2011-03-12</date>
+ <notes>
+- Change the return value for non-existing keys to be NULL rather than
+ 'false', affects simple get only
+- Add fastlz library that provides better/faster payload compression
+- Add configure switch to enable/disable JSON serialization support
+- Add getAllKeys() method
+- Add deleteMulti() and deleteMultiByKey() methods
+- Add isPristine() and isPersistent() methods
+- Add setOptions() method to set multiple options at once
+- Add SERIALIZER_JSON_ARRAY type that decodes JSON payloads as arrays
+ instead of objects
+- Add support for Unix domain socket connections
+- Add memcached.compression_threshold INI setting
+- Add memcached.compression_factor INI setting
+- Add memcached.compression_type INI setting
+- Implement a few speed optimizations
+- Many bug fixes and memory leaks plugged
+- Add several more tests
+- Add constants for libmemcached 0.37+:
+ * Memcached::OPT_NUMBER_OF_REPLICAS
+ * Memcached::OPT_RANDOMIZE_REPLICA_READ
+- Add 'on_new' callback to constructor
+- Add SASL support
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.2</release>
+ <api>1.0.2</api>
+ </version>
+ <date>2010-05-03</date>
+ <notes>
+- Fix build for libmemcached-0.39 (memcached_server_list() issue)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.1</release>
+ <api>1.0.1</api>
+ </version>
+ <date>2010-03-11</date>
+ <notes>
+- Fix build for libmemcached-0.38.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.0</release>
+ <api>1.0.0</api>
+ </version>
+ <date>2009-07-04</date>
+ <notes>
+- First stable release.
+- Add getResultMessage() method.
+- Fix OPT_RECV_TIMEOUT definition.
+- Initialize Session lock wait to max execution time (if max execution
+ time is unlimited, default to 30 seconds).
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.2.0</release>
+ <api>0.2.0</api>
+ </version>
+ <date>2009-06-04</date>
+ <notes>
+- Refactor the way payload types are stored in memcached flags to optimize the structure
+ and allow for future expansion. WARNING! You have to flush the cache when upgrading from
+ an older version.
+- Add JSON serializer support, requires PHP 5.2.10+.
+- Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective
+ serializers are available.
+- Add 'flags' parameter to getMulti() and getMultiByKey().
+- Add GET_PRESERVE_ORDER class constant that can be used with abovementioned flags
+ parameter to make the order of the keys in the response match the request.
+- Fix an issue with retrieving 0-length payloads (FALSE boolean value).
+- Add several tests.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.1.5</release>
+ <api>0.1.5</api>
+ </version>
+ <date>2009-03-31</date>
+ <notes>
+- Implement getVersion().
+- Add support for preserving boolean value types.
+- Fix crash when child class does not call constructor.
+- Fix bug #16084 (Crash when addServers is called with an associative array).
+- ZTS compilation fixes.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.1.4</release>
+ <api>0.1.4</api>
+ </version>
+ <date>2009-02-13</date>
+ <notes>
+- Fix compilation against PHP 5.3.
+- Add support for 'igbinary' serializer (Oleg Grenrus)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.1.3</release>
+ <api>0.1.3</api>
+ </version>
+ <date>2009-02-06</date>
+ <notes>
+- Bludgeon bug #15896 (Memcached setMulti error) into submission.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.1.2</release>
+ <api>0.1.2</api>
+ </version>
+ <date>2009-02-06</date>
+ <notes>
+- Fix bug #15896 (Memcached setMulti error).
+- Check for empty key in getServerByKey().
+- Allow passing 'null' for callbacks.
+- get() with cas token fetching wasn't erroring out properly.
+- Rename certain parameters in the API to be more clear.
+- Allow only strings as the append/prepend value.
+- Remove expiration parameter from append/prepend.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <version>
+ <release>0.1.1</release>
+ <api>0.1.1</api>
+ </version>
+ <date>2009-02-02</date>
+ <notes>
+- Add OPT_LIBKETAMA_COMPATIBLE option.
+- Implement addServers() method.
+- Swap internal compressed and serialized flags to be compatible with other clients.
+ </notes>
+ </release>
+ <release>
+ <stability>
<release>beta</release>
<api>beta</api>
</stability>
@@ -60,7 +340,9 @@
<api>0.1.0</api>
</version>
<date>2009-01-29</date>
- <notes>- Initial PECL release</notes>
+ <notes>
+- Initial PECL release
+ </notes>
</release>
</changelog>
</package>
|
[-]
[+]
|
Deleted |
package.xml
^
|
@@ -1,188 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<package packagerversion="1.8.0" 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>memcached</name>
- <channel>pecl.php.net</channel>
- <summary>PHP extension for interfacing with memcached via libmemcached library</summary>
- <description>This extension uses libmemcached library to provide API for communicating with memcached servers.</description>
- <lead>
- <name>Andrei Zmievski</name>
- <user>andrei</user>
- <email>andrei@php.net</email>
- <active>yes</active>
- </lead>
- <date>2009-06-04</date>
- <time>16:25:44</time>
- <version>
- <release>0.2.0</release>
- <api>0.2.0</api>
- </version>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <license uri="http://www.php.net/license">PHP</license>
- <notes>
-- Refactor the way payload types are stored in memcached flags to optimize the structure
- and allow for future expansion. WARNING! You have to flush the cache when upgrading from
- an older version.
-- Add JSON serializer support, requires PHP 5.2.10+.
-- Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective
- serializers are available.
-- Add 'flags' parameter to getMulti() and getMultiByKey().
-- Add GET_PRESERVE_ORDER class constant that can be used with abovementioned flags
- parameter to make the order of the keys in the response match the request.
-- Fix an issue with retrieving 0-length payloads (FALSE boolean value).
-- Add several tests.
- </notes>
- <contents>
- <dir name="/">
- <file md5sum="7291f1b05a4608bc9223993fd2bea6c2" name="EXPERIMENTAL" role="doc" />
- <file md5sum="6c6f0e1acb0d69171f0e7a4f3e42643a" name="README.markdown" role="doc" />
- <file md5sum="f15b54956edc11e9bf1c995385b433b4" name="CREDITS" role="doc" />
- <file md5sum="56e7876babee694afcf5aa631bbe2a54" name="LICENSE" role="doc" />
- <file md5sum="641b6ba8dcfe3869679789692f577728" name="ChangeLog" role="doc" />
- <file md5sum="9ee7befc35df0a9bf702107a5a344152" name="memcached-api.php" role="doc" />
- <file md5sum="3ab0b68483e95a36422960e918ea0687" name="config.m4" role="src" />
- <file md5sum="e91185048e5901055861ae041a7ad84a" name="config.w32" role="src" />
- <file md5sum="5f4d074a7c41f04d8dc6565ccd31df06" name="php_memcached.c" role="src" />
- <file md5sum="243744be5a3e2b0845678d124a4742db" name="php_memcached.h" role="src" />
- </dir>
- </contents>
- <dependencies>
- <required>
- <php>
- <min>5.2.0</min>
- <max>6.0.0</max>
- <exclude>6.0.0</exclude>
- </php>
- <pearinstaller>
- <min>1.4.0b1</min>
- </pearinstaller>
- </required>
- </dependencies>
- <providesextension>memcached</providesextension>
- <extsrcrelease />
- <changelog>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.2.0</release>
- <api>0.2.0</api>
- </version>
- <date>2009-06-04</date>
- <notes>
-- Refactor the way payload types are stored in memcached flags to optimize the structure
- and allow for future expansion. WARNING! You have to flush the cache when upgrading from
- an older version.
-- Add JSON serializer support, requires PHP 5.2.10+.
-- Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective
- serializers are available.
-- Add 'flags' parameter to getMulti() and getMultiByKey().
-- Add GET_PRESERVE_ORDER class constant that can be used with abovementioned flags
- parameter to make the order of the keys in the response match the request.
-- Fix an issue with retrieving 0-length payloads (FALSE boolean value).
-- Add several tests.
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.5</release>
- <api>0.1.5</api>
- </version>
- <date>2009-03-31</date>
- <notes>
-- Implement getVersion().
-- Add support for preserving boolean value types.
-- Fix crash when child class does not call constructor.
-- Fix bug #16084 (Crash when addServers is called with an associative array).
-- ZTS compilation fixes.
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.4</release>
- <api>0.1.4</api>
- </version>
- <date>2009-02-13</date>
- <notes>
-- Fix compilation against PHP 5.3.
-- Add support for 'igbinary' serializer (Oleg Grenrus)
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.3</release>
- <api>0.1.3</api>
- </version>
- <date>2009-02-06</date>
- <notes>
-- Bludgeon bug #15896 (Memcached setMulti error) into submission.
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.2</release>
- <api>0.1.2</api>
- </version>
- <date>2009-02-06</date>
- <notes>
-- Fix bug #15896 (Memcached setMulti error).
-- Check for empty key in getServerByKey().
-- Allow passing 'null' for callbacks.
-- get() with cas token fetching wasn't erroring out properly.
-- Rename certain parameters in the API to be more clear.
-- Allow only strings as the append/prepend value.
-- Remove expiration parameter from append/prepend.
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.1</release>
- <api>0.1.1</api>
- </version>
- <date>2009-02-02</date>
- <notes>
-- Add OPT_LIBKETAMA_COMPATIBLE option.
-- Implement addServers() method.
-- Swap internal compressed and serialized flags to be compatible with other clients.
- </notes>
- </release>
- <release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.0</release>
- <api>0.1.0</api>
- </version>
- <date>2009-01-29</date>
- <notes>
-- Initial PECL release
- </notes>
- </release>
- </changelog>
-</package>
|