├── code ├── CMakeLists.txt ├── run.sh ├── include │ ├── data_storage_manager.h │ ├── typedef.h │ ├── Replacer.h │ └── buffer_manager.h └── src │ ├── LRU_k_Replacer.cpp │ ├── LRU_Replacer.cpp │ ├── CLOCK_Replacer.cpp │ ├── data_storage_manager.cpp │ ├── main.cpp │ └── buffer_manager.cpp └── README.md /code/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(lab) 3 | include_directories(./include) 4 | 5 | add_executable(lab1 src/main.cpp 6 | src/buffer_manager.cpp 7 | src/data_storage_manager.cpp 8 | src/LRU_Replacer.cpp 9 | src/CLOCK_Replacer.cpp 10 | src/LRU_k_Replacer.cpp) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ustc-adb-lab 2 | 3 | 中科大高级数据库系统实验-2023fall(金培权) 4 | 5 | ### 运行所有算法 6 | 在code文件夹下运行 7 | `` 8 | ./run.sh 9 | `` 10 | 或者 11 | `` 12 | ./run.sh 13 | `` 14 | 15 | ### 测试单个算法 16 | 在code文件夹下运行 17 | ``` 18 | mkdir build 19 | cd build 20 | cmake .. && make 21 | ./lab1 -r -k -d 22 | ``` 23 | 可以用`./lab1 -h`查看各个参数的具体介绍 -------------------------------------------------------------------------------- /code/run.sh: -------------------------------------------------------------------------------- 1 | if [ $# -gt 0 ]; 2 | then 3 | max_k=$1 4 | else 5 | max_k=5 6 | fi 7 | 8 | if [ ! -d "./build" ];then 9 | mkdir build 10 | fi 11 | cd build 12 | cmake .. && make 13 | 14 | ./lab1 -r lru -d ../data/data-5w-50w-zipf.txt 15 | ./lab1 -r clock -d ../data/data-5w-50w-zipf.txt 16 | 17 | for ((i=2; i<=$max_k; i++)) 18 | do 19 | ./lab1 -r lru-k -k $i -d ../data/data-5w-50w-zipf.txt 20 | done 21 | -------------------------------------------------------------------------------- /code/include/data_storage_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef DSMgr_H_ 2 | #define DSMgr_H_ 3 | #include 4 | #include 5 | #include "typedef.h" 6 | 7 | class DSMgr 8 | { 9 | public: 10 | DSMgr(std::string filename) 11 | { 12 | OpenFile(filename); 13 | } 14 | ~DSMgr() 15 | { 16 | CloseFile(); 17 | } 18 | 19 | int io_count = 0; 20 | 21 | int OpenFile(std::string filename); 22 | 23 | int CloseFile(); 24 | 25 | bFrame ReadPage(int page_id); 26 | 27 | int WritePage(int page_id, bFrame frm); // 将模板中的frame_id改为page_id 28 | 29 | int Seek(int offset, int pos); 30 | 31 | FILE *GetFile(); 32 | 33 | void IncNumPages(); 34 | 35 | int GetNumPages(); 36 | 37 | void SetUse(int index, int use_bit); 38 | 39 | int GetUse(int index); 40 | 41 | private: 42 | FILE *currFile; 43 | int numPages; 44 | int pages[MAXPAGES]; // 该实验中用不到,默认所有页use_bit均为1 45 | }; 46 | #endif -------------------------------------------------------------------------------- /code/include/typedef.h: -------------------------------------------------------------------------------- 1 | #ifndef Typedef_H_ 2 | #define Typedef_H_ 3 | 4 | #define MAXPAGES 50000 5 | #define FRAMESIZE 4096 6 | #define PAGESIZE FRAMESIZE 7 | #define DEFBUFSIZE 1024 8 | 9 | struct bFrame 10 | { 11 | char field[FRAMESIZE]; 12 | }; 13 | 14 | struct BCB 15 | { 16 | BCB() = default; 17 | BCB(int page_id, int frame_id, int count, int dirty) 18 | { 19 | this->page_id = page_id; 20 | this->frame_id = frame_id; 21 | this->count = count; 22 | this->dirty = dirty; 23 | this->next = nullptr; 24 | this->replacer_next = nullptr; 25 | this->replacer_prev = nullptr; 26 | this->referenced = 1; 27 | this->lru_count = 1; 28 | } 29 | int page_id; 30 | int frame_id; 31 | // int latch; // 乐观内存锁 32 | int count; // 和latch一样,在并发情况中使用,本实验不会处理 33 | int dirty; 34 | BCB *next; // bucket next 35 | // 替换算法的双向链表 36 | BCB *replacer_next; 37 | BCB *replacer_prev; 38 | // CLOCK替换算法 39 | int referenced = 1; 40 | // LRU-k替换算法 41 | int lru_count = 1; 42 | }; 43 | #endif -------------------------------------------------------------------------------- /code/src/LRU_k_Replacer.cpp: -------------------------------------------------------------------------------- 1 | #include "Replacer.h" 2 | 3 | void LRU_k_Replacer::Update(BCB *new_bcb, BCB *old_bcb, int hit) 4 | { 5 | if (!hit) 6 | { 7 | if (old_bcb) 8 | Delete(old_bcb); 9 | Insert(new_bcb); 10 | } 11 | else 12 | { // 命中时new_bcb和old_bcb是同一个 13 | new_bcb->lru_count++; 14 | if (new_bcb->lru_count == k) 15 | { 16 | lru_list1->Delete(old_bcb); 17 | lru_list2->Insert(new_bcb); 18 | } 19 | else if (new_bcb->lru_count < k) 20 | lru_list1->Update(new_bcb, old_bcb, hit); 21 | else if (new_bcb->lru_count > k) 22 | lru_list2->Update(new_bcb, old_bcb, hit); 23 | } 24 | } 25 | 26 | int LRU_k_Replacer::SelectVictim() 27 | { 28 | if (lru_list1->GetHead()) 29 | return lru_list1->GetHead()->frame_id; 30 | else 31 | return lru_list2->GetHead()->frame_id; 32 | } 33 | 34 | void LRU_k_Replacer::Insert(BCB *bcb) 35 | { 36 | lru_list1->Insert(bcb); 37 | } 38 | 39 | void LRU_k_Replacer::Delete(BCB *bcb) 40 | { 41 | if (bcb->lru_count >= k) 42 | lru_list2->Delete(bcb); 43 | else 44 | lru_list1->Delete(bcb); 45 | } -------------------------------------------------------------------------------- /code/src/LRU_Replacer.cpp: -------------------------------------------------------------------------------- 1 | #include "Replacer.h" 2 | 3 | Replacer::Replacer() {} 4 | // 是否hit都是删除旧的,插入新的,只是hit的情况旧的和新的是相同的bcb 5 | void LRU_Replacer::Update(BCB *new_bcb, BCB *old_bcb, int hit) 6 | { 7 | if (old_bcb) 8 | Delete(old_bcb); 9 | Insert(new_bcb); 10 | } 11 | 12 | int LRU_Replacer::SelectVictim() 13 | { 14 | return head->frame_id; 15 | } 16 | 17 | void LRU_Replacer::Insert(BCB *bcb) 18 | { 19 | if (!head) 20 | { 21 | head = bcb; 22 | bcb->replacer_next = bcb; 23 | bcb->replacer_prev = bcb; 24 | } 25 | else 26 | { // 插入到LRU的最末端 27 | auto tail = head->replacer_prev; 28 | head->replacer_prev = bcb; 29 | bcb->replacer_next = head; 30 | tail->replacer_next = bcb; 31 | bcb->replacer_prev = tail; 32 | } 33 | } 34 | 35 | void LRU_Replacer::Delete(BCB *bcb) 36 | { 37 | auto prev = bcb->replacer_prev; 38 | auto next = bcb->replacer_next; 39 | if (bcb == head) 40 | { 41 | head = next; 42 | if (head->replacer_next == head) 43 | { // 只有一个head节点 44 | head = nullptr; 45 | return; 46 | } 47 | } 48 | prev->replacer_next = next; 49 | next->replacer_prev = prev; 50 | } -------------------------------------------------------------------------------- /code/src/CLOCK_Replacer.cpp: -------------------------------------------------------------------------------- 1 | #include "Replacer.h" 2 | 3 | // 命中时将对应bcb的referenced置为1 4 | void CLOCK_Replacer::Update(BCB *new_bcb, BCB *old_bcb, int hit) 5 | { 6 | if (!hit) 7 | { 8 | if (old_bcb) 9 | Delete(old_bcb); 10 | Insert(new_bcb); 11 | } 12 | else 13 | new_bcb->referenced = 1; 14 | } 15 | 16 | int CLOCK_Replacer::SelectVictim() 17 | { 18 | if (!current) 19 | return -1; 20 | while (true) 21 | { 22 | if (current->referenced) 23 | { 24 | current->referenced = 0; 25 | current = current->replacer_next; 26 | } 27 | else 28 | { 29 | int frame_id = current->frame_id; 30 | current = current->replacer_next; 31 | return frame_id; 32 | } 33 | } 34 | return -1; 35 | } 36 | 37 | // 更新时由于SelectVictim算法的保证,如果是需要替换的情况,current一定是old_bcb->next 38 | // 所以插入时插入到current的prev 39 | void CLOCK_Replacer::Insert(BCB *bcb) 40 | { 41 | if (!current) 42 | { 43 | current = bcb; 44 | current->replacer_next = bcb; 45 | current->replacer_prev = bcb; 46 | } 47 | else 48 | { // 插入到current前面 49 | auto prev = current->replacer_prev; 50 | current->replacer_prev = bcb; 51 | bcb->replacer_next = current; 52 | prev->replacer_next = bcb; 53 | bcb->replacer_prev = prev; 54 | } 55 | } 56 | 57 | void CLOCK_Replacer::Delete(BCB *bcb) 58 | { 59 | auto prev = bcb->replacer_prev; 60 | auto next = bcb->replacer_next; 61 | prev->replacer_next = next; 62 | next->replacer_prev = prev; 63 | } 64 | -------------------------------------------------------------------------------- /code/include/Replacer.h: -------------------------------------------------------------------------------- 1 | #ifndef Replacer_H_ 2 | #define Replacer_H_ 3 | #include 4 | #include "typedef.h" 5 | 6 | class Replacer 7 | { 8 | public: 9 | Replacer(); 10 | std::string name; 11 | virtual void Insert(BCB *bcb) = 0; 12 | virtual void Delete(BCB *bcb) = 0; 13 | virtual void Update(BCB *new_bcb, BCB *old_bcb, int hit) = 0; // 删除old_bcb,插入bcb 14 | virtual int SelectVictim() = 0; 15 | }; 16 | 17 | class LRU_Replacer : public Replacer 18 | { 19 | public: 20 | LRU_Replacer() 21 | { 22 | name = "LRU"; 23 | head = nullptr; 24 | } 25 | void Insert(BCB *bcb); 26 | void Delete(BCB *bcb); 27 | BCB *GetHead() { return head; } // 给LRU-k使用 28 | void Update(BCB *new_bcb, BCB *old_bcb, int hit); 29 | virtual int SelectVictim(); 30 | 31 | private: 32 | BCB *head; 33 | }; 34 | 35 | class CLOCK_Replacer : public Replacer 36 | { 37 | public: 38 | CLOCK_Replacer() 39 | { 40 | name = "CLOCK"; 41 | current = nullptr; 42 | } 43 | void Insert(BCB *bcb); 44 | void Delete(BCB *bcb); 45 | void Update(BCB *new_bcb, BCB *old_bcb, int hit); 46 | virtual int SelectVictim(); 47 | 48 | private: 49 | BCB *current; 50 | }; 51 | 52 | class LRU_k_Replacer : public Replacer 53 | { 54 | public: 55 | LRU_k_Replacer(int k) 56 | { 57 | this->k = k; 58 | name = "LRU-" + std::to_string(k); 59 | lru_list1 = new LRU_Replacer(); 60 | lru_list2 = new LRU_Replacer(); 61 | } 62 | void Insert(BCB *bcb); 63 | void Delete(BCB *bcb); 64 | void Update(BCB *new_bcb, BCB *old_bcb, int hit); 65 | virtual int SelectVictim(); 66 | 67 | private: 68 | LRU_Replacer *lru_list1; 69 | LRU_Replacer *lru_list2; 70 | int k; 71 | }; 72 | #endif -------------------------------------------------------------------------------- /code/src/data_storage_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "data_storage_manager.h" 2 | 3 | int DSMgr::OpenFile(std::string filename) 4 | { 5 | currFile = fopen(filename.c_str(), "r+"); 6 | if (!currFile) 7 | { // 没有则创建文件 8 | currFile = fopen(filename.c_str(), "w+"); 9 | } 10 | // 获取文件大小并初始化页相关参数 11 | fseek(currFile, 0, SEEK_END); 12 | auto size = ftell(currFile); 13 | numPages = (size + PAGESIZE - 1) / PAGESIZE; 14 | if (numPages > MAXPAGES) 15 | throw "too large file, you need to increase MAXPAGES"; 16 | for (int i = 0; i < numPages; i++) 17 | { 18 | pages[i] = 1; 19 | } 20 | return 0; 21 | } 22 | 23 | int DSMgr::CloseFile() 24 | { 25 | return fclose(currFile); 26 | } 27 | 28 | bFrame DSMgr::ReadPage(int page_id) 29 | { 30 | struct bFrame frm; 31 | if (fseek(currFile, page_id * PAGESIZE, SEEK_SET) == 0) 32 | { 33 | fread(&frm, 1, FRAMESIZE, currFile); 34 | io_count++; 35 | return frm; 36 | } 37 | else 38 | return frm; 39 | } 40 | 41 | int DSMgr::WritePage(int page_id, bFrame frm) 42 | { // 将模板中的frame_id改为page_id 43 | if (fseek(currFile, page_id * PAGESIZE, SEEK_SET) == 0) 44 | { 45 | io_count++; 46 | return fwrite(frm.field, 1, FRAMESIZE, currFile); 47 | } 48 | else 49 | return 0; 50 | } 51 | 52 | int DSMgr::Seek(int offset, int pos) 53 | { 54 | return fseek(currFile, offset, pos); 55 | } 56 | 57 | FILE *DSMgr::GetFile() 58 | { 59 | return currFile; 60 | } 61 | 62 | void DSMgr::IncNumPages() 63 | { 64 | pages[numPages] = 1; 65 | char data[PAGESIZE]; 66 | memset(data, 'a', sizeof(data)); 67 | fseek(currFile, 0, SEEK_END); 68 | fwrite(data, 1, PAGESIZE, currFile); 69 | numPages++; 70 | } 71 | 72 | int DSMgr::GetNumPages() 73 | { 74 | return numPages; 75 | } 76 | 77 | void DSMgr::SetUse(int index, int use_bit) 78 | { 79 | pages[index] = use_bit; 80 | } 81 | 82 | int DSMgr::GetUse(int index) 83 | { 84 | return pages[index]; 85 | } 86 | -------------------------------------------------------------------------------- /code/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "buffer_manager.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char opt; 9 | const char *optstring = "r:k:d:h"; // r表示替换算法,k表示LRU-k的k,d表示trace_file路径,h表示参数说明 10 | 11 | std::string replacer_name, trace_path; 12 | int k = 2; 13 | while ((opt = getopt(argc, argv, optstring)) != -1) 14 | { 15 | if (opt == 'r') 16 | { 17 | if (strcmp(optarg, "lru") && strcmp(optarg, "clock") && strcmp(optarg, "lru-k")) 18 | { 19 | std::cout << "-r need lru or clock or lru-k" << std::endl; 20 | exit(1); 21 | } 22 | replacer_name = optarg; 23 | } 24 | else if (opt == 'k') 25 | { 26 | k = atoi(optarg); 27 | if (k < 2) 28 | { 29 | std::cout << "The value of k in lru-k is a positive integer larger than 1" << std::endl; 30 | exit(1); 31 | } 32 | } 33 | else if (opt == 'd') 34 | { 35 | trace_path = optarg; 36 | } 37 | else if (opt == 'h') 38 | { 39 | std::cout << "optional parameters are '-r','-k','-d' " << std::endl; 40 | std::cout << "-r represents the type of replacement algorithm, which can be either lru, clock or lru-k, the default is lru" << std::endl; 41 | std::cout << "-k represents the value of k in lru-k, which is only needed when the value of the '-r' is lru-k, the default is 2" << std::endl; 42 | std::cout << "-d represents the path of trace file, the default is '../data/data-5w-50w-zipf.txt'" << std::endl; 43 | exit(1); 44 | } 45 | } 46 | 47 | if (replacer_name.size() == 0) 48 | replacer_name = "lru"; 49 | Replacer *replacer; 50 | if (replacer_name == "lru") 51 | replacer = new LRU_Replacer(); 52 | else if (replacer_name == "clock") 53 | replacer = new CLOCK_Replacer(); 54 | else if (replacer_name == "lru-k") 55 | replacer = new LRU_k_Replacer(k); 56 | 57 | DSMgr *dsm = new DSMgr("data.dbf"); 58 | BMgr *bm = new BMgr(dsm, replacer); 59 | if (dsm->GetNumPages() == 0) 60 | { 61 | for (int i = 0; i < 50000; i++) 62 | bm->FixNewPage(); 63 | // bm->UnfixPage(); // 串行情况无需调用 64 | } 65 | 66 | if (trace_path.size() == 0) 67 | trace_path = "../data/data-5w-50w-zipf.txt"; 68 | auto trace_file = fopen(trace_path.c_str(), "r"); 69 | if (!trace_file) 70 | { 71 | std::cout << "trace file cannot be opened" << std::endl; 72 | exit(1); 73 | } 74 | 75 | auto beforeTime = std::chrono::steady_clock::now(); 76 | 77 | int r_or_w, page_num; 78 | while (fscanf(trace_file, "%d,%d", &r_or_w, &page_num) == 2) 79 | { 80 | bm->FixPage(page_num, r_or_w); // 0为read,1为write 81 | } 82 | bm->WriteDirtys(); 83 | 84 | auto afterTime = std::chrono::steady_clock::now(); 85 | double duration_second = std::chrono::duration(afterTime - beforeTime).count(); 86 | std::string statistics = "\ttime: " + std::to_string(duration_second) + "\n"; 87 | statistics.append(bm->GetStatistics()); 88 | std::cout << "replacement algorithm: " << replacer->name << std::endl; 89 | std::cout << statistics; 90 | } -------------------------------------------------------------------------------- /code/include/buffer_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef BMgr_H_ 2 | #define BMgr_H_ 3 | #include 4 | #include "data_storage_manager.h" 5 | #include "Replacer.h" 6 | 7 | class BMgr 8 | { 9 | public: 10 | BMgr(DSMgr *dsm, Replacer *replacer) 11 | { 12 | memset(ftop, -1, sizeof(ftop)); 13 | dsm_ = dsm; 14 | replacer_ = replacer; 15 | } 16 | // Interface functions 17 | int FixPage(int page_id, int prot); 18 | 19 | void FixNewPage(); 20 | 21 | int UnfixPage(int page_id); 22 | 23 | int NumFreeFrames(); 24 | 25 | // Internal Functions 26 | BCB *SelectVictim(); // 有free frame返回空指针,否则返回要被替换的frame对应的BCB 27 | 28 | int Hash(int page_id); 29 | 30 | void RemoveBCB(BCB *ptr, int page_id); 31 | 32 | void RemoveLRUEle(int frid); 33 | 34 | void SetDirty(int frame_id); 35 | 36 | void UnsetDirty(int frame_id); 37 | 38 | void WriteDirtys(); 39 | 40 | void PrintFrame(int frame_id); 41 | 42 | std::string GetStatistics(); 43 | 44 | private: 45 | // Tables 46 | int ftop[DEFBUFSIZE]; 47 | BCB *ptof[DEFBUFSIZE]; 48 | // buffer 49 | bFrame buf[DEFBUFSIZE]; 50 | // DSMgr 51 | DSMgr *dsm_; 52 | 53 | Replacer *replacer_; 54 | int total_count = 0; 55 | int hit_count = 0; 56 | // 本实验frame按顺序占用,且中途不会释放frame,所以可以只用一个first_free_frame表示 57 | // first_free_frame之前的全都不free,之后的全都free 58 | int first_free_frame = 0; 59 | 60 | BCB *hash_find_BCB(int page_id) 61 | { // 根据page_id找到对应的BCB 62 | auto bcb = ptof[Hash(page_id)]; 63 | while (bcb) 64 | { 65 | if (bcb->page_id == page_id) 66 | { 67 | break; 68 | } 69 | else 70 | bcb = bcb->next; 71 | } 72 | return bcb; 73 | } 74 | 75 | void hash_insert_BCB(BCB *bcb) 76 | { 77 | int page_id = bcb->page_id; 78 | ftop[bcb->frame_id] = page_id; 79 | auto old_bucket_head = ptof[Hash(page_id)]; 80 | ptof[Hash(page_id)] = bcb; 81 | bcb->next = old_bucket_head; 82 | } 83 | 84 | void hash_delete_BCB(int frame_id) 85 | { 86 | int page_id = ftop[frame_id]; 87 | auto bcb = ptof[Hash(page_id)]; 88 | ftop[frame_id] = -1; 89 | auto prev = bcb; 90 | if (!bcb) 91 | return; 92 | // 该page在桶的头部 93 | if (bcb->page_id == page_id) 94 | { 95 | ptof[Hash(page_id)] = bcb->next; 96 | } 97 | // 不在桶的头部,则遍历该桶查找 98 | else 99 | { 100 | prev = bcb; 101 | bcb = bcb->next; 102 | while (bcb) 103 | { 104 | if (bcb->page_id == page_id) 105 | break; 106 | else 107 | { 108 | prev = bcb; 109 | bcb = bcb->next; 110 | } 111 | } 112 | if (!bcb) 113 | return; 114 | prev->next = bcb->next; 115 | } 116 | } 117 | 118 | // old_bcb不为空则删除old_bcb再插入new_bcb;否则直接插入new_bcb 119 | void update_BCB(BCB *new_bcb, BCB *old_bcb) 120 | { 121 | if (old_bcb) 122 | { 123 | hash_delete_BCB(old_bcb->frame_id); 124 | } 125 | hash_insert_BCB(new_bcb); 126 | replacer_->Update(new_bcb, old_bcb, 0); 127 | delete old_bcb; 128 | } 129 | }; 130 | 131 | #endif -------------------------------------------------------------------------------- /code/src/buffer_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer_manager.h" 2 | 3 | // Interface functions 4 | int BMgr::FixPage(int page_id, int prot) 5 | { // prot表示是否写,0为read,1为write 6 | total_count++; 7 | auto bcb = hash_find_BCB(page_id); 8 | if (bcb) 9 | { // 命中 10 | hit_count++; 11 | if (prot) 12 | bcb->dirty = 1; // 因为没有提供实际写的数据,默认写的数据和原数据一样,不用更改frame中的值 13 | replacer_->Update(bcb, bcb, 1); // 命中时需要更新替换算法相关数据结构 14 | return bcb->frame_id; 15 | } 16 | else 17 | { // 不命中 18 | auto bcb = SelectVictim(); 19 | int frame_id; 20 | if (!bcb) 21 | { 22 | frame_id = first_free_frame - 1; 23 | } 24 | else 25 | { 26 | frame_id = bcb->frame_id; 27 | } 28 | struct bFrame bf = {dsm_->ReadPage(page_id)}; 29 | buf[frame_id] = bf; // 这里因为没有提供实际写的数据,所以就默认写的数据和原数据一样 30 | // 创建新的BCB加入ptof对应桶的头部 31 | auto new_bcb = new BCB(page_id, frame_id, 1, prot); 32 | update_BCB(new_bcb, bcb); // 更改两个表和替换算法相应的数据结构 33 | return frame_id; 34 | } 35 | } 36 | 37 | void BMgr::FixNewPage() 38 | { 39 | int page_num = dsm_->GetNumPages(); 40 | for (int i = 0; i < page_num; i++) 41 | { 42 | if (dsm_->GetUse(i) == 0) 43 | return; 44 | } 45 | // 找不到则分配新Page 46 | dsm_->IncNumPages(); 47 | } 48 | 49 | int BMgr::UnfixPage(int page_id) // 本实验未实现并发情况,不会调用该函数 50 | { 51 | auto bcb = hash_find_BCB(page_id); 52 | if (bcb) 53 | { 54 | if (bcb->count) 55 | bcb->count--; 56 | return bcb->frame_id; 57 | } 58 | return -1; 59 | } 60 | 61 | int BMgr::NumFreeFrames() 62 | { 63 | int cnt = 0; 64 | for (int i = 0; i < DEFBUFSIZE; i++) 65 | { 66 | if (ftop[i] < 0) 67 | cnt++; 68 | } 69 | return cnt; 70 | } 71 | 72 | // Internal Functions 73 | // 找到free的frame或者根据不同的替换算法找到替换frame 74 | BCB *BMgr::SelectVictim() 75 | { 76 | int frame_id; 77 | if (first_free_frame < DEFBUFSIZE) 78 | { 79 | frame_id = first_free_frame; 80 | first_free_frame++; 81 | return nullptr; 82 | } 83 | else 84 | { 85 | frame_id = replacer_->SelectVictim(); 86 | auto bcb = hash_find_BCB(ftop[frame_id]); 87 | if (bcb->dirty) 88 | { 89 | dsm_->WritePage(bcb->page_id, buf[frame_id]); 90 | bcb->dirty = 0; 91 | } 92 | return bcb; 93 | } 94 | } 95 | 96 | int BMgr::Hash(int page_id) 97 | { 98 | return page_id % DEFBUFSIZE; 99 | } 100 | 101 | void BMgr::SetDirty(int frame_id) 102 | { 103 | int page_id = ftop[frame_id]; 104 | if (page_id < 0) 105 | throw "Cannot set dirty to empty frame"; 106 | auto bcb = hash_find_BCB(page_id); 107 | if (bcb) 108 | bcb->dirty = 1; 109 | } 110 | 111 | void BMgr::UnsetDirty(int frame_id) 112 | { 113 | int page_id = ftop[frame_id]; 114 | if (page_id < 0) 115 | throw "Cannot unset dirty to empty frame"; 116 | auto bcb = hash_find_BCB(page_id); 117 | if (bcb) 118 | bcb->dirty = 0; 119 | } 120 | 121 | void BMgr::WriteDirtys() 122 | { 123 | for (int i = 0; i < DEFBUFSIZE; i++) 124 | { 125 | auto bcb = ptof[i]; 126 | while (bcb) 127 | { 128 | if (bcb->dirty) 129 | { 130 | dsm_->WritePage(bcb->page_id, buf[bcb->frame_id]); 131 | bcb->dirty = 0; 132 | } 133 | bcb = bcb->next; 134 | } 135 | } 136 | } 137 | 138 | void BMgr::PrintFrame(int frame_id) 139 | { 140 | std::cout << buf[frame_id].field << std::endl; 141 | } 142 | 143 | std::string BMgr::GetStatistics() 144 | { 145 | std::string a; 146 | a.append("\ttotal count: " + std::to_string(total_count) + "\n"); 147 | a.append("\tI/O count: " + std::to_string(dsm_->io_count) + "\n"); 148 | a.append("\thit rate: " + std::to_string((double)hit_count / total_count) + "\n"); 149 | return a; 150 | } 151 | --------------------------------------------------------------------------------