diff --git a/db/db_impl.cc b/db/db_impl.cc index 4c0f2e5..e3dc639 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1202,7 +1202,7 @@ Status DBImpl::Get_Fields(const ReadOptions& options, const Slice& key, slot_page_->get_slot(slot_num, &sc); vlog_set_->get_value(sc.vlog_num, sc.value_offset, &vlog_value); - std::cout << "value from value_log: " << key.ToString() << vlog_value << std::endl; + // std::cout << "value from value_log: " << key.ToString() << std::endl; *fields = DeserializeValue(vlog_value); return Status::OK(); // Todo(end) @@ -1257,9 +1257,13 @@ Status DBImpl::Put_Fields(const WriteOptions& opt, const Slice& key, const FieldArray& fields) { // TODO(begin): allocate slot_num in slotpage and put value in vlog // 将字段数组序列化 - std::string serialized_value = SerializeValue(fields); - std::cout << "Put_Fields: " << key.ToString() << " " << serialized_value << std::endl; size_t slot_num = slot_page_->alloc_slot(); + std::string slot_num_str((char *)&slot_num, sizeof(size_t)); + size_t slot_num_str_num; + std::memcpy(&slot_num_str_num, slot_num_str.c_str(), sizeof(size_t)); + std::cout << "slot_num_str_num: " << slot_num_str_num << std::endl; + std::string serialized_value = SerializeValue(fields, slot_num_str); + std::cout << "Put_Fields: " << key.ToString() << " " << serialized_value << std::endl; struct slot_content sc; vlog_set_->put_value(&sc.vlog_num, &sc.value_offset, serialized_value); slot_page_->set_slot(slot_num, &sc); @@ -1268,7 +1272,8 @@ Status DBImpl::Put_Fields(const WriteOptions& opt, const Slice& key, memcpy(data, &slot_num, sizeof(size_t)); Slice slot_val(data, sizeof(data)); - return DB::Put(opt, key, slot_val); + // return DB::Put(opt, key, slot_val); + return DB::Put(opt, key, serialized_value); // TODO(end) } @@ -1584,45 +1589,48 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { FieldArray DBImpl::DeserializeValue(const std::string& value_str) { // 存放解析后的字段数组 FieldArray fields; - // 将输入字符串转换为输入流 iss, 方便读取 + // 将 value 字符串转换为输入流 iss std::istringstream iss(value_str); std::string content; // 临时存放读取的数据 - char buffer[100]; - // 读取长度(定长,16比特) - iss.read(buffer, 16); - buffer[16] = '\0'; - size_t total_length = std::stoi(buffer); - // std::cout << "读取到的总长度为: " << total_length << std::endl; - std::string value_content(value_str.begin() + 16, value_str.begin() + 16 + total_length); - // std::cout << value_content << std::endl; + char buffer_1[sizeof(uint16_t)]; + // 读取 value 的长度 + iss.read(buffer_1, sizeof(uint16_t)); + size_t total_length; + std::memcpy(&total_length, buffer_1, sizeof(uint16_t)); + std::cout << "total_length: " << total_length << std::endl; + char buffer_2[sizeof(size_t)]; + // 读取 slot_num + iss.read(buffer_2, sizeof(size_t)); + size_t slot_num_str; + std::memcpy(&slot_num_str, buffer_2, sizeof(size_t)); + std::cout << "slot_num_str: " << slot_num_str << std::endl; + size_t sum_size = sizeof(size_t) + sizeof(uint16_t); + // 存放 value 的字符串 + std::string value_content(value_str.begin() + sum_size, value_str.begin() + sum_size + total_length); + std::cout << value_content << std::endl; std::istringstream iss_content(value_content); - iss_content.read(buffer, sizeof(size_t)); - buffer[sizeof(size_t)] = '\0'; - std::string slot_num = buffer; // 读取属性个数 - iss_content.read(buffer, 16); - // 在第17个比特位处添加终结符,确保字符串以终结符结尾 - buffer[16] = '\0'; - // 将 buffer 中的内容转化为整数并赋值给 field_count - int field_count = std::stoi(buffer); - // std::cout << "读取到的字段个数为: " << field_count << std::endl; + iss_content.read(buffer_1, sizeof(uint16_t)); + size_t field_count; + std::memcpy(&field_count, buffer_1, sizeof(uint16_t)); + std::cout << "field_count: " << field_count << std::endl; for (int i = 0; i < field_count; ++i) { Field field; - // 读取属性名长度(定长,16比特) - iss_content.read(buffer, 16); - buffer[16] = '\0'; - int name_length = std::stoi(buffer); - // std::cout << "读取到的属性名长度为: " << name_length << std::endl; - // 读取属性名(变长) + // 读取属性名长度 + iss_content.read(buffer_1, sizeof(uint16_t)); + size_t name_length; + std::memcpy(&name_length, buffer_1, sizeof(uint16_t)); + // std::cout << "name_length: " << name_length << std::endl; + // 读取属性名 field.name.resize(name_length); iss_content.read(&field.name[0], name_length); // std::cout << "读取到的属性名为: " << field.name << std::endl; // 读取属性值长度(定长,16比特) - iss_content.read(buffer, 16); - buffer[16] = '\0'; - int value_length = std::stoi(buffer); + iss_content.read(buffer_1, 16); + buffer_1[16] = '\0'; + int value_length = std::stoi(buffer_1); // std::cout << "读取到的属性值长度为: " << value_length << std::endl; // 读取属性值(变长) field.value.resize(value_length); @@ -1635,28 +1643,41 @@ FieldArray DBImpl::DeserializeValue(const std::string& value_str) { // Todo(end) // Todo(begin) // 序列化函数,将字段数组序列化为字符串 -std::string DBImpl::SerializeValue(const FieldArray& fields) { - // 创建并初始化一个字符串流 oss,用于逐步构建最终的序列化字符串 +std::string DBImpl::SerializeValue(const FieldArray& fields, std::string slot_num_str) { + // 创建临时字符串流 oss_temp,用于存放 value 的内容 std::ostringstream oss_temp; - std::string slot_num = "slot_num"; - oss_temp << std::setw(sizeof(size_t)) << std::setfill('0') << slot_num; - // 写入属性个数(定长,16比特),使用std::setw(16)设置宽度,使用std::setfull(0)设置填充字符,将字段数组的大小写入oss中 - oss_temp << std::setw(16) << std::setfill('0') << fields.size(); + // 写入属性个数 + size_t fields_num = fields.size(); + std::string field_num_str((char*)& fields_num, sizeof(uint16_t)); + oss_temp << field_num_str; for (const auto& field : fields) { - // 写入属性名长度(定长,16比特) - oss_temp << std::setw(16) << std::setfill('0') << field.name.size(); - // 写入属性名(变长) + // 写入属性名长度 + size_t name_length = field.name.size(); + std::string name_length_str((char*)& name_length, sizeof(uint16_t)); + oss_temp << name_length_str; + // 写入属性名 oss_temp << field.name; - // 写入属性值长度(定长,16比特) - oss_temp << std::setw(16) << std::setfill('0') << field.value.size(); - // 写入属性值(变长) + // 写入属性值长度 + size_t value_length = field.value.size(); + std::string value_length_str((char*)& value_length, sizeof(uint16_t)); + oss_temp << value_length_str; + // 写入属性值 oss_temp << field.value; } std::string temp_str = oss_temp.str(); size_t value_length = temp_str.size(); - + // std::cout << "value_length: " << value_length << std::endl; + std::string value_length_str((char*)& value_length, sizeof(uint16_t)); + size_t value_length_str_var; + std::memcpy(&value_length_str_var, value_length_str.c_str(), sizeof(uint16_t)); + // std::cout << "value_length_str_var: " << value_length_str_var << std::endl; + // 创建最终输出流 oss std::ostringstream oss; - oss << std::setw(16) << std::setfill('0') << value_length; + // 写入 value 的长度 + oss << value_length_str; + // 写入 slot_num + oss << slot_num_str; + // 写入 value oss << temp_str; return oss.str(); } diff --git a/db/db_impl.h b/db/db_impl.h index 1f77d07..1fbb2cb 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -91,7 +91,7 @@ class DBImpl : public DB { // TODO(begin) SlotPage *slot_page_; VlogSet *vlog_set_; - static std::string SerializeValue(const FieldArray& fields); + static std::string SerializeValue(const FieldArray& fields, std::string slot_num_str); static FieldArray DeserializeValue(const std::string& value_str); // TODO(end) // Information for a manual compaction diff --git a/test/db_test3.cc b/test/db_test3.cc index b5f9563..bf214bd 100644 --- a/test/db_test3.cc +++ b/test/db_test3.cc @@ -175,12 +175,12 @@ TEST(TestSchema, Basic) { std::cerr << "open db failed" << std::endl; abort(); } - std::string key = "key"; + // std::string key = "key"; std::string key0 = "k_0"; std::string key1 = "k_1"; std::string key2 = "k_2"; std::string key3 = "k_3"; - std::string value = "value"; + // std::string value = "value"; FieldArray fields0 = {{"name", "wxf"}}; FieldArray fields1 = { {"name", "Customer1"}, @@ -198,15 +198,15 @@ TEST(TestSchema, Basic) { {"address", "ecnu"}, {"phone", "11111"} }; - db->Put(writeOptions, key, value); - std::cout << "put_value: " << value << std::endl; + // db->Put(writeOptions, key, value); + // std::cout << "put_value: " << value << std::endl; db->Put_Fields(leveldb::WriteOptions(), key0, fields0); db->Put_Fields(leveldb::WriteOptions(), key1, fields1); db->Put_Fields(leveldb::WriteOptions(), key2, fields2); db->Put_Fields(leveldb::WriteOptions(), key3, fields3); - std::string value_ret; - db->Get(readOptions, key, &value_ret); - std::cout << "get_value: " << value_ret << std::endl; + // std::string value_ret; + // db->Get(readOptions, key, &value_ret); + // std::cout << "get_value: " << value_ret << std::endl; // 读取并反序列化 FieldArray fields_ret_0; FieldArray fields_ret_1; @@ -217,8 +217,8 @@ TEST(TestSchema, Basic) { // 检查反序列化结果 ASSERT_EQ(fields_ret_0.size(), fields0.size()); for (size_t i = 0; i < fields_ret_0.size(); ++i) { - ASSERT_EQ(fields_ret_0[i].name, fields1[i].name); - ASSERT_EQ(fields_ret_0[i].value, fields1[i].value); + ASSERT_EQ(fields_ret_0[i].name, fields0[i].name); + ASSERT_EQ(fields_ret_0[i].value, fields0[i].value); } ASSERT_EQ(fields_ret_1.size(), fields1.size());