/* * pmemobj_pool_by_oid -- returns the pool handle associated with the oid */ PMEMobjpool * pmemobj_pool_by_oid(PMEMoid oid) { LOG(3, "oid.off 0x%016jx", oid.off); return cuckoo_get(pools_ht, oid.pool_uuid_lo); }
static bool _get_key(struct response *rsp, struct bstring *key) { struct item *it; struct val val; it = cuckoo_get(key); if (it != NULL) { rsp->type = RSP_VALUE; rsp->key = *key; rsp->flag = item_flag(it); rsp->vcas = item_cas(it); item_val(&val, it); if (val.type == VAL_TYPE_INT) { rsp->num = 1; rsp->vint = val.vint; } else { rsp->vstr = val.vstr; } log_verb("found key at %p, location %p", key, it); return true; } else { log_verb("key at %p not found", key); return false; } }
void test_cas(uint32_t policy) { #define KEY "key" #define VAL "value" #define VAL2 "value2" struct bstring key; struct val val; rstatus_i status; struct item *it; uint64_t cas1, cas2; test_reset(policy, true); key.data = KEY; key.len = sizeof(KEY) - 1; val.type = VAL_TYPE_STR; val.vstr.data = VAL; val.vstr.len = sizeof(VAL) - 1; time_update(); status = cuckoo_insert(&key, &val, UINT32_MAX - 1); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); it = cuckoo_get(&key); cas1 = item_cas(it); ck_assert_uint_ne(cas1, 0); val.vstr.data = VAL2; val.vstr.len = sizeof(VAL2) - 1; status = cuckoo_update(it, &val, UINT32_MAX - 1); ck_assert_msg(status == CC_OK, "cuckoo_update not OK - return status %d", status); it = cuckoo_get(&key); cas2 = item_cas(it); ck_assert_uint_ne(cas2, 0); ck_assert_uint_ne(cas1, cas2); #undef KEY #undef VAL #undef VAL2 }
void test_delete_basic(uint32_t policy, bool cas) { #define KEY "key" #define VAL "value" struct bstring key; struct val val; rstatus_i status; struct item *it; bool deleted; test_reset(policy, cas); key.data = KEY; key.len = sizeof(KEY) - 1; val.type = VAL_TYPE_STR; val.vstr.data = VAL; val.vstr.len = sizeof(VAL) - 1; time_update(); status = cuckoo_insert(&key, &val, UINT32_MAX - 1); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); it = cuckoo_get(&key); ck_assert_msg(it != NULL, "cuckoo_get returned NULL"); deleted = cuckoo_delete(&key); ck_assert_msg(deleted, "cuckoo_delete return false"); it = cuckoo_get(&key); ck_assert_msg(it == NULL, "cuckoo_get returned not NULL"); deleted = cuckoo_delete(&key); ck_assert_msg(!deleted, "cuckoo_delete return true"); #undef KEY #undef VAL }
static void test_assert_entry_exists(struct bstring *key, struct val *val) { struct item *it = cuckoo_get(key); ck_assert_msg(it != NULL, "cuckoo_get returned NULL"); ck_assert_int_eq(it->vlen, val->vstr.len); ck_assert_int_eq(it->klen, key->len); ck_assert_int_eq(it->vlen, val->vstr.len); struct bstring testval; item_value_str(&testval, it); ck_assert_int_eq(it->vlen, testval.len); ck_assert_int_eq(cc_memcmp(testval.data, val->vstr.data, testval.len), 0); }
/* * alloc_class_by_run -- returns the allocation class that has the given * unit size */ struct alloc_class * alloc_class_by_run(struct alloc_class_collection *ac, size_t unit_size, uint16_t flags, uint32_t size_idx) { size_t map_idx = SIZE_TO_CLASS_MAP_INDEX(unit_size, ac->granularity); ASSERT(map_idx <= UINT32_MAX); uint32_t map_idx_s = (uint32_t)map_idx; ASSERT(size_idx <= UINT16_MAX); uint16_t size_idx_s = (uint16_t)size_idx; uint16_t flags_s = (uint16_t)flags; return cuckoo_get(ac->class_map_by_unit_size, RUN_CLASS_KEY_PACK(map_idx_s, flags_s, size_idx_s)); }
static void test_insert_get_remove() { struct cuckoo *c = cuckoo_new(); ASSERT(c != NULL); for (int i = 0; i < TEST_INSERTS; ++i) ASSERT(cuckoo_insert(c, i, TEST_VAL(i)) == 0); for (int i = 0; i < TEST_INSERTS; ++i) ASSERT(cuckoo_get(c, i) == TEST_VAL(i)); for (int i = 0; i < TEST_INSERTS; ++i) ASSERT(cuckoo_remove(c, i) == TEST_VAL(i)); for (int i = 0; i < TEST_INSERTS; ++i) ASSERT(cuckoo_remove(c, i) == NULL); for (int i = 0; i < TEST_INSERTS; ++i) ASSERT(cuckoo_get(c, i) == NULL); cuckoo_delete(c); }
void test_expire_basic(uint32_t policy, bool cas) { #define KEY "key" #define VAL "value" #define NOW 12345678 struct bstring key; struct val val; rstatus_i status; struct item *it; test_reset(policy, cas); key.data = KEY; key.len = sizeof(KEY) - 1; val.type = VAL_TYPE_STR; val.vstr.data = VAL; val.vstr.len = sizeof(VAL) - 1; now = NOW; status = cuckoo_insert(&key, &val, NOW + 1); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); it = cuckoo_get(&key); ck_assert_msg(it != NULL, "cuckoo_get returned NULL"); now += 2; it = cuckoo_get(&key); ck_assert_msg(it == NULL, "cuckoo_get returned not NULL after expiration"); #undef NOW #undef KEY #undef VAL }
/* * pmemobj_alloc_usable_size -- returns usable size of object */ size_t pmemobj_alloc_usable_size(PMEMoid oid) { LOG(3, "oid.off 0x%016jx", oid.off); if (oid.off == 0) return 0; PMEMobjpool *pop = cuckoo_get(pools, oid.pool_uuid_lo); ASSERTne(pop, NULL); ASSERT(OBJ_OID_IS_VALID(pop, oid)); return (pmalloc_usable_size(pop, oid.off - OBJ_OOB_SIZE) - OBJ_OOB_SIZE); }
END_TEST START_TEST(test_insert_insert_expire_swap) { #define NOW 12345678 struct bstring key; struct val val; rstatus_i status; char keystring[30]; uint64_t i; int hits = 0; metrics = (cuckoo_metrics_st) { CUCKOO_METRIC(METRIC_INIT) }; test_reset(CUCKOO_POLICY_EXPIRE, false); now = NOW; for (i = 0; metrics.item_curr.counter < CUCKOO_NITEM; i++) { key.len = sprintf(keystring, "%"PRIu64, i); key.data = keystring; val.type = VAL_TYPE_INT; val.vint = i; status = cuckoo_insert(&key, &val, now + i); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); } key.len = sprintf(keystring, "%"PRIu64, i); key.data = keystring; val.type = VAL_TYPE_INT; val.vint = i; status = cuckoo_insert(&key, &val, now + i); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); for (;i > 0 && hits < CUCKOO_NITEM;i--) { if (cuckoo_get(&key) != NULL) { hits++; } } ck_assert_msg(hits == CUCKOO_NITEM, "expected %d hits, got %d", CUCKOO_NITEM, hits); #undef NOW }
/* * pmemobj_free -- frees an existing object */ void pmemobj_free(PMEMoid *oidp) { LOG(3, "oid.off 0x%016jx", oidp->off); /* log notice message if used inside a transaction */ _POBJ_DEBUG_NOTICE_IN_TX(); if (oidp->off == 0) return; PMEMobjpool *pop = cuckoo_get(pools, oidp->pool_uuid_lo); ASSERTne(pop, NULL); ASSERT(OBJ_OID_IS_VALID(pop, *oidp)); obj_free(pop, oidp); }
void test_insert_collision(uint32_t policy, bool cas) { struct bstring key; struct val val; rstatus_i status; struct item *it; int hits = 0; char keystring[CC_UINTMAX_MAXLEN]; uint64_t i, testval; test_reset(policy, cas); time_update(); for (i = 0; i < CUCKOO_NITEM + 1; i++) { key.len = sprintf(keystring, "%"PRIu64, i); key.data = keystring; val.type = VAL_TYPE_INT; val.vint = i; status = cuckoo_insert(&key, &val, UINT32_MAX - 1); ck_assert_msg(status == CC_OK, "cuckoo_insert not OK - return status %d", status); } for (i = 0; i < CUCKOO_NITEM + 1; i++) { key.len = sprintf(keystring, "%"PRIu64, i); key.data = keystring; it = cuckoo_get(&key); if (it == NULL) { continue; } hits++; ck_assert_int_eq(it->klen, key.len); testval = item_value_int(it); ck_assert_int_eq(testval, i); } ck_assert_msg(hits > (double)CUCKOO_NITEM * 9 / 10, "hit rate is lower than expected when hash collision occurs"); ck_assert_msg(hits <= CUCKOO_NITEM, "hit rate is too high, expected more evicted values"); }
/* * get_lane_info_record -- (internal) get lane record attached to memory pool * or first free */ static inline struct lane_info * get_lane_info_record(PMEMobjpool *pop) { if (likely(Lane_info_cache != NULL && Lane_info_cache->pop_uuid_lo == pop->uuid_lo)) { return Lane_info_cache; } if (unlikely(Lane_info_ht == NULL)) { lane_info_ht_boot(); } struct lane_info *info = cuckoo_get(Lane_info_ht, pop->uuid_lo); if (unlikely(info == NULL)) { info = Malloc(sizeof(struct lane_info)); if (unlikely(info == NULL)) { FATAL("Malloc"); } info->pop_uuid_lo = pop->uuid_lo; info->lane_idx = UINT64_MAX; info->nest_count = 0; info->next = Lane_info_records; info->prev = NULL; if (Lane_info_records) { Lane_info_records->prev = info; } Lane_info_records = info; if (unlikely(cuckoo_insert( Lane_info_ht, pop->uuid_lo, info) != 0)) { FATAL("cuckoo_insert"); } } Lane_info_cache = info; return info; }
/* * pmemobj_next - returns next object of specified type */ PMEMoid pmemobj_next(PMEMoid oid) { LOG(3, "oid.off 0x%016jx", oid.off); if (oid.off == 0) return OID_NULL; PMEMobjpool *pop = cuckoo_get(pools, oid.pool_uuid_lo); ASSERTne(pop, NULL); ASSERT(OBJ_OID_IS_VALID(pop, oid)); struct oob_header *pobj = OOB_HEADER_FROM_OID(pop, oid); uint16_t user_type = pobj->data.user_type; ASSERT(user_type < PMEMOBJ_NUM_OID_TYPES); if (pobj->oob.pe_next.off != pop->store->bytype[user_type].head.pe_first.off) return pobj->oob.pe_next; else return OID_NULL; }
/* * pmemobj_pool -- returns the pool handle associated with the oid */ PMEMobjpool * pmemobj_pool(PMEMoid oid) { return cuckoo_get(pools, oid.pool_uuid_lo); }