BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/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     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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends