3 Commits

13 changed files with 775 additions and 139 deletions
Split View
  1. +3
    -1
      CMakeLists.txt
  2. +3
    -0
      db/db_impl.cc
  3. +72
    -50
      db/slotpage.h
  4. +1
    -1
      db/vlog.h
  5. +187
    -0
      db/vlog_cache.cpp
  6. +129
    -0
      db/vlog_cache.h
  7. +3
    -3
      db/vlog_gc.cpp
  8. +232
    -72
      db/vlog_set.cpp
  9. +20
    -2
      db/vlog_set.h
  10. +83
    -2
      test/db_test1.cc
  11. +3
    -3
      test/db_test4.cc
  12. +37
    -3
      test/db_test5.cc
  13. +2
    -2
      test/db_test6.cc

+ 3
- 1
CMakeLists.txt View File

@ -126,7 +126,9 @@ add_library(leveldb ""
db/vlog_gc.cpp
db/vlog_gc.h
db/gc_executor.cpp
db/gc_executor.h)
db/gc_executor.h
db/vlog_cache.cpp
db/vlog_cache.h)
target_sources(leveldb
PRIVATE
"${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"

+ 3
- 0
db/db_impl.cc View File

@ -1224,6 +1224,9 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key,
struct slot_content sc;
std::string vlog_value;
slot_page_->get_slot(slot_num, &sc);
if (sc.value_offset == 0) {
std::cout << sc.value_offset << std::endl;
}
vlog_set_->get_value(sc, &vlog_value);
*value = vlog_value;

+ 72
- 50
db/slotpage.h View File

@ -16,6 +16,8 @@
#include <iostream>
#include <unordered_map>
#include "shared_lock.h"
// bitmap: || bitmap_size(size_t) | first_empty_slot(size_t) || bits... |
#define BITMAP_SIZE 8192
@ -36,6 +38,7 @@ struct slot_content {
}
};
// test passed
class SlotCache {
// slot number -> slot content
@ -44,41 +47,37 @@ class SlotCache {
#define SLOT_PER_BLOCK (BLOCK_SIZE/sizeof(slot_content))
#define SLOT_OFFSET_IN_BLOCK(slot_num) ((slot_num)%SLOT_PER_BLOCK)
public:
SlotCache(const std::string &slotpage_fname) {
this->slotpage_fname = slotpage_fname;
// this->slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
this->slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
if (!this->slotpage_handler.is_open()) {
SlotCache(const std::string &sf) {
assert(!(BLOCK_SIZE % sizeof(slot_content)));
slotpage_fname = sf;
auto slotpage_handler = new std::fstream(slotpage_fname, std::ios::in | std::ios::out);
if (!slotpage_handler->is_open()) {
//
this->slotpage_handler = std::fstream(slotpage_fname, std::ios::out);
this->slotpage_handler.close();
delete slotpage_handler;
slotpage_handler = new std::fstream(slotpage_fname, std::ios::out);
slotpage_handler->close();
delete slotpage_handler;
//
this->slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
slotpage_handler = new std::fstream(slotpage_fname, std::ios::in | std::ios::out);
}
if (!this->slotpage_handler.is_open()) {
if (!slotpage_handler->is_open()) {
std::cerr << "Failed to open or create the file: " << slotpage_fname << std::endl;
std::exit(EXIT_FAILURE);
}
for (auto i = 0; i < BLOCK_NUM; i++) {
block_cache[i] = static_cast<struct slot_content*>(malloc(BLOCK_SIZE));
block_cache[i] = static_cast<char*>(malloc(BLOCK_SIZE));
access_time[i] = 0;
info[i] = block_info();
}
}
~SlotCache() {
for (auto i = 0; i < BLOCK_NUM; i++) {
latches_[i].lock();
if (info[i].is_dirty) {
write_back_block(info[i].block_num);
}
latches_[i].unlock();
}
this->slotpage_handler.close();
flush_all_blk();
}
/// methods only for test
void write_for_test(char *sc, size_t bytes) {
auto slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
slotpage_handler.seekp(0);
slotpage_handler.write(reinterpret_cast<const char*>(sc), bytes);
slotpage_handler.flush();
@ -86,11 +85,10 @@ public:
void flush_all_blk() {
for (auto blkinfo : info) {
if (blkinfo.is_dirty) {
if (blkinfo.used && blkinfo.is_dirty) {
write_back_block(blkinfo.block_num);
}
}
this->slotpage_handler.flush();
}
void get_slot(size_t slot_num, struct slot_content *sc) {
@ -134,7 +132,7 @@ private:
size_t block_num;
bool is_dirty;
block_info() { used = false; is_dirty = false; }
block_info(size_t block_num, bool is_dirty=false, bool used = false) {
block_info(size_t block_num, bool is_dirty=false, bool used=false) {
this->block_num = block_num;
this->is_dirty = is_dirty;
this->used = used;
@ -145,7 +143,11 @@ private:
inline static size_t slotnum_hash2_blocknum(size_t slot_num) {
return slot_num * sizeof(slot_content) / BLOCK_SIZE;
}
inline size_t offset_in_block(size_t slot_num_offset) {
return slot_num_offset * sizeof(slot_content);
}
void write_back_block(size_t blockcache_num) {
auto slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
auto write_pos = info[blockcache_num].block_num * BLOCK_SIZE;
slotpage_handler.seekp(write_pos);
slotpage_handler.write(
@ -153,28 +155,33 @@ private:
slotpage_handler.flush();
}
void read_in_block(size_t blockcache_num, size_t block_num) {
auto slotpage_handler = std::fstream(slotpage_fname, std::ios::in | std::ios::out);
slotpage_handler.seekp(block_num*BLOCK_SIZE);
slotpage_handler.read(reinterpret_cast<char*>(block_cache[blockcache_num]), BLOCK_SIZE);
}
inline void read_slot(struct slot_content *sc, size_t blockcache_num, size_t slot_num_offset) {
auto src = &block_cache[blockcache_num][slot_num_offset];
auto off = offset_in_block(slot_num_offset);
auto src = &block_cache[blockcache_num][off];
memcpy(sc, src, sizeof(slot_content));
}
inline void set_slot(struct slot_content *sc, size_t blockcache_num, size_t slot_num_offset) {
auto src = &block_cache[blockcache_num][slot_num_offset];
auto off = offset_in_block(slot_num_offset);
auto src = &block_cache[blockcache_num][off];
memcpy(src, sc, sizeof(slot_content));
}
private:
std::string slotpage_fname;
std::fstream slotpage_handler;
std::mutex latches_[BLOCK_NUM];
struct slot_content *block_cache[BLOCK_NUM];
char *block_cache[BLOCK_NUM];
size_t access_time[BLOCK_NUM];
struct block_info info[BLOCK_NUM];
};
/// test passed
// bitmap: || bitmap_size(size_t) | first_empty_slot(size_t) || bits... |
class BitMap {
// in memory bitmap
public:
@ -187,18 +194,28 @@ public:
}
BitMap(const std::string &dbname) {
name = dbname + "_bitmap";
name = "./" + dbname + "/" + dbname + "_bitmap";
config_file_name = name + "_config_file";
auto bitmap_handler = std::fstream(name, std::ios::in | std::ios::out);
auto config_handler = std::fstream(config_file_name, std::ios::in | std::ios::out);
if (!config_handler.is_open()) {
config_handler = std::fstream(config_file_name, std::ios::out);
config_handler.close();
config_handler = std::fstream(config_file_name, std::ios::in | std::ios::out);
}
if (!bitmap_handler.is_open()) {
//
bitmap_handler = std::fstream(name, std::ios::out);
bitmap_handler.close();
//
bitmap_handler = std::fstream(name, std::ios::in | std::ios::out);
bitmap_handler.seekp(0);
size_t tmp[2] = {2*sizeof(size_t), 0};
bitmap_handler.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
bitmap_handler.close();
size_t tmp[2] = {BLOCK_SIZE, 0};
config_handler.seekp(0);
config_handler.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
config_handler.flush();
config_handler.close();
// init bitmap
char *bitmap = static_cast<char*>(malloc(BITMAP_SIZE*sizeof(char)));
@ -208,20 +225,24 @@ public:
first_empty_slot = 0;
} else {
// read in bitmap content
assert(config_handler.is_open());
size_t bitmap_header[2];
bitmap_handler.seekp(0);
bitmap_handler.read(reinterpret_cast<char*>(bitmap_header), 2*sizeof(size_t));
config_handler.seekp(0);
config_handler.read(reinterpret_cast<char*>(bitmap_header), 2*sizeof(size_t));
this->first_empty_slot = bitmap_header[1];
this->size = bitmap_header[0];
const size_t page_num = (size - 2*sizeof(size_t)) / BITMAP_SIZE;
const size_t page_num = size / BITMAP_SIZE;
assert(size % BITMAP_SIZE == 0);
for (auto i = 0; i < page_num; i++) {
char *bitmap = static_cast<char*>(malloc(BITMAP_SIZE*sizeof(char)));
bitmap_handler.seekp(2*sizeof(size_t) + i*BITMAP_SIZE);
bitmap_handler.seekp( i*BITMAP_SIZE);
bitmap_handler.read(bitmap, BITMAP_SIZE);
bitmaps_.push_back(bitmap);
}
bitmap_handler.close();
// init bitmap
if (page_num == 0) {
char *bitmap = static_cast<char*>(malloc(BITMAP_SIZE*sizeof(char)));
@ -235,18 +256,24 @@ public:
~BitMap() {
auto bitmap_handler = std::fstream(name, std::ios::in | std::ios::out);
auto config_handler = std::fstream(config_file_name, std::ios::in | std::ios::out);
assert(bitmap_handler.is_open());
assert(config_handler.is_open());
size_t tmp[2] = {size, first_empty_slot};
bitmap_handler.seekp(0);
bitmap_handler.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
size_t off = 2 * sizeof(size_t);
config_handler.seekp(0);
config_handler.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
config_handler.flush();
size_t off = 0;
for (auto bitmap : bitmaps_) {
bitmap_handler.seekp(off);
bitmap_handler.write(bitmap, BITMAP_SIZE);
delete bitmap;
off += BITMAP_SIZE;
}
assert(off == size);
bitmap_handler.flush();
bitmap_handler.close();
config_handler.close();
}
/** methods for test **/
@ -351,6 +378,7 @@ private:
private:
std::string name;
std::string config_file_name;
std::vector<char *> bitmaps_;
size_t size;
size_t first_empty_slot;
@ -371,6 +399,11 @@ public:
assert(slotcache);
}
~SlotPage() {
delete bitmap;
delete slotcache;
}
public:
void get_slot(size_t slot_num, struct slot_content *sc) {
slotcache->get_slot(slot_num, sc);
@ -397,16 +430,5 @@ private:
};
//#ifndef ENABLE_SLOT_CACHES
//#define ENABLE_SLOT_CACHES
//std::unordered_map<std::string, SlotCache *> slotcaches_;
//#endif
//
//SlotCache * get_slotcache(const std::string &dbname) {
// if (slotcaches_.find(dbname) == slotcaches_.end()) {
// slotcaches_[dbname] = new SlotCache(dbname);
// }
// return slotcaches_[dbname];
//}
#endif // LEVELDB_SLOTPAGE_H

+ 1
- 1
db/vlog.h View File

@ -28,7 +28,7 @@
#define vlog_num_size sizeof(size_t)
#define KiB 1024
#define MiB 1024*KiB
#define VLOG_SIZE 1*MiB // origin: 32*MiB
#define VLOG_SIZE 64*MiB // origin: 32*MiB
#define GC_THREDHOLD 0.5
#define VALUE_BUFF_SIZE 0x7fff // value size cannot exceed this number

+ 187
- 0
db/vlog_cache.cpp View File

@ -0,0 +1,187 @@
//
// Created by 马也驰 on 2025/1/4.
//
#include "vlog_cache.h"
#include <fstream>
void VlogCache::read_data(std::string &vlog_name, std::string& value, size_t offset, size_t len) {
std::string value_part1;
std::string value_part2;
size_t offset1, len1, offset2, len2;
offset1 = offset;
if (VALUE_ACROSS_BLOCK(offset, len)) {
offset2 = ((offset+len) / BLOCK_SIZE) * BLOCK_SIZE;
// offset2 = ((offset+len) & ~(size_t)BLOCK_SIZE);
len1 = offset2 - offset1;
len2 = offset1 + len - offset2;
} else {
len1 = len;
offset2 = offset1 + len;
len2 = 0;
}
read_data_inblock(vlog_name, value_part1, offset1, len1);
read_data_inblock(vlog_name, value_part2, offset2, len2);
value = value_part1 + value_part2;
}
void VlogCache::write_data(std::string &vlog_name, std::string& value, size_t offset, size_t len) {
std::string value_part1;
std::string value_part2;
size_t offset1, len1, offset2, len2;
offset1 = offset;
if (VALUE_ACROSS_BLOCK(offset, len)) {
// FIXME: compute correct offset2
offset2 = ((offset+len) / BLOCK_SIZE) * BLOCK_SIZE;
// offset2 = ((offset+len) & ~(size_t)BLOCK_SIZE);
len1 = offset2 - offset1;
len2 = offset1 + len - offset2;
} else {
len1 = len;
offset2 = 0;
len2 = 0;
}
const char *data = value.data();
value_part1 = std::string(data, len1);
value_part2 = std::string(&data[len1], len2);
write_data_inblock(vlog_name, value_part1, offset1, len1);
write_data_inblock(vlog_name, value_part2, offset2, len2);
}
uint16_t VlogCache::delete_data(std::string &vlog_name, size_t offset) {
uint16_t value_size;
std::string value_size_str;
read_data(vlog_name, value_size_str, offset, sizeof(uint16_t));
memcpy(&value_size, value_size_str.data(), sizeof(uint16_t));
if (value_size & DATA_DELE_MASK) {
return value_size & DATA_SIZE_MASK;
}
assert(!(value_size & DATA_DELE_MASK));
uint16_t masked_value_size = value_size | (uint16_t)DATA_DELE_MASK;
value_size_str = std::string((char *)&masked_value_size, sizeof(uint16_t));
write_data(vlog_name, value_size_str, offset, sizeof(uint16_t));
return value_size;
}
void VlogCache::read_data_inblock(std::string &vlog_name, std::string& value, size_t offset, size_t len) {
if (len == 0) return ;
auto block_num = offset_2_blocknum(offset);
auto block_offset = offset_2_inblock_offset(offset);
// auto vlog_handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
auto blk_frame = block_frames[block_num];
auto frame_info_ptr = &blk_frame->frame_info_;
blk_frame->mtx.lock();
frame_info_ptr->info_latch_.lock();
if (!frame_info_ptr->cache_hit(vlog_name, block_num)) {
// cache miss
// swap old page
if (frame_info_ptr->used && frame_info_ptr->is_dirty) {
write_back_block(block_num);
}
// read new page
read_in_block(block_num, vlog_name, offset/BLOCK_SIZE);
// update frame info
frame_info_ptr->used = true;
frame_info_ptr->vlog_name = vlog_name;
frame_info_ptr->vlog_block_num = offset / BLOCK_SIZE;
frame_info_ptr->is_dirty = false;
}
value = std::string(&blk_frame->block_buff[block_offset], len);
frame_info_ptr->info_latch_.unlock();
blk_frame->mtx.unlock();
}
void VlogCache::write_data_inblock(std::string &vlog_name, std::string& value, size_t offset, size_t len) {
if (len == 0) return ;
auto block_num = offset_2_blocknum(offset);
auto block_offset = offset_2_inblock_offset(offset);
// auto vlog_handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
auto blk_frame = block_frames[block_num];
auto frame_info_ptr = &blk_frame->frame_info_;
blk_frame->mtx.lock();
frame_info_ptr->info_latch_.lock();
if (!frame_info_ptr->cache_hit(vlog_name, block_num)) {
// cache miss
// swap old page
if (frame_info_ptr->used && frame_info_ptr->is_dirty) {
write_back_block(block_num);
}
// read new page
read_in_block(block_num, vlog_name, offset/BLOCK_SIZE);
// update frame info
frame_info_ptr->used = true;
frame_info_ptr->vlog_name = vlog_name;
frame_info_ptr->vlog_block_num = offset / BLOCK_SIZE;
}
memcpy(&blk_frame->block_buff[block_offset], value.c_str(), len);
frame_info_ptr->is_dirty = true;
frame_info_ptr->info_latch_.unlock();
blk_frame->mtx.unlock();
}
void VlogCache::flush_all_blocks() {
for (auto i = 0; i < BLOCK_NUMS; i++) {
auto blk_frame = block_frames[i];
auto frame_info_ptr = &blk_frame->frame_info_;
blk_frame->mtx.lock();
frame_info_ptr->info_latch_.lock();
if (frame_info_ptr->used && frame_info_ptr->is_dirty) {
write_back_block(i);
}
blk_frame->mtx.unlock();
frame_info_ptr->info_latch_.unlock();
}
}
void VlogCache::write_back_block(size_t block_num) {
auto frame_info_ptr = &block_frames[block_num]->frame_info_;
auto vlog_handler = std::fstream(frame_info_ptr->vlog_name, std::ios::in | std::ios::out);
if (!vlog_handler.is_open()) return ;
vlog_handler.seekp(frame_info_ptr->vlog_block_num*BLOCK_SIZE);
vlog_handler.write(block_frames[block_num]->block_buff, BLOCK_SIZE);
vlog_handler.flush();
vlog_handler.close();
}
void VlogCache::read_in_block(size_t block_num, std::string& vlog_name,
size_t vlog_block_num) {
auto vlog_handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
if (!vlog_handler.is_open()) return ;
vlog_handler.seekp(vlog_block_num*BLOCK_SIZE);
vlog_handler.read(block_frames[block_num]->block_buff, BLOCK_SIZE);
vlog_handler.close();
}

+ 129
- 0
db/vlog_cache.h View File

@ -0,0 +1,129 @@
//
// Created by on 2025/1/4.
//
#ifndef LEVELDB_VLOG_CACHE_H
#define LEVELDB_VLOG_CACHE_H
#include <mutex>
#include <cassert>
#define BLOCK_SIZE 4096
struct frame_info {
std::mutex info_latch_;
bool used;
std::string vlog_name;
size_t vlog_block_num;
bool is_dirty;
inline void set_used() {
info_latch_.lock();
assert(used == false);
used = true;
info_latch_.unlock();
}
inline void set_unused() {
info_latch_.lock();
assert(used == true);
used = false;
info_latch_.unlock();
}
inline void set_dirty() {
info_latch_.lock();
assert(is_dirty == false);
is_dirty = true;
info_latch_.unlock();
}
inline void set_nondirty() {
info_latch_.lock();
assert(is_dirty == true);
is_dirty = false;
info_latch_.unlock();
}
inline void set_vlog_block_num(size_t vb) {
info_latch_.lock();
vlog_block_num = vb;
info_latch_.unlock();
}
inline void set_vlog_name(std::string &vn) {
info_latch_.lock();
vlog_name = vn;
info_latch_.unlock();
}
inline bool cache_hit(std::string &vn, size_t vbn) {
return used && (vlog_name == vn) && (vlog_block_num == vbn);
}
};
struct block_frame {
// ,, mutex上锁线
// mutex上锁线
std::mutex mtx;
frame_info frame_info_;
char *block_buff;
block_frame() {
frame_info_.used = false;
frame_info_.is_dirty = false;
block_buff = static_cast<char*>(malloc(BLOCK_SIZE));
}
void free_block_buff() {
free(block_buff);
}
};
class VlogCache {
#define BLOCK_NUMS 1024
#define VALUE_ACROSS_BLOCK(offset, len) (((offset)/BLOCK_SIZE) != (((offset)+(len)-1)/BLOCK_SIZE))
#define DATA_SIZE_MASK 0x7fff
#define DATA_DELE_MASK 0x8000
public:
VlogCache() {
for (auto i = 0; i < BLOCK_NUMS; i++) {
block_frames[i] = new block_frame();
}
}
~VlogCache() {
flush_all_blocks();
for (auto i = 0; i < BLOCK_NUMS; i++) {
block_frames[i]->free_block_buff();
}
}
public:
void read_data(std::string &vlog_name, std::string& value, size_t offset, size_t len);
void write_data(std::string &vlog_name, std::string& value, size_t offset, size_t len);
uint16_t delete_data(std::string &vlog_name, size_t offset);
private:
void read_data_inblock(std::string &vlog_name, std::string& value, size_t offset, size_t len);
void write_data_inblock(std::string &vlog_name, std::string& value, size_t offset, size_t len);
void write_back_block(size_t block_num);
void read_in_block(size_t block_num, std::string &vlog_name, size_t vlog_block_num);
private:
void flush_all_blocks();
inline size_t offset_2_blocknum(size_t offset) {
return (offset / BLOCK_SIZE) % BLOCK_NUMS;
}
inline size_t offset_2_inblock_offset(size_t offset) {
return offset % BLOCK_SIZE;
}
private:
block_frame *block_frames[BLOCK_NUMS];
};
#endif // LEVELDB_VLOG_CACHE_H

+ 3
- 3
db/vlog_gc.cpp View File

@ -142,11 +142,11 @@ void VlogGC::exec_gc(size_t gc_num_) {
curr_thread_nums_ --;
curr_thread_nums_latch_.unlock();
std::cout << "vlog_gc.cpp line 138" << std::endl;
// std::cout << "vlog_gc.cpp line 138" << std::endl;
del_executor_params(gc_num_);
std::cout << "vlog_gc.cpp line 140" << std::endl;
// std::cout << "vlog_gc.cpp line 140" << std::endl;
del_vlog_gc(gc_num_);
std::cout << "vlog_gc.cpp line 142" << std::endl;
// std::cout << "vlog_gc.cpp line 142" << std::endl;
del_vlog_in_gc(ep.old_vlog_num);

+ 232
- 72
db/vlog_set.cpp View File

@ -12,34 +12,33 @@
// value: { value_len(uint16_t) | slot_num(size_t) | value }
// no bugs
VlogSet::VlogSet(std::string dbname, VlogGC *vlog_gc) : dbname(dbname), vlog_gc(vlog_gc) {
auto cfname = get_config_file_name();
this- class="o">>config_file_ = new std::fstream(cfname, std::ios::in | std::ios::out);
if (!this->config_file_->is_open()) {
config_file_name = get_config_file_name();
auto config_file_ = std::fstream(config_file_name, std::ios::in | std::ios::out);
if (!config_file_.is_open()) {
// config 文件不存在,尝试创建
delete this->config_file_;
this->config_file_ = new std::fstream(cfname, std::ios::out);
this->config_file_->close();
delete this->config_file_;
config_file_ = std::fstream(config_file_name, std::ios::out);
config_file_.close();
// 重新以读写模式打开
this->config_file_ = new std::fstream(cfname, std::ios::in | std::ios::out);
this->config_file_->seekp(0);
config_file_ = std::fstream(config_file_name, std::ios::in | std::ios::out);
config_file_.seekp(0);
size_t tmp = 0;
this->config_file_->write(reinterpret_cast<const char*>(&tmp), sizeof(size_t));
this->config_file_->flush();
config_file_.write(reinterpret_cast<const char*>(&tmp), sizeof(size_t));
config_file_.flush();
this->vlog_nums_ = 0;
register_new_vlog();
} else {
// config 文件存在
size_t _vlog_nums_;
config_file_->seekp(0);
config_file_->read(reinterpret_cast<char*>(&_vlog_nums_), sizeof(size_t));
config_file_.seekp(0);
config_file_.read(reinterpret_cast<char*>(&_vlog_nums_), sizeof(size_t));
this->vlog_nums_ = _vlog_nums_;
// 从 config file 中读取所有有效的vlog名字
config_file_->seekp(sizeof(size_t));
config_file_.seekp(sizeof(size_t));
size_t tmp[_vlog_nums_];
config_file_->read(reinterpret_cast<char*>(tmp), sizeof(tmp));
config_file_.read(reinterpret_cast<char*>(tmp), sizeof(tmp));
for (auto i = 0; i < _vlog_nums_; i++) {
size_t curr_vlog_num = tmp[i];
if (!(curr_vlog_num & CONFIG_FILE_DELE_MASK)) {
@ -47,17 +46,22 @@ VlogSet::VlogSet(std::string dbname, VlogGC *vlog_gc) : dbname(dbname), vlog_gc(
size_t curr_vlog_header[2];
curr_vlog.seekp(0);
curr_vlog.read(reinterpret_cast<char*>(curr_vlog_header), 2*sizeof(size_t));
curr_vlog.close();
restore_vlog_inmaps(new vlog_info(curr_vlog_num, curr_vlog_header[1], curr_vlog_header[0]));
}
}
}
if (!this->config_file_->is_open()) {
std::cerr << "Failed to open or create the db config file: " << cfname << std::endl;
if (!config_file_.is_open()) {
std::cerr << "Failed to open or create the db config file: " << config_file_name << std::endl;
std::exit(EXIT_FAILURE);
}
config_file_.close();
if (USING_VLOG_CACHE) {
vlog_cache = new VlogCache();
}
}
VlogSet::~VlogSet() {
@ -73,26 +77,42 @@ VlogSet::~VlogSet() {
}
}
config_file_->seekp(0);
config_file_->write(reinterpret_cast<const char*>(&vlog_nums_), sizeof(size_t));
config_file_->flush();
config_file_->close();
auto config_file_ = std::fstream(config_file_name, std::ios::in | std::ios::out);
config_file_.seekp(0);
config_file_.write(reinterpret_cast<const char*>(&vlog_nums_), sizeof(size_t));
config_file_.flush();
config_file_.close();
mtx.lock();
for (auto & it : vlog_info_map_) {
struct vlog_info* vinfo = it.second;
auto vlog_handler = get_vlog_handler(vinfo->vlog_num);
vinfo->vlog_info_latch_.lock();
// FIXME: SIGSEGV
vlog_handler->vlog_latch_.hard_lock();
// 所有操作都已经同步完成
// 使用 vlog_info* 进行操作
size_t tmp[2] = {vinfo->curr_size, vinfo->value_nums};
vinfo->vlog_info_latch_.unlock();
auto vlog_file_handler = std::fstream(get_vlog_name(vinfo->vlog_num), std::ios::in | std::ios::out);
vlog_file_handler.seekp(0);
vlog_file_handler.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
vlog_file_handler.flush();
vlog_file_handler.close();
}
std::cout << "vlog_set.cpp line 102" << std::endl;
vlog_handler->vlog_latch_.hard_unlock();
}
mtx.unlock();
std::cout << "vlog_set.cpp line 106" << std::endl;
delete vlog_gc;
if (USING_VLOG_CACHE) {
delete vlog_cache;
}
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
@ -211,15 +231,18 @@ void VlogSet::remove_old_vlog(size_t old_vlog_num) {
std::string old_vlog_name = get_vlog_name(old_vlog_num);
remove_from_config_file(old_vlog_num);
remove_vlog_from_maps(old_vlog_name); // FIXME: this function should be called after all access on this vlog finished !!!
remove_vlog_file(old_vlog_name); // FIXME: this function should be called after all access on this vlog finished !!!
vi_old->vlog_valid_ = false;
vi_old->vlog_info_latch_.unlock();
vlog_nums_ --;
mtx.unlock();
}
bool VlogSet::vlog_need_gc(size_t vlog_num) {
// TODO: need to judge whether vlog is full
auto vi = get_vlog_info(vlog_num);
if ((double)(vi->curr_size*1.0)/VLOG_SIZE < VLOG_GC_THREHOLD) {
if ((double)(vi->curr_size*1.0)/VLOG_SIZE >= VLOG_GC_VOLUM_THRESHOLD &&
(double)(vi->curr_size*1.0)/VLOG_SIZE < VLOG_GC_THREHOLD) {
return false;
}
bool retval = vi->vlog_valid_ && (vi->discard/vi->value_nums >= GC_THREDHOLD);
@ -231,49 +254,53 @@ void VlogSet::register_inconfig_file(size_t vlog_num) {
// first size_t in config file indicates current vlog_nums_(size_t)
// second size_t in config file indicates current vlog_count_(size_t)
config_file_latch_.lock();
config_file_->seekp(sizeof(size_t) + vlog_nums_* sizeof(size_t));
config_file_->write(reinterpret_cast<const char*>(&vlog_num), sizeof(size_t));
config_file_->flush();
auto config_file_ = std::fstream(config_file_name, std::ios::in | std::ios::out);
config_file_.seekp(sizeof(size_t) + vlog_nums_* sizeof(size_t));
config_file_.write(reinterpret_cast<const char*>(&vlog_num), sizeof(size_t));
config_file_.flush();
config_file_.close();
config_file_latch_.unlock();
}
void VlogSet::remove_from_config_file(size_t vlog_num) {
// FIXME: concurrency on config file
config_file_latch_.lock();
char tmp[vlog_nums_*vlog_num_size];
config_file_->seekp(sizeof(size_t));
config_file_->read(tmp, sizeof(tmp));
size_t *vlog_num_ptr = reinterpret_cast<size_t*>(tmp);
size_t tmp[vlog_nums_];
auto config_file_ = std::fstream(config_file_name, std::ios::in | std::ios::out);
config_file_.seekp(sizeof(size_t));
config_file_.read(reinterpret_cast<char*>(tmp), sizeof(tmp));
for (auto i = 0; i < vlog_nums_; i++) {
size_t curr_vlog_num = *vlog_num_ptr;
size_t curr_vlog_num = tmp[i];
if (!(curr_vlog_num & CONFIG_FILE_DELE_MASK) && curr_vlog_num == vlog_num) {
curr_vlog_num |= CONFIG_FILE_DELE_MASK;
config_file_->seekp(sizeof(size_t) + i*sizeof(size_t));
config_file_->write(reinterpret_cast<const char*>(&curr_vlog_num), sizeof(size_t));
config_file_->flush();
config_file_.seekp(sizeof(size_t) + i*sizeof(size_t));
config_file_.write(reinterpret_cast<const char*>(&curr_vlog_num), sizeof(size_t));
config_file_.flush();
break;
}
}
config_file_.close();
config_file_latch_.unlock();
}
void VlogSet::create_vlog(size_t vlog_num) {
auto vlog_name = get_vlog_name(vlog_num);
std::fstream *vlog_new = new std::fstream(vlog_name, std::ios::out);
vlog_new->close();
delete vlog_new;
auto vlog_new = std::fstream(vlog_name, std::ios::out);
vlog_new.close();
// 重新以读写模式打开
vlog_new = new std::fstream(vlog_name, std::ios::in | std::ios::out);
if (!vlog_new->is_open()) {
vlog_new = std::fstream(vlog_name, std::ios::in | std::ios::out);
if (!vlog_new.is_open()) {
std::cerr << "Failed to open or create the vlog file: " << vlog_name << std::endl;
std::exit(EXIT_FAILURE);
}
size_t tmp[2] = {2*sizeof(size_t), vlog_num};
vlog_new->seekp(0);
vlog_new->write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
vlog_new->flush();
vlog_new->close();
delete vlog_new;
size_t tmp[2] = {2*sizeof(size_t), 0};
vlog_new.seekp(0);
vlog_new.write(reinterpret_cast<const char*>(tmp), sizeof(tmp));
vlog_new.flush();
vlog_new.close();
}
inline void VlogSet::restore_vlog_inmaps(struct vlog_info *vi) {
@ -289,9 +316,9 @@ inline void VlogSet::register_vlog_inmaps(size_t vlog_num, std::string &vlog_nam
vlog_handler_map_[vlog_name] = vhandler;
}
void VlogSet::remove_vlog_from_maps(std::string &vlog_name) {
void VlogSet::remove_vlog_file(std::string &vlog_name) {
assert(!std::remove(vlog_name.c_str()));
vlog_handler_map_.erase(vlog_name);
// vlog_handler_map_.erase(vlog_name);
}
inline std::string VlogSet::get_config_file_name() {
@ -310,43 +337,110 @@ struct vlog_handler * VlogSet::get_vlog_handler(size_t vlog_num) {
return vlog_handler_map_[get_vlog_name(vlog_num)];
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
// single attr: | attr1_name_len(uint8_t) | attr1_name | attr1_len(uint16_t) | attr1 |
void VlogSet::read_vlog_value(const struct slot_content &sc, std::string *value) {
auto vlog_name = get_vlog_name(sc.vlog_num);
auto handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
handler.seekp(sc.value_offset);
char value_buff[VALUE_BUFF_SIZE];
handler.read(value_buff, VALUE_BUFF_SIZE);
size_t VlogSet::serialize_data(const leveldb::Slice &buff, size_t slot_num, std::string &value) {
const char *value_buff = buff.data();
const size_t off = sizeof(uint16_t) + sizeof(size_t);
const size_t value_size = off + buff.size();
char data[value_size];
memcpy(data, &value_size, sizeof(uint16_t));
memcpy(data+sizeof(uint16_t), &slot_num, sizeof(size_t));
memcpy(data+off, value_buff, buff.size());
value = std::string(data, value_size);
return value_size;
}
void VlogSet::deserialize_data(char *buff, std::string &value) {
uint16_t value_size;
memcpy(&value_size, value_buff, sizeof(uint16_t));
memcpy(&value_size, buff, sizeof(uint16_t));
if (value_size & VALUE_DELE_MASK) {
*value = "";
value = "";
return ;
}
value_size &= VALUE_SIZE_MASK;
assert(value_size <= VALUE_BUFF_SIZE);
const size_t off = sizeof(uint16_t)+sizeof(size_t);
*value = std::string(&value_buff[off], value_size-off);
value = std::string(&buff[off], value_size-off);
}
void VlogSet::read_vlog_value(const struct slot_content &sc, std::string *value) {
if (USING_VLOG_CACHE) {
read_vlog_value_cache(sc, value);
} else {
read_vlog_value_direct(sc, value);
}
}
void VlogSet::write_vlog_value(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value) {
if (USING_VLOG_CACHE) {
write_vlog_value_cache(sc, slot_num, value);
} else {
write_vlog_value_direct(sc, slot_num, value);
}
}
uint16_t VlogSet::delete_vlog_value(const struct slot_content &sc) {
uint16_t value_size;
if (USING_VLOG_CACHE) {
value_size = delete_vlog_value_cache(sc);
} else {
value_size = delete_vlog_value_direct(sc);
}
return value_size;
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
// single attr: | attr1_name_len(uint8_t) | attr1_name | attr1_len(uint16_t) | attr1 |
void VlogSet::read_vlog_value_direct(const struct slot_content &sc, std::string *value) {
auto vlog_name = get_vlog_name(sc.vlog_num);
auto handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
handler.seekp(sc.value_offset);
char value_buff[VALUE_BUFF_SIZE];
handler.read(value_buff, VALUE_BUFF_SIZE);
handler.close();
std::string vlog_value;
deserialize_data(value_buff, vlog_value);
*value = vlog_value;
// uint16_t value_size;
// memcpy(&value_size, value_buff, sizeof(uint16_t));
// if (value_size & VALUE_DELE_MASK) {
// *value = "";
// return ;
// }
// value_size &= VALUE_SIZE_MASK;
// assert(value_size <= VALUE_BUFF_SIZE);
//
// const size_t off = sizeof(uint16_t)+sizeof(size_t);
// *value = std::string(&value_buff[off], value_size-off);
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
// single attr: | attr1_name_len(uint8_t) | attr1_name | attr1_len(uint16_t) | attr1 |
void VlogSet::write_vlog_value(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value) {
void VlogSet::write_vlog_value_direct(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value) {
auto vlog_name = get_vlog_name(sc.vlog_num);
auto handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
handler.seekp(sc.value_offset);
const char *value_buff = value.data();
const size_t off = sizeof(uint16_t) + sizeof(size_t);
const size_t value_size = off + value.size();
char data[value_size];
memcpy(data, &value_size, sizeof(uint16_t));
memcpy(data+sizeof(uint16_t), &slot_num, sizeof(size_t));
memcpy(data+off, value_buff, value.size());
std::string vlog_value;
auto value_size = serialize_data(value, slot_num, vlog_value);
const char *data = vlog_value.data();
// const char *value_buff = value.data();
//
// const size_t off = sizeof(uint16_t) + sizeof(size_t);
// const size_t value_size = off + value.size();
// char data[value_size];
// memcpy(data, &value_size, sizeof(uint16_t));
// memcpy(data+sizeof(uint16_t), &slot_num, sizeof(size_t));
// memcpy(data+off, value_buff, value.size());
handler.write(data, value_size);
@ -354,9 +448,7 @@ void VlogSet::write_vlog_value(const struct slot_content &sc, size_t slot_num, c
handler.close();
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
// single attr: | attr1_name_len(uint8_t) | attr1_name | attr1_len(uint16_t) | attr1 |
void VlogSet::mark_del_value(const struct slot_content &sc) {
uint16_t VlogSet::delete_vlog_value_direct(const struct slot_content &sc) {
auto vinfo = get_vlog_info(sc.vlog_num);
auto vlog_name = get_vlog_name(sc.vlog_num);
auto handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
@ -369,7 +461,7 @@ void VlogSet::mark_del_value(const struct slot_content &sc) {
if (value_size & VALUE_DELE_MASK) {
// case when value has been deleted
handler.close();
return ;
return value_size & VALUE_SIZE_MASK;
}
assert(!(value_size & VALUE_DELE_MASK));
uint16_t masked_value_size = value_size | (uint16_t)VALUE_DELE_MASK;
@ -379,6 +471,74 @@ void VlogSet::mark_del_value(const struct slot_content &sc) {
handler.flush();
handler.close();
return value_size;
}
void VlogSet::read_vlog_value_cache(const struct slot_content &sc, std::string *value) {
auto vlog_name = get_vlog_name(sc.vlog_num);
std::string tmp_value;
vlog_cache->read_data(vlog_name, tmp_value, sc.value_offset, sizeof(uint16_t));
uint16_t value_len;
memcpy(&value_len, tmp_value.data(), sizeof(uint16_t));
if (value_len & VALUE_DELE_MASK) {
*value = "";
return ;
}
assert(!(value_len & VALUE_DELE_MASK));
std::string value_str;
vlog_cache->read_data(vlog_name, value_str, sc.value_offset, value_len);
std::string vlog_value;
char *value_buff = const_cast<char*>(value_str.data());
deserialize_data(value_buff, vlog_value);
*value = vlog_value;
}
void VlogSet::write_vlog_value_cache(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value) {
auto vlog_name = get_vlog_name(sc.vlog_num);
auto value_str = value.ToString();
std::string vlog_value;
auto value_size = serialize_data(value.data(), slot_num, vlog_value);
vlog_cache->write_data(vlog_name, vlog_value, sc.value_offset, value_size);
}
uint16_t VlogSet::delete_vlog_value_cache(const struct slot_content &sc) {
auto vlog_name = get_vlog_name(sc.vlog_num);
return vlog_cache->delete_data(vlog_name, sc.value_offset);
}
// single value: || value_size(uint16_t) | slot_num(size_t) || {field_nums(uint16_t), attr1, attr2, ... } |
// single attr: | attr1_name_len(uint8_t) | attr1_name | attr1_len(uint16_t) | attr1 |
void VlogSet::mark_del_value(const struct slot_content &sc) {
auto vinfo = get_vlog_info(sc.vlog_num);
auto value_size = delete_vlog_value(sc);
// auto vlog_name = get_vlog_name(sc.vlog_num);
// auto handler = std::fstream(vlog_name, std::ios::in | std::ios::out);
// handler.seekp(sc.value_offset);
// char value_buff[VALUE_BUFF_SIZE];
// handler.read(value_buff, VALUE_BUFF_SIZE);
//
// uint16_t value_size;
// memcpy(&value_size, value_buff, sizeof(uint16_t));
// if (value_size & VALUE_DELE_MASK) {
// // case when value has been deleted
// handler.close();
// return ;
// }
// assert(!(value_size & VALUE_DELE_MASK));
// uint16_t masked_value_size = value_size | (uint16_t)VALUE_DELE_MASK;
// memcpy(value_buff, &masked_value_size, sizeof(uint16_t));
// handler.seekp(sc.value_offset);
// handler.write(value_buff, sizeof(uint16_t));
// handler.flush();
// handler.close();
// handle gc, mtx is locked outside, vlog_info_latch and vlog hard lock is locked outside too
vinfo->discard ++;
vinfo->value_nums --;

+ 20
- 2
db/vlog_set.h View File

@ -13,6 +13,7 @@
#include "../include/leveldb/slice.h"
#include "../db/shared_lock.h"
#include "../db/vlog.h"
#include "../db/vlog_cache.h"
// VlogGC
class VlogGC;
@ -21,9 +22,11 @@ class VlogSet {
friend class VlogGC;
friend class gc_executor;
#define USING_VLOG_CACHE true
#define CONFIG_FILE_DELE_MASK (0x1 << (sizeof(size_t)-1))
#define CONFIG_FILE_VLOG_NUM(v) ((v) & ~CONFIG_FILE_DELE_MASK)
#define VLOG_GC_THREHOLD 0.5
#define VLOG_GC_VOLUM_THRESHOLD 0.9
public:
VlogSet(std::string dbname, VlogGC *vlog_gc);
@ -46,23 +49,36 @@ friend class gc_executor;
struct vlog_info *get_writable_vlog_info(size_t value_size);
inline void restore_vlog_inmaps(struct vlog_info *vi);
inline void register_vlog_inmaps(size_t vlog_num, std::string &vlog_name);
void remove_vlog_from_maps(std::string &vlog_name);
void remove_vlog_file(std::string &vlog_name);
inline std::string get_config_file_name();
std::string get_vlog_name(size_t vlog_num);
struct vlog_info *get_vlog_info(size_t vlog_num);
struct vlog_handler *get_vlog_handler(size_t vlog_num);
inline size_t serialize_data(const leveldb::Slice &buff, size_t slot_num, std::string &value);
inline void deserialize_data(char *buff, std::string &value);
void read_vlog_value(const struct slot_content &sc, std::string *value);
void write_vlog_value(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
uint16_t delete_vlog_value(const struct slot_content &sc);
void mark_del_value(const struct slot_content &sc);
private:
void read_vlog_value_direct(const struct slot_content &sc, std::string *value);
void write_vlog_value_direct(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
uint16_t delete_vlog_value_direct(const struct slot_content &sc);
void read_vlog_value_cache(const struct slot_content &sc, std::string *value);
void write_vlog_value_cache(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
uint16_t delete_vlog_value_cache(const struct slot_content &sc);
private:
std::mutex mtx;
std::string dbname;
size_t vlog_nums_;
std::unordered_map<std::string, struct vlog_info *> vlog_info_map_;
std::unordered_map<std::string, struct vlog_handler *> vlog_handler_map_;
std::mutex config_file_latch_;
std::fstream *config_file_;
// std::fstream *config_file_;
// config_file的处理有问题
std::string config_file_name;
int counter = 0; // gc线程正在进行
std::mutex counter_latch_;
@ -70,6 +86,8 @@ friend class gc_executor;
bool finished = true; // gc线程都已结束
VlogGC *vlog_gc; // vlog_set.cpp
VlogCache *vlog_cache;
};

+ 83
- 2
test/db_test1.cc View File

@ -37,8 +37,12 @@ int test2() {
assert(status.ok());
const std::string value_prefix = "value_";
const size_t loop_times = 100000;
const size_t loop_times = 1000000;
int k = 0;
for (auto i = 0; i < loop_times; i++) {
if (i == 220) {
k ++;
}
auto key = std::to_string(i);
auto value = value_prefix + key;
db->Put(WriteOptions(), key, value);
@ -66,7 +70,84 @@ int test2() {
return 0;
}
int test3() {
DB* db = nullptr;
Options op;
op.create_if_missing = true;
Status status = DB::Open(op, "testdb2", &db);
assert(status.ok());
const std::string value_prefix = "value_";
const size_t loop_times = 10;
for (auto i = 0; i < loop_times; i++) {
auto key = std::to_string(i);
auto value = value_prefix + key;
db->Put(WriteOptions(), key, value);
string s;
db->Get(ReadOptions(), key, &s);
cout << s << " | " << s.size() << endl;
}
// cout << endl << "all put are done" << endl << endl;
//
// for (auto i = 0; i < loop_times; i++) {
// auto key = std::to_string(i);
// auto value = value_prefix + key;
//
// // db->Put(WriteOptions(), key, value+"_");
// string s1;
// db->Delete(WriteOptions(), key); // sc: {0, 33}
// db->Get(ReadOptions(), key, &s1);
// cout << s1 << " | " << s1.size() << " | " << i << endl;
// }
delete db;
std::cout << "db has been deleted!" << std::endl;
return 0;
}
int test4() {
DB* db = nullptr;
Options op;
op.create_if_missing = true;
Status status = DB::Open(op, "testdb2", &db);
assert(status.ok());
const std::string value_prefix = "value_";
const size_t loop_times = 10;
// for (auto i = 0; i < loop_times; i++) {
// auto key = std::to_string(i);
// auto value = value_prefix + key;
// db->Put(WriteOptions(), key, value);
// string s;
// db->Get(ReadOptions(), key, &s);
// cout << s << " | " << s.size() << endl;
//
// }
// cout << endl << "all put are done" << endl << endl;
for (auto i = 0; i < loop_times; i++) {
auto key = std::to_string(i);
auto value = value_prefix + key;
// db->Put(WriteOptions(), key, value+"_");
string s1;
db->Delete(WriteOptions(), key); // sc: {0, 33}
db->Get(ReadOptions(), key, &s1);
cout << s1 << " | " << s1.size() << " | " << i << endl;
}
delete db;
std::cout << "db has been deleted!" << std::endl;
return 0;
}
int main() {
test2();
// test3();
// std::cout << std::endl << std::endl;
// test4();
test2();
}

+ 3
- 3
test/db_test4.cc View File

@ -17,7 +17,7 @@ void printVector(const std::vector& vec) {
}
int test1() {
BitMap bitmap;
BitMap bitmap("test");
std::vector<size_t> slots;
slots.reserve(SLOTNUM<<2);
int i = 0;
@ -53,7 +53,7 @@ int test1() {
int test2() {
BitMap bitmap;
BitMap bitmap("test");
std::vector<size_t> slots;
slots.reserve(SLOTNUM);
for (auto i = 0; i < SLOTNUM; i++) {
@ -85,7 +85,7 @@ void allocate_slots(BitMap& bitmap, std::vector& slots, int num_slots) {
}
int test3() {
BitMap bitmap;
BitMap bitmap("db");
std::vector<size_t> slots1;
slots1.reserve(1000);

+ 37
- 3
test/db_test5.cc View File

@ -90,8 +90,8 @@ void process_slots(SlotCache& slot_cache,
slot_content sc;
for (size_t i = start; i < end; ++i) {
slot_cache.get_slot(i, &sc);
// assert(sc.vlog_num == slot_contents[i].vlog_num);
// assert(sc.value_offset == slot_contents[i].vlog_num);
assert(sc.vlog_num == slot_contents[i].vlog_num);
assert(sc.value_offset == slot_contents[i].vlog_num);
slots.push_back(sc.vlog_num);
}
@ -143,7 +143,41 @@ int test3() {
}
int test4() {
SlotCache *slot_cache = new SlotCache("test_slotpage");
slot_content sc = {0, 16};
slot_cache->set_slot(0, &sc);
sc = {0, 17};
slot_cache->set_slot(1, &sc);
sc = {0, 18};
slot_cache->set_slot(2, &sc);
slot_cache->get_slot(0, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
slot_cache->get_slot(1, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
slot_cache->get_slot(2, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
delete slot_cache;
slot_cache = new SlotCache("test_slotpage");
slot_cache->get_slot(0, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
slot_cache->get_slot(1, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
slot_cache->get_slot(2, &sc);
std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
delete slot_cache;
return 0;
}
int main() {
test3();
test4();
}

+ 2
- 2
test/db_test6.cc View File

@ -46,7 +46,7 @@ TEST(ConcurrentTest, Basic) {
DB* db;
WriteOptions writeOptions;
ReadOptions readOptions;
if (!OpenDB("testdb_current", &db).ok()) {
if (!OpenDB("testdb6", &db).ok()) {
std::cerr << "open db failed" << std::endl;
abort();
}
@ -92,7 +92,7 @@ TEST(ConcurrentTest, Basic) {
}
// 测试查找功能
// std::vector<std::string> foundKeys = db.FindKeysByField(queryField);
// std::vector<std::string> foundKeys = db.FindKeysByField(queryField);
// 添加断言检查查找的正确性
// ASSERT_EQ(foundKeys.size(), expectedSize);
});

Loading…
Cancel
Save