struct item *item_alloc(uint8_t id, char *key, uint16_t nkey, int exptime, char *value, uint32_t nbyte) { struct item *it, *oit; pthread_mutex_lock(&cache_lock); it = _item_alloc(id, key, nkey, exptime, value, nbyte); if (it == NULL) return NULL; oit = _item_get(key, nkey); if (oit != NULL) _item_replace(oit, it); else { _item_link(it); } if (oit != NULL) _item_remove(oit); pthread_mutex_unlock(&cache_lock); return it; }
item_rstatus_e item_reserve(struct item **it_p, const struct bstring *key, const struct bstring *val, uint32_t vlen, uint8_t olen, proc_time_i expire_at) { item_rstatus_e status; struct item *it; if ((status = _item_alloc(it_p, key->len, vlen, olen)) != ITEM_OK) { log_debug("item reservation failed"); return status; } it = *it_p; _item_define(it, key, val, olen, expire_at); log_verb("reserve it %p of id %"PRIu8" for key '%.*s' optional len %"PRIu8, it, it->id,key->len, key->data, olen); return ITEM_OK; }
item_rstatus_e item_annex(struct item *oit, const struct bstring *key, const struct bstring *val, bool append) { item_rstatus_e status = ITEM_OK; struct item *nit = NULL; uint8_t id; uint32_t ntotal = oit->vlen + val->len; id = item_slabid(oit->klen, ntotal, oit->olen); if (id == SLABCLASS_INVALID_ID) { log_info("client error: annex operation results in oversized item with" "key size %"PRIu8" old value size %"PRIu32" and new value " "size %"PRIu32, oit->klen, oit->vlen, ntotal); return ITEM_EOVERSIZED; } if (append) { /* if it is large enough to hold the extra data and left-aligned, * which is the default behavior, we copy the delta to the end of * the existing data. Otherwise, allocate a new item and store the * payload left-aligned. */ if (id == oit->id && !(oit->is_raligned)) { cc_memcpy(item_data(oit) + oit->vlen, val->data, val->len); oit->vlen = ntotal; INCR_N(slab_metrics, item_keyval_byte, val->len); INCR_N(slab_metrics, item_val_byte, val->len); item_set_cas(oit); } else { status = _item_alloc(&nit, oit->klen, ntotal, oit->olen); if (status != ITEM_OK) { log_debug("annex failed due to failure to allocate new item"); return status; } _copy_key_item(nit, oit); nit->expire_at = oit->expire_at; nit->create_at = time_proc_sec(); item_set_cas(nit); /* value is left-aligned */ cc_memcpy(item_data(nit), item_data(oit), oit->vlen); cc_memcpy(item_data(nit) + oit->vlen, val->data, val->len); nit->vlen = ntotal; item_insert(nit, key); } } else { /* if oit is large enough to hold the extra data and is already * right-aligned, we copy the delta to the front of the existing * data. Otherwise, allocate a new item and store the payload * right-aligned, assuming more prepends will happen in the future. */ if (id == oit->id && oit->is_raligned) { cc_memcpy(item_data(oit) - val->len, val->data, val->len); oit->vlen = ntotal; INCR_N(slab_metrics, item_keyval_byte, val->len); INCR_N(slab_metrics, item_val_byte, val->len); item_set_cas(oit); } else { status = _item_alloc(&nit, oit->klen, ntotal, oit->olen); if (status != ITEM_OK) { log_debug("annex failed due to failure to allocate new item"); return status; } _copy_key_item(nit, oit); nit->expire_at = oit->expire_at; nit->create_at = time_proc_sec(); item_set_cas(nit); /* value is right-aligned */ nit->is_raligned = 1; cc_memcpy(item_data(nit) - ntotal, val->data, val->len); cc_memcpy(item_data(nit) - oit->vlen, item_data(oit), oit->vlen); nit->vlen = ntotal; item_insert(nit, key); } } log_verb("annex to it %p of id %"PRIu8", new it at %p", oit, oit->id, nit ? oit : nit); return status; }