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