@@ -48,6 +48,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
48
48
char * lock_key = NULL ;
49
49
int lock_key_len = 0 ;
50
50
unsigned long attempts ;
51
+ long write_retry_attempts = 0 ;
51
52
long lock_maxwait ;
52
53
long lock_wait = MEMC_G (sess_lock_wait );
53
54
time_t expiration ;
@@ -64,6 +65,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
64
65
expiration = time (NULL ) + lock_maxwait + 1 ;
65
66
attempts = (unsigned long )((1000000.0 / lock_wait ) * lock_maxwait );
66
67
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_num_replicas ) * ( memcached_behavior_get (memc , MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT ) + 1 );
71
+ }
72
+
67
73
lock_key_len = spprintf (& lock_key , 0 , "lock.%s" , key );
68
74
do {
69
75
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)
73
79
MEMC_G (sess_lock_key_len ) = lock_key_len ;
74
80
return 0 ;
75
81
} 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" );
76
87
break ;
77
88
}
78
89
@@ -195,6 +206,30 @@ PS_OPEN_FUNC(memcached)
195
206
}
196
207
}
197
208
209
+ if (MEMC_G (sess_consistent_hashing_enabled )) {
210
+ if (memcached_behavior_set (memc_sess -> memc_sess , MEMCACHED_BEHAVIOR_KETAMA , (uint64_t ) 1 ) == MEMCACHED_FAILURE ) {
211
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "failed to set memcached consistent hashing" );
212
+ return FAILURE ;
213
+ }
214
+ }
215
+
216
+ /* Allow libmemcached remove failed servers */
217
+ if (MEMC_G (sess_remove_failed_enabled )) {
218
+ if (memcached_behavior_set (memc_sess -> memc_sess , MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS , (uint64_t ) 1 ) == MEMCACHED_FAILURE ) {
219
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "failed to set: remove failed servers" );
220
+ return FAILURE ;
221
+ }
222
+ }
223
+
224
+ /* Allow replicas section */
225
+ long num_replicas = MEMC_G (sess_num_replicas );
226
+ if (num_replicas > 0 ) {
227
+ /* Set the number of replicas libmemcached will use */
228
+ if (memcached_behavior_set (memc_sess -> memc_sess , MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS , (uint64_t ) num_replicas ) == MEMCACHED_FAILURE ) {
229
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "failed to set memcached client replicating" );
230
+ return FAILURE ;
231
+ }
232
+ }
198
233
return SUCCESS ;
199
234
}
200
235
}
@@ -243,6 +278,7 @@ PS_READ_FUNC(memcached)
243
278
244
279
if (MEMC_G (sess_locking_enabled )) {
245
280
if (php_memc_sess_lock (memc_sess -> memc_sess , key TSRMLS_CC ) < 0 ) {
281
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to clear session lock record" );
246
282
return FAILURE ;
247
283
}
248
284
}
@@ -263,6 +299,7 @@ PS_WRITE_FUNC(memcached)
263
299
{
264
300
int key_len = strlen (key );
265
301
time_t expiration = 0 ;
302
+ long write_try_attempts = 1 ;
266
303
memcached_return status ;
267
304
memcached_sess * memc_sess = PS_GET_MOD_DATA ();
268
305
size_t key_length ;
@@ -277,13 +314,22 @@ PS_WRITE_FUNC(memcached)
277
314
if (PS (gc_maxlifetime ) > 0 ) {
278
315
expiration = PS (gc_maxlifetime );
279
316
}
280
- status = memcached_set (memc_sess -> memc_sess , key , key_len , val , vallen , expiration , 0 );
281
317
282
- if (status == MEMCACHED_SUCCESS ) {
283
- return SUCCESS ;
284
- } else {
285
- return FAILURE ;
318
+ /* 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 */
319
+ if (MEMC_G (sess_remove_failed_enabled )) {
320
+ write_try_attempts = 1 + MEMC_G (sess_num_replicas ) * ( memcached_behavior_get (memc_sess -> memc_sess , MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT ) + 1 );
286
321
}
322
+
323
+ do {
324
+ status = memcached_set (memc_sess -> memc_sess , key , key_len , val , vallen , expiration , 0 );
325
+ if (status == MEMCACHED_SUCCESS ) {
326
+ return SUCCESS ;
327
+ } else {
328
+ write_try_attempts -- ;
329
+ }
330
+ } while (write_try_attempts > 0 );
331
+
332
+ return FAILURE ;
287
333
}
288
334
289
335
PS_DESTROY_FUNC (memcached )
0 commit comments