Skip to content

Commit 40ce9b4

Browse files
committed
Merge branch 'master' of https://github.com/Vendini/php-memcached into Vendini-master
Conflicts: memcached.ini php_memcached.c php_memcached.h php_memcached_session.c
2 parents 5ff9516 + faf84af commit 40ce9b4

File tree

7 files changed

+73
-10
lines changed

7 files changed

+73
-10
lines changed

memcached.ini

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@ memcached.sess_prefix = "memc.sess.key."
2525
; default is Off
2626
memcached.sess_consistent_hash = Off
2727

28+
; Allow failed memcached server to automatically be removed
29+
memcached.sess_remove_failed = 1
30+
31+
; Write data to a number of additional memcached servers
32+
; This is "poor man's HA" as libmemcached calls it.
33+
; If this value is positive and sess_remove_failed is enabled
34+
; when a memcached server fails the session will continue to be available
35+
; from a replica. However, if the failed memcache server
36+
; becomes available again it will read the session from there
37+
; which could have old data or no data at all
38+
memcached.sess_num_replicas = 0;
39+
2840
; memcached session binary mode
41+
; libmemcached replicas only work if binary mode is enabled
2942
memcached.sess_binary = Off
3043

3144
; memcached session number of replicas
@@ -68,4 +81,3 @@ memcached.compression_threshold = 2000
6881
;
6982
; The default is igbinary if available and php otherwise.
7083
memcached.serializer = "igbinary"
71-

php_memcached.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,11 @@ PHP_INI_BEGIN()
289289
STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals)
290290
STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals)
291291
STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals)
292+
292293
STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals)
293294
STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals)
295+
STD_PHP_INI_ENTRY("memcached.sess_consistent_hashing", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hashing_enabled, zend_php_memcached_globals, php_memcached_globals)
296+
STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals)
294297
#endif
295298
STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals)
296299
STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals)
@@ -2589,7 +2592,8 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr,
25892592
/*
25902593
* API does not allow to get at this field.
25912594
add_assoc_long(array, "weight", instance->weight);
2592-
*/
2595+
*/
2596+
25932597
add_next_index_zval(context->return_value, array);
25942598
return MEMCACHED_SUCCESS;
25952599
}
@@ -3038,6 +3042,9 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob
30383042
#ifdef HAVE_MEMCACHED_SESSION
30393043
MEMC_G(sess_locking_enabled) = 1;
30403044
MEMC_G(sess_binary_enabled) = 1;
3045+
MEMC_G(sess_consistent_hashing_enabled) = 0;
3046+
MEMC_G(sess_number_of_replicas) = 0;
3047+
MEMC_G(sess_remove_failed_enabled) = 0;
30413048
MEMC_G(sess_prefix) = NULL;
30423049
MEMC_G(sess_lock_wait) = 0;
30433050
MEMC_G(sess_locked) = 0;

php_memcached.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
6666
zend_bool sess_locked;
6767
char* sess_lock_key;
6868
int sess_lock_key_len;
69+
6970
int sess_number_of_replicas;
7071
zend_bool sess_randomize_replica_read;
72+
zend_bool sess_remove_failed_enabled;
73+
zend_bool sess_consistent_hashing_enabled;
7174
#endif
7275
char *serializer_name;
7376
enum memcached_serializer serializer;

php_memcached_session.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
4848
char *lock_key = NULL;
4949
int lock_key_len = 0;
5050
unsigned long attempts;
51+
long write_retry_attempts = 0;
5152
long lock_maxwait;
5253
long lock_wait = MEMC_G(sess_lock_wait);
5354
time_t expiration;
@@ -64,6 +65,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
6465
expiration = time(NULL) + lock_maxwait + 1;
6566
attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait);
6667

68+
/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */
69+
if (MEMC_G(sess_remove_failed_enabled)) {
70+
write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
71+
}
72+
6773
lock_key_len = spprintf(&lock_key, 0, "lock.%s", key);
6874
do {
6975
status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
@@ -73,6 +79,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
7379
MEMC_G(sess_lock_key_len) = lock_key_len;
7480
return 0;
7581
} else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) {
82+
if (write_retry_attempts > 0) {
83+
write_retry_attempts--;
84+
continue;
85+
}
86+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Write of lock failed");
7687
break;
7788
}
7889

@@ -214,6 +225,20 @@ PS_OPEN_FUNC(memcached)
214225
}
215226
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) {
216227
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session randomize replica read");
228+
}
229+
}
230+
231+
if (MEMC_G(sess_consistent_hashing_enabled)) {
232+
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA, (uint64_t) 1) == MEMCACHED_FAILURE) {
233+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached consistent hashing");
234+
return FAILURE;
235+
}
236+
}
237+
238+
/* Allow libmemcached remove failed servers */
239+
if (MEMC_G(sess_remove_failed_enabled)) {
240+
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) {
241+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set: remove failed servers");
217242
return FAILURE;
218243
}
219244
}
@@ -266,6 +291,7 @@ PS_READ_FUNC(memcached)
266291

267292
if (MEMC_G(sess_locking_enabled)) {
268293
if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) {
294+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to clear session lock record");
269295
return FAILURE;
270296
}
271297
}
@@ -286,6 +312,7 @@ PS_WRITE_FUNC(memcached)
286312
{
287313
int key_len = strlen(key);
288314
time_t expiration = 0;
315+
long write_try_attempts = 1;
289316
memcached_return status;
290317
memcached_sess *memc_sess = PS_GET_MOD_DATA();
291318
size_t key_length;
@@ -300,13 +327,22 @@ PS_WRITE_FUNC(memcached)
300327
if (PS(gc_maxlifetime) > 0) {
301328
expiration = PS(gc_maxlifetime);
302329
}
303-
status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0);
304330

305-
if (status == MEMCACHED_SUCCESS) {
306-
return SUCCESS;
307-
} else {
308-
return FAILURE;
331+
/* 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 */
332+
if (MEMC_G(sess_remove_failed_enabled)) {
333+
write_try_attempts = 1 + MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
309334
}
335+
336+
do {
337+
status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0);
338+
if (status == MEMCACHED_SUCCESS) {
339+
return SUCCESS;
340+
} else {
341+
write_try_attempts--;
342+
}
343+
} while (write_try_attempts > 0);
344+
345+
return FAILURE;
310346
}
311347

312348
PS_DESTROY_FUNC(memcached)

tests/experimental/getmulti_badserver.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ switch ($m->getResultCode()) {
2121
echo $m->getResultMessage(), "\n";
2222
}
2323

24-
--EXPECT--
24+
--EXPECTF--
2525
array(0) {
2626
}
2727
NO SERVERS DEFINED
2828
array(0) {
2929
}
30-
3: CONNECTION FAILURE
30+
%d: %s

tests/experimental/moduleinfo.phpt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ memcached.compression_threshold => %d => %d
2424
memcached.compression_type => %s => %s
2525
memcached.serializer => %s => %s
2626
memcached.sess_binary => %d => %d
27+
memcached.sess_consistent_hash => %d => %d
28+
memcached.sess_consistent_hashing => %d => %d
2729
memcached.sess_lock_wait => %d => %d
2830
memcached.sess_locking => %d => %d
31+
memcached.sess_number_of_replicas => %d => %d
2932
memcached.sess_prefix => %s => %s
33+
memcached.sess_randomize_replica_read => %d => %d
34+
memcached.sess_remove_failed => %d => %d

tests/types.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ $data = array(
3333
array('array', array(1,2,3,"foo")),
3434

3535
array('object_array_empty', (object)array()),
36-
array('object_array', (object)array(1,2,3)),
36+
array('object_array', (object)array("a" => "1","b" => "2","c" => "3")),
3737
array('object_dummy', new testclass()),
3838
);
3939

0 commit comments

Comments
 (0)