//
|
|
// Created by 马也驰 on 2025/1/4.
|
|
//
|
|
|
|
#ifndef LEVELDB_VLOG_CACHE_H
|
|
#define LEVELDB_VLOG_CACHE_H
|
|
|
|
#include <cassert>
|
|
#include <mutex>
|
|
#include <string>
|
|
|
|
#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
|