BadgerDB
|
00001 00008 #include <memory> 00009 #include <iostream> 00010 #include "buffer.h" 00011 #include "exceptions/buffer_exceeded_exception.h" 00012 #include "exceptions/page_not_pinned_exception.h" 00013 #include "exceptions/page_pinned_exception.h" 00014 #include "exceptions/bad_buffer_exception.h" 00015 #include "exceptions/hash_not_found_exception.h" 00016 00017 namespace badgerdb { 00018 00019 //---------------------------------------- 00020 // Constructor of the class BufMgr 00021 //---------------------------------------- 00022 00023 BufMgr::BufMgr(std::uint32_t bufs) 00024 : numBufs(bufs) { 00025 bufDescTable = new BufDesc[bufs]; 00026 00027 for (FrameId i = 0; i < bufs; i++) 00028 { 00029 bufDescTable[i].frameNo = i; 00030 bufDescTable[i].valid = false; 00031 } 00032 00033 bufPool = new Page[bufs]; 00034 00035 int htsize = ((((int) (bufs * 1.2))*2)/2)+1; 00036 hashTable = new BufHashTbl (htsize); // allocate the buffer hash table 00037 00038 clockHand = bufs - 1; 00039 } 00040 00041 00042 BufMgr::~BufMgr() { 00043 //Flush out all unwritten pages 00044 for (std::uint32_t i = 0; i < numBufs; i++) 00045 { 00046 std::cerr << "index:" << i << "\n"; 00047 BufDesc* tmpbuf = &bufDescTable[i]; 00048 if (tmpbuf->valid == true && tmpbuf->dirty == true) 00049 { 00050 tmpbuf->file->writePage(tmpbuf->pageNo, bufPool[i]); 00051 } 00052 } 00053 00054 delete [] bufDescTable; 00055 delete [] bufPool; 00056 } 00057 00058 void BufMgr::allocBuf(FrameId & frame) 00059 { 00060 // perform first part of clock algorithm to search for 00061 // open buffer frame 00062 // Assumes non-concurrent access to buffer manager 00063 std::uint32_t numScanned = 0; 00064 bool found = 0; 00065 00066 while (numScanned < 2*numBufs) //Need to scn twice 00067 { 00068 // advance the clock 00069 advanceClock(); 00070 numScanned++; 00071 00072 // if invalid, use frame 00073 if (! bufDescTable[clockHand].valid) 00074 { 00075 break; 00076 } 00077 00078 // is valid, check referenced bit 00079 if (! bufDescTable[clockHand].refbit) 00080 { 00081 // check to see if someone has it pinned 00082 if (bufDescTable[clockHand].pinCnt == 0) 00083 { 00084 // hasn't been referenced and is not pinned, use it 00085 // remove previous entry from hash table 00086 hashTable->remove(bufDescTable[clockHand].file, bufDescTable[clockHand].pageNo); 00087 found = true; 00088 break; 00089 } 00090 } 00091 else 00092 { 00093 // has been referenced, clear the bit 00094 bufStats.accesses++; 00095 bufDescTable[clockHand].refbit = false; 00096 } 00097 } 00098 00099 // check for full buffer pool 00100 if (!found && numScanned >= 2*numBufs) 00101 { 00102 throw BufferExceededException(); 00103 } 00104 00105 // flush any existing changes to disk if necessary 00106 if (bufDescTable[clockHand].dirty) 00107 { 00108 bufStats.diskwrites++; 00109 //status = bufDescTable[clockHand].file->writePage(bufDescTable[clockHand].pageNo, 00110 bufDescTable[clockHand].file->writePage(bufDescTable[clockHand].pageNo, bufPool[clockHand]); 00111 } 00112 00113 //Reset all the BufDesc entry for the frame before returning the frame 00114 bufDescTable[clockHand].Clear(); 00115 00116 // return new frame number 00117 frame = clockHand; 00118 } // end allocBuf 00119 00120 00121 void BufMgr::readPage(File* file, const PageId pageNo, Page*& page) 00122 { 00123 // check to see if it is already in the buffer pool 00124 // std::cout << "readPage called on file.page " << file << "." << pageNo << endl; 00125 FrameId frameNo = 0; 00126 try 00127 { 00128 hashTable->lookup(file, pageNo, frameNo); 00129 00130 // set the referenced bit 00131 bufDescTable[frameNo].refbit = true; 00132 bufDescTable[frameNo].pinCnt++; 00133 page = &bufPool[frameNo]; 00134 } 00135 catch(HashNotFoundException e) //not in the buffer pool, must allocate a new page 00136 { 00137 // alloc a new frame 00138 allocBuf(frameNo); 00139 00140 // read the page into the new frame 00141 bufStats.diskreads++; 00142 //status = file->readPage(pageNo, &bufPool[frameNo]); 00143 bufPool[frameNo] = file->readPage(pageNo); 00144 00145 // set up the entry properly 00146 bufDescTable[frameNo].Set(file, pageNo); 00147 page = &bufPool[frameNo]; 00148 00149 // insert in the hash table 00150 hashTable->insert(file, pageNo, frameNo); 00151 } 00152 } 00153 00154 00155 void BufMgr::unPinPage(File* file, const PageId pageNo, 00156 const bool dirty) 00157 { 00158 // lookup in hashtable 00159 FrameId frameNo = 0; 00160 hashTable->lookup(file, pageNo, frameNo); 00161 00162 if (dirty == true) bufDescTable[frameNo].dirty = dirty; 00163 00164 // make sure the page is actually pinned 00165 if (bufDescTable[frameNo].pinCnt == 0) 00166 { 00167 throw PageNotPinnedException(file->filename(), pageNo, frameNo); 00168 } 00169 else bufDescTable[frameNo].pinCnt--; 00170 } 00171 00172 void BufMgr::flushFile(const File* file) 00173 { 00174 for (std::uint32_t i = 0; i < numBufs; i++) 00175 { 00176 BufDesc* tmpbuf = &(bufDescTable[i]); 00177 if(tmpbuf->valid == true && tmpbuf->file == file) 00178 { 00179 if (tmpbuf->pinCnt > 0) 00180 throw PagePinnedException(file->filename(), tmpbuf->pageNo, tmpbuf->frameNo); 00181 00182 if (tmpbuf->dirty == true) 00183 { 00184 //if ((status = tmpbuf->file->writePage(tmpbuf->pageNo, &(bufPool[i]))) != OK) 00185 tmpbuf->file->writePage(tmpbuf->pageNo, bufPool[i]); 00186 tmpbuf->dirty = false; 00187 } 00188 00189 hashTable->remove(file,tmpbuf->pageNo); 00190 tmpbuf->Clear(); 00191 } 00192 else if (tmpbuf->valid == false && tmpbuf->file == file) 00193 throw BadBufferException(tmpbuf->frameNo, tmpbuf->dirty, tmpbuf->valid, tmpbuf->refbit); 00194 } 00195 } 00196 00197 void BufMgr::disposePage(File* file, const PageId pageNo) 00198 { 00199 //Deallocate from file altogether 00200 //See if it is in the buffer pool 00201 FrameId frameNo = 0; 00202 hashTable->lookup(file, pageNo, frameNo); 00203 00204 // clear the page 00205 bufDescTable[frameNo].Clear(); 00206 00207 hashTable->remove(file, pageNo); 00208 00209 // deallocate it in the file 00210 file->deletePage(pageNo); 00211 } 00212 00213 00214 void BufMgr::allocPage(File* file, PageId &pageNo, Page*& page) 00215 { 00216 FrameId frameNo; 00217 00218 // alloc a new frame 00219 allocBuf(frameNo); 00220 00221 // allocate a new page in the file 00222 //std::cerr << "buffer data size:" << bufPool[frameNo].data_.length() << "\n"; 00223 bufPool[frameNo] = file->allocatePage(pageNo); 00224 page = &bufPool[frameNo]; 00225 00226 // set up the entry properly 00227 bufDescTable[frameNo].Set(file, pageNo); 00228 00229 // insert in the hash table 00230 hashTable->insert(file, pageNo, frameNo); 00231 } 00232 00233 int BufMgr::numUnpinnedPages() 00234 { 00235 int retValue = 0; 00236 BufDesc* tmpbuf; 00237 00238 for(std::uint32_t i = 0; i < numBufs; i++) 00239 { 00240 tmpbuf = &(bufDescTable[i]); 00241 00242 if(tmpbuf->pinCnt == 0) 00243 retValue++; 00244 } 00245 00246 return retValue; 00247 } 00248 00249 void BufMgr::printSelf(void) 00250 { 00251 BufDesc* tmpbuf; 00252 int validFrames = 0; 00253 00254 for (std::uint32_t i = 0; i < numBufs; i++) 00255 { 00256 tmpbuf = &(bufDescTable[i]); 00257 std::cout << "FrameNo:" << i << " "; 00258 tmpbuf->Print(); 00259 00260 if (tmpbuf->valid == true) 00261 validFrames++; 00262 } 00263 00264 std::cout << "Total Number of Valid Frames:" << validFrames << "\n"; 00265 } 00266 00267 }