├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md └── lab1 ├── BM.cpp ├── BM.h ├── DSM.cpp ├── DSM.h ├── data-5w-50w-zipf.txt ├── main.cpp └── readme.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | *.cbp 34 | *.layout 35 | *.save 36 | *.depend 37 | *.dbf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # USTC-Advanced-Database-System-Lab 2 | USTC Advanced Database System Lab Homework 中国科学技术大学高级数据库系统课程实验作业 3 | -------------------------------------------------------------------------------- /lab1/BM.cpp: -------------------------------------------------------------------------------- 1 | #include "bm.h" 2 | #include 3 | 4 | int hit = 0; 5 | int miss = 0; 6 | 7 | 8 | BCB::BCB(): page_id(-1), frame_id(-1), count(0), dirty(0), next(NULL) 9 | { 10 | } 11 | 12 | BMgr::BMgr() 13 | { 14 | for(int i = 0; i < DEFBUFSIZE; i++) 15 | { 16 | ftop[i] = -1; 17 | ptof[i] = NULL; 18 | buf[i] = (bFrame*)malloc( sizeof(bFrame)); 19 | } 20 | } 21 | 22 | int BMgr::newBCB(int page_id) 23 | { 24 | int frame_id = -1; 25 | BCB* bcb = new BCB(); 26 | if(lru.size() < DEFBUFSIZE) //lru没满 27 | { 28 | 29 | } 30 | else //LRU满了 需要淘汰 31 | { 32 | frame_id = SelectVictim(); //此时已经被淘汰、释放 33 | lru.remove(frame_id); 34 | } 35 | //找到ftop的空余并使用 但是需要之后的操作建立BCB->frame关系 36 | bcb->page_id = page_id; 37 | bool suc = false; 38 | for(int i = 0; i < DEFBUFSIZE; i++) 39 | if(ftop[i] == -1) 40 | { 41 | ftop[i] = page_id; 42 | bcb->frame_id = i; 43 | frame_id = i; 44 | suc = true; 45 | break; 46 | } 47 | if(suc == false)cout << "错误!LRU和ftop关系维护错误!!!!!" << endl; 48 | //新建的bcb需要连接到ptof哈希表开链上 找到BCB才获取frame 从而实现ptof 49 | BCB* head = ptof[Hash(bcb->page_id)]; 50 | if(head == NULL) //此处是空 直接指向自身 51 | { 52 | ptof[Hash(bcb->page_id)] = bcb; 53 | } 54 | else //已有 最后一项的next指向自身 55 | { 56 | while(head->next != NULL)head = head->next; 57 | head->next = bcb; 58 | } 59 | bcb->count = bcb->count + 1; 60 | 61 | lru.push_front(frame_id); 62 | return frame_id; 63 | } 64 | 65 | int BMgr::FixPage(int page_id, int prot) 66 | { 67 | int frame_id = -1; //返回值 68 | if (page_id >= 50000 || page_id<0) 69 | { 70 | cout << "警告!!测试数据超出允许范围! " <next != NULL && bcb->page_id != page_id) 78 | { 79 | bcb = bcb->next; 80 | } 81 | if(bcb != NULL && bcb->page_id == page_id) //准备读写的页面已经在缓存中,应该更新lru表 缓存命中 82 | { 83 | hit += 1; 84 | frame_id = bcb->frame_id; 85 | lru.remove(frame_id); 86 | lru.push_front(frame_id); 87 | bcb->count = bcb->count + 1; 88 | } 89 | else //准备读写的页面不在缓存中,需要读取、建立BCB、检查并处理LRU是否需要淘汰、更新LRU 90 | { 91 | miss += 1; 92 | frame_id = newBCB(page_id); 93 | memcpy(buf[frame_id], (ds.ReadPage(page_id)).field, sizeof(*(buf[frame_id]))); 94 | } 95 | 96 | return frame_id; 97 | } 98 | 99 | NewPage BMgr::FixNewPage() //题目写错了! 100 | { 101 | NewPage newpage; 102 | int i=0; 103 | for(i = 0; i < ds.GetNumPages(); i++) 104 | { 105 | if(ds.GetUse(i) == 0)break; 106 | } 107 | if(i == ds.GetNumPages()) //所有page都被使用 需要增加dbf文件大小 108 | { 109 | ds.IncNumPages(); 110 | ds.SetUse(i, 1); 111 | } 112 | newpage.page_id = i; 113 | newpage.frame_id = FixPage(i, 0); 114 | return newpage; 115 | } 116 | 117 | int BMgr::UnfixPage(int page_id) 118 | { 119 | BCB* bcb = ptof[Hash(page_id)]; 120 | while(bcb->next != NULL && bcb->page_id != page_id) 121 | { 122 | bcb = bcb->next; 123 | } 124 | if(bcb == NULL) 125 | { 126 | cout << "缓存错误!尝试释放不在缓存中的页面!" << endl; 127 | } 128 | bcb->count = bcb->count - 1; 129 | return bcb->frame_id; 130 | } 131 | 132 | int BMgr::NumFreeFrames() 133 | { 134 | int answer = 0; 135 | for (int i = 0; i < DEFBUFSIZE; i++) 136 | { 137 | if(ftop[i] == -1) 138 | { 139 | answer += 1; 140 | } 141 | } 142 | return answer; 143 | } 144 | 145 | // Internal Functions 146 | int BMgr::SelectVictim() 147 | { 148 | int answer; 149 | BCB* bcb = NULL; 150 | list::iterator it = lru.end(); //指向尾部后面一个元素 151 | while(1) 152 | { 153 | if(it == lru.begin())break; 154 | it--; 155 | bcb = ptof[Hash(ftop[*it])]; 156 | while(bcb->frame_id != *it && bcb->next != NULL) bcb = bcb->next; 157 | if(bcb->frame_id == *it && bcb->count <= 0)break; 158 | } 159 | if(bcb->frame_id != *it || bcb->count > 0) 160 | { 161 | cout << "错误!Buffer中所有项目都被占用,无法释放!" << endl; 162 | return -1; 163 | } 164 | else 165 | { 166 | answer = bcb->frame_id; 167 | if(bcb->dirty == true) 168 | { 169 | ds.WritePage(bcb->page_id, *(buf[answer])); 170 | } 171 | RemoveBCB(bcb, bcb->page_id); 172 | return answer; 173 | } 174 | } 175 | 176 | int BMgr::Hash(int page_id) 177 | { 178 | return page_id % DEFBUFSIZE; 179 | } 180 | 181 | void BMgr::RemoveBCB(BCB * ptr, int page_id) //删除链表元素 182 | { 183 | BCB* head = ptof[Hash(ptr->page_id)]; 184 | ftop[ptr->frame_id] = -1; //释放哈希表 185 | if(head == ptr) //要删除的是链表头 186 | { 187 | ptof[Hash(ptr->page_id)] = ptr->next; 188 | delete ptr; 189 | } 190 | else //要删除的不是头 191 | { 192 | while(head->next != ptr)head = head->next; 193 | head->next = ptr->next; 194 | delete ptr; 195 | } 196 | } 197 | 198 | void BMgr::RemoveLRUEle(int frid) 199 | { 200 | lru.remove(frid); 201 | } 202 | 203 | void BMgr::SetDirty(int frame_id) 204 | { 205 | BCB* bcb = ptof[Hash(ftop[frame_id])]; 206 | while(bcb->next != NULL && bcb->frame_id != frame_id)bcb = bcb->next; 207 | if(bcb->frame_id != frame_id)cout << "错误!缓存内容异常!!!!!!!!!!!!"; 208 | else bcb->dirty = 1; 209 | } 210 | 211 | void BMgr::UnsetDirty(int frame_id) 212 | { 213 | BCB* bcb = ptof[Hash(ftop[frame_id])]; 214 | while(bcb->next != NULL && bcb->frame_id != frame_id)bcb = bcb->next; 215 | if(bcb->frame_id != frame_id)cout << "错误!缓存内容异常!!!!!!!!!!!!"; 216 | else bcb->dirty = 0; 217 | } 218 | 219 | void BMgr::WriteDirtys() 220 | { 221 | list::iterator it; 222 | for(it = lru.begin(); it != lru.end(); it++) 223 | { 224 | BCB* bcb = ptof[Hash(ftop[*it])]; 225 | while(bcb->next != NULL && bcb->frame_id != *it)bcb = bcb->next; 226 | if(bcb->frame_id != *it) 227 | { 228 | cout << "错误!缓存内容异常!!!!!!!!!!!!无法判断是否应该写回"; 229 | } 230 | else 231 | { 232 | if(bcb->dirty == 1) 233 | { 234 | ds.WritePage(bcb->page_id, *(buf[bcb->frame_id])); 235 | } 236 | } 237 | } 238 | } 239 | void BMgr::PrintFrame(int frame_id) 240 | { 241 | cout << "frame_id:" << frame_id << " \nvalue:" << (*buf[frame_id]).field << endl; 242 | } 243 | 244 | 245 | -------------------------------------------------------------------------------- /lab1/BM.h: -------------------------------------------------------------------------------- 1 | #ifndef BM_H_INCLUDED 2 | #define BM_H_INCLUDED 3 | 4 | #include "dsm.h" 5 | #include 6 | #include 7 | struct NewPage 8 | { 9 | int page_id; 10 | int frame_id; 11 | }; 12 | 13 | struct BCB 14 | { 15 | BCB(); 16 | int page_id; 17 | int frame_id; 18 | int count; 19 | int dirty; 20 | BCB * next; 21 | }; 22 | 23 | class BMgr 24 | { 25 | public: 26 | 27 | BMgr(); 28 | // Interface functions 29 | int FixPage(int page_id, int prot); 30 | NewPage FixNewPage(); //题目写错了! 而且这个函数根本用不到! 31 | int UnfixPage(int page_id); 32 | int NumFreeFrames(); 33 | // Internal Functions 34 | int SelectVictim(); 35 | int Hash(int page_id); 36 | void RemoveBCB(BCB * ptr, int page_id); 37 | void RemoveLRUEle(int frid); 38 | void SetDirty(int frame_id); 39 | void UnsetDirty(int frame_id); 40 | void WriteDirtys(); 41 | void PrintFrame(int frame_id); 42 | //自定义函数 43 | DSMgr ds; //Data Storage Manager of this Buffer Manager 44 | 45 | private: 46 | 47 | // Hash Table page_id:0-49999 frame_id of buf:0-4095 48 | int ftop[DEFBUFSIZE]; //frame_id to page_id, default value -1 49 | BCB *ptof[DEFBUFSIZE]; //page_id to BCB chain head (contains BCB->frame_id) 例如实体文件page的4096*1、2、3都进了缓存 这些的ptof是个链表 即开链法解决哈希冲突 50 | 51 | list lru; //lru列表 内容为frame_id list头表示最近使用 尾部表示最近最久未使用 52 | bFrame* buf[DEFBUFSIZE]; // or the size that the user defined by the input parameter --X 53 | int newBCB(int page_id); //return frame_id 54 | }; 55 | 56 | 57 | #endif // BM_H_INCLUDED 58 | -------------------------------------------------------------------------------- /lab1/DSM.cpp: -------------------------------------------------------------------------------- 1 | #include "dsm.h" 2 | 3 | int read = 0; 4 | int write = 0; 5 | 6 | 7 | int DSMgr::OpenFile(string filename) 8 | { 9 | cout<<"打开dbf文件"< char 35 | char pagesbyte[MAXPAGES]; 36 | memset(pagesbyte, 0, numPages); 37 | for(int i = 0; i < numPages; i++) 38 | { 39 | if(pages[i] == 0) 40 | pagesbyte[i] = '0'; 41 | else 42 | pagesbyte[i] = '1'; 43 | } 44 | //--------------- 45 | fwrite(pagesbyte, numPages, 1, currFile); 46 | return fclose(currFile); 47 | } 48 | 49 | bFrame DSMgr::ReadPage(int page_id) 50 | { 51 | bFrame bf; 52 | Seek(PagesStart, page_id * 4); 53 | int p; 54 | fread(&p, 4, 1, currFile); 55 | 56 | Seek(PagesStart, p); 57 | fread(bf.field, FRAMESIZE, 1, currFile); 58 | read+=1; 59 | return bf; 60 | } 61 | 62 | int DSMgr::WritePage(int page_id, bFrame frm) //写页时不涉及写入页使用情况 63 | { 64 | Seek(PagesStart, page_id * 4); 65 | int p; 66 | fread(&p, 4, 1, currFile); 67 | 68 | Seek(PagesStart, p); 69 | fwrite(frm.field, FRAMESIZE, 1, currFile); 70 | write+=1; 71 | return FRAMESIZE; 72 | } 73 | 74 | int DSMgr::Seek(int offset, int pos) 75 | { 76 | return fseek(currFile, offset + pos, SEEK_SET); 77 | } 78 | 79 | FILE * DSMgr::GetFile() 80 | { 81 | return currFile; 82 | } 83 | 84 | void DSMgr::IncNumPages() 85 | { 86 | if(numPages >= 53248)cout << "警告!超出实验允许的范围,dbf文件将损坏!!!" << endl; 87 | numPages++; 88 | } 89 | 90 | int DSMgr::GetNumPages() 91 | { 92 | return numPages; 93 | } 94 | 95 | void DSMgr::SetUse(int index, int use_bit) 96 | { 97 | if(pages[index]==0 && use_bit==1) //新开辟 98 | { 99 | int p=((MAXPAGES*4-1)/4096+1)*4096+4096*index; 100 | Seek(PagesStart,index*4); 101 | fwrite(&p, 4, 1, currFile); //写入指针 102 | Seek(PagesStart,p); 103 | bFrame b; 104 | memset(b.field,0,FRAMESIZE); 105 | fwrite(b.field,FRAMESIZE,1,currFile); 106 | } 107 | pages[index] = use_bit; 108 | } 109 | 110 | int DSMgr::GetUse(int index) 111 | { 112 | return pages[index]; 113 | } 114 | 115 | //自定义函数 116 | void DSMgr::InitFile(string filename) 117 | { 118 | FILE* file = fopen(filename.c_str(), "w"); 119 | char usage[1] = {'0'}; 120 | int page_count=0; 121 | fwrite(&page_count, 4, 1, file); //写入int类型的0 占4个字节 122 | for(int i = 0; i < MAXPAGES; i++) 123 | fwrite(usage, 1, 1, file); //写50000个1字节的'0' 124 | fclose(file); 125 | } 126 | -------------------------------------------------------------------------------- /lab1/DSM.h: -------------------------------------------------------------------------------- 1 | #ifndef DSM_H_INCLUDED 2 | #define DSM_H_INCLUDED 3 | 4 | #define DEFBUFSIZE 1 5 | #define FRAMESIZE 4096 6 | #define MAXPAGES 50000 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | struct bFrame 15 | { 16 | char field[FRAMESIZE]; //题目写错了!typo 17 | }; 18 | 19 | 20 | class DSMgr 21 | { 22 | public: 23 | int OpenFile(string filename); 24 | int CloseFile(); 25 | bFrame ReadPage(int page_id); 26 | int WritePage(int frame_id, bFrame frm); 27 | int Seek(int offset, int pos); 28 | FILE * GetFile(); 29 | void IncNumPages(); 30 | int GetNumPages(); 31 | void SetUse(int index, int use_bit); 32 | int GetUse(int index); 33 | //自定义函数 34 | void InitFile(string filename); 35 | 36 | private: 37 | FILE *currFile; 38 | int numPages; //页数 就是50000 实验中应该不会变 39 | int pages[MAXPAGES]; //就是初始化那里写了50000个1的地方 表示对应的page是否被使用 实验中应该都是1 40 | //自定义数据 41 | int PagesStart;//Page内容开始的字节数 应该对齐4096 从页数、50000个1之后开始 42 | }; 43 | 44 | #endif // DSM_H_INCLUDED 45 | -------------------------------------------------------------------------------- /lab1/main.cpp: -------------------------------------------------------------------------------- 1 | #include "bm.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | extern int hit; 9 | extern int miss; 10 | extern int read; 11 | extern int write; 12 | 13 | int main() 14 | { 15 | 16 | cout << "创建空dbf文件" << endl; 17 | FILE* file = fopen("data.dbf", "w"); 18 | fclose(file); 19 | cout << "创建dbf文件完毕" << endl; 20 | 21 | BMgr buffer_manager; 22 | BMgr buffer_manager_init; //初始化用的 23 | 24 | buffer_manager_init.ds.InitFile("data.dbf"); 25 | buffer_manager_init.ds.OpenFile("data.dbf"); 26 | for (int i=0;i<50000;i++) 27 | { 28 | NewPage newpage; 29 | newpage=buffer_manager_init.FixNewPage(); 30 | buffer_manager_init.UnfixPage(newpage.page_id); 31 | } 32 | buffer_manager_init.ds.CloseFile(); 33 | cout << "hit: " << hit << " miss:" << miss << endl; 34 | cout << "DSMgr初始化dbf文件完毕\n\n开始测试" << endl; 35 | 36 | hit=0;miss=0;read=0;write=0; 37 | buffer_manager.ds.OpenFile("data.dbf"); 38 | FILE* file2 = fopen("data-5w-50w-zipf.txt", "r"); 39 | // FILE* file2 = fopen("t2.txt", "r"); 40 | int operation; 41 | int page; 42 | int frame_id; 43 | int i = 0; 44 | while(fscanf(file2, "%d,%d", &operation, &page) != EOF) 45 | { 46 | i++; 47 | page-=1; 48 | frame_id = buffer_manager.FixPage(page, 0); 49 | if(operation == 1) 50 | { 51 | //if write, set frame to dirty 52 | buffer_manager.SetDirty(frame_id); 53 | } 54 | buffer_manager.UnfixPage(page); 55 | } 56 | buffer_manager.WriteDirtys(); 57 | buffer_manager.ds.CloseFile(); 58 | cout << "total tests:" << i << "\nhit: " << hit << " miss:" << miss << " read:" << read << " write:" << write << endl; 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /lab1/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1970633640/USTC-Advanced-Database-System-Lab/f06ae72b66591e680f7dc7a37efa57bbe1f7409e/lab1/readme.txt --------------------------------------------------------------------------------