mirror of
https://github.com/php-win-ext/php-memcached.git
synced 2026-03-24 00:52:18 +01:00
Cleaning up driver for php7. WIP
This commit is contained in:
1165
php_memcached.c
1165
php_memcached.c
File diff suppressed because it is too large
Load Diff
@@ -129,46 +129,60 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
|
||||
|
||||
#ifdef HAVE_MEMCACHED_SESSION
|
||||
zend_bool sess_locking_enabled;
|
||||
long sess_lock_wait;
|
||||
long sess_lock_max_wait;
|
||||
long sess_lock_expire;
|
||||
char* sess_prefix;
|
||||
zend_bool sess_locked;
|
||||
char* sess_lock_key;
|
||||
int sess_lock_key_len;
|
||||
/* Session related variables */
|
||||
struct {
|
||||
zend_bool lock_enabled;
|
||||
zend_long lock_wait_max;
|
||||
zend_long lock_wait_min;
|
||||
zend_long lock_retries;
|
||||
zend_long lock_expiration;
|
||||
|
||||
int sess_number_of_replicas;
|
||||
zend_bool sess_randomize_replica_read;
|
||||
zend_bool sess_remove_failed_enabled;
|
||||
long sess_connect_timeout;
|
||||
zend_bool sess_consistent_hash_enabled;
|
||||
zend_bool sess_binary_enabled;
|
||||
zend_bool compression_enabled;
|
||||
zend_bool binary_protocol_enabled;
|
||||
zend_bool consistent_hash_enabled;
|
||||
|
||||
zend_long server_failure_limit;
|
||||
zend_long number_of_replicas;
|
||||
zend_bool randomize_replica_read_enabled;
|
||||
zend_bool remove_failed_servers_enabled;
|
||||
|
||||
zend_long connect_timeout;
|
||||
|
||||
char *prefix;
|
||||
zend_bool persistent_enabled;
|
||||
|
||||
char *sasl_username;
|
||||
char *sasl_password;
|
||||
} session_ini;
|
||||
|
||||
#endif
|
||||
|
||||
struct {
|
||||
char *serializer_name;
|
||||
char *compression_type;
|
||||
zend_long compression_threshold;
|
||||
double compression_factor;
|
||||
zend_long store_retry_count;
|
||||
|
||||
#if HAVE_MEMCACHED_SASL
|
||||
char *sess_sasl_username;
|
||||
char *sess_sasl_password;
|
||||
zend_bool sess_sasl_data;
|
||||
zend_bool sasl_enabled;
|
||||
#endif
|
||||
#endif
|
||||
char *serializer_name;
|
||||
enum memcached_serializer serializer;
|
||||
|
||||
char *compression_type;
|
||||
int compression_type_real;
|
||||
int compression_threshold;
|
||||
/* Converted values*/
|
||||
enum memcached_serializer serializer;
|
||||
zend_long compression_type_real;
|
||||
} memc_ini;
|
||||
|
||||
|
||||
|
||||
double compression_factor;
|
||||
#if HAVE_MEMCACHED_SASL
|
||||
zend_bool use_sasl;
|
||||
#endif
|
||||
#ifdef HAVE_MEMCACHED_PROTOCOL
|
||||
struct {
|
||||
php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX];
|
||||
} server;
|
||||
#endif
|
||||
long store_retry_count;
|
||||
|
||||
ZEND_END_MODULE_GLOBALS(php_memcached)
|
||||
|
||||
PHP_RINIT_FUNCTION(memcached);
|
||||
@@ -177,19 +191,6 @@ PHP_MINIT_FUNCTION(memcached);
|
||||
PHP_MSHUTDOWN_FUNCTION(memcached);
|
||||
PHP_MINFO_FUNCTION(memcached);
|
||||
|
||||
#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_persistent;
|
||||
} memcached_sess;
|
||||
|
||||
int php_memc_sess_list_entry(void);
|
||||
|
||||
char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC);
|
||||
|
||||
memcached_return php_memcached_exist (memcached_st *memc, zend_string *key);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "php_memcached_private.h"
|
||||
#include "php_memcached_session.h"
|
||||
|
||||
#include "Zend/zend_smart_str_public.h"
|
||||
|
||||
extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached)
|
||||
|
||||
#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000
|
||||
@@ -27,278 +29,350 @@ ps_module ps_mod_memcached = {
|
||||
PS_MOD_UPDATE_TIMESTAMP(memcached)
|
||||
};
|
||||
|
||||
static int php_memc_sess_lock(memcached_st *memc, const char *key)
|
||||
typedef struct {
|
||||
zend_bool is_persistent;
|
||||
zend_bool has_sasl_data;
|
||||
zend_bool is_locked;
|
||||
zend_string *lock_key;
|
||||
} php_memcached_user_data;
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session_ini.v)
|
||||
#else
|
||||
#define MEMC_SESS_INI(v) (php_memcached_globals.session_ini.v)
|
||||
#endif
|
||||
|
||||
#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL)
|
||||
|
||||
static
|
||||
int le_memc_sess;
|
||||
|
||||
static
|
||||
int s_memc_sess_list_entry(void)
|
||||
{
|
||||
char *lock_key = NULL;
|
||||
int lock_key_len = 0;
|
||||
unsigned long attempts;
|
||||
long write_retry_attempts = 0;
|
||||
long lock_maxwait = MEMC_G(sess_lock_max_wait);
|
||||
long lock_wait = MEMC_G(sess_lock_wait);
|
||||
long lock_expire = MEMC_G(sess_lock_expire);
|
||||
time_t expiration;
|
||||
memcached_return status;
|
||||
/* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */
|
||||
if (lock_maxwait <= 0) {
|
||||
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;
|
||||
}
|
||||
if (lock_expire <= 0) {
|
||||
lock_expire = lock_maxwait;
|
||||
}
|
||||
expiration = lock_expire + 1;
|
||||
attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait);
|
||||
|
||||
/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (write_retry_attempts > 0) {
|
||||
write_retry_attempts--;
|
||||
continue;
|
||||
}
|
||||
php_error_docref(NULL, E_WARNING, "Write of lock failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_wait > 0) {
|
||||
usleep(lock_wait);
|
||||
}
|
||||
} while(--attempts > 0);
|
||||
|
||||
efree(lock_key);
|
||||
return -1;
|
||||
return le_memc_sess;
|
||||
}
|
||||
|
||||
static void php_memc_sess_unlock(memcached_st *memc)
|
||||
static
|
||||
void s_destroy_mod_data(memcached_st *memc)
|
||||
{
|
||||
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;
|
||||
php_memcached_user_data *user_data = memcached_get_user_data(memc);
|
||||
|
||||
if (user_data->has_sasl_data) {
|
||||
memcached_destroy_sasl_auth_data(memc);
|
||||
}
|
||||
|
||||
memcached_free(memc);
|
||||
pefree(memc, user_data->is_persistent);
|
||||
pefree(user_data, user_data->is_persistent);
|
||||
}
|
||||
|
||||
ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor)
|
||||
{
|
||||
if (res->ptr) {
|
||||
s_destroy_mod_data((memcached_st *) res->ptr);
|
||||
res->ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int php_memc_session_minit(int module_number)
|
||||
{
|
||||
le_memc_sess =
|
||||
zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number);
|
||||
|
||||
php_session_register_module(ps_memcached_ptr);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
time_t s_lock_expiration()
|
||||
{
|
||||
zend_long max_execution_time;
|
||||
|
||||
if (MEMC_SESS_INI(lock_expiration) > 0) {
|
||||
return time(NULL) + MEMC_SESS_INI(lock_expiration);
|
||||
}
|
||||
else {
|
||||
zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0);
|
||||
if (max_execution_time > 0) {
|
||||
return time(NULL) + max_execution_time;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
zend_bool s_lock_session(memcached_st *memc, zend_string *sid)
|
||||
{
|
||||
char *lock_key;
|
||||
size_t lock_key_len;
|
||||
time_t expiration;
|
||||
zend_long wait_time, retries;
|
||||
php_memcached_user_data *user_data = memcached_get_user_data(memc);
|
||||
|
||||
lock_key_len = spprintf(&lock_key, 0, "lock.%s", sid->val);
|
||||
expiration = s_lock_expiration();
|
||||
|
||||
wait_time = MEMC_SESS_INI(lock_wait_min);
|
||||
retries = MEMC_SESS_INI(lock_retries);
|
||||
|
||||
do {
|
||||
memcached_return rc =
|
||||
memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0);
|
||||
|
||||
switch (rc) {
|
||||
|
||||
case MEMCACHED_SUCCESS:
|
||||
user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent);
|
||||
user_data->is_locked = 1;
|
||||
break;
|
||||
|
||||
case MEMCACHED_NOTSTORED:
|
||||
case MEMCACHED_DATA_EXISTS:
|
||||
usleep(wait_time * 1000);
|
||||
wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error_docref(NULL, E_WARNING, "Failed to write session lock: %s", memcached_strerror (memc, rc));
|
||||
break;
|
||||
}
|
||||
} while (!user_data->is_locked && retries-- > 0);
|
||||
|
||||
efree(lock_key);
|
||||
return user_data->is_locked;
|
||||
}
|
||||
|
||||
static
|
||||
void s_unlock_session(memcached_st *memc)
|
||||
{
|
||||
php_memcached_user_data *user_data = memcached_get_user_data(memc);
|
||||
|
||||
if (user_data->is_locked) {
|
||||
memcached_delete(memc, user_data->lock_key->val, user_data->lock_key->len, 0);
|
||||
user_data->is_locked = 0;
|
||||
zend_string_release (user_data->lock_key);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
zend_bool s_configure_from_ini_values(memcached_st *memc)
|
||||
{
|
||||
memcached_return rc;
|
||||
|
||||
#define check_set_behavior(behavior, value) \
|
||||
if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \
|
||||
php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(binary_protocol_enabled)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(consistent_hash_enabled)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_KETAMA, 1);
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(server_failure_limit)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, MEMC_SESS_INI(server_failure_limit));
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(number_of_replicas)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, MEMC_SESS_INI(number_of_replicas));
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(randomize_replica_read_enabled)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, 1);
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(remove_failed_servers_enabled)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, 1);
|
||||
}
|
||||
|
||||
if (MEMC_SESS_INI(connect_timeout)) {
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_SESS_INI(connect_timeout));
|
||||
}
|
||||
|
||||
if (MEMC_SESS_STR_INI(prefix)) {
|
||||
memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, MEMC_SESS_STR_INI(prefix));
|
||||
}
|
||||
|
||||
#ifdef HAVE_MEMCACHED_SASL
|
||||
if (MEMC_SESS_STR_INI(sasl_username) && MEMC_SESS_STR_INI(sasl_password)) {
|
||||
php_memcached_user_data *user_data;
|
||||
|
||||
check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
|
||||
|
||||
if (memcached_set_sasl_auth_data(memc, MEMC_SESS_STR_INI(sasl_username), MEMC_SESS_STR_INI(sasl_password)) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials");
|
||||
return 0;
|
||||
}
|
||||
user_data = memcached_get_user_data(memc);
|
||||
user_data->has_sasl_data = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef safe_set_behavior
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void *s_pemalloc_fn(const memcached_st *memc, size_t size, void *context)
|
||||
{
|
||||
zend_bool *is_persistent = memcached_get_user_data(memc);
|
||||
|
||||
return
|
||||
pemalloc(size, *is_persistent);
|
||||
}
|
||||
|
||||
static
|
||||
void s_pefree_fn(const memcached_st *memc, void *mem, void *context)
|
||||
{
|
||||
zend_bool *is_persistent = memcached_get_user_data(memc);
|
||||
|
||||
return
|
||||
pefree(mem, *is_persistent);
|
||||
}
|
||||
|
||||
static
|
||||
void *s_perealloc_fn(const memcached_st *memc, void *mem, const size_t size, void *context)
|
||||
{
|
||||
zend_bool *is_persistent = memcached_get_user_data(memc);
|
||||
|
||||
return
|
||||
perealloc(mem, size, *is_persistent);
|
||||
}
|
||||
|
||||
static
|
||||
void *s_pecalloc_fn(const memcached_st *memc, size_t nelem, const size_t elsize, void *context)
|
||||
{
|
||||
zend_bool *is_persistent = memcached_get_user_data(memc);
|
||||
|
||||
return
|
||||
pecalloc(nelem, elsize, *is_persistent);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool is_persistent)
|
||||
{
|
||||
void *buffer;
|
||||
php_memcached_user_data *user_data;
|
||||
memcached_st *memc;
|
||||
|
||||
buffer = pecalloc(1, sizeof(memcached_st), is_persistent);
|
||||
memc = memcached_create (buffer);
|
||||
|
||||
if (!memc) {
|
||||
php_error_docref(NULL, E_ERROR, "failed to allocate memcached structure");
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
memcached_set_memory_allocators(memc, s_pemalloc_fn, s_pefree_fn, s_perealloc_fn, s_pecalloc_fn, NULL);
|
||||
|
||||
user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent);
|
||||
user_data->is_persistent = is_persistent;
|
||||
user_data->has_sasl_data = 0;
|
||||
user_data->lock_key = NULL;
|
||||
user_data->is_locked = 0;
|
||||
|
||||
memcached_set_user_data(memc, user_data);
|
||||
memcached_server_push (memc, servers);
|
||||
return memc;
|
||||
}
|
||||
|
||||
PS_OPEN_FUNC(memcached)
|
||||
{
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
memcached_return status;
|
||||
char *p, *plist_key = NULL;
|
||||
int plist_key_len = 0;
|
||||
memcached_st *memc = NULL;
|
||||
char *plist_key = NULL;
|
||||
size_t plist_key_len = 0;
|
||||
memcached_server_list_st servers;
|
||||
|
||||
if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) {
|
||||
zend_resource *le = NULL;
|
||||
zval *le_z = NULL;
|
||||
char *e;
|
||||
// First parse servers
|
||||
servers = memcached_servers_parse(save_path);
|
||||
|
||||
p = (char *)save_path + sizeof("PERSISTENT=") - 1;
|
||||
if (!*p) {
|
||||
error:
|
||||
php_error_docref(NULL, 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 ((le_z = zend_hash_str_find(&EG(persistent_list), plist_key, plist_key_len)) != NULL) {
|
||||
le = Z_RES_P(le_z);
|
||||
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_persistent = 1;
|
||||
} else {
|
||||
p = (char *)save_path;
|
||||
memc_sess = ecalloc(sizeof(*memc_sess), 1);
|
||||
memc_sess->is_persistent = 0;
|
||||
if (!servers) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to parse session.save_path");
|
||||
PS_SET_MOD_DATA(NULL);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (MEMC_G(sess_consistent_hash_enabled)) {
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, (uint64_t) 1) == MEMCACHED_FAILURE) {
|
||||
PS_SET_MOD_DATA(NULL);
|
||||
if (plist_key) {
|
||||
efree(plist_key);
|
||||
}
|
||||
memcached_free(memc_sess->memc_sess);
|
||||
php_error_docref(NULL, E_WARNING, "failed to enable memcached consistent hashing");
|
||||
return FAILURE;
|
||||
}
|
||||
if (MEMC_SESS_INI(persistent_enabled)) {
|
||||
zend_resource *le_p;
|
||||
|
||||
plist_key_len = spprintf(&plist_key, 0, "memc-session:%s", save_path);
|
||||
|
||||
if ((le_p = zend_hash_str_find_ptr(&EG(persistent_list), plist_key, plist_key_len)) != NULL) {
|
||||
if (le_p->type == s_memc_sess_list_entry()) {
|
||||
memc = (memcached_st *) le_p->ptr;
|
||||
|
||||
if (!s_configure_from_ini_values(memc)) {
|
||||
// Remove existing plist entry
|
||||
zend_hash_str_del(&EG(persistent_list), plist_key, plist_key_len);
|
||||
memc = NULL;
|
||||
}
|
||||
|
||||
status = memcached_server_push(memc_sess->memc_sess, servers);
|
||||
memcached_server_list_free(servers);
|
||||
|
||||
if (MEMC_G(sess_prefix) && MEMC_G(sess_prefix)[0] != 0 && 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, 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, E_WARNING, "could not allocate libmemcached structure");
|
||||
}
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "failed to parse session.save_path");
|
||||
}
|
||||
} else {
|
||||
memc_sess->memc_sess = php_memc_create_str(p, strlen(p));
|
||||
if (!memc_sess->memc_sess) {
|
||||
#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION
|
||||
char error_buffer[1024];
|
||||
if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) {
|
||||
php_error_docref(NULL, E_WARNING, "session.save_path configuration error %s", error_buffer);
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage");
|
||||
}
|
||||
#else
|
||||
php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage");
|
||||
#endif
|
||||
|
||||
} else {
|
||||
success:
|
||||
PS_SET_MOD_DATA(memc_sess);
|
||||
|
||||
if (plist_key) {
|
||||
zend_resource le;
|
||||
zend_string *tmp_key;
|
||||
|
||||
le.type = php_memc_sess_list_entry();
|
||||
le.ptr = memc_sess;
|
||||
|
||||
tmp_key = zend_string_init(plist_key, plist_key_len, 0);
|
||||
if (zend_hash_update_mem(&EG(persistent_list), tmp_key, (void *)&le, sizeof(le)) == NULL) {
|
||||
zend_string_release(tmp_key);
|
||||
else {
|
||||
efree(plist_key);
|
||||
php_error_docref(NULL, E_ERROR, "could not register persistent entry");
|
||||
}
|
||||
zend_string_release(tmp_key);
|
||||
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, E_WARNING, "failed to set memcached session binary protocol");
|
||||
return FAILURE;
|
||||
PS_SET_MOD_DATA(memc);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MEMCACHED_SASL
|
||||
if (MEMC_G(use_sasl)) {
|
||||
/*
|
||||
* Enable SASL support if username and password are set
|
||||
*
|
||||
*/
|
||||
if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) {
|
||||
/* Force binary protocol */
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol");
|
||||
return FAILURE;
|
||||
}
|
||||
if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials");
|
||||
return FAILURE;
|
||||
}
|
||||
MEMC_G(sess_sasl_data) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
if (MEMC_G(sess_number_of_replicas) > 0) {
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached session number of replicas");
|
||||
return FAILURE;
|
||||
}
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached session randomize replica read");
|
||||
}
|
||||
}
|
||||
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set memcached connection timeout");
|
||||
return FAILURE;
|
||||
}
|
||||
#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS
|
||||
/* Allow libmemcached remove failed servers */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL, E_WARNING, "failed to set: remove failed servers");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
memc = s_init_mod_data(servers, MEMC_SESS_INI(persistent_enabled));
|
||||
memcached_server_list_free(servers);
|
||||
|
||||
if (plist_key) {
|
||||
zend_resource le;
|
||||
|
||||
le.type = s_memc_sess_list_entry();
|
||||
le.ptr = memc;
|
||||
|
||||
GC_REFCOUNT(&le) = 1;
|
||||
|
||||
/* plist_key is not a persistent allocated key, thus we use str_update here */
|
||||
if (zend_hash_str_update_mem(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(le)) == NULL) {
|
||||
php_error_docref(NULL, E_ERROR, "Could not register persistent entry for the memcached session");
|
||||
/* not reached */
|
||||
}
|
||||
efree(plist_key);
|
||||
}
|
||||
PS_SET_MOD_DATA(NULL);
|
||||
return FAILURE;
|
||||
PS_SET_MOD_DATA(memc);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PS_CLOSE_FUNC(memcached)
|
||||
{
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
php_memcached_user_data *user_data;
|
||||
|
||||
if (!memc_sess) {
|
||||
if (!memc) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (MEMC_G(sess_locking_enabled)) {
|
||||
php_memc_sess_unlock(memc_sess->memc_sess);
|
||||
}
|
||||
if (memc_sess->memc_sess) {
|
||||
if (!memc_sess->is_persistent) {
|
||||
#ifdef HAVE_MEMCACHED_SASL
|
||||
if (MEMC_G(sess_sasl_data)) {
|
||||
memcached_destroy_sasl_auth_data(memc_sess->memc_sess);
|
||||
}
|
||||
#endif
|
||||
memcached_free(memc_sess->memc_sess);
|
||||
efree(memc_sess);
|
||||
}
|
||||
PS_SET_MOD_DATA(NULL);
|
||||
user_data = memcached_get_user_data(memc);
|
||||
|
||||
if (user_data->is_locked) {
|
||||
s_unlock_session(memc);
|
||||
}
|
||||
|
||||
if (!user_data->is_persistent) {
|
||||
s_destroy_mod_data(memc);
|
||||
}
|
||||
|
||||
PS_SET_MOD_DATA(NULL);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -306,35 +380,27 @@ PS_READ_FUNC(memcached)
|
||||
{
|
||||
char *payload = NULL;
|
||||
size_t payload_len = 0;
|
||||
int key_len = key->len;
|
||||
uint32_t flags = 0;
|
||||
memcached_return status;
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
size_t key_length;
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
|
||||
if (!memc_sess) {
|
||||
if (!memc) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock."
|
||||
if (!key_length || key_length >= MEMCACHED_MAX_KEY) {
|
||||
php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (MEMC_G(sess_locking_enabled)) {
|
||||
if (php_memc_sess_lock(memc_sess->memc_sess, key->val) < 0) {
|
||||
if (MEMC_SESS_INI(lock_enabled)) {
|
||||
if (!s_lock_session(memc, key)) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to clear session lock record");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
payload = memcached_get(memc_sess->memc_sess, key->val, key_len, &payload_len, &flags, &status);
|
||||
payload = memcached_get(memc, key->val, key->len, &payload_len, &flags, &status);
|
||||
|
||||
if (status == MEMCACHED_SUCCESS) {
|
||||
*val = zend_string_init(payload, payload_len, 1);
|
||||
free(payload);
|
||||
*val = zend_string_init(payload, payload_len, 0);
|
||||
efree(payload);
|
||||
return SUCCESS;
|
||||
} else if (status == MEMCACHED_NOTFOUND) {
|
||||
*val = ZSTR_EMPTY_ALLOC();
|
||||
@@ -346,59 +412,53 @@ PS_READ_FUNC(memcached)
|
||||
|
||||
PS_WRITE_FUNC(memcached)
|
||||
{
|
||||
int key_len = key->len;
|
||||
time_t expiration = 0;
|
||||
long write_try_attempts = 1;
|
||||
memcached_return status;
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
zend_long retries = 1;
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
size_t key_length;
|
||||
time_t expiration;
|
||||
|
||||
if (!memc_sess) {
|
||||
if (!memc) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock."
|
||||
if (!key_length || key_length >= MEMCACHED_MAX_KEY) {
|
||||
php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (maxlifetime > 0) {
|
||||
expiration = maxlifetime;
|
||||
}
|
||||
|
||||
/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
write_try_attempts = 1 + MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
|
||||
if (MEMC_SESS_INI(remove_failed_servers_enabled)) {
|
||||
zend_long replicas, failure_limit;
|
||||
|
||||
replicas = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
|
||||
failure_limit = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT);
|
||||
|
||||
retries = 1 + replicas * (failure_limit + 1);
|
||||
}
|
||||
|
||||
expiration = time(NULL) + maxlifetime;
|
||||
|
||||
do {
|
||||
status = memcached_set(memc_sess->memc_sess, key->val, key_len, val->val, val->len, expiration, 0);
|
||||
if (status == MEMCACHED_SUCCESS) {
|
||||
if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
write_try_attempts--;
|
||||
}
|
||||
} while (write_try_attempts > 0);
|
||||
} while (--retries > 0);
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
PS_DESTROY_FUNC(memcached)
|
||||
{
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
php_memcached_user_data *user_data;
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
|
||||
if (!memc_sess) {
|
||||
if (!memc) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
memcached_delete(memc_sess->memc_sess, key->val, key->len, 0);
|
||||
if (MEMC_G(sess_locking_enabled)) {
|
||||
php_memc_sess_unlock(memc_sess->memc_sess);
|
||||
}
|
||||
memcached_delete(memc, key->val, key->len, 0);
|
||||
user_data = memcached_get_user_data(memc);
|
||||
|
||||
if (user_data->is_locked) {
|
||||
s_unlock_session(memc);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -410,34 +470,31 @@ PS_GC_FUNC(memcached)
|
||||
PS_CREATE_SID_FUNC(memcached)
|
||||
{
|
||||
zend_string *sid;
|
||||
int retries = 3;
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
time_t expiration = PS(gc_maxlifetime);
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
|
||||
if (!memc_sess) {
|
||||
return NULL;
|
||||
if (!memc) {
|
||||
sid = php_session_create_id(NULL);
|
||||
}
|
||||
else {
|
||||
int retries = 3;
|
||||
while (retries-- > 0) {
|
||||
sid = php_session_create_id((void **) &memc);
|
||||
|
||||
while (retries-- > 0) {
|
||||
sid = php_session_create_id((void**)&memc_sess);
|
||||
|
||||
if (sid) {
|
||||
if (memcached_add(memc_sess->memc_sess, sid->val, sid->len, "0", 0, expiration, 0) == MEMCACHED_SUCCESS) {
|
||||
return sid;
|
||||
}
|
||||
else {
|
||||
zend_string_release(sid);
|
||||
if (memcached_add (memc, sid->val, sid->len, NULL, 0, s_lock_expiration(), 0) == MEMCACHED_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
zend_string_release(sid);
|
||||
sid = NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return sid;
|
||||
}
|
||||
|
||||
PS_VALIDATE_SID_FUNC(memcached)
|
||||
{
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
|
||||
if (php_memcached_exist(memc_sess->memc_sess, key) == MEMCACHED_SUCCESS) {
|
||||
if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
@@ -446,13 +503,10 @@ PS_VALIDATE_SID_FUNC(memcached)
|
||||
|
||||
PS_UPDATE_TIMESTAMP_FUNC(memcached)
|
||||
{
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
time_t expiration = 0;
|
||||
memcached_st *memc = PS_GET_MOD_DATA();
|
||||
time_t expiration = time(NULL) + maxlifetime;
|
||||
|
||||
if (maxlifetime > 0) {
|
||||
expiration = maxlifetime;
|
||||
}
|
||||
if (memcached_touch(memc_sess->memc_sess, key->val, key->len, expiration) == MEMCACHED_FAILURE) {
|
||||
if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
|
||||
@@ -36,4 +36,7 @@ PS_CREATE_SID_FUNC(memcached);
|
||||
PS_VALIDATE_SID_FUNC(memcached);
|
||||
PS_UPDATE_TIMESTAMP_FUNC(memcached);
|
||||
|
||||
/* Called from php_memcached.c */
|
||||
int php_memc_session_minit(int module_number);
|
||||
|
||||
#endif /* PHP_MEMCACHED_SESSION_H */
|
||||
|
||||
@@ -13,6 +13,10 @@ $first_key = uniqid ('cache_test_');
|
||||
$second_key = uniqid ('cache_test_');
|
||||
$third_key = uniqid ('cache_test_');
|
||||
|
||||
$m->delete($first_key);
|
||||
$m->delete($second_key);
|
||||
$m->delete($third_key);
|
||||
|
||||
var_dump (
|
||||
$m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) {
|
||||
$value = "hello";
|
||||
|
||||
@@ -8,47 +8,12 @@ include dirname (__FILE__) . '/config.inc';
|
||||
$m = memc_get_instance ();
|
||||
|
||||
$m->delete('cas_test');
|
||||
$cas_token = null;
|
||||
$cas_token = 0;
|
||||
|
||||
$m->set('cas_test', 10);
|
||||
$v = $m->get('cas_test', null, $cas_token);
|
||||
|
||||
if (is_null($cas_token)) {
|
||||
echo "Null cas token for key: cas_test value: 10\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$v = $m->cas($cas_token, 'cas_test', 11);
|
||||
if (!$v) {
|
||||
echo "Error setting key: cas_test value: 11 with CAS: $cas_token\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$v = $m->get('cas_test');
|
||||
|
||||
if ($v !== 11) {
|
||||
echo "Wanted cas_test to be 11, value is: ";
|
||||
var_dump($v);
|
||||
}
|
||||
|
||||
$v = $m->get('cas_test', null, 2);
|
||||
if ($v != 11) {
|
||||
echo "Failed to get the value with \$cas_token passed by value (2)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$v = $m->get('cas_test', null, null);
|
||||
if ($v != 11) {
|
||||
echo "Failed to get the value with \$cas_token passed by value (null)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$v = $m->get('cas_test', null, $data = array(2, 4));
|
||||
if ($v != 11 || $data !== array(2, 4)) {
|
||||
echo "Failed to get the value with \$cas_token passed by value (\$data = array(2, 4))\n";
|
||||
return;
|
||||
}
|
||||
$m->set('cas_test', 'hello');
|
||||
$cas_token = $m->get('cas_test', null, Memcached::GET_EXTENDED)['cas'];
|
||||
|
||||
$v = $m->cas($cas_token, 'cas_test', 0);
|
||||
echo "OK\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
|
||||
@@ -16,25 +16,22 @@ foreach ($data as $key => $v) {
|
||||
$m->delete($key);
|
||||
}
|
||||
|
||||
$cas_tokens = array();
|
||||
$m->setMulti($data, 10);
|
||||
$actual = $m->getMulti(array_keys($data), $cas_tokens);
|
||||
$actual = $m->getMulti(array_keys($data), Memcached::GET_EXTENDED);
|
||||
|
||||
foreach ($data as $key => $v) {
|
||||
if (is_null($cas_tokens[$key])) {
|
||||
foreach ($actual as $key => $v) {
|
||||
if (is_null($v['cas'])) {
|
||||
echo "missing cas token(s)\n";
|
||||
echo "data: ";
|
||||
var_dump($data);
|
||||
echo "actual data: ";
|
||||
var_dump($actual);
|
||||
echo "cas tokens: ";
|
||||
var_dump($cas_tokens);
|
||||
return;
|
||||
}
|
||||
|
||||
$v = $m->cas($cas_tokens[$key], $key, 11);
|
||||
$v = $m->cas($v['cas'], $key, 11);
|
||||
if (!$v) {
|
||||
echo "Error setting key: $key value: 11 with CAS: ", $cas_tokens[$key], "\n";
|
||||
echo "Error setting key: $key value: 11 with CAS: ", $v['cas'], "\n";
|
||||
return;
|
||||
}
|
||||
$v = $m->get($key);
|
||||
@@ -54,24 +51,6 @@ if (array_keys($actual) !== array_keys($data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$actual = $m->getMulti(array_keys($data), 2);
|
||||
if (array_keys($actual) !== array_keys($data)) {
|
||||
echo "Failed to getMulti \$cas_token passed by value (2)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$actual = $m->getMulti(array_keys($data), null);
|
||||
if (array_keys($actual) !== array_keys($data)) {
|
||||
echo "Failed to getMulti \$cas_token passed by value (null)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$actual = $m->getMulti(array_keys($data), $cas_tokens = array(2, 4));
|
||||
if (array_keys($actual) !== array_keys($data) || $cas_tokens !== array(2, 4)) {
|
||||
echo "Failed to getMulti \$cas_token passed by value (\$cas_tokens = array(2, 4))\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "OK\n";
|
||||
|
||||
?>
|
||||
|
||||
@@ -21,10 +21,9 @@ foreach ($data as $k => $v) {
|
||||
$m->set($k, $v, 3600);
|
||||
}
|
||||
|
||||
$null = null;
|
||||
$keys = array_keys($data);
|
||||
$keys[] = 'zoo';
|
||||
$got = $m->getMulti($keys, $null, Memcached::GET_PRESERVE_ORDER);
|
||||
$got = $m->getMulti($keys, Memcached::GET_PRESERVE_ORDER);
|
||||
|
||||
foreach ($got as $k => $v) {
|
||||
echo "$k $v\n";
|
||||
|
||||
@@ -11,8 +11,7 @@ $memcached->addServer('localhost', 5555); // Server should not exist
|
||||
$result = $memcached->get('foo_not_exists');
|
||||
var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE);
|
||||
|
||||
$cas = 7;
|
||||
$result = $memcached->get('foo_not_exists', null, $cas);
|
||||
$result = $memcached->get('foo_not_exists');
|
||||
var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE);
|
||||
|
||||
echo "OK\n";
|
||||
|
||||
@@ -23,6 +23,7 @@ $m->delete('bar_foo');
|
||||
echo $m->getResultCode(), "\n";
|
||||
echo $m->getResultMessage(), "\n";
|
||||
|
||||
$m->set ('asdf_a', 'aa');
|
||||
$m->getMulti(array('asdf_a', 'jkhjkhjkb', 'nbahsdgc'));
|
||||
echo $m->getResultMessage(), "\n";
|
||||
$code = $m->getResultCode();
|
||||
|
||||
@@ -9,8 +9,9 @@ $m = memc_get_instance ();
|
||||
|
||||
$key = 'foobarbazDEADC0DE';
|
||||
$value = str_repeat("foo bar", 1024 * 1024);
|
||||
$m->set($key, $value, 360);
|
||||
var_dump($m->set($key, $value, 360));
|
||||
var_dump($m->get($key) === $value);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
@@ -16,6 +16,10 @@ function check_flags ($flags, $expected_flags)
|
||||
echo "Flags OK" . PHP_EOL;
|
||||
}
|
||||
|
||||
function get_flags($m, $key) {
|
||||
return $m->get($key, null, Memcached::GET_EXTENDED)['flags'];
|
||||
}
|
||||
|
||||
define ('FLAG_1', 1);
|
||||
define ('FLAG_2', 2);
|
||||
define ('FLAG_4', 4);
|
||||
@@ -30,26 +34,26 @@ $key = uniqid ('udf_test_');
|
||||
|
||||
// Set with flags off
|
||||
$m->set ($key, '1', 10);
|
||||
$m->get($key);
|
||||
var_dump($m->getLastUserFlags());
|
||||
$v = $m->get($key, null, Memcached::GET_EXTENDED);
|
||||
var_dump($v);
|
||||
|
||||
// Set flags on
|
||||
$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1);
|
||||
$m->set ($key, '1', 10);
|
||||
$m->get($key);
|
||||
check_flags($m->getLastUserFlags()[$key], array(FLAG_1));
|
||||
check_flags(get_flags($m, $key), array(FLAG_1));
|
||||
|
||||
// Multiple flags
|
||||
$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4);
|
||||
$m->set ($key, '1', 10);
|
||||
$m->get($key);
|
||||
check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4));
|
||||
check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4));
|
||||
|
||||
// Even more flags
|
||||
$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4 | FLAG_32 | FLAG_64);
|
||||
$m->set ($key, '1', 10);
|
||||
$m->get($key);
|
||||
check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64));
|
||||
check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64));
|
||||
|
||||
// User flags with get multi
|
||||
$values = array(
|
||||
@@ -61,10 +65,10 @@ $values = array(
|
||||
$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_2 | FLAG_4);
|
||||
$m->setMulti($values);
|
||||
$m->getMulti(array_keys($values));
|
||||
$flags = $m->getLastUserFlags();
|
||||
$flags = $m->getMulti(array_keys($values), Memcached::GET_EXTENDED);
|
||||
|
||||
foreach (array_keys($values) as $key) {
|
||||
check_flags($flags[$key], array(FLAG_2, FLAG_4));
|
||||
check_flags($flags[$key]['flags'], array(FLAG_2, FLAG_4));
|
||||
}
|
||||
|
||||
// User flags with compression on
|
||||
@@ -74,7 +78,7 @@ $m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ);
|
||||
|
||||
$m->set ($key, '1', 10);
|
||||
$m->get($key);
|
||||
check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4));
|
||||
check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4));
|
||||
|
||||
|
||||
// Too large flags
|
||||
@@ -83,8 +87,12 @@ $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE);
|
||||
echo "DONE TEST\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(1) {
|
||||
["udf_test_%s"]=>
|
||||
array(3) {
|
||||
["value"]=>
|
||||
string(1) "1"
|
||||
["cas"]=>
|
||||
int(%d)
|
||||
["flags"]=>
|
||||
int(0)
|
||||
}
|
||||
Flags OK
|
||||
|
||||
Reference in New Issue
Block a user