BadgerDB
/afs/cs.wisc.edu/u/s/a/sangmin/private/btree/src/buffer.cpp
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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends