@@ -121,7 +121,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
121
121
it = search ;
122
122
it -> refcount = 1 ;
123
123
slabs_adjust_mem_requested (it -> slabs_clsid , ITEM_ntotal (it ), ntotal );
124
- do_item_unlink (it , hash (ITEM_key (it ), it -> nkey , 0 ));
124
+ do_item_unlink_nolock (it , hash (ITEM_key (it ), it -> nkey , 0 ));
125
125
/* Initialize the item block: */
126
126
it -> slabs_clsid = 0 ;
127
127
it -> refcount = 0 ;
@@ -151,7 +151,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
151
151
it = search ;
152
152
it -> refcount = 1 ;
153
153
slabs_adjust_mem_requested (it -> slabs_clsid , ITEM_ntotal (it ), ntotal );
154
- do_item_unlink (it , hash (ITEM_key (it ), it -> nkey , 0 ));
154
+ do_item_unlink_nolock (it , hash (ITEM_key (it ), it -> nkey , 0 ));
155
155
/* Initialize the item block: */
156
156
it -> slabs_clsid = 0 ;
157
157
it -> refcount = 0 ;
@@ -172,7 +172,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
172
172
search -> time + TAIL_REPAIR_TIME < current_time ) {
173
173
itemstats [id ].tailrepairs ++ ;
174
174
search -> refcount = 0 ;
175
- do_item_unlink (search , hash (ITEM_key (search ), search -> nkey , 0 ));
175
+ do_item_unlink_nolock (search , hash (ITEM_key (search ), search -> nkey , 0 ));
176
176
}
177
177
return NULL ;
178
178
}
@@ -275,23 +275,41 @@ int do_item_link(item *it, const uint32_t hv) {
275
275
assert ((it -> it_flags & (ITEM_LINKED |ITEM_SLABBED )) == 0 );
276
276
it -> it_flags |= ITEM_LINKED ;
277
277
it -> time = current_time ;
278
- assoc_insert (it , hv );
279
278
280
279
STATS_LOCK ();
281
280
stats .curr_bytes += ITEM_ntotal (it );
282
281
stats .curr_items += 1 ;
283
282
stats .total_items += 1 ;
284
283
STATS_UNLOCK ();
285
284
285
+ mutex_lock (& cache_lock );
286
286
/* Allocate a new CAS ID on link. */
287
287
ITEM_set_cas (it , (settings .use_cas ) ? get_cas_id () : 0 );
288
-
288
+ assoc_insert ( it , hv );
289
289
item_link_q (it );
290
+ pthread_mutex_unlock (& cache_lock );
290
291
291
292
return 1 ;
292
293
}
293
294
294
295
void do_item_unlink (item * it , const uint32_t hv ) {
296
+ MEMCACHED_ITEM_UNLINK (ITEM_key (it ), it -> nkey , it -> nbytes );
297
+ if ((it -> it_flags & ITEM_LINKED ) != 0 ) {
298
+ it -> it_flags &= ~ITEM_LINKED ;
299
+ STATS_LOCK ();
300
+ stats .curr_bytes -= ITEM_ntotal (it );
301
+ stats .curr_items -= 1 ;
302
+ STATS_UNLOCK ();
303
+ mutex_lock (& cache_lock );
304
+ assoc_delete (ITEM_key (it ), it -> nkey , hv );
305
+ item_unlink_q (it );
306
+ pthread_mutex_unlock (& cache_lock );
307
+ if (it -> refcount == 0 ) item_free (it );
308
+ }
309
+ }
310
+
311
+ /* FIXME: Is it necessary to keep thsi copy/pasted code? */
312
+ void do_item_unlink_nolock (item * it , const uint32_t hv ) {
295
313
MEMCACHED_ITEM_UNLINK (ITEM_key (it ), it -> nkey , it -> nbytes );
296
314
if ((it -> it_flags & ITEM_LINKED ) != 0 ) {
297
315
it -> it_flags &= ~ITEM_LINKED ;
@@ -323,9 +341,11 @@ void do_item_update(item *it) {
323
341
assert ((it -> it_flags & ITEM_SLABBED ) == 0 );
324
342
325
343
if ((it -> it_flags & ITEM_LINKED ) != 0 ) {
344
+ mutex_lock (& cache_lock );
326
345
item_unlink_q (it );
327
346
it -> time = current_time ;
328
347
item_link_q (it );
348
+ pthread_mutex_unlock (& cache_lock );
329
349
}
330
350
}
331
351
}
@@ -387,22 +407,6 @@ void do_item_stats(ADD_STAT add_stats, void *c) {
387
407
char key_str [STAT_KEY_LEN ];
388
408
char val_str [STAT_VAL_LEN ];
389
409
int klen = 0 , vlen = 0 ;
390
- int search = 50 ;
391
- while (search > 0 &&
392
- tails [i ] != NULL &&
393
- ((settings .oldest_live != 0 && /* Item flushd */
394
- settings .oldest_live <= current_time &&
395
- tails [i ]-> time <= settings .oldest_live ) ||
396
- (tails [i ]-> exptime != 0 && /* and not expired */
397
- tails [i ]-> exptime < current_time ))) {
398
- -- search ;
399
- if (tails [i ]-> refcount == 0 ) {
400
- do_item_unlink (tails [i ], hash (ITEM_key (tails [i ]),
401
- tails [i ]-> nkey , 0 ));
402
- } else {
403
- break ;
404
- }
405
- }
406
410
if (tails [i ] == NULL ) {
407
411
/* We removed all of the items in this slab class */
408
412
continue ;
@@ -470,7 +474,9 @@ void do_item_stats_sizes(ADD_STAT add_stats, void *c) {
470
474
471
475
/** wrapper around assoc_find which does the lazy expiration logic */
472
476
item * do_item_get (const char * key , const size_t nkey , const uint32_t hv ) {
477
+ mutex_lock (& cache_lock );
473
478
item * it = assoc_find (key , nkey , hv );
479
+ pthread_mutex_unlock (& cache_lock );
474
480
int was_found = 0 ;
475
481
476
482
if (settings .verbose > 2 ) {
@@ -484,7 +490,7 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
484
490
485
491
if (it != NULL && settings .oldest_live != 0 && settings .oldest_live <= current_time &&
486
492
it -> time <= settings .oldest_live ) {
487
- do_item_unlink (it , hv ); /* MTSAFE - cache_lock held */
493
+ do_item_unlink (it , hv ); /* MTSAFE - item_lock held */
488
494
it = NULL ;
489
495
}
490
496
@@ -494,7 +500,7 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
494
500
}
495
501
496
502
if (it != NULL && it -> exptime != 0 && it -> exptime <= current_time ) {
497
- do_item_unlink (it , hv ); /* MTSAFE - cache_lock held */
503
+ do_item_unlink (it , hv ); /* MTSAFE - item_lock held */
498
504
it = NULL ;
499
505
}
500
506
@@ -524,16 +530,6 @@ item *do_item_touch(const char *key, size_t nkey, uint32_t exptime,
524
530
return it ;
525
531
}
526
532
527
- /** returns an item whether or not it's expired. */
528
- item * do_item_get_nocheck (const char * key , const size_t nkey , const uint32_t hv ) {
529
- item * it = assoc_find (key , nkey , hv );
530
- if (it ) {
531
- it -> refcount ++ ;
532
- DEBUG_REFCNT (it , '+' );
533
- }
534
- return it ;
535
- }
536
-
537
533
/* expires items that are more recent than the oldest_live setting. */
538
534
void do_item_flush_expired (void ) {
539
535
int i ;
@@ -550,7 +546,7 @@ void do_item_flush_expired(void) {
550
546
if (iter -> time >= settings .oldest_live ) {
551
547
next = iter -> next ;
552
548
if ((iter -> it_flags & ITEM_SLABBED ) == 0 ) {
553
- do_item_unlink (iter , hash (ITEM_key (iter ), iter -> nkey , 0 ));
549
+ do_item_unlink_nolock (iter , hash (ITEM_key (iter ), iter -> nkey , 0 ));
554
550
}
555
551
} else {
556
552
/* We've hit the first old item. Continue to the next queue. */
0 commit comments