ENHANCE: modify do_item_replace function for optimization.
@@ -1204,11 +1204,59 @@ static void do_item_replace(hash_item *old_it, hash_item *new_it)
{
MEMCACHED_ITEM_REPLACE(item_get_key(old_it), old_it->nkey, old_it->nbytes,
item_get_key(new_it), new_it->nkey, new_it->nbytes);
- do_item_unlink(old_it, ITEM_UNLINK_REPLACE);
- /* Cache item replacement does not drop the prefix item even if it's empty.
- * So, the below do_item_link function always return SUCCESS.
+
+ assert((old_it->iflag & ITEM_LINKED) != 0);
+
+ CLOG_ITEM_UNLINK(old_it, ITEM_UNLINK_REPLACE);
+
+ /* unlink the item from LUR list */
+ item_unlink_q(old_it);
+
+ /* Allocate a new CAS ID on link. */
+ item_set_cas(new_it, get_cas_id());
+
+ /* link the item to the hash table */
+ new_it->iflag |= ITEM_LINKED;
+ new_it->time = svcore->get_current_time();
+ new_it->khash = old_it->khash;
+
+ /* replace the item from hash table */
+ assoc_replace(old_it, new_it);
+ old_it->iflag &= ~ITEM_LINKED;
+
+ /* update prefix information */
+ prefix_t *pt = old_it->pfxptr;
+ new_it->pfxptr = old_it->pfxptr;
+ old_it->pfxptr = NULL;
+ assert(pt != NULL);
+
+ /* if old_it->iflag has ITEM_INTERNAL */
+ if (old_it->iflag & ITEM_INTERNAL) {
+ new_it->iflag |= ITEM_INTERNAL;
+ }
+
+ /* update prefix info and stats */
+ do_item_stat_replace(old_it, new_it);
+
+ if (IS_COLL_ITEM(old_it)) {
+ /* IMPORTANT NOTE)
+ * The element space statistics has already been decreased.
+ * So, we must not decrease the space statistics any more
+ * even if the elements are freed later.
+ * For that purpose, we set info->stotal to 0 like below.
*/
- (void)do_item_link(new_it);
+ coll_meta_info *info = (coll_meta_info *)item_get_meta(old_it);
+ info->stotal = 0;
+ }
+
+ /* free the item if no one reference it */
+ if (old_it->refcount == 0) {
+ do_item_free(old_it);
+ }
+
+ /* link the item to LRU list */
+ item_link_q(new_it);
+ CLOG_ITEM_LINK(new_it);
}
/*
