BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/src/btree.cpp
00001 
00008 #include "btree.h"
00009 #include "filescan.h"
00010 #include "exceptions/bad_index_info_exception.h"
00011 #include "exceptions/bad_opcodes_exception.h"
00012 #include "exceptions/bad_scanrange_exception.h"
00013 #include "exceptions/no_such_key_found_exception.h"
00014 #include "exceptions/scan_not_initialized_exception.h"
00015 #include "exceptions/index_scan_completed_exception.h"
00016 #include "exceptions/file_not_found_exception.h"
00017 #include "exceptions/end_of_file_exception.h"
00018 #include "exceptions/page_not_pinned_exception.h"
00019 
00020 
00021 //#define DEBUG
00022 
00023 namespace badgerdb
00024 {
00025 // -----------------------------------------------------------------------------
00026 // BTreeIndex::fillLeafNodes 
00027 // -----------------------------------------------------------------------------
00028 template <class T>
00029 int BTreeIndex::fillLeafNodes( 
00030     std::deque< PageKeyPair< T > > &thisLevelNodes,
00031     std::deque< RIDKeyPair< T > > &dataList)
00032 {
00033   bool firstPage = true;
00034   PageKeyPair< T > tempPair;
00035   PageId pageNo = 0;
00036   PageId lastPageNo=0;
00037   Page* currentPage = NULL;
00038   Page* lastPage = NULL;
00039   int currentPageIndex = 0;
00040   
00041   //while there are elements on list
00042   while( dataList.size() != 0 )
00043   {
00044     //allocate a page if no space left on current page and then put 1st value and page number into list
00045     if( currentPage == NULL || currentPageIndex >= (leafOccupancy+1)/2 )
00046     {
00047       //save the value of the last page allocated so that its right sib
00048       //ptr can be set once we allocate this new page
00049       lastPageNo = pageNo;
00050       lastPage = currentPage;
00051       //allocate a new page
00052       bufMgr->allocPage( file, pageNo, currentPage );
00053 
00054       zeroOutLeaf(currentPage);
00055       //can only set the right sib ptr once the second page has been 
00056       //allocated. so skip the first time
00057       if( !firstPage)
00058       {
00059         copySibPtr( pageNo, lastPage );
00060         bufMgr->unPinPage( file, lastPageNo, true);
00061       }
00062       currentPageIndex = 0;
00063       //so entries in thisLevelNodes have keys corresponding to first entries in leaf nodes
00064       tempPair.set( pageNo, dataList.front().key ); 
00065       thisLevelNodes.push_back( tempPair );
00066     }
00067     #ifdef DEBUG
00068       std::cout << "Adding data: " << dataList.front().key << " to page " << pageNo << std::endl;
00069     #endif
00070     
00071     // put the values into the page
00072     copyKey<T>( dataList.front().key, currentPage, currentPageIndex, true);
00073     copyRid( dataList.front().rid, currentPage, currentPageIndex);
00074     firstPage = false;
00075     
00076     //delete data off of list
00077     dataList.pop_front();
00078     currentPageIndex++;
00079   }
00080   //set the right sib ptr of the last page allocated to 0
00081   if( currentPage!= NULL ) copySibPtr( 0, currentPage );
00082   if( currentPage!= NULL ) bufMgr->unPinPage( file, pageNo, true);
00083   return pageNo;
00084 }
00085 
00086 // -----------------------------------------------------------------------------
00087 // BTreeIndex::fillNonLeafNodes
00088 // -----------------------------------------------------------------------------
00089 template <class T>
00090 int BTreeIndex::fillNonLeafNodes( 
00091   std::deque< PageKeyPair< T > > &thisLevelNodes,
00092   std::deque< PageKeyPair< T > > &lastLevelNodes,
00093   const int level)
00094 {
00095   PageKeyPair< T > tempPair;
00096   PageId pageNo;
00097   PageId lastPageNo;
00098   Page* currentPage = NULL;
00099   int currentPageIndex = 0;
00100   bool firstPage = true;
00101   
00102   //while there are elements on list
00103   while( lastLevelNodes.size() != 0 )
00104   {
00105     //allocate a page if no space left on current page and then put 1st value and page number into list
00106     if( currentPage == NULL || currentPageIndex >= (nodeOccupancy+1)/2 )
00107     {
00108       lastPageNo = pageNo;
00109       bufMgr->allocPage( file, pageNo, currentPage );
00110       zeroOutNonLeaf(currentPage);
00111       if( !firstPage) 
00112       {
00113         bufMgr->unPinPage( file, lastPageNo, true);
00114       }     
00115       currentPageIndex = 0;
00116       tempPair.set( pageNo, lastLevelNodes.front().key ) ;
00117       thisLevelNodes.push_back( tempPair );
00118       //first entry is just the pageno, key corresponding to it is passed to the parent page, 
00119       //so first page has keys greater than or equal to parent's key for this page
00120       copyPageNo( lastLevelNodes.front().pageNo, currentPage, 0 );
00121       copyLevel( level, currentPage );
00122       #ifdef DEBUG
00123         std::cout << "Creating Page # " << pageNo << std::endl;
00124       #endif
00125     }
00126     // Otherwise, copy key as well
00127     else
00128     {
00129       copyPageNo( lastLevelNodes.front().pageNo, currentPage, currentPageIndex );
00130       //NOTE -1 BELOW 
00131       copyKey( lastLevelNodes.front().key, currentPage, currentPageIndex-1, false );
00132     }
00133     //delete data off of list
00134     #ifdef DEBUG
00135       std::cout << "Adding data: " << lastLevelNodes.front().key << " that points to Page: " 
00136       << lastLevelNodes.front().pageNo << std::endl;
00137     #endif
00138     lastLevelNodes.pop_front();
00139     currentPageIndex++;
00140     firstPage = false;
00141   }
00142   if( currentPage!= NULL ) bufMgr->unPinPage( file, pageNo, true);
00143   return pageNo;
00144 }
00145 
00146 // -----------------------------------------------------------------------------
00147 // BTreeIndex::BtreeTemplateConstructor
00148 // -----------------------------------------------------------------------------
00149 template <class T>
00150 void BTreeIndex::BTreeTemplateConstructor(const std::string & relationName,
00151     std::string & outIndexName,
00152     const int attrByteOffset,
00153     const Datatype attrType)
00154 {
00155   Page* metap;
00156   IndexMetaInfo* metaPage;
00157   scanExecuting = false;
00158 
00159   #ifdef DEBUG
00160     std::cout << "Initializing constructor" << std::endl;
00161   #endif
00162   // Set Class values
00163   switch( attrType ){
00164     case INTEGER:
00165       leafOccupancy = INTARRAYLEAFSIZE; 
00166       nodeOccupancy = INTARRAYNONLEAFSIZE; 
00167       break;
00168     case DOUBLE:
00169       leafOccupancy = DOUBLEARRAYLEAFSIZE; 
00170       nodeOccupancy = DOUBLEARRAYNONLEAFSIZE; 
00171       break;
00172     case STRING:
00173       leafOccupancy = STRINGARRAYLEAFSIZE; 
00174       nodeOccupancy = STRINGARRAYNONLEAFSIZE; 
00175       break;
00176     default: break;
00177   }
00178   attributeType = attrType;
00179   
00180   //create indexfile name
00181   std::ostringstream idxStr;
00182   idxStr << relationName << '.' << attrByteOffset;
00183   outIndexName = idxStr.str(); // indexName is the name of the index file
00184 
00185   //check to see if the indexfile already exists and if so open it
00186   //Sandeep::TODO delete file when done
00187   file = 0;
00188   try
00189   {
00190     file = new BlobFile(outIndexName, false/*open*/); //open file
00191 
00192     //if the file opened successfully return from constructor
00193     bufMgr->readPage( file, 1, metap);
00194     metaPage = (IndexMetaInfo*) metap;
00195 
00196     //check to make sure that the relationname input matches the relation
00197     //name stored in the metapage for the index
00198     if( strncmp(metaPage->relationName, relationName.c_str(), 20) )
00199     {
00200       throw BadIndexInfoException("Index relation name doesn't match parameters");
00201     }
00202     //check the attrByteOffset input with the one stored for the key value 
00203     //for which the tree was created.
00204     else if( metaPage->attrByteOffset != attrByteOffset )
00205     {
00206       throw BadIndexInfoException("Index attrByteOffset doesn't match parameters");
00207     }
00208     //make sure the types match
00209     else if( metaPage->attrType != attrType )
00210     {
00211       throw BadIndexInfoException("Index attribute type doesn't match parameters");
00212     }
00213     else
00214     {
00215       //if the index was openned and is indeed for this relation
00216       //store the value of the rootpageno so that the tree can be 
00217       //searched and inserted into
00218       rootPageNum = metaPage->rootPageNo;
00219     }
00220 
00221     bufMgr->unPinPage( file, 1, false);
00222     return;
00223   }
00224   catch(FileNotFoundException e)
00225   {
00226   }
00227 
00228   //if the file did not open create a file and store the index
00229   #ifdef DEBUG
00230     std::cout << "File " << outIndexName << " does not exist." << std::endl;
00231   #endif
00232 
00233   file = new BlobFile(outIndexName, true/*create*/);  //create file
00234 
00235   //scan the heap file for all records and store the <index key,rid>
00236   //in an array 
00237   FileScan fileScan(relationName, bufMgr);
00238   
00239   RecordId currentRID;
00240   std::string currentRecord;
00241   
00242   std::deque< RIDKeyPair< T > > dataList;
00243 
00244   try
00245   {
00246     while(1)
00247     {
00248       fileScan.scanNext(currentRID);
00249       currentRecord = fileScan.getRecord();
00250       dataList.push_back( copyRecordToRidKeyPair<T>( currentRecord, currentRID, attrByteOffset) );
00251     }
00252   }
00253   catch(EndOfFileException e)
00254   {
00255     //THIS IS EXPECTED
00256     //if an error occured and we didnt reach the end of the file 
00257     //delete file;  //this will call the file destructor and close the file
00258     //file = 0;
00259     //File::remove(outIndexName);
00260     //return;
00261   }
00262 
00263   //sort the datalist deque 
00264   sort(dataList.begin(), dataList.end());
00265   if(dataList.size() == 0)
00266   {
00267     bufMgr->flushFile(file);
00268     delete file;  //this will call the file destructor and close the file
00269     file = 0;
00270     File::remove(outIndexName);
00271     return;
00272   } 
00273 
00274   PageId pageNo = 0;
00275   //allocate a page for the meta information - will always be page 1
00276   bufMgr->allocPage( file, pageNo, metap );
00277   metaPage = (IndexMetaInfo*)(metap);
00278   headerPageNum = pageNo;
00279   PageId nextLevelNode = 1;
00280   
00281   //when creating a level each value not placed into node is placed into
00282   //this deqeu and then once the current level is created this deque becomes
00283   //lastlevelnodes and is used to create the next level
00284   std::deque< PageKeyPair< T > > thisLevelNodes;
00285   //contains the values that will be used to create a level above the last level created
00286   std::deque< PageKeyPair< T > > lastLevelNodes;
00287   #ifdef DEBUG
00288     std::cout << "Filling Leaf Nodes" << std::endl;
00289   #endif
00290   pageNo = fillLeafNodes( lastLevelNodes, dataList);
00291   //Create all non-root nodes
00292   //keeps creating levels of the tree till we dont reach a point where
00293   // the lastLevelNodes only has enough entries to make one node
00294   //for the next level as that means that level is the root and we done.
00295   while( lastLevelNodes.size() > static_cast<unsigned int>((nodeOccupancy+1)/2) )
00296   {
00297     fillNonLeafNodes<T>( thisLevelNodes, lastLevelNodes, nextLevelNode);
00298     lastLevelNodes = thisLevelNodes;
00299     thisLevelNodes.clear();
00300     nextLevelNode = 0;
00301   }
00302   
00303   // Create root node
00304   rootPageNum = fillNonLeafNodes<T>( thisLevelNodes, lastLevelNodes, nextLevelNode);
00305   // assign pageNo and other information to metapage
00306   strncpy( metaPage->relationName, relationName.c_str(), 20);
00307   metaPage->attrByteOffset = attrByteOffset;
00308   metaPage->attrType = attrType;
00309   metaPage->rootPageNo = rootPageNum;
00310   bufMgr->unPinPage( file, headerPageNum, true);
00311   //printTreeExternal();
00312 }
00313 
00314 // -----------------------------------------------------------------------------
00315 // BTreeIndex::BTreeIndex -- Constructor
00316 // -----------------------------------------------------------------------------
00317 BTreeIndex::BTreeIndex(const std::string & relationName,
00318     std::string & outIndexName,
00319     BufMgr *bufMgrIn,
00320     const int attrByteOffset,
00321     const Datatype attrType)
00322 {
00323   bufMgr = bufMgrIn;
00324   //call the appropriate templated version of the BtreeTemplateConstructor based
00325   //on the attr type
00326   switch( attrType ){
00327     case INTEGER:
00328       BTreeTemplateConstructor< int >(relationName, outIndexName, attrByteOffset, attrType);
00329       break;
00330     case DOUBLE:
00331       BTreeTemplateConstructor< double >(relationName, outIndexName, attrByteOffset, attrType);
00332       break;
00333     case STRING:
00334       BTreeTemplateConstructor< std::string >(relationName, outIndexName, attrByteOffset, attrType);
00335       break;
00336     default:
00337       // Print Error
00338       break;
00339   }
00340 }
00341 
00342 
00343 // -----------------------------------------------------------------------------
00344 // BTreeIndex::~BTreeIndex -- destructor
00345 // -----------------------------------------------------------------------------
00346 
00347 BTreeIndex::~BTreeIndex()
00348 {
00349   if( scanExecuting )
00350   {
00351     try
00352     {
00353       endScan();
00354     }
00355     catch(ScanNotInitializedException e)
00356     {
00357     }
00358   }
00359 
00360   if(file)
00361     bufMgr->flushFile(file);
00362 
00363   delete file;
00364 }
00365 
00366 // -----------------------------------------------------------------------------
00367 // BTreeIndex::insertEntry
00368 // -----------------------------------------------------------------------------
00369 
00370 const void BTreeIndex::insertEntry(const void *value, const RecordId rid) 
00371 {
00372   //helps keep track of what level of the tree we are at during the 
00373   //execution of insertEntry
00374   //if the value at the top of the stack is 1 we know that we are handling
00375   //leaf nodes. otherwise we handling non leaf nodes.
00376   std::stack<int> treePath;
00377   RecordId ridValue = rid;
00378   
00379   #ifdef DEBUG
00380       std::cout<<"*******************************************"<<std::endl;
00381       std::cout << "Root Page Number: " << rootPageNum <<std::endl;
00382   #endif
00383   
00384   //call the templated insertEntry function with values based on the type
00385   //of tree we are working with here
00386   if(attributeType == INTEGER)
00387   {
00388     #ifdef DEBUG
00389       std::cout <<" Inserting integer"<<std::endl;
00390     #endif
00391     int key = *((int*)value);
00392     PageKeyPair<int> newPageKeyPair;
00393     //pageNo for this dummy newPageKeyPair will be set to 0 in insertInto as necessary, might be safe doing that in the constructor
00394     insertInto<int>(rootPageNum, key, newPageKeyPair, 
00395                               ridValue, treePath);
00396   }
00397   if(attributeType == DOUBLE)
00398   {
00399     #ifdef DEBUG
00400       std::cout <<" Inserting double"<<std::endl;
00401     #endif
00402     double key = *((double*)value);
00403     PageKeyPair<double> newPageKeyPair; 
00404     insertInto<double>(rootPageNum, key, newPageKeyPair, 
00405                             ridValue, treePath);
00406   }
00407   if(attributeType == STRING)
00408   {
00409     #ifdef DEBUG
00410       std::cout <<" Inserting string"<<std::endl;
00411     #endif
00412     std::string key;
00413     for(int i=0; i<10; i++)
00414       key+= *( ((char*)value)+i );
00415        
00416     PageKeyPair<std::string> newPageKeyPair;  
00417     insertInto<std::string>(rootPageNum, key, newPageKeyPair, 
00418                               ridValue, treePath);
00419   }
00420 }
00421 
00422 // -----------------------------------------------------------------------------
00423 // BTreeIndex::startScan
00424 // -----------------------------------------------------------------------------
00425 const void BTreeIndex::startScan(const void* lowValParm,
00426            const Operator lowOpParm,
00427            const void* highValParm,
00428            const Operator highOpParm)
00429 {
00430   //make sure that there's no current scan.  If there is, end it. 
00431   if( scanExecuting )
00432     endScan();
00433   //check to make sure the op values are used the correct way for ranges
00434   if( ( lowOpParm != GT && lowOpParm != GTE ) || ( highOpParm != LT && highOpParm != LTE ) )
00435     throw BadOpcodesException();
00436 
00437   // Set member variables for scan
00438   lowOp = lowOpParm;
00439   highOp = highOpParm;
00440 
00441   //set to root before scan starts
00442   currentPageNum = rootPageNum;
00443 
00444   switch( attributeType ){
00445     case INTEGER:
00446       setHighLowVal<int>(highValParm, true);
00447       setHighLowVal<int>(lowValParm, false);
00448       templateStartScan<int>();
00449       return;
00450       break;
00451     case DOUBLE:
00452       setHighLowVal<double>(highValParm, true);
00453       setHighLowVal<double>(lowValParm, false);
00454       templateStartScan<double>();
00455       return;
00456       break;
00457     case STRING:
00458       setHighLowVal<std::string>(highValParm, true);
00459       setHighLowVal<std::string>(lowValParm, false);
00460       templateStartScan<std::string>();
00461       return;
00462       break;
00463     default: break;
00464   }
00465 }
00466 
00467 // -----------------------------------------------------------------------------
00468 // BTreeIndex::templateStartScan
00469 // -----------------------------------------------------------------------------
00470 
00471 template <class T>
00472 const void BTreeIndex::templateStartScan()
00473 {
00474   #ifdef DEBUG
00475     std::cout << "Begin: Start Scan." << std::endl
00476     << "Low = " << getHighLowVal<T>( false ) << " High = " << getHighLowVal<T>( true ) << std::endl;
00477   #endif
00478   // set local variables
00479   int nextLevelLeaf = 0;
00480   PageId lastPageNum;
00481   nextEntry = 0;
00482   RecordId tempRid;
00483   T tempKey;
00484   PageId tempPageNo;
00485   
00486   //make sure the upper bound specified is greater than the lower bound specified
00487   if( getHighLowVal<T>( false ) > getHighLowVal<T>( true ) )
00488     throw BadScanrangeException();
00489 
00490   scanExecuting = true;
00491 
00492   //go down the tree along the appropriate path based on the lower bound value input
00493   //loop goes through all the non leaf nodes in the path 
00494   do
00495   {
00496     #ifdef DEBUG
00497       std::cout << "Searching Node" << std::endl;
00498     #endif
00499     //read page for node in path
00500     bufMgr->readPage( file, currentPageNum, currentPageData );
00501 
00502     //get the level so that we only go upto the last non leaf level
00503     extractLevel( nextLevelLeaf, currentPageData );
00504     lastPageNum = currentPageNum;
00505     //figure out next node to go to in the path
00506     currentPageNum = findPageNoInNonLeaf( currentPageData, getHighLowVal<T>( false ) ); 
00507     bufMgr->unPinPage( file, lastPageNum, false );
00508   }while( nextLevelLeaf != 1 );
00509 
00510   // currentPageNum is now a leaf
00511   bufMgr->readPage( file, currentPageNum, currentPageData );
00512   nextEntry = 0;
00513   //figure out the first value for the scan
00514   while( extractKey<T>( tempKey, currentPageData, nextEntry, true ) < getHighLowVal<T>( false ) 
00515     && extractRid( tempRid, currentPageData, nextEntry ).page_number != 0
00516     && nextEntry < INTARRAYLEAFSIZE )
00517   {
00518     nextEntry++;
00519   }
00520   
00521   //if we went beyond the page this means the first value of the scan is the first value 
00522   //of the next page.
00523   //if there is no right sib it means the lower bound is the larger than all values in the index
00524   //???????????????? why so
00525   if( extractRid( tempRid, currentPageData, nextEntry ).page_number == 0 || nextEntry >= INTARRAYLEAFSIZE )
00526   {
00527     // If it is last entry of last page, return error
00528     if(extractSibPtr( tempPageNo, currentPageData) == 0)
00529     {
00530       bufMgr->unPinPage( file, currentPageNum, false );
00531 
00532       scanExecuting = false;
00533       throw NoSuchKeyFoundException();
00534     }
00535     else
00536     {
00537       //set next entry to the first entry of the right sib page
00538       lastPageNum = currentPageNum;
00539       currentPageNum = extractSibPtr( tempPageNo, currentPageData);
00540       bufMgr->unPinPage( file, lastPageNum, false );
00541       bufMgr->readPage( file, currentPageNum, currentPageData );
00542       nextEntry = 0;
00543     }
00544   }
00545   else
00546   {
00547     // If we wanted greater than and we are at an equal, move nextEntry over
00548     if( extractKey<T>( tempKey, currentPageData, nextEntry, true ) == getHighLowVal<T>( false ) 
00549       && lowOp == GT )
00550     {
00551     #ifdef DEBUG
00552       std::cout << "Shifting nextEntry" << std::endl;
00553     #endif
00554       try
00555       {
00556         scanNext(tempRid);
00557       }
00558       catch(IndexScanCompletedException e)
00559       {
00560         bufMgr->unPinPage( file, currentPageNum, false );
00561         scanExecuting = false;
00562         throw NoSuchKeyFoundException();
00563       }
00564     }
00565   }
00566   #ifdef DEBUG
00567     std::cout << "End: Start Scan" << std::endl;
00568   #endif
00569 }
00570 
00571 // -----------------------------------------------------------------------------
00572 // BTreeIndex::scanNext
00573 // -----------------------------------------------------------------------------
00574 //throws and rethrows IndexScanCompletedException
00575 const void BTreeIndex::scanNext(RecordId& outRid) 
00576 {
00577   //check to make sure a scan is in progress
00578   if(!scanExecuting )
00579     throw ScanNotInitializedException();
00580 
00581   //to check if the scan is over
00582   if(nextEntry == -1)
00583     throw IndexScanCompletedException();
00584   
00585   //call templated function with the appropriate type   
00586   switch(attributeType){
00587     case INTEGER:
00588       templateScanNext<int>( outRid );
00589       return; 
00590       break;
00591     case DOUBLE:
00592       templateScanNext<double>( outRid );
00593       return;
00594       break;
00595     case STRING:
00596       templateScanNext<std::string>( outRid );
00597       return;
00598       break;
00599     default: break;
00600   }
00601 }
00602 
00603 // -----------------------------------------------------------------------------
00604 // BTreeIndex::templateScanNext
00605 // -----------------------------------------------------------------------------
00606 template <class T>
00607 const void BTreeIndex::templateScanNext(RecordId& outRid) 
00608 {
00609   #ifdef DEBUG
00610     std::cout << "Begin: Scan Next" << std::endl;
00611   #endif
00612   
00613   PageId lastPageNum = 0;
00614   T tempKey;
00615   PageId tempPageNo;
00616   RecordId tempRid;
00617   
00618   // See if we've gone beyond range
00619   if( ( highOp == LTE && extractKey<T>( tempKey, currentPageData, nextEntry, true ) > getHighLowVal<T>(true) )
00620     || ( highOp == LT && extractKey<T>( tempKey, currentPageData, nextEntry, true ) >= getHighLowVal<T>(true) ) )
00621   {
00622     nextEntry = -1;
00623     throw IndexScanCompletedException();
00624   }
00625   
00626   //otherwise, set outRid and increment nextEntry
00627   #ifdef DEBUG
00628     std::cout << "key = " << extractKey<T>( tempKey, currentPageData, nextEntry, true ) << std::endl
00629     << "RID = " << extractRid( outRid, currentPageData, nextEntry).page_number << std::endl;
00630   #endif
00631   
00632   extractRid(outRid, currentPageData, nextEntry);
00633   nextEntry++;
00634 
00635   //see if we have to change the page
00636   if( nextEntry >= INTARRAYLEAFSIZE || extractRid( tempRid, currentPageData, nextEntry).page_number == 0 )
00637   {
00638     //if there is no right sib the scan has ended
00639     if( extractSibPtr( tempPageNo, currentPageData) == 0)
00640     {
00641       nextEntry = -1;
00642     }
00643     else
00644     {
00645       #ifdef DEBUG
00646         std::cout << "Moving to sibling page : " << extractSibPtr( tempPageNo, currentPageData ) << std::endl;
00647       #endif
00648       lastPageNum = currentPageNum;
00649       currentPageNum = extractSibPtr( tempPageNo, currentPageData);
00650       nextEntry = 0;
00651       bufMgr->readPage( file, currentPageNum, currentPageData ); 
00652       bufMgr->unPinPage( file, lastPageNum, false );
00653     }
00654   }
00655   #ifdef DEBUG
00656     std::cout << "End: Scan Next" << std::endl;
00657   #endif
00658 }
00659 
00660 // -----------------------------------------------------------------------------
00661 // BTreeIndex::endScan
00662 // -----------------------------------------------------------------------------
00663 const void BTreeIndex::endScan() 
00664 {
00665   //check to make sure there is a scan running 
00666   if( !scanExecuting )
00667     throw ScanNotInitializedException();
00668 
00669   bufMgr->unPinPage( file, currentPageNum, false );
00670 
00671   scanExecuting = false;
00672 }
00673 
00674 // -----------------------------------------------------------------------------
00675 // BTreeIndex::insertInto
00676 // -----------------------------------------------------------------------------
00677 template <class T>
00678 void BTreeIndex::insertInto(PageId pageNo, T key, PageKeyPair<T> &newPageKeyPair, 
00679                               RecordId &rid, std::stack<int> &treePath)
00680 {
00681   //this function will always be called with the pageNo set to 
00682   //the root page no to begin with and then subsequent recursive calls
00683   //will set the appropriate pageNo values depending on the path followed
00684   PageId tempPageNo;
00685   T tempKey;
00686   Page* currentNode;
00687   int level;
00688   bool isLeaf = false;  
00689   bool isRoot = false;
00690   
00691   //variable to figure out if a given node is full or not
00692   //if not full it indicated which index can be used next to add data
00693   //it represents the index in the pageNo array - NOT THE KEY ARRAY
00694   int lastIndexUsed = 0;
00695   
00696   //read the page in from the buffer manager
00697   bufMgr->readPage(file, pageNo, currentNode);
00698   
00699   #ifdef DEBUG
00700     std::cout << "InsertInto called on pageNo: " << pageNo <<std::endl;
00701   #endif
00702   
00703   //check to see if its a leaf node or non leaf node
00704   if( treePath.size() != 0 && treePath.top() == 1)
00705   {
00706     #ifdef DEBUG
00707       std::cout << "Recursive call has reached the leaf node level." <<std::endl;
00708     #endif
00709     isLeaf = true;
00710   }
00711   else
00712   {
00713     memcpy( &level, currentNode, sizeof(int) );
00714     treePath.push(level);
00715     #ifdef DEBUG
00716       std::cout << "Inserting level: " <<level<<" into the treePath stack" << std::endl;
00717     #endif    
00718   }
00719     
00720   //if node is a non leaf node
00721   if( !isLeaf )
00722   {
00723     #ifdef DEBUG
00724       std::cout << "Current level is a non leaf level" <<std::endl;
00725     #endif
00726 
00727     //find the next pageno to determine the path down the btree
00728     PageId nextPageNo = findPageNoInNonLeaf<T>( currentNode, key );
00729     
00730     #ifdef DEBUG
00731       std::cout << "Next page in path being followed is: " << nextPageNo << std::endl;
00732     #endif
00733 
00734     //call insert on the page number found above, the key input and
00735     //newPageNo)
00736     #ifdef DEBUG
00737       std::cout << "Making recursive call with for the above pageNo" <<std::endl;
00738     #endif
00739 
00740     insertInto<T>(nextPageNo, key, newPageKeyPair, rid, treePath);
00741     
00742     #ifdef DEBUG
00743       std::cout << std::endl << "Returning from recursive call for pageNo:" << nextPageNo <<std::endl;
00744     #endif
00745 
00746     /*if(status != OK )
00747     {
00748       #ifdef DEBUG
00749         std::cout << "Error occured on return from recursive call" <<endl;
00750       #endif
00751       //even though error has occured need to make sure we unpin the page
00752       //no change was made to this page, so hasnt been dirtied
00753       bufMgr->unPinPage(file, pageNo, 0);
00754       return;
00755     }*/
00756 
00757     //check if we have been through all the recursive calls and have reached the
00758     //the root
00759     if( treePath.size() == 1 )
00760     { 
00761       #ifdef DEBUG
00762         std::cout << "We have reached back to the root after going all the way down" <<std::endl;
00763       #endif
00764       isRoot = true;
00765     }
00766 
00767     treePath.pop();
00768       
00769     //on return from this recursive call check to see if a split occured
00770     //in the level below by checking the value of pageNo in newPageKeyPair
00771     //if newPageKeyPair.pageNo =0 then no split occured
00772     if( newPageKeyPair.pageNo == 0 )
00773     { 
00774       #ifdef DEBUG
00775         std::cout << "Lower level was not split" <<std::endl;
00776       #endif
00777       //no change was made to this page, so hasnt been dirtied
00778       bufMgr->unPinPage(file, pageNo, 0);
00779       return;
00780     }
00781     // else a split has occured 
00782   
00783     //check to see if there is space in this level to
00784     //accomadate the split and place the key in the parent node
00785     isNonLeafFull(currentNode, lastIndexUsed);
00786     if( lastIndexUsed < nodeOccupancy )
00787     {
00788       #ifdef DEBUG
00789         std::cout << "non leaf node is not full, inserting into the node" <<std::endl;
00790       #endif
00791       //there is place in the node to add the new key
00792       insertPageKeyPair<T>( currentNode, newPageKeyPair, lastIndexUsed );
00793 
00794       //set the newPageKeyPair.pageNo = 0 so that if no further split
00795       //the higher recursive calls dont think there are more splits
00796       newPageKeyPair.pageNo = 0;
00797       
00798       //change has been made to this page, so set dirty flag while unpinning
00799       bufMgr->unPinPage(file, pageNo, 1);
00800       return;
00801     }
00802     
00803     //the currentNode needs to be split due to lack of space to add new 
00804     //keypageno pair
00805     #ifdef DEBUG
00806       std::cout << "Need to split node, creating new node" <<std::endl;
00807     #endif
00808     //allocate a new page for the new node
00809     PageId newPageNo;
00810     Page *newNode;
00811     bufMgr->allocPage( file, newPageNo, newNode );  
00812 
00813     //set the level
00814     #ifdef DEBUG
00815       std::cout << "Setting the level of the new node to: " <<*(int*)currentNode<<std::endl;
00816     #endif
00817 
00818     //first item in all NonLeafNodeInt/Double/String structs is the level variable
00819     //it is just called a page* though its actually not pointing to object of Page class
00820     //or even though it is we are not using that Page as a Page object instead we are using that as a NonLeafNode pointer 
00821     //since its also of the same size as Page object but then calls to any method on these modified objects would fail?????
00822     *(int*)(newNode) = *(int*)currentNode;
00823     extractKey<T>(tempKey, currentNode , nodeOccupancy/2, false);
00824     
00825     #ifdef DEBUG
00826       std::cout << "Value being pushed up one level:" << tempKey << std::endl;
00827     #endif
00828 
00829     //put all the remaining elements of the node being split into new node
00830     splitNonLeafNode<T>(currentNode, newNode );
00831 
00832     //check to see if the key from lower level goes into old node or the new node created
00833     if( newPageKeyPair.key < tempKey )
00834     {
00835       #ifdef DEBUG
00836         std::cout <<" Inserting page no:"<<newPageKeyPair.key<<std::endl;
00837       #endif
00838       isNonLeafFull( currentNode, lastIndexUsed);
00839       insertPageKeyPair<T>( currentNode, newPageKeyPair, lastIndexUsed );
00840     }
00841     else
00842     {
00843       isNonLeafFull( newNode, lastIndexUsed);
00844       insertPageKeyPair<T>( newNode, newPageKeyPair, lastIndexUsed );
00845     }
00846     
00847     //set the newPageKeyPair.pageNo to the 
00848     //the new pageno that has been just allocated for the split
00849     newPageKeyPair.pageNo = newPageNo;
00850     newPageKeyPair.key = tempKey;
00851     
00852     //if the node that was just split was the root 
00853     if( isRoot )
00854     {
00855       #ifdef DEBUG
00856         std::cout << "splitting the root" <<std::endl;
00857       #endif
00858 
00859       //allocate a new page for the new root node
00860       PageId newRootPageNo;
00861       Page *newRootNode;
00862       bufMgr->allocPage( file, newRootPageNo, newRootNode );
00863       
00864       zeroOutNonLeaf(newRootNode);
00865       
00866       //set the level
00867       *(int*)(newRootNode) = 0;
00868     
00869       //set the p0 pointer to the pageno that was split
00870       copyPageNo(pageNo, newRootNode , 0);
00871       
00872       //set the key value to the element being pushed up to the new root
00873       copyKey<T>(tempKey, newRootNode , 0 , false);
00874       
00875       //set the p1 pointer to the the pageno of new node resulting from the split
00876       copyPageNo(newPageNo, newRootNode , 1);
00877       
00878       //update the meta information - need to decide when this is written back
00879       //to the meta information page !!!!
00880       /****************************************************************/
00881       rootPageNum = newRootPageNo;
00882       
00883       //change was made to this page, so has been dirtied
00884       bufMgr->unPinPage(file, newRootPageNo, 1);
00885       
00886       //dont return here as the only thing happening next is the unpinning and return of status
00887       //which is what would be done in the return here anyways
00888       
00889       Page* metaPage;
00890       bufMgr->readPage(file, 1, metaPage);
00891       ((IndexMetaInfo*)metaPage)->rootPageNo = rootPageNum;
00892       bufMgr->unPinPage(file, 1, 1);
00893     }
00894     //change was made to this page, so has been dirtied
00895     #ifdef DEBUG
00896       std::cout << "unpinning "<< pageNo<<std::endl;
00897     #endif
00898     bufMgr->unPinPage(file, pageNo, 1);
00899     //change was made to this page, so has been dirtied
00900     #ifdef DEBUG
00901       std::cout << "unpinning "<< newPageNo<<std::endl;
00902     #endif
00903     bufMgr->unPinPage(file, newPageNo, 1);
00904     return;
00905   }
00906       
00907   //HANDLE INSERTION INTO A LEAF NODE
00908   
00909   #ifdef DEBUG
00910     std::cout << "Handling leaf level" <<std::endl;
00911   #endif
00912 
00913   //make an ridkey pair
00914   RIDKeyPair<T> keyRidPair;
00915   keyRidPair.set( rid, key);
00916   
00917   isLeafFull(currentNode, lastIndexUsed);
00918   
00919   //check to see if there is place in the node to add the key value
00920   if( lastIndexUsed < leafOccupancy-1 )
00921   {
00922     #ifdef DEBUG
00923       std::cout << "Inserting into the leaf level node" <<std::endl;
00924     #endif
00925 
00926     insertKeyRidPair<T>( currentNode, keyRidPair, lastIndexUsed );
00927     newPageKeyPair.pageNo = 0;
00928     bufMgr->unPinPage(file, pageNo, 1);
00929     return;
00930   }
00931   
00932   //need to split the currentNode
00933   #ifdef DEBUG
00934     std::cout << "Splitting leaf level node" <<std::endl;
00935   #endif
00936 
00937 
00938   //create a new node
00939   PageId newPageNo;
00940   Page *newLeafNode;
00941   bufMgr->allocPage( file, newPageNo, newLeafNode );  
00942   
00943   //first split the the node and then figure out where the new keyRidPair should go
00944   
00945   //split the node
00946   splitLeafNode<T>( currentNode, newLeafNode, lastIndexUsed);
00947   
00948   //set the sibling pointer in the new node to the sibling pointer in the old
00949   //node and set the old nodes sibling pointer to this new node
00950   extractSibPtr( tempPageNo, currentNode);
00951   copySibPtr( tempPageNo, newLeafNode);
00952   copySibPtr( newPageNo, currentNode);
00953   
00954   //figure out which node , current or new node created is going to be used
00955   //to insert the new key value into by looking at the first value in the new node
00956   
00957   extractKey<T>(tempKey, newLeafNode , 0, true);
00958   if( keyRidPair.key < tempKey )
00959   {
00960     #ifdef DEBUG
00961       std::cout << "!!!placing into in old page" <<std::endl;
00962     #endif
00963     isLeafFull( currentNode,lastIndexUsed);
00964     insertKeyRidPair<T>( currentNode, keyRidPair, lastIndexUsed );
00965   }
00966   else
00967   {
00968     #ifdef DEBUG
00969       std::cout << "!!!placing into in new page" <<std::endl;
00970     #endif
00971     isLeafFull( newLeafNode,lastIndexUsed);
00972     insertKeyRidPair<T>( newLeafNode, keyRidPair, lastIndexUsed );
00973   } 
00974   
00975   #ifdef DEBUG
00976     std::cout <<"after insert"<<std::endl;
00977   #endif
00978 
00979   extractKey<T>(tempKey, newLeafNode , 0, true);
00980   newPageKeyPair.key = tempKey;
00981   newPageKeyPair.pageNo = newPageNo;
00982   
00983   bufMgr->unPinPage(file, pageNo, 1);
00984   bufMgr->unPinPage(file, newPageNo, 1);
00985   return;
00986 }
00987 
00988 // -----------------------------------------------------------------------------
00989 // BTreeIndex::splitNonLeafNode
00990 // -----------------------------------------------------------------------------
00991 template <class T>
00992 void BTreeIndex::splitNonLeafNode(Page* currentNode, Page* newNode )
00993 {
00994   int nonLeafNodeSize = nodeOccupancy;
00995   T tempKey;
00996   PageId tempPageNo;
00997   char zero[11] = "0000000000";
00998   //INTARRAYNONLEAFSIZE = 4
00999   //0   0   1   1   2   2   3   3   4
01000   //p0  k1  p1  k2  p2  k3  p3  k4  p4
01001 
01002   //copy the second half of the node being split ( minus the first element
01003   //that has been pushed up) in this new node
01004   
01005   //zero out the key at this index as it is the one being pushed up to
01006   //the non leaf level above the level at which this split is taking place
01007   if( attributeType != STRING)
01008     copyKey<T>(0, currentNode , nonLeafNodeSize/2, false);
01009   else
01010     copyKey<std::string>(zero, currentNode , nonLeafNodeSize/2, false);
01011     
01012   int j =0;
01013   for( int i = nonLeafNodeSize/2 + 1; i < nonLeafNodeSize ; ++i)
01014   {           
01015     extractKey<T>(tempKey, currentNode, i , false);
01016     copyKey<T>(tempKey, newNode , j, false);
01017       
01018     extractPageNo(tempPageNo, currentNode, i);
01019     copyPageNo(tempPageNo, newNode , j);
01020     ++j;
01021     
01022     //zero out the values that have been copied to the new node
01023     if(attributeType != STRING)
01024       copyKey<T>(0, currentNode , i, false);
01025     else
01026       copyKey<std::string>(zero, currentNode , i, false);
01027       
01028     copyPageNo(0, currentNode , i);
01029   }
01030   
01031   //set the last pointer in the new node
01032   extractPageNo(tempPageNo, currentNode, nonLeafNodeSize);
01033   copyPageNo(tempPageNo, newNode , j);
01034   copyPageNo(0, currentNode , nonLeafNodeSize);
01035   
01036   if( attributeType != STRING)
01037   {
01038     //zero out the rest of the node entries
01039     copyKey<T>(0, newNode , j, false);
01040     for(int i = j+1; i<nonLeafNodeSize;++i)
01041     {
01042       copyKey<T>(0, newNode , i, false);
01043       copyPageNo(0, newNode , i);
01044     }
01045   
01046     copyPageNo(0, newNode , nonLeafNodeSize);
01047   }
01048   else
01049   {
01050     //zero out the rest of the node entries
01051     copyKey<std::string>(zero, newNode , j, false);
01052     for(int i = j+1; i<nonLeafNodeSize;++i)
01053     {
01054       copyKey<std::string>(zero, newNode , i, false);
01055       copyPageNo(0, newNode , i);
01056     }
01057   
01058     copyPageNo(0, newNode , nonLeafNodeSize); 
01059   }
01060 }
01061 
01062 // -----------------------------------------------------------------------------
01063 // BTreeIndex::splitLeafNode
01064 // -----------------------------------------------------------------------------
01065 template <class T>
01066 void BTreeIndex::splitLeafNode(Page* currentNode, Page* newLeafNode, int &newNodeIndexNotUsed)
01067 {
01068   int leafNodeSize = leafOccupancy;
01069   T tempKey;
01070   RecordId tempRid;
01071   newNodeIndexNotUsed = 0;
01072   RecordId zeroRid;
01073   zeroRid.page_number = 0;
01074   char zero[11] = "0000000000";
01075   
01076   for( int i = leafNodeSize/2 + 1; i < leafNodeSize ; ++i )
01077   {
01078     extractKey<T>(tempKey, currentNode, i , true);
01079     copyKey<T>(tempKey, newLeafNode , newNodeIndexNotUsed, true);
01080 
01081     extractRid(tempRid, currentNode, i);
01082     copyRid(tempRid, newLeafNode , newNodeIndexNotUsed++);
01083     
01084     if(attributeType != STRING)
01085       copyKey<T>(0, currentNode , i, true);
01086     else
01087       copyKey<std::string>(zero, currentNode , i, true);
01088       
01089     copyRid(zeroRid, currentNode , i);
01090   } 
01091   
01092   if( attributeType != STRING )
01093   {
01094     //zero out the rest of the new leaf node entries
01095     copyKey<T>(0, newLeafNode , newNodeIndexNotUsed, true);
01096     copyRid(zeroRid, newLeafNode , newNodeIndexNotUsed);
01097     
01098     for(int i = newNodeIndexNotUsed+1; i<leafNodeSize;++i)
01099     {
01100       copyKey<T>(0, newLeafNode , i, true);
01101       copyRid(zeroRid, newLeafNode , i);
01102     }
01103   }
01104   else
01105   {
01106     //zero out the rest of the new leaf node entries
01107     copyKey<std::string>(zero, newLeafNode , newNodeIndexNotUsed, true);
01108     copyRid(zeroRid, newLeafNode , newNodeIndexNotUsed);
01109     
01110     for(int i = newNodeIndexNotUsed+1; i<leafNodeSize;++i)
01111     {
01112       copyKey<std::string>(zero, newLeafNode , i, true);
01113       copyRid(zeroRid, newLeafNode , i);
01114     }
01115   }
01116 }
01117 
01118 // -----------------------------------------------------------------------------
01119 // BTreeIndex::isNonLeafFull
01120 // -----------------------------------------------------------------------------
01121 void BTreeIndex::isNonLeafFull(Page* currentNode, int &lastIndexUsed)
01122 {
01123   int nonLeafNodeSize = nodeOccupancy;
01124   PageId tempPageNo;
01125   int indexCounter = 0;
01126   for( indexCounter = 0; indexCounter < nonLeafNodeSize; ++indexCounter )
01127   {
01128     extractPageNo(tempPageNo, currentNode, indexCounter + 1);
01129     //if page no is 0 the last page no index was the last index with
01130     //valid data in it
01131     if( tempPageNo == 0 )
01132     {
01133       lastIndexUsed = indexCounter;
01134       return;
01135     } 
01136   }
01137   //the node is full, so set the lastIndexUsed to the nonLeafNodeSize
01138   lastIndexUsed = nonLeafNodeSize;
01139 }
01140 
01141 // -----------------------------------------------------------------------------
01142 // BTreeIndex::isLeafFull
01143 // -----------------------------------------------------------------------------
01144 void BTreeIndex::isLeafFull( Page* currentNode, int &lastIndexUsed)
01145 {
01146   int leafNodeSize = leafOccupancy;
01147   RecordId tempRid;
01148   int indexCounter = 0;
01149   for( indexCounter = 0; indexCounter < leafNodeSize; ++indexCounter )
01150   {
01151     //if the page no is 0 the last page no index was the last index with valid
01152     //data in it
01153     extractRid(tempRid, currentNode, indexCounter);
01154     if( tempRid.page_number == 0 )
01155     {
01156       lastIndexUsed = indexCounter-1;
01157       return;
01158     } 
01159   }
01160   //the node is full and so set the lastIndexUsed to the leafNodeSize - 1
01161   lastIndexUsed = leafNodeSize-1;
01162 }
01163 
01164 // -----------------------------------------------------------------------------
01165 // BTreeIndex::insertKeyRidPair
01166 // -----------------------------------------------------------------------------
01167 template <class T>
01168 void BTreeIndex::insertKeyRidPair( Page* currentNode, RIDKeyPair<T> keyRidPair, int lastIndexUsed )
01169 {
01170   int keyIter;
01171   int ridIter = 0;
01172   
01173   T tempKey;
01174   RecordId rid;
01175   
01176   for( keyIter = 0; keyIter <= lastIndexUsed; ++keyIter)
01177   {
01178     extractKey<T>( tempKey, currentNode, keyIter, true);
01179     if( keyRidPair.key < tempKey )
01180     {
01181       //shift everything starting from lastIndexUsed to the right
01182       //to make place for the values being inserted
01183       for(int subIter = lastIndexUsed; subIter >= keyIter ; --subIter )
01184       {
01185         extractKey<T>(tempKey, currentNode, subIter , true);
01186         copyKey<T>(tempKey, currentNode , subIter+1, true);
01187         
01188         extractRid(rid, currentNode, subIter);
01189         copyRid(rid, currentNode , subIter+1);
01190       }
01191       
01192       //insert the new values in the appropriate position
01193       copyKey<T>(keyRidPair.key, currentNode , keyIter, true);
01194       copyRid(keyRidPair.rid, currentNode, keyIter);
01195       
01196       return;
01197     }
01198     ++ridIter;
01199   }
01200   
01201   //key being inserted is the largest in the node 
01202   copyKey<T>(keyRidPair.key, currentNode , lastIndexUsed+1, true);
01203   copyRid(keyRidPair.rid, currentNode, lastIndexUsed+1);
01204 }
01205 
01206 
01207 // -----------------------------------------------------------------------------
01208 // BTreeIndex::insertPageKeyPair
01209 // -----------------------------------------------------------------------------
01210 template <class T>
01211 void BTreeIndex::insertPageKeyPair( Page* currentNode, PageKeyPair<T> keyPagePair, int lastIndexUsed )
01212 {
01213   int pageNoIter = 0; 
01214 
01215   T tempValue;
01216   PageId pageNo;
01217   
01218   for( int keyIter=0; keyIter < lastIndexUsed; ++keyIter )
01219   {
01220     extractKey<T>(tempValue, currentNode, keyIter, false);
01221     if( keyPagePair.key < tempValue )
01222     {
01223       //shift everything starting from lastIndexUsed to the right
01224       //to make place for the values being inserted
01225       for(int subIter = lastIndexUsed; subIter >= keyIter ; --subIter )
01226       {
01227         extractKey<T>(tempValue, currentNode, subIter-1 , false);
01228         copyKey<T>(tempValue, currentNode , subIter, false);
01229         
01230         extractPageNo(pageNo, currentNode, subIter );
01231         copyPageNo(pageNo, currentNode , subIter+1 );
01232       }
01233       
01234       //insert the new values in the appropriate position
01235       copyKey<T>(keyPagePair.key, currentNode , keyIter, false);
01236       copyPageNo(keyPagePair.pageNo, currentNode , keyIter+1);
01237       return;
01238     } 
01239     ++pageNoIter;
01240   } 
01241   
01242   //value to be inserted is bigger than everything else in the node
01243   #ifdef DEBUG
01244     std::cout << "lastIndex Value being inserted into" << lastIndexUsed << std::endl;
01245     std::cout << "keyPagePair.key value "<< keyPagePair.key<<std::endl;
01246     std::cout << "keyPagePair.pageNo "<< keyPagePair.pageNo<<std::endl;
01247   #endif
01248   copyKey<T>(keyPagePair.key, currentNode , lastIndexUsed, false);
01249   copyPageNo(keyPagePair.pageNo, currentNode , lastIndexUsed+1);
01250 }
01251 
01252 // -----------------------------------------------------------------------------
01253 // BTreeIndex::findPageNoInNonLeaf
01254 // -----------------------------------------------------------------------------
01255 template <class T>
01256 PageId BTreeIndex::findPageNoInNonLeaf( Page *currentNode,  T key )
01257 {
01258   PageId pageNo;
01259   int lastIndexUsed;
01260   //figure out the last valid index in the node
01261   isNonLeafFull( currentNode, lastIndexUsed);
01262 
01263   T higherValue;
01264   for( int i=0; i <= lastIndexUsed ; i++)
01265   {
01266     extractKey<T>(higherValue, currentNode, i, false);
01267     //if the current value of i is the same as the lastindex used then
01268     //this is the path we must follow, or if the value of the key
01269     //at this index is less than the higherValue we know that this
01270     //is the path we want to follow
01271     if( i == lastIndexUsed || key < higherValue )
01272     {
01273       extractPageNo( pageNo, currentNode, i);
01274       #ifdef DEBUG
01275         std::cout << "$$pageNo chosen" << pageNo << std::endl;
01276       #endif
01277       return pageNo;
01278     } 
01279   }
01280   return 0;
01281 }
01282 
01283 // -----------------------------------------------------------------------------
01284 // BTreeIndex::setHighLowVal
01285 // -----------------------------------------------------------------------------
01286 template <class T>
01287 void BTreeIndex::setHighLowVal( const void* val, bool high)
01288 {
01289   //set the appropriate member values depending on the type of
01290   //index being scanned at this point
01291   if( attributeType == INTEGER )
01292   {
01293     if( high ) highValInt = *(int*)( (char*)val );
01294     else       lowValInt = *(int*)( (char*)val );
01295   }
01296   else if( attributeType == DOUBLE )
01297   {
01298     if( high ) highValDouble = *(double*)( (char*)val );
01299     else       lowValDouble = *(double*)( (char*)val );
01300   }
01301   else if( attributeType == STRING )
01302   {
01303     if( high )
01304     {
01305       highValString.clear();
01306       for( int i = 0; i < 10; i++ )
01307         highValString += *((char*)val + i );
01308     }
01309     else
01310     {
01311       lowValString.clear();
01312       for( int i = 0; i < 10; i++ )
01313         lowValString += *((char*)val + i );
01314     }
01315   }
01316 }
01317 
01318 // -----------------------------------------------------------------------------
01319 // BTreeIndex::copyRecordToRidKeyPair
01320 // -----------------------------------------------------------------------------
01321 template <class T>
01322 RIDKeyPair<T> BTreeIndex::copyRecordToRidKeyPair(std::string rec, RecordId rid, const int attrByteOffset )
01323 {
01324   RIDKeyPair<T> ridKeyVal;
01325   T key;
01326 
01327   //copy the key and rid value for the given RID into a ridKeyVal object
01328   key = *(T*)(rec.c_str() + attrByteOffset);  
01329   ridKeyVal.set( rid, key);
01330   return ridKeyVal;
01331 }
01332 
01333 // -----------------------------------------------------------------------------
01334 // BTreeIndex::copyRecordToRidKeyPair
01335 // string version of above templatized function
01336 // -----------------------------------------------------------------------------
01337 template <>
01338 RIDKeyPair<std::string> BTreeIndex::copyRecordToRidKeyPair<std::string>(std::string rec, RecordId rid ,const int attrByteOffset )
01339 {
01340   RIDKeyPair<std::string> ridKeyVal;
01341   std::string key = rec.substr(attrByteOffset, 10);
01342   ridKeyVal.set(rid, key);
01343   return ridKeyVal;
01344 }
01345 
01346 // -----------------------------------------------------------------------------
01347 // BTreeIndex::getHighLowVal
01348 // -----------------------------------------------------------------------------
01349 template <class T>
01350 T BTreeIndex::getHighLowVal(bool high)
01351 {
01352   if( high ) return highValInt;
01353   else       return lowValInt;
01354 }
01355 
01356 // -----------------------------------------------------------------------------
01357 // BTreeIndex::getHighLowVal
01358 // double version of above templatized function
01359 // -----------------------------------------------------------------------------
01360 template<>
01361 double BTreeIndex::getHighLowVal<double>(bool high)
01362 {
01363   if( high ) return highValDouble;
01364   else       return lowValDouble;
01365 }
01366 
01367 // -----------------------------------------------------------------------------
01368 // BTreeIndex::getHighLowVal
01369 // string version of above templatized function
01370 // -----------------------------------------------------------------------------
01371 template<>
01372 std::string BTreeIndex::getHighLowVal<std::string>(bool high)
01373 {
01374   if( high ) return highValString;
01375   else       return lowValString;
01376 }
01377 
01378 // -----------------------------------------------------------------------------
01379 // BTreeIndex::copyKey
01380 // -----------------------------------------------------------------------------
01381 template <class T>
01382 void BTreeIndex::copyKey( T key, Page *nodePagePtr , int index, bool leaf)
01383 {
01384   if( leaf ) ( (LeafNodeInt*)(nodePagePtr) ) -> keyArray[index] = key;
01385   else       ( (NonLeafNodeInt*)(nodePagePtr) ) -> keyArray[index] = key;
01386 }
01387 
01388 // -----------------------------------------------------------------------------
01389 // BTreeIndex::copyKey
01390 // double version of above templatized function
01391 // -----------------------------------------------------------------------------
01392 template <>
01393 void BTreeIndex::copyKey<double>( double key, Page *nodePagePtr, int index, bool leaf)
01394 {
01395   if( leaf ) ( (LeafNodeDouble*)(nodePagePtr) ) -> keyArray[index] = key;
01396   else       ( (NonLeafNodeDouble*)(nodePagePtr) ) -> keyArray[index] = key;
01397 }
01398 
01399 // -----------------------------------------------------------------------------
01400 // BTreeIndex::copyKey
01401 // string version of above templatized function
01402 // -----------------------------------------------------------------------------
01403 template <>
01404 void BTreeIndex::copyKey<std::string>( std::string key, Page *nodePagePtr, int index, bool leaf)
01405 {
01406   if( leaf )
01407   {
01408     for( int i = 0; i < 10; i++ )
01409       ( (LeafNodeString*)(nodePagePtr) ) -> keyArray[index][i] = key[i];
01410   } 
01411   else
01412   {
01413     for( int i = 0; i < 10; i++ )
01414       ( (NonLeafNodeString*)(nodePagePtr) ) -> keyArray[index][i] = key[i];
01415   }
01416   key.clear();
01417 }
01418 
01419 // -----------------------------------------------------------------------------
01420 // BTreeIndex::extractKey
01421 // -----------------------------------------------------------------------------
01422 template <class T>
01423 T BTreeIndex::extractKey(T &value, Page *nodePagePtr , int index, bool leaf)
01424 {
01425   if( leaf ) value = ( (LeafNodeInt*)(nodePagePtr) ) -> keyArray[index];
01426   else       value = ( (NonLeafNodeInt*)(nodePagePtr) ) -> keyArray[index];
01427   return value;
01428 }
01429 
01430 // -----------------------------------------------------------------------------
01431 // BTreeIndex::extractKey
01432 // double version of above templatized function
01433 // -----------------------------------------------------------------------------
01434 template <>
01435 double BTreeIndex::extractKey<double>( double &value, Page *nodePagePtr, int index, bool leaf)
01436 {
01437   if( leaf ) value = ( (LeafNodeDouble*)(nodePagePtr) ) -> keyArray[index];
01438   else       value = ( (NonLeafNodeDouble*)(nodePagePtr) ) -> keyArray[index];
01439   return value;
01440 }
01441 
01442 // -----------------------------------------------------------------------------
01443 // BTreeIndex::extractKey
01444 // string version of above templatized function
01445 // -----------------------------------------------------------------------------
01446 template <>
01447 std::string BTreeIndex::extractKey<std::string>( std::string &value, Page *nodePagePtr, int index, bool leaf)
01448 {
01449   value.clear();
01450   if( leaf )
01451   {
01452     for( int i = 0; i < 10; i++ )
01453       value+= ( (LeafNodeString*)(nodePagePtr) ) -> keyArray[index][i];
01454   }
01455   else
01456   {
01457     for( int i = 0; i < 10; i++ )
01458       value+= ( (NonLeafNodeString*)(nodePagePtr) ) -> keyArray[index][i];
01459   }
01460   return value;
01461 }
01462 
01463 // -----------------------------------------------------------------------------
01464 // BTreeIndex::extractPageNo
01465 // -----------------------------------------------------------------------------
01466 PageId BTreeIndex::extractPageNo( PageId &pageNo, Page *nodePagePtr, int index)
01467 {
01468   if( attributeType == INTEGER )
01469     pageNo = ( (NonLeafNodeInt*)(nodePagePtr) ) -> pageNoArray[index];
01470   if( attributeType == DOUBLE )
01471     pageNo = ( (NonLeafNodeDouble*)(nodePagePtr) ) -> pageNoArray[index];
01472   if( attributeType == STRING )
01473     pageNo = ( (NonLeafNodeString*)(nodePagePtr) ) -> pageNoArray[index];
01474   return pageNo;
01475 }
01476 
01477 // -----------------------------------------------------------------------------
01478 // BTreeIndex::copyPageNo
01479 // -----------------------------------------------------------------------------
01480 void BTreeIndex::copyPageNo( PageId pageNo, Page *nodePagePtr, int index)
01481 {
01482   if( attributeType == INTEGER )
01483     ( (NonLeafNodeInt*)(nodePagePtr) ) -> pageNoArray[index] = pageNo;
01484   if( attributeType == DOUBLE )
01485     ( (NonLeafNodeDouble*)(nodePagePtr) ) -> pageNoArray[index] = pageNo;
01486   if( attributeType == STRING )
01487     ( (NonLeafNodeString*)(nodePagePtr) ) -> pageNoArray[index] = pageNo;
01488 }
01489 
01490 // -----------------------------------------------------------------------------
01491 // BTreeIndex::extractLevel
01492 // -----------------------------------------------------------------------------
01493 int BTreeIndex::extractLevel( int &level, Page *nodePagePtr)
01494 {
01495   if( attributeType == INTEGER )
01496     level = ( (NonLeafNodeInt*)(nodePagePtr) ) -> level;
01497   if( attributeType == DOUBLE )
01498     level = ( (NonLeafNodeDouble*)(nodePagePtr) ) -> level;
01499   if( attributeType == STRING )
01500     level = ( (NonLeafNodeString*)(nodePagePtr) ) -> level;
01501   return level;
01502 }
01503 
01504 // -----------------------------------------------------------------------------
01505 // BTreeIndex::copyLevel
01506 // -----------------------------------------------------------------------------
01507 void BTreeIndex::copyLevel( int level, Page *nodePagePtr)
01508 {
01509   if( attributeType == INTEGER )
01510     ( (NonLeafNodeInt*)(nodePagePtr) ) -> level = level;
01511   if( attributeType == DOUBLE )
01512     ( (NonLeafNodeDouble*)(nodePagePtr) ) -> level = level;
01513   if( attributeType == STRING )
01514     ( (NonLeafNodeString*)(nodePagePtr) ) -> level = level;
01515 }
01516 
01517 // -----------------------------------------------------------------------------
01518 // BTreeIndex::copyRid
01519 // -----------------------------------------------------------------------------
01520 void BTreeIndex::copyRid( RecordId rid, Page *nodePagePtr, int index)
01521 {
01522   if( attributeType == INTEGER )
01523     ( (LeafNodeInt*)(nodePagePtr) ) -> ridArray[index] = rid;
01524   if( attributeType == DOUBLE )
01525     ( (LeafNodeDouble*)(nodePagePtr) ) -> ridArray[index] = rid;
01526   if( attributeType == STRING )
01527     ( (LeafNodeString*)(nodePagePtr) ) -> ridArray[index] = rid;
01528 }
01529 
01530 // -----------------------------------------------------------------------------
01531 // BTreeIndex::extractRid
01532 // -----------------------------------------------------------------------------
01533 RecordId BTreeIndex::extractRid( RecordId &rid, Page *nodePagePtr, int index)
01534 {
01535   if( attributeType == INTEGER )
01536     rid = ( (LeafNodeInt*)(nodePagePtr) ) -> ridArray[index];
01537   if( attributeType == DOUBLE )
01538     rid = ( (LeafNodeDouble*)(nodePagePtr) ) -> ridArray[index];
01539   if( attributeType == STRING )
01540     rid = ( (LeafNodeString*)(nodePagePtr) ) -> ridArray[index];
01541   return rid;
01542 }
01543 
01544 // -----------------------------------------------------------------------------
01545 // BTreeIndex::copySibPtr
01546 // -----------------------------------------------------------------------------
01547 void BTreeIndex::copySibPtr(PageId pageNo, Page *nodePagePtr)
01548 {
01549   if( attributeType == INTEGER )
01550     ( (LeafNodeInt*)(nodePagePtr) ) -> rightSibPageNo = pageNo;
01551   if( attributeType == DOUBLE )
01552     ( (LeafNodeDouble*)(nodePagePtr) ) -> rightSibPageNo = pageNo;
01553   if( attributeType == STRING )
01554     ( (LeafNodeString*)(nodePagePtr) ) -> rightSibPageNo = pageNo;
01555 }
01556 
01557 // -----------------------------------------------------------------------------
01558 // BTreeIndex::extractSibPtr
01559 // -----------------------------------------------------------------------------
01560 PageId BTreeIndex::extractSibPtr(PageId &pageNo, Page *nodePagePtr)
01561 {
01562   if( attributeType == INTEGER )
01563     pageNo = ( (LeafNodeInt*)(nodePagePtr) ) -> rightSibPageNo;
01564   if( attributeType == DOUBLE )
01565     pageNo = ( (LeafNodeDouble*)(nodePagePtr) ) -> rightSibPageNo;
01566   if( attributeType == STRING )
01567     pageNo = ( (LeafNodeString*)(nodePagePtr) ) -> rightSibPageNo;
01568   return pageNo;
01569 }
01570 
01571 // -----------------------------------------------------------------------------
01572 // BTreeIndex::zeroOutNonLeaf
01573 // -----------------------------------------------------------------------------
01574 void BTreeIndex::zeroOutNonLeaf(Page *currentNode)
01575 {
01576   char zero[11] = "0000000000";
01577   if( attributeType == INTEGER )  
01578   { 
01579     for(int i = 0; i<INTARRAYNONLEAFSIZE; ++i)
01580     {
01581       copyKey<int>(0, currentNode , i, false);
01582       copyPageNo(0, currentNode , i);
01583     }
01584   }
01585   
01586   if( attributeType == DOUBLE ) 
01587   { 
01588     for(int i = 0; i<DOUBLEARRAYNONLEAFSIZE; ++i)
01589     {
01590       copyKey<double>(0, currentNode , i, false);
01591       copyPageNo(0, currentNode , i);
01592     }
01593   }
01594   
01595   if( attributeType == STRING ) 
01596   { 
01597     for(int i = 0; i<STRINGARRAYNONLEAFSIZE; ++i)
01598     {
01599       copyKey<std::string>(zero, currentNode , i, false);
01600       copyPageNo(0, currentNode , i);
01601     }
01602   }
01603 }
01604 
01605 // -----------------------------------------------------------------------------
01606 // BTreeIndex::zeroOutNonLeaf
01607 // -----------------------------------------------------------------------------
01608 void BTreeIndex::zeroOutLeaf(Page *currentNode)
01609 {
01610   RecordId zeroRid;
01611   zeroRid.page_number = 0;
01612   char zero[11] = "0000000000";
01613   if( attributeType == INTEGER )  
01614   { 
01615     for(int i = 0; i<INTARRAYLEAFSIZE; ++i)
01616     {
01617       copyKey<int>(0, currentNode , i, true);
01618       copyRid(zeroRid, currentNode , i);
01619     }
01620   }
01621   
01622   if( attributeType == DOUBLE ) 
01623   { 
01624     for(int i = 0; i<DOUBLEARRAYLEAFSIZE; ++i)
01625     {
01626       copyKey<double>(0, currentNode , i, true);
01627       copyRid(zeroRid, currentNode , i);
01628     }
01629   }
01630   
01631   if( attributeType == STRING )
01632   { 
01633     for(int i = 0; i<STRINGARRAYLEAFSIZE; ++i)
01634     {
01635       copyKey<std::string>(zero, currentNode , i, true);
01636       copyRid(zeroRid, currentNode , i);
01637     }
01638   }
01639 }
01640 
01641 // -----------------------------------------------------------------------------
01642 // BTreeIndex::printTreeExternal
01643 // -----------------------------------------------------------------------------
01644 void BTreeIndex::printTreeExternal()
01645 {
01646   switch(attributeType)
01647   {
01648     case INTEGER: printTree<int>( rootPageNum, false); break;
01649     case DOUBLE: printTree<double>( rootPageNum, false); break;
01650     case STRING: printTree<std::string>( rootPageNum, false); break;
01651     default: break;
01652   }
01653 }
01654 
01655 // -----------------------------------------------------------------------------
01656 // BTreeIndex::printTree
01657 // -----------------------------------------------------------------------------
01658 template <class T>
01659 void BTreeIndex::printTree(PageId pageNum , bool isLeaf)
01660 {
01661   int lastIndexUsed;
01662   Page *currentNode;
01663   PageId pNum1;
01664   T tKey1;
01665   bufMgr->readPage( file, pageNum , currentNode );
01666   
01667   if( !isLeaf )
01668   {
01669     if(*(int*)currentNode == 0)
01670     { 
01671       isNonLeafFull( currentNode, lastIndexUsed);
01672     
01673       for(int i=0; i< lastIndexUsed;i++)
01674       {
01675         extractPageNo(pNum1, currentNode, i );  
01676         std::cout << pNum1 << " | ";
01677         extractKey<T>(tKey1, currentNode, i , false); 
01678         std::cout << tKey1 << " | ";
01679       }
01680       extractPageNo(pNum1, currentNode, lastIndexUsed );  
01681       std::cout << pNum1 << " ";
01682       std::cout << std::endl;
01683       
01684       for(int i=0; i< lastIndexUsed;i++)
01685       {
01686         extractPageNo(pNum1, currentNode, i );  
01687         printTree<T>(pNum1, false);
01688       }
01689       extractPageNo(pNum1, currentNode, lastIndexUsed );  
01690       printTree<T>(pNum1, false);
01691       bufMgr->unPinPage(file, pageNum, 0);
01692     }
01693     else
01694     {
01695       isNonLeafFull( currentNode, lastIndexUsed);
01696     
01697       for(int i=0; i< lastIndexUsed;i++)
01698       {
01699         extractPageNo(pNum1, currentNode, i );  
01700         std::cout << pNum1 << " | ";
01701         extractKey<T>(tKey1, currentNode, i , false); 
01702         std::cout << tKey1 << " | ";
01703       }
01704       extractPageNo(pNum1, currentNode, lastIndexUsed );  
01705       std::cout << pNum1 << " ";
01706       std::cout << std::endl;
01707       
01708       for(int i=0; i< lastIndexUsed;i++)
01709       {
01710         extractPageNo(pNum1, currentNode, i );  
01711         printTree<T>(pNum1, true);
01712       }
01713       extractPageNo(pNum1, currentNode, lastIndexUsed );  
01714       printTree<T>(pNum1, true);
01715       bufMgr->unPinPage(file, pageNum, 0);
01716     }
01717     return;
01718   }
01719   
01720   //for leafNode
01721   isLeafFull( currentNode,lastIndexUsed);
01722   for(int i=0; i<= lastIndexUsed;i++)
01723   {
01724     extractKey<T>(tKey1, currentNode, i , true);  
01725     std::cout << tKey1 << " ";
01726   }
01727   std::cout << std::endl;
01728   bufMgr->unPinPage(file, pageNum, 0);
01729 }
01730 
01731 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends