TEST(TestObHashMap, create) { ObHashMap<HashKey, HashValue> hm; // 参数错误 EXPECT_EQ(-1, hm.create(0)); // 正常create EXPECT_EQ(0, hm.create(cal_next_prime(gHashItemNum))); // 重复create EXPECT_EQ(-1, hm.create(cal_next_prime(gHashItemNum))); }
TEST(TestObHashMap, destroy) { ObHashMap<HashKey, HashValue> hm; // 没有create EXPECT_EQ(0, hm.destroy()); hm.create(cal_next_prime(gHashItemNum)); EXPECT_EQ(0, hm.destroy()); EXPECT_EQ(0, hm.create(gHashItemNum)); }
TEST(TestObHashMap, atomic) { ObHashMap<HashKey, HashValue> hm; uint64_t key = 1; uint64_t value = 100; uint64_t value_update = 3000; CallBack callback; callback.set_v(value_update); HashValue value_tmp; // 没有create EXPECT_EQ(-1, hm.atomic(key, callback)); hm.create(cal_next_prime(gHashItemNum)); hm.set(key, value, 0); EXPECT_EQ(HASH_EXIST, hm.get(key, value_tmp)); EXPECT_EQ(value, value_tmp); EXPECT_EQ(HASH_EXIST, hm.atomic(key, callback)); EXPECT_EQ(HASH_EXIST, hm.get(key, value_tmp)); EXPECT_EQ(value_update, value_tmp); EXPECT_EQ(HASH_NOT_EXIST, hm.atomic(key + 1, callback)); EXPECT_EQ(HASH_EXIST, hm.get(key, value_tmp)); EXPECT_EQ(value_update, value_tmp); }
static void init_obj_type_map_() { static bool inited = false; if (!inited) { obj_type_map.create(16); obj_type_map.set("null", ObNullType); obj_type_map.set("int", ObIntType); obj_type_map.set("float", ObFloatType); obj_type_map.set("double", ObDoubleType); obj_type_map.set("date_time", ObDateTimeType); obj_type_map.set("precise_date_time", ObPreciseDateTimeType); obj_type_map.set("var_char", ObVarcharType); obj_type_map.set("seq", ObSeqType); obj_type_map.set("create_time", ObCreateTimeType); obj_type_map.set("modify_time", ObModifyTimeType); inited = true; } }
TEST(TestObHashMap, clear) { ObHashMap<HashKey, HashValue> hm; uint64_t key[4] = {1, 2, 1, 1 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 300, 301}; // 没有create EXPECT_EQ(-1, hm.clear()); hm.create(cal_next_prime(gHashItemNum)); EXPECT_EQ(0, hm.clear()); hm.set(key[0], value[0], 0); hm.set(key[1], value[1], 0); hm.set(key[3], value[3], 0); EXPECT_EQ(3, hm.size()); EXPECT_EQ(0, hm.clear()); EXPECT_EQ(0, hm.size()); }
TEST(TestObHashMap, set) { ObHashMap<HashKey, HashValue> hm; uint64_t key[4] = {1, 2, 1, 1 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 300, 301}; // 没有create EXPECT_EQ(-1, hm.set(key[0], value[0], 0)); hm.create(cal_next_prime(gHashItemNum)); // 正常插入 EXPECT_EQ(HASH_INSERT_SUCC, hm.set(key[0], value[0], 0)); // 正常插入不同bucket的key EXPECT_EQ(HASH_INSERT_SUCC, hm.set(key[1], value[1], 0)); // 正常插入相同bucket的key EXPECT_EQ(HASH_INSERT_SUCC, hm.set(key[3], value[3], 0)); // key存在但不覆盖 EXPECT_EQ(HASH_EXIST, hm.set(key[2], value[2], 0)); // key存在覆盖 EXPECT_EQ(HASH_OVERWRITE_SUCC, hm.set(key[2], value[2], 1)); }
TEST(TestObHashMap, erase) { ObHashMap<HashKey, HashValue> hm; uint64_t key[4] = {1, 2, 1, 1 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 300, 301}; // 没有create EXPECT_EQ(-1, hm.erase(key[0])); hm.create(cal_next_prime(gHashItemNum)); // 删除已存在的数据 hm.set(key[0], value[0], 0); hm.set(key[1], value[1], 0); hm.set(key[3], value[3], 0); EXPECT_EQ(HASH_EXIST, hm.erase(key[0])); EXPECT_EQ(HASH_EXIST, hm.erase(key[1])); uint64_t value_ret = 0; EXPECT_EQ(HASH_EXIST, hm.erase(key[3], &value_ret)); EXPECT_EQ(value[3], value_ret); // 删除不存在的数据 EXPECT_EQ(HASH_NOT_EXIST, hm.erase(-1)); }
static void init_opt_map_() { static bool inited = false; if (!inited) { opt_map.create(16); opt_map.set("update", +ObActionFlag::OP_UPDATE, 1); opt_map.set("add", +ObActionFlag::OP_UPDATE, 1); opt_map.set("insert", +ObActionFlag::OP_INSERT, 1); //opt_map.set("read", +ObActionFlag::OP_READ, 1); //opt_map.set("delete", +ObActionFlag::OP_DEL, 1); opt_map.set("delete_row", +ObActionFlag::OP_DEL_ROW, 1); opt_map.set("db_sem", +ObActionFlag::OP_USE_DB_SEM, 1); opt_map.set("ob_sem", +ObActionFlag::OP_USE_OB_SEM, 1); inited = true; } }
void read_cell_infos(const char *fname, const char *section, PageArena<char> &allocer, ObMutator &mutator, ObMutator &result) { init_opt_map_(); init_obj_type_map_(); TBSYS_CONFIG.load(fname); int32_t cell_infos_num = TBSYS_CONFIG.getInt(section, CELL_INFOS_NUM); std::vector<int64_t> table_ids; std::vector<int64_t> column_ids; for (int32_t i = 0; i < cell_infos_num; i++) { const char *str = NULL; int32_t len = 0; ObCellInfo *ci = (ObCellInfo*)allocer.alloc(sizeof(ObCellInfo)); //ObCellInfo *op = (ObCellInfo*)allocer.alloc(sizeof(ObCellInfo)); ci->reset(); sprintf(buffer, OP_TYPE_KEY_FORMAT, i); str = getAndCopySting_(allocer, section, buffer, len); int8_t op_type = 0; bool is_add = (0 == strncmp("add", str, 3)); opt_map.get(str, op_type); // table name sprintf(buffer, TABLE_NAME_KEY_FORMAT, i); str = getAndCopySting_(allocer, section, buffer, len); ci->table_name_.assign_ptr(const_cast<char*>(str), len); // table id sprintf(buffer, TABLE_ID_KEY_FORMAT, i); ci->table_id_ = TBSYS_CONFIG.getInt(section, buffer); // row key sprintf(buffer, ROW_KEY_KEY_FORMAT, i); str = getAndCopySting_(allocer, section, buffer, len); ci->row_key_.assign_ptr(const_cast<char*>(str), len); // column name sprintf(buffer, COLUMN_NAME_KEY_FORMAT, i); str = getAndCopySting_(allocer, section, buffer, len); ci->column_name_.assign_ptr(const_cast<char*>(str), len); // column id sprintf(buffer, COLUMN_ID_KEY_FORMAT, i); ci->column_id_ = TBSYS_CONFIG.getInt(section, buffer); //*op = *ci; //op->value_.set_ext(op_type); //mutator.add_cell(*op); //table_ids.push_back(op->table_id_); //column_ids.push_back(op->column_id_); //if (ObActionFlag::OP_DEL_ROW == op_type) //{ // result.add_cell(*op); // continue; //} // value type sprintf(buffer, VALUE_TYPE_KEY_FORMAT, i); str = TBSYS_CONFIG.getString(section, buffer); int value_type = 0; obj_type_map.get(str, value_type); // value sprintf(buffer, VALUE_KEY_FORMAT, i); if (ObVarcharType == value_type) { str = getAndCopySting_(allocer, section, buffer, len); ObString varchar; varchar.assign_ptr(const_cast<char*>(str), len); //char *tmp = (char*)malloc(1024 * 1024 + 512 * 1024); //memset(tmp, 'a', 1024 * 1024 + 512 * 1024); //varchar.assign_ptr(tmp, 1024 * 1024 + 512 * 1024); ci->value_.set_varchar(varchar); } else if (ObIntType == value_type) { int64_t value = TBSYS_CONFIG.getInt(section, buffer); ci->value_.set_int(value, is_add); } else if (ObFloatType == value_type) { str = TBSYS_CONFIG.getString(section, buffer); float value = atof(str); ci->value_.set_float(value, is_add); } else if (ObDoubleType == value_type) { str = TBSYS_CONFIG.getString(section, buffer); double value = atof(str); ci->value_.set_double(value, is_add); } else if (ObDateTimeType == value_type) { int64_t value = TBSYS_CONFIG.getInt(section, buffer); ci->value_.set_datetime(value); } else if(ObPreciseDateTimeType == value_type) { int64_t value = TBSYS_CONFIG.getInt(section, buffer); ci->value_.set_precise_datetime(value); } else if (ObSeqType == value_type) { ci->value_.set_seq(); } else if (ObCreateTimeType == value_type) { int64_t value = TBSYS_CONFIG.getInt(section, buffer); ci->value_.set_createtime(value); } else if(ObModifyTimeType == value_type) { int64_t value = TBSYS_CONFIG.getInt(section, buffer); ci->value_.set_modifytime(value); } else if (ObNullType == value_type) { ci->value_.set_null(); } else { fprintf(stderr, "value_type=%d is not supported\n", value_type); } switch (op_type) { case ObActionFlag::OP_UPDATE: mutator.update(ci->table_name_, ci->row_key_, ci->column_name_, ci->value_); break; case ObActionFlag::OP_INSERT: mutator.insert(ci->table_name_, ci->row_key_, ci->column_name_, ci->value_); break; case ObActionFlag::OP_DEL_ROW: mutator.del_row(ci->table_name_, ci->row_key_); break; case ObActionFlag::OP_USE_DB_SEM: mutator.use_db_sem(); break; case ObActionFlag::OP_USE_OB_SEM: mutator.use_ob_sem(); break; default: fprintf(stderr, "op_type not support %d\n", op_type); break; } table_ids.push_back(ci->table_id_); column_ids.push_back(ci->column_id_); ObMutatorCellInfo mutator_ci; mutator_ci.cell_info = *ci; result.add_cell(mutator_ci); } for (int32_t i = 0; i < cell_infos_num; i++) { result.next_cell(); ObMutatorCellInfo *mutator_ci = NULL; ObCellInfo *ci = NULL; result.get_cell(&mutator_ci); ci = &(mutator_ci->cell_info); // table id sprintf(buffer, TABLE_ID_KEY_FORMAT, i); ci->table_id_ = TBSYS_CONFIG.getInt(section, buffer); // column id sprintf(buffer, COLUMN_ID_KEY_FORMAT, i); ci->column_id_ = TBSYS_CONFIG.getInt(section, buffer); } result.reset_iter(); for (uint64_t i = 0; i < table_ids.size(); i++) { mutator.next_cell(); ObMutatorCellInfo *mutator_ci = NULL; ObCellInfo *ci = NULL; mutator.get_cell(&mutator_ci); ci = &(mutator_ci->cell_info); // table id ci->table_id_ = table_ids[i]; // column id ci->column_id_ = column_ids[i]; } mutator.reset_iter(); }
TEST(TestObHashMap, get) { ObHashMap<HashKey, HashValue> hm; uint64_t key[4] = {1, 2, 1, 1 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 300, 301}; int fail = -1; HashValue value_tmp; // 没有create EXPECT_EQ(fail, hm.get(key[0], value_tmp)); hm.create(cal_next_prime(gHashItemNum)); // 查询已存在的数据 hm.set(key[0], value[0], 0); hm.set(key[1], value[1], 0); hm.set(key[3], value[3], 0); EXPECT_EQ(HASH_EXIST, hm.get(key[0], value_tmp)); EXPECT_EQ(value[0], value_tmp); EXPECT_EQ(HASH_EXIST, hm.get(key[1], value_tmp)); EXPECT_EQ(value[1], value_tmp); EXPECT_EQ(HASH_EXIST, hm.get(key[3], value_tmp)); EXPECT_EQ(value[3], value_tmp); // 查询更新后的数据 hm.set(key[0], value[2], 1); EXPECT_EQ(HASH_EXIST, hm.get(key[0], value_tmp)); EXPECT_EQ(value[2], value_tmp); // 查询不存在的数据 EXPECT_EQ(HASH_NOT_EXIST, hm.get(-1, value_tmp)); }
TEST(TestObHashMap, serialization) { ObHashMap<HashKey, HashValue> hm; SimpleArchive arw, arr; arw.init("./hash.data", SimpleArchive::FILE_OPEN_WFLAG); arr.init("./hash.data", SimpleArchive::FILE_OPEN_RFLAG); SimpleArchive arw_nil, arr_nil; // 没有create EXPECT_EQ(-1, hm.serialization(arw)); hm.create(cal_next_prime(gHashItemNum)); // 没有元素 EXPECT_EQ(0, hm.serialization(arw)); EXPECT_EQ(0, hm.deserialization(arr)); uint64_t key[4] = {1, 2, 1, 1 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 300, 301}; for (uint32_t i = 0; i < 4; i++) { hm.set(key[i], value[i], 0); } EXPECT_EQ(-1, hm.serialization(arw_nil)); arw.destroy(); arr.destroy(); arw.init("./hash.data", SimpleArchive::FILE_OPEN_WFLAG); arr.init("./hash.data", SimpleArchive::FILE_OPEN_RFLAG); EXPECT_EQ(0, hm.serialization(arw)); hm.destroy(); EXPECT_EQ(0, hm.deserialization(arr)); EXPECT_EQ(-1, hm.deserialization(arr)); EXPECT_EQ(3, hm.size()); arr_nil.init("./hash.data.nil", SimpleArchive::FILE_OPEN_RFLAG); EXPECT_EQ(-1, hm.deserialization(arr_nil)); remove("./hash.data"); remove("./hash.data.nil"); }
TEST(TestObHashMap, iterator) { ObHashMap<HashKey, HashValue> hm; const ObHashMap<HashKey, HashValue>& chm = hm; ObHashMap<HashKey, HashValue>::iterator iter; ObHashMap<HashKey, HashValue>::const_iterator citer; // 没有create EXPECT_EQ(true, hm.begin() == hm.end()); iter = hm.begin(); citer = chm.begin(); EXPECT_EQ(true, iter == hm.end()); EXPECT_EQ(true, citer == chm.end()); EXPECT_EQ(true, (++iter) == hm.end()); EXPECT_EQ(true, (++citer) == chm.end()); // 没有数据 hm.create(cal_next_prime(gHashItemNum)); EXPECT_EQ(true, hm.begin() == hm.end()); iter = hm.begin(); citer = hm.begin(); EXPECT_EQ(true, iter == hm.end()); EXPECT_EQ(true, citer == hm.end()); EXPECT_EQ(true, (++iter) == hm.end()); EXPECT_EQ(true, (++citer) == hm.end()); uint64_t key[4] = {1, 2, 5, 5 + cal_next_prime(gHashItemNum)}; uint64_t value[4] = {100, 200, 500, 501}; for (int32_t i = 3; i >= 0; i--) { hm.set(key[i], value[i], 0); } iter = hm.begin(); citer = chm.begin(); for (uint32_t i = 0; iter != hm.end(); iter++, i++) { EXPECT_EQ(value[i], iter->second); } for (uint32_t i = 0; citer != chm.end(); citer++, i++) { EXPECT_EQ(value[i], citer->second); } }