BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/src/filescan.cpp
00001 
00008 #include <cstring>
00009 #include "filescan.h"
00010 #include "exceptions/end_of_file_exception.h"
00011 #include "exceptions/file_not_found_exception.h"
00012 #include "exceptions/insufficient_space_exception.h"
00013 
00014 namespace badgerdb { 
00015 
00016 FileScan::FileScan(const std::string &name, BufMgr *bufferMgr)
00017 {
00018   try
00019   {
00020     file = new PageFile(name, false); //dont create new file
00021     //std::cout << "File:" << name << " opened.\n";
00022   }
00023   catch(FileNotFoundException e)
00024   {
00025     file = new PageFile(name, true);  //dont create new file
00026     //std::cout << "File:" << name << " created.\n";
00027   }
00028 
00029   bufMgr = bufferMgr;
00030   curDirtyFlag = false;
00031   curPage = NULL;
00032   filePageIter = file->begin();
00033 }
00034 
00035 void FileScan::gotoMark(RecordId rid)
00036 {
00037   if(curPage != NULL)
00038   {
00039     bufMgr->unPinPage(file, (*filePageIter).page_number(), curDirtyFlag);
00040   }
00041 
00042   curDirtyFlag = false;
00043   filePageIter = file->beginAt(rid.page_number);
00044   bufMgr->readPage(file, rid.page_number, curPage); 
00045   pageRecordIter = curPage->beginAt(rid.slot_number);
00046 }
00047 
00048 void FileScan::insertRecord(const std::string &rec, RecordId &outRid)
00049 {
00050   Page *iPage;
00051   PageId iPageNo;
00052 
00053   for (FileIterator iter = file->begin(); iter != file->end(); ++iter)
00054   {
00055     iPageNo = iter.getCurrentPageNo();
00056 
00057     if(iPageNo == Page::INVALID_NUMBER)
00058       break;
00059 
00060     bufMgr->readPage(file, iPageNo, iPage);
00061 
00062     try
00063     {
00064       outRid = iPage->insertRecord(rec);
00065       bufMgr->unPinPage(file, iPageNo, true);
00066       return;
00067     }
00068     catch(InsufficientSpaceException &e)
00069     {
00070       bufMgr->unPinPage(file, iPageNo, false);
00071     }
00072   }
00073 
00074   bufMgr->allocPage(file, iPageNo, iPage);
00075   outRid = iPage->insertRecord(rec);
00076   bufMgr->unPinPage(file, iPageNo, true);
00077 }
00078 
00079 void FileScan::deleteRecord(RecordId rid)
00080 {
00081   Page *dPage;
00082   bufMgr->readPage(file, rid.page_number, dPage);
00083   dPage->deleteRecord(rid);
00084   bufMgr->unPinPage(file, rid.page_number, true);
00085 }
00086 
00087 void FileScan::flushFile()
00088 {
00089   // generally must unpin last page of the scan
00090   if (curPage != NULL)
00091   {
00092     bufMgr->unPinPage(file, (*filePageIter).page_number(), curDirtyFlag);
00093     curPage = NULL;
00094     curDirtyFlag = false;
00095     filePageIter = file->begin();
00096   }
00097 
00098   bufMgr->flushFile(file);
00099 }
00100 
00101 FileScan::~FileScan()
00102 {
00103   flushFile();
00104 
00105   delete file;
00106 }
00107 
00108 void FileScan::startScan(int offsetIn, int lengthIn, Datatype typeIn, std::string filterIn, Operator opIn)
00109 {
00110   curPage = NULL;
00111   curDirtyFlag = false;
00112   filePageIter = file->begin();
00113 
00114   if (filterIn.empty()) {                        // no filtering requested
00115     filter.clear();
00116     return;
00117   }
00118 
00119   offset = offsetIn;
00120   length = lengthIn;
00121   type = typeIn;
00122   filter = filterIn;
00123   op = opIn;
00124 }
00125 
00126 void FileScan::endScan()
00127 {
00128   if (curPage != NULL)
00129   {
00130     bufMgr->unPinPage(file, (*filePageIter).page_number(), curDirtyFlag);
00131   }
00132 
00133   curPage = NULL;
00134   curDirtyFlag = false;
00135   filePageIter = file->begin();
00136   filter.clear();
00137 }
00138 
00139 void FileScan::scanNext(RecordId& outRid)
00140 {
00141   std::string rec;
00142 
00143   if(filePageIter == file->end())
00144   {
00145     throw EndOfFileException();
00146   }
00147 
00148   // special case of the first record of the first page of the file
00149   if (curPage == NULL)
00150   {
00151     // need to get the first page of the file
00152     filePageIter = file->begin();
00153     if(filePageIter == file->end())
00154     {
00155       throw EndOfFileException();
00156     }
00157    
00158     // read the first page of the file
00159     bufMgr->readPage(file, (*filePageIter).page_number(), curPage); 
00160     curDirtyFlag = false;
00161 
00162     // get the first record off the page
00163     pageRecordIter = curPage->begin(); 
00164 
00165     if(pageRecordIter != curPage->end()) 
00166     {
00167       // get pointer to record
00168       rec = *pageRecordIter;
00169       if(matchRec(rec))
00170       {
00171         outRid = pageRecordIter.getCurrentRecord();
00172         return;
00173       }
00174     }
00175   }
00176 
00177   // Loop, looking for a record that satisfied the predicate.
00178   // First try and get the next record off the current page
00179   pageRecordIter++;
00180 
00181   while(1)
00182   {
00183     while (pageRecordIter == curPage->end())
00184     {
00185       // unpin the current page
00186       bufMgr->unPinPage(file, (*filePageIter).page_number(), curDirtyFlag);
00187       curPage = NULL;
00188       curDirtyFlag = false;
00189 
00190       filePageIter++;
00191       if (filePageIter == file->end())
00192       {
00193         curPage = NULL;
00194         throw EndOfFileException();
00195       }
00196 
00197       // read the next page of the file
00198       bufMgr->readPage(file, (*filePageIter).page_number(), curPage);
00199 
00200       // get the first record off the page
00201       pageRecordIter = curPage->begin(); 
00202     }
00203 
00204     while (pageRecordIter != curPage->end())
00205     {
00206       rec = *pageRecordIter;
00207 
00208       if(matchRec(rec))
00209       {
00210         // return rid of the record
00211         outRid = pageRecordIter.getCurrentRecord();
00212         return;
00213       }
00214       pageRecordIter++;
00215     }
00216   }
00217 }
00218 
00219 // returns pointer to the current record.  page is left pinned
00220 // and the scan logic is required to unpin the page 
00221 std::string FileScan::getRecord()
00222 {
00223   return *pageRecordIter;
00224 }
00225 
00226 std::string FileScan::getRandomRecord(RecordId rid)
00227 {
00228   // Solution Starts
00229   Page* page;
00230 
00231   bufMgr->readPage(file, rid.page_number, page);
00232   std::string retStr = page->getRecord(rid);
00233   bufMgr->unPinPage(file, rid.page_number, false);
00234 
00235   return retStr;
00236 }
00237 
00238 bool FileScan::matchRec(const std::string &rec)
00239 {
00240   // no filtering requested
00241   if (filter.empty()) return true;
00242 
00243   // see if offset + length is beyond end of record
00244   // maybe this should be an error???
00245   if ((offset + length -1 ) >= rec.size())
00246     return false;
00247 
00248   double diff = 0;                       // < 0 if attr < fltr
00249   switch(type) {
00250 
00251     case INTEGER:
00252       int iattr, ifltr;                 // word-alignment problem possible
00253       memcpy(&iattr, rec.c_str() + offset,  length);
00254       memcpy(&ifltr, filter.c_str(),  length);
00255       //ifltr = atoi(filter.c_str());
00256       diff = iattr - ifltr;
00257       break;
00258 
00259     case DOUBLE:
00260       double fattr, ffltr;               // word-alignment problem possible
00261       memcpy(&fattr, rec.c_str() + offset,  length);
00262       memcpy(&ffltr, filter.c_str(),  length);
00263       //ffltr = atof(filter.c_str());
00264       diff = fattr - ffltr;
00265       break;
00266 
00267     case STRING:
00268       diff = strncmp(rec.c_str() + offset,  filter.c_str(), length);
00269       break;
00270   }
00271 
00272   switch(op) {
00273     case LT:  if (diff < 0.0) return true; break;
00274     case LTE: if (diff <= 0.0) return true; break;
00275     case EQ:  if (diff == 0.0) return true; break;
00276     case GTE: if (diff >= 0.0) return true; break;
00277     case GT:  if (diff > 0.0) return true; break;
00278     case NE:  if (diff != 0.0) return true; break;
00279     default: break;
00280   }
00281 
00282   return false;
00283 
00284 }
00285 
00286 // mark current page of scan dirty
00287 void FileScan::markDirty()
00288 {
00289   curDirtyFlag = true;
00290 }
00291 
00292 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends