/* * Unlinks an item from the LRU and hashtable. */ void item_unlink(item *item) { uint32_t hv; hv = hash(ITEM_key(item), item->nkey, 0); item_lock(hv); do_item_unlink(item, hv); item_unlock(hv); }
/* * Decrements the reference count on an item and adds it to the freelist if * needed. */ void item_remove(item *item) { uint32_t hv; hv = hash(ITEM_key(item), item->nkey); item_lock(hv); do_item_remove(item); item_unlock(hv); }
item *item_touch(const char *key, size_t nkey, uint32_t exptime) { item *it; uint32_t hv; hv = hash(key, nkey, 0); item_lock(hv); it = do_item_touch(key, nkey, exptime, hv); item_unlock(hv); return it; }
/* * Returns an item if it hasn't been marked as expired, * lazy-expiring as needed. */ item *item_get(const char *key, const size_t nkey, conn *c, const bool do_update) { item *it; uint32_t hv; hv = hash(key, nkey); item_lock(hv); it = do_item_get(key, nkey, hv, c, do_update); item_unlock(hv); return it; }
/* * Returns an item if it hasn't been marked as expired, * lazy-expiring as needed. */ item *item_get(const char *key, const size_t nkey) { item *it; uint32_t hv; hv = hash(key, nkey); item_lock(hv); it = do_item_get(key, nkey, hv); item_unlock(hv); return it; }
/* * Links an item into the LRU and hashtable. */ int item_link(item *item) { int ret; uint32_t hv; hv = hash(ITEM_key(item), item->nkey, 0); item_lock(hv); ret = do_item_link(item, hv); item_unlock(hv); return ret; }
/* * Stores an item in the cache (high level, obeys set/add/replace semantics) */ enum store_item_type store_item(item *item, int comm, conn* c) { enum store_item_type ret; uint32_t hv; hv = hash(ITEM_key(item), item->nkey); item_lock(hv); ret = do_store_item(item, comm, c, hv); item_unlock(hv); return ret; }
/* * Stores an item in the cache (high level, obeys set/add/replace semantics) */ enum store_item_type store_item(item *item, int comm, conn* c) { //注意该函数外层在该函数执行完后一般会调用一次item_remove enum store_item_type ret; uint32_t hv; hv = hash(ITEM_key(item), item->nkey); item_lock(hv); ret = do_store_item(item, comm, c, hv); item_unlock(hv); return ret; }
/* * Does arithmetic on a numeric item value. */ enum delta_result_type add_delta(conn *c, const char *key, const size_t nkey, int incr, const int64_t delta, char *buf, uint64_t *cas) { enum delta_result_type ret; uint32_t hv; hv = hash(key, nkey); item_lock(hv); ret = do_add_delta(c, key, nkey, incr, delta, buf, cas, hv); item_unlock(hv); return ret; }
/* * Stores an item in the cache (high level, obeys set/add/replace semantics) * 在缓存中存储一个数据项 */ enum store_item_type store_item(item *item, int comm, conn* c) { enum store_item_type ret; uint32_t hv; // 先做一次哈希计算 hv = hash(ITEM_key(item), item->nkey, 0); item_lock(hv); // 正真存储数据的方法 do_store_item() ret = do_store_item(item, comm, c, hv); item_unlock(hv); return ret; }
static void storage_compact_readback(void *storage, logger *l, bool drop_unread, char *readback_buf, uint32_t page_id, uint64_t page_version, uint64_t read_size) { uint64_t offset = 0; unsigned int rescues = 0; unsigned int lost = 0; unsigned int skipped = 0; while (offset < read_size) { item *hdr_it = NULL; item_hdr *hdr = NULL; item *it = (item *)(readback_buf+offset); unsigned int ntotal; // probably zeroed out junk at the end of the wbuf if (it->nkey == 0) { break; } ntotal = ITEM_ntotal(it); uint32_t hv = (uint32_t)it->time; item_lock(hv); // We don't have a conn and don't need to do most of do_item_get hdr_it = assoc_find(ITEM_key(it), it->nkey, hv); if (hdr_it != NULL) { bool do_write = false; refcount_incr(hdr_it); // Check validity but don't bother removing it. if ((hdr_it->it_flags & ITEM_HDR) && !item_is_flushed(hdr_it) && (hdr_it->exptime == 0 || hdr_it->exptime > current_time)) { hdr = (item_hdr *)ITEM_data(hdr_it); if (hdr->page_id == page_id && hdr->page_version == page_version) { // Item header is still completely valid. extstore_delete(storage, page_id, page_version, 1, ntotal); // drop inactive items. if (drop_unread && GET_LRU(hdr_it->slabs_clsid) == COLD_LRU) { do_write = false; skipped++; } else { do_write = true; } } } if (do_write) { bool do_update = false; int tries; obj_io io; io.len = ntotal; io.mode = OBJ_IO_WRITE; for (tries = 10; tries > 0; tries--) { if (extstore_write_request(storage, PAGE_BUCKET_COMPACT, PAGE_BUCKET_COMPACT, &io) == 0) { memcpy(io.buf, it, io.len); extstore_write(storage, &io); do_update = true; break; } else { usleep(1000); } } if (do_update) { if (it->refcount == 2) { hdr->page_version = io.page_version; hdr->page_id = io.page_id; hdr->offset = io.offset; rescues++; } else { lost++; // TODO: re-alloc and replace header. } } else { lost++; } } do_item_remove(hdr_it); } item_unlock(hv); offset += ntotal; if (read_size - offset < sizeof(struct _stritem)) break; } STATS_LOCK(); stats.extstore_compact_lost += lost; stats.extstore_compact_rescues += rescues; stats.extstore_compact_skipped += skipped; STATS_UNLOCK(); LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_COMPACT_READ_END, NULL, page_id, offset, rescues, lost, skipped); }