summaryrefslogtreecommitdiff
path: root/items.c
diff options
context:
space:
mode:
Diffstat (limited to 'items.c')
-rw-r--r--items.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/items.c b/items.c
index f9ccb03..3594432 100644
--- a/items.c
+++ b/items.c
@@ -85,7 +85,7 @@ static size_t item_make_header(const uint8_t nkey, const int flags, const int nb
/*@null@*/
item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes) {
uint8_t nsuffix;
- item *it;
+ item *it = NULL;
char suffix[40];
size_t ntotal = item_make_header(nkey + 1, flags, nbytes, suffix, &nsuffix);
if (settings.use_cas) {
@@ -96,10 +96,34 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
if (id == 0)
return 0;
- it = slabs_alloc(ntotal, id);
- if (it == 0) {
- int tries = 50;
- item *search;
+ /* do a quick check if we have any expired items in the tail.. */
+ int tries = 50;
+ item *search;
+
+ for (search = tails[id];
+ tries > 0 && search != NULL;
+ tries--, search=search->prev) {
+ if (search->refcount == 0 &&
+ (search->exptime != 0 && search->exptime < current_time)) {
+ it = search;
+ /* I don't want to actually free the object, just steal
+ * the item to avoid to grab the slab mutex twice ;-)
+ */
+ it->refcount = 1;
+ do_item_unlink(it);
+ /* Initialize the item block: */
+ it->slabs_clsid = 0;
+ it->refcount = 0;
+ break;
+ }
+ }
+
+ if (it == NULL && (it = slabs_alloc(ntotal, id)) == NULL) {
+ /*
+ ** Could not find an expired item at the tail, and memory allocation
+ ** failed. Try to evict some items!
+ */
+ tries = 50;
/* If requested to not push old items out of cache when memory runs out,
* we're out of luck at this point...