first version of fast lruk
This commit is contained in:
9
bpt/include/bpt/config.h
Normal file
9
bpt/include/bpt/config.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
#include <cstddef>
|
||||
extern const size_t kPageSize;
|
||||
typedef unsigned int default_numeric_index_t;
|
||||
typedef default_numeric_index_t page_id_t;
|
||||
typedef default_numeric_index_t block_id_t;
|
||||
typedef default_numeric_index_t frame_id_t;
|
||||
#endif
|
46
bpt/include/bpt/disk_manager.h
Normal file
46
bpt/include/bpt/disk_manager.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef DISK_MANAGER_H
|
||||
#define DISK_MANAGER_H
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include "config.h"
|
||||
extern const size_t kPageSize;
|
||||
class DiskManager {
|
||||
/**
|
||||
* The Data Structure on Disk:
|
||||
* [Internal Page] [Page 1] [Page 2] .....
|
||||
* In Internal Page, the first meta_data_size bytes are used to store
|
||||
* metadata(first_empty_page_id, current_total_page_count, current_none_empty_page_count), the rest are allocated to
|
||||
* raw_data_memory.
|
||||
* When a page is Deallocated, the first sizeof(page_id_t) bytes are used to store the next empty page
|
||||
* id, then update first_empty_page_id, just like a list. To avoid unnecessary cache, use C style file operation
|
||||
* instead of fstream. Note that the page_id is the offset of the page in the file, as the first page is internal,
|
||||
* thus page_id is 1-based. In the list of empty pages, if the there is no next empty page, the value is 0(the same
|
||||
* for first_empty_page_id).
|
||||
*/
|
||||
public:
|
||||
explicit DiskManager(const std::string &file_path_);
|
||||
~DiskManager();
|
||||
char *RawDataMemory();
|
||||
size_t RawDatMemorySize();
|
||||
void FlushInternalPage();
|
||||
void Close();
|
||||
void ReadPage(page_id_t page_id, char *page_data_ptr);
|
||||
void WritePage(page_id_t page_id, const char *page_data_ptr); // in fact, the page_id is the offest
|
||||
bool CurrentFileIsNew();
|
||||
page_id_t AllocNewEmptyPageId();
|
||||
void DeallocatePage(page_id_t page_id);
|
||||
size_t CurrentTotalPageCount();
|
||||
size_t CurrentNoneEmptyPageCount();
|
||||
|
||||
private:
|
||||
std::string file_path;
|
||||
page_id_t first_empty_page_id;
|
||||
size_t current_total_page_count;
|
||||
size_t current_none_empty_page_count;
|
||||
static const size_t meta_data_size = sizeof(page_id_t) + sizeof(size_t) + sizeof(size_t);
|
||||
char *raw_data_memory;
|
||||
FILE *fp;
|
||||
bool is_new;
|
||||
char *page_buf;
|
||||
};
|
||||
#endif
|
72
bpt/include/bpt/replacer.h
Normal file
72
bpt/include/bpt/replacer.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef REPLACER_H
|
||||
#define REPLACER_H
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include "bpt/config.h"
|
||||
class LRUKReplacer {
|
||||
public:
|
||||
LRUKReplacer() = delete;
|
||||
explicit LRUKReplacer(size_t max_frame_count, size_t k_value);
|
||||
~LRUKReplacer();
|
||||
bool TryEvictLeastImportant(frame_id_t &frame_id);
|
||||
void RecordAccess(frame_id_t frame_id);
|
||||
void SetEvictable(frame_id_t frame_id, bool evitable);
|
||||
bool TryEvictExactFrame(frame_id_t frame_id);
|
||||
LRUKReplacer &operator=(const LRUKReplacer &) = delete;
|
||||
size_t GetCurrentEvitableCount();
|
||||
|
||||
private:
|
||||
struct LRUChainNodeType { // for not has k visit
|
||||
frame_id_t frame_id;
|
||||
LRUChainNodeType *prev, *next;
|
||||
LRUChainNodeType() = delete;
|
||||
explicit LRUChainNodeType(frame_id_t frame_id, LRUChainNodeType *prev, LRUChainNodeType *next)
|
||||
: frame_id(frame_id), prev(prev), next(next) {}
|
||||
};
|
||||
struct MainChainNodeType { // for has k visit
|
||||
frame_id_t frame_id;
|
||||
size_t time_stamp;
|
||||
MainChainNodeType *prev, *next;
|
||||
MainChainNodeType *next_self_record;
|
||||
MainChainNodeType() = delete;
|
||||
explicit MainChainNodeType(frame_id_t frame_id, size_t time_stamp, MainChainNodeType *prev, MainChainNodeType *next,
|
||||
MainChainNodeType *next_self_record)
|
||||
: frame_id(frame_id), time_stamp(time_stamp), prev(prev), next(next), next_self_record(next_self_record) {}
|
||||
};
|
||||
template <typename ListNodeType>
|
||||
inline void RemoveFromList(ListNodeType *node) {
|
||||
if (node->prev != nullptr) {
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
if (node->next != nullptr) {
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
}
|
||||
template <typename ListNodeType>
|
||||
inline void InsertAt(ListNodeType *node, ListNodeType *prev, ListNodeType *next) {
|
||||
node->prev = prev;
|
||||
node->next = next;
|
||||
if (prev != nullptr) prev->next = node;
|
||||
if (next != nullptr) next->prev = node;
|
||||
}
|
||||
struct LRUKRecord {
|
||||
LRUKRecord() = default;
|
||||
bool evitable;
|
||||
size_t visit_count;
|
||||
bool active;
|
||||
MainChainNodeType *head_node_in_main_chain, *tail_node_in_main_chain;
|
||||
LRUChainNodeType *node_in_LRU_chain;
|
||||
};
|
||||
void RemoveWholeFrameFromLRUKChain(MainChainNodeType *first_occurrence_ptr); // remove and delete nodes
|
||||
MainChainNodeType *AddRecordToMainChain(frame_id_t frame_it, size_t time_stamp,
|
||||
MainChainNodeType *last_node_in_main_chain);
|
||||
LRUChainNodeType *LRU_chain_head_guard, *LRU_chain_tail_guard;
|
||||
MainChainNodeType *LRUK_chain_head_guard, *LRUK_chain_tail_guard;
|
||||
size_t current_timestamp_{0};
|
||||
size_t current_evitable_count_{0};
|
||||
size_t max_frame_count;
|
||||
size_t k_value;
|
||||
std::mutex latch;
|
||||
LRUKRecord *hash_for_record;
|
||||
};
|
||||
#endif
|
Reference in New Issue
Block a user