@@ -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
312348PS_DESTROY_FUNC (memcached )
0 commit comments