Status BufMgr::freePage(PageId globalPageId){ Status st; int framein = h.lookup(globalPageId); if(framein!=-1 && bufDescr[framein].pin_count==0){ if ( bufDescr[framein].dirtybit ){ st =MINIBASE_DB->write_page(globalPageId,(Page*) &bufDescr[framein]); if(st!=OK){ return MINIBASE_CHAIN_ERROR(BUFMGR, st); } } bufDescr[framein].PageNumber = INVALID_PAGE; bufDescr[framein].pin_count = 0; bufDescr[framein].dirtybit = FALSE; h.remove(globalPageId); //blist.remove() st = MINIBASE_DB->deallocate_page(globalPageId,1); if(st!=OK){ return MINIBASE_CHAIN_ERROR(BUFMGR, st); } return OK; } return FAIL; }
Status DB::delete_file_entry(const char* fname) { #ifdef DEBUG cout << "Deleting the file entry for " << fname << endl; #endif char* pg = 0; Status status; directory_page* dp = 0; bool found = false; unsigned slot = 0; PageId hpid, nexthpid = 0; do { hpid = nexthpid; // Pin the header page. status = MINIBASE_BM->pinPage( hpid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // This complication is because the first page has a different // structure from that of subsequent pages. dp = (hpid == 0)? &((first_page*)pg)->dir : (directory_page*)pg; nexthpid = dp->next_page; unsigned entry = 0; while ((entry < dp->num_entries) && ((dp->entries[entry].pagenum == INVALID_PAGE) || (strcmp(fname,dp->entries[entry].fname) != 0)) ) ++entry; if ( entry < dp->num_entries ) { slot = entry; found = true; } else { status = MINIBASE_BM->unpinPage( hpid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } } while ( nexthpid != INVALID_PAGE && !found ); if ( !found ) // Entry not found - nothing deleted return MINIBASE_FIRST_ERROR( DBMGR, FILE_NOT_FOUND ); // Have to delete record at hpnum:slot dp->entries[slot].pagenum = INVALID_PAGE; status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) status = MINIBASE_CHAIN_ERROR( DBMGR, status ); return OK; }
Status DB::dump_space_map() { unsigned num_map_pages = (num_pages + bits_per_page - 1) / bits_per_page; unsigned bit_number = 0; // This loop goes over each page in the space map. for( unsigned i=0; i < num_map_pages; ++i ) { PageId pgid = 1 + i; // The space map starts at page #1. // Pin the space-map page. char* pg; Status status; status = MINIBASE_BM->pinPage( pgid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // How many bits should we examine on this page? int num_bits_this_page = num_pages - i*bits_per_page; if ( num_bits_this_page > bits_per_page ) num_bits_this_page = bits_per_page; // Walk the page looking for a sequence of 0 bits of the appropriate // length. The outer loop steps through the page's bytes, the inner // one steps through each byte's bits. for ( ; num_bits_this_page > 0; ++pg ) for ( unsigned mask=1; mask < 256 && num_bits_this_page > 0; mask <<= 1, --num_bits_this_page, ++bit_number ) { int bit = (*pg & mask) != 0; if ( bit_number % 10 == 0 ){ if ( bit_number % 50 == 0 ) { if ( bit_number ) cout << endl; cout << setw(8) << bit_number << ": "; } else cout << ' '; } // add by cclee cout << bit; } // Unpin the space-map page. status = MINIBASE_BM->unpinPage( pgid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } cout << endl; return OK; }
// ******************************************* // Retrieve the next data page Status Scan::nextDataPage() { Status st; PageId nextDataPageId; if (datapage == NULL) { if (datapageId == INVALID_PAGE) { // heapfile is empty to begin with return DONE; } else { // pin first data page st = MINIBASE_BM->pinPage(datapageId, (Page *&) datapage); if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); // find the first record st = datapage->firstRecord(userrid); if (st != DONE) { if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); return OK; } } } nextDataPageId = datapage->getNextPage(); // unpin the current datapage st = MINIBASE_BM->unpinPage(datapageId); datapage = NULL; if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); datapageId = nextDataPageId; if (datapageId == INVALID_PAGE) return DONE; st = MINIBASE_BM->pinPage(datapageId, (Page *&) datapage); if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); nxtUserStatus = datapage->firstRecord(userrid); if (nxtUserStatus != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); return OK; }
Status DB::get_file_entry(const char* fname, PageId& start_page) { #ifdef DEBUG cout << "Getting the file entry for " << fname << endl; #endif char* pg = 0; Status status; directory_page* dp = 0; bool found = false; unsigned slot = 0; PageId hpid, nexthpid = 0; do { hpid = nexthpid; // Pin the header page. status = MINIBASE_BM->pinPage( hpid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // This complication is because the first page has a different // structure from that of subsequent pages. dp = (hpid == 0)? &((first_page*)pg)->dir : (directory_page*)pg; nexthpid = dp->next_page; unsigned entry = 0; while ((entry < dp->num_entries) && ((dp->entries[entry].pagenum == INVALID_PAGE) || (strcmp(fname,dp->entries[entry].fname) != 0)) ) ++entry; if ( entry < dp->num_entries ) { slot = entry; found = true; } status = MINIBASE_BM->unpinPage( hpid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } while ((nexthpid != INVALID_PAGE) && !found ); if ( !found ) // Entry not found - don't post error, just fail. return FAIL; start_page = dp->entries[slot].pagenum; return OK; }
Status BufMgr::unpinPage(PageId page_num, int dirty=FALSE, int hate = FALSE){ // put your code here void *qptr; Status st; int framein = h.lookup(page_num); //cout << "framein :: "<< framein << endl; if(framein !=-1){ // set dirty bit fro fram if its true if(dirty==TRUE){ bufDescr[framein].dirtybit = dirty; st =MINIBASE_DB->write_page(page_num, &bufPool[framein]); if(st!=OK){ return MINIBASE_CHAIN_ERROR(BUFMGR, st); } } // decrement pin count for frame if its greater than 0 if(bufDescr[framein].pin_count>0){ --(bufDescr[framein].pin_count); }else{ return FAIL; } st = blist.insert(!hate, page_num, framein); if(st!=OK){ MINIBASE_FIRST_ERROR(BUFMGR,LISTINSERT_ERROR); }return OK; } return FAIL; }
DB::DB(const char* fname, Status& status) { #ifdef DEBUG cout << "opening database "<< fname << endl; #endif name = strcpy(new char[strlen(fname)+1],fname); // Open the file in both input and output mode. fd = ::open( name, O_RDWR ); if ( fd < 0 ) { status = MINIBASE_FIRST_ERROR( DBMGR, UNIX_ERROR ); return; } MINIBASE_DB = this; //set the global variable to be this. Status s; first_page* fp; num_pages = 1; // We initialize it to this. // We will know the real size after we read page 0. #ifdef BM_TRACE s = MINIBASE_BM->pinPage( 0, (Page*&)fp, false /*not empty*/, "*** DB admin ***" ); #else s = MINIBASE_BM->pinPage( 0, (Page*&)fp ); #endif if ( s != OK ) { status = MINIBASE_CHAIN_ERROR( DBMGR, s ); return; } num_pages = fp->num_db_pages; s = MINIBASE_BM->unpinPage( 0 ); if ( s != OK ) { status = MINIBASE_CHAIN_ERROR( DBMGR, s ); return; } status = OK; }
Status BufMgr::newPage(PageId& firstPageId, Page*& firstpage, int howmany) { Status s = MINIBASE_DB->allocate_page(firstPageId, howmany); if (s != OK) { MINIBASE_CHAIN_ERROR(BUFMGR, s); return s; } s = pinPage(firstPageId, firstpage, 0); if (s != OK) { Status s2 = MINIBASE_DB->deallocate_page(firstPageId, howmany); MINIBASE_CHAIN_ERROR(BUFMGR, s2); MINIBASE_CHAIN_ERROR(BUFMGR, s); return s; } return OK; }
Status BufMgr::flushPage(PageId pageid) { int i = hashTable->find(pageid); Status s = MINIBASE_DB->write_page(pageid, &bufPool[i]); if (s != OK) { MINIBASE_CHAIN_ERROR(BUFMGR, s); return s; } return OK; }
// ******************************************* // Position the scan cursor to the record with the given rid. // Returns OK if successful, non-OK otherwise. Status Scan::position(RID rid) { Status st; RID nxtrid; st = peekNext(nxtrid); if (nxtrid == rid) return OK; // This is kinda lame, but otherwise it will take all day. PageId pgid = rid.pageNo; if (datapageId != pgid) { // reset everything and start over from the beginning reset(); st = firstDataPage(); if (st != OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, st); while (datapageId != pgid) { st = nextDataPage(); if (st != OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, st); } } // Now we are on the correct page. st = datapage->firstRecord(userrid); if (st != OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, st); st = peekNext(nxtrid); while ((st == OK) && (nxtrid != rid)) st = mvNext(nxtrid); return st; }
Status BufMgr::flushAllPages(){ //put your code here int i,framein; Status st; for(i=0;i<numbuffer;i++){ framein = i; if(bufDescr[framein].dirtybit){ st =MINIBASE_DB->write_page(bufDescr[framein].PageNumber, (Page*)&bufPool[framein]); if(st!=OK){ return MINIBASE_CHAIN_ERROR(BUFMGR, st); } } } return OK; }
// ******************************************* Status Scan::reset() { Status st = OK; if (datapage != NULL) { st = MINIBASE_BM->unpinPage(datapageId); if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st); } datapageId = 0; datapage = NULL; nxtUserStatus = OK; return st; }
// ******************************************* Status Scan::firstDataPage() { Status st; // copy data about first page datapageId = _hf->_firstPageId; nxtUserStatus = OK; datapage = NULL; // Actually get the page st = nextDataPage(); if ((st != OK) && (st != DONE)) return MINIBASE_CHAIN_ERROR( HEAPFILE, st); return OK; }
Status BufMgr::flushAllPages(){ int* z = new int[numbuf]; for (int i = 0; i < numbuf; i++) z[i] = 1; for (int i = 0; i < freeFrames.size(); i++) z[freeFrames[i]] = 0; for (int i = 0; i < numbuf; i++) if (z[i] && bufDescr[i]->dirty) { Status s = flushPage(bufDescr[i]->pageNum); if (s != OK) { MINIBASE_CHAIN_ERROR(BUFMGR, s); return s; } } return OK; }
//------------------------------------------------------------- // test //------------------------------------------------------------- Status test(int t) { char outfile[10]; int Rarray[] = { 0, 1, 0, 3, 4, 4, 4 }; int Sarray[] = { 1, 0, 2, 2, 2, 3, 0 }; int R = Rarray[t-1]; int S = Sarray[t-1]; Status s; sprintf(outfile,"test%d", t); // Perform sort-merge on R and S sortMerge sm(files[R],NUM_COLS,attrType,attrSize,JOIN_COL,files[S],NUM_COLS,attrType,attrSize,JOIN_COL,outfile,SORTPGNUM,Ascending,s); if (s != OK) { cout << "Test " << t << " -- sortMerge failed" << endl; return s; } // Write merged results to stdout HeapFile* outf = new HeapFile (outfile,s); if (s != OK) { cout << "Test " << t << " -- result file not created " << endl; return s; } Scan* scan = outf->openScan(s); assert(s == OK); int len; RID rid; char rec[sizeof(struct _rec)*2]; cout << endl; cout << "------------ Test " << t << " ---------------" << endl; for (s = scan->getNext(rid, rec, len); s == OK; s = scan->getNext(rid, rec, len)) { cout << (*((struct _rec*)&rec)).key << "\t" << (*((struct _rec*)&rec[8])).key << endl; } cout << "-------- Test " << t << " completed --------" << endl; delete scan; s=outf->deleteFile(); if(s!=OK) MINIBASE_CHAIN_ERROR(JOINS,s); delete outf; return s; }
Status BufMgr::pinPage(PageId PageId_in_a_DB, Page*& page, int emptyPage) { int i = hashTable->find(PageId_in_a_DB); if (i != -1) { if (bufDescr[i]->pinCount == 0) { lhm->erase(PageId_in_a_DB, bufDescr[i]->ts, bufDescr[i]->loved); } bufDescr[i]->pinCount++; } else { if (!freeFrames.empty()) { i = freeFrames.back(); freeFrames.pop_back(); } else { i = lhm->findVictim(); if (i == -1) { MINIBASE_FIRST_ERROR(BUFMGR, FAIL); return FAIL; } i = hashTable->find(i); assert(i != -1); deleteFrame(i); } if (!emptyPage) { Status s = MINIBASE_DB->read_page(PageId_in_a_DB, &bufPool[i]); if (s != OK) { MINIBASE_CHAIN_ERROR(BUFMGR, s); freeFrames.push_back(i); return s; } } bufDescr[i] = new Descriptor(PageId_in_a_DB, ts, 1); hashTable->put(PageId_in_a_DB, i); } page = &bufPool[i]; return OK; }
Status BufMgr::freePage(PageId globalPageId){ int i = hashTable->find(globalPageId); if (i != -1) { if (bufDescr[i]->pinCount > 0) { MINIBASE_FIRST_ERROR(BUFMGR, FAIL); return FAIL; } freeFrames.push_back(i); } Status s = MINIBASE_DB->deallocate_page(globalPageId); if (s != OK) { MINIBASE_CHAIN_ERROR(BUFMGR, s); return s; } return OK; }
// ******************************************* // Retrieve the next record in a sequential scan. // Also returns the RID of the retrieved record. Status Scan::getNext(RID& rid, char *recPtr, int& recLen) { Status st; if (nxtUserStatus != OK) nextDataPage(); if (datapage == NULL) return DONE; rid = userrid; st = datapage->getRecord(rid, recPtr, recLen); if (st != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, st ); nxtUserStatus = datapage->nextRecord(rid, userrid); return st; }
Status BTreeFile::insert (const void *key, const RID rid) { Status returnStatus; KeyDataEntry newRootEntry; int newRootEntrySize; KeyDataEntry* newRootEntryPtr = &newRootEntry; if (get_key_length(key, headerPage->key_type) > headerPage->keysize) return MINIBASE_FIRST_ERROR(BTREE, KEY_TOO_LONG); // TWO CASES: // 1. headerPage->root == INVALID_PAGE: // - the tree is empty and we have to create a new first page; // this page will be a leaf page // 2. headerPage->root != INVALID_PAGE: // - we call _insert() to insert the pair (key, rid) PageId shit; if (headerPage->root == INVALID_PAGE) { // TODO: fill the body PageId rootPageId = -1; BTLeafPage* rootLeafPage = NULL; Status st = MINIBASE_BM->newPage( (PageId&)rootPageId, (Page*&)rootLeafPage ); rootLeafPage->init( rootPageId); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); assert( st == OK); assert( rootPageId != -1); rootLeafPage->init( rootPageId); headerPage->root = rootPageId; st = MINIBASE_BM->unpinPage( headerPage->root, TRUE ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); shit = rootPageId; // return OK; } returnStatus = _insert(key, rid, &newRootEntryPtr, &newRootEntrySize, headerPage->root); if (returnStatus != OK) MINIBASE_FIRST_ERROR(BTREE, INSERT_FAILED); // TWO CASES: // - newRootEntryPtr != NULL: a leaf split propagated up to the root // and the root split: the new pageNo is in // newChildEntry->data->pageNo // - newRootEntryPtr == NULL: no new root was created; // information on headerpage is still valid if (newRootEntryPtr != NULL) { // TODO: fill the body fprintf(stdout, "key_data_entry goingup: %d %d\n", newRootEntryPtr->key.intkey, newRootEntryPtr->data.pageNo); BTIndexPage* rootIndexPage = NULL; PageId rootPageId; Status st = MINIBASE_BM->newPage( (PageId&)rootPageId, (Page*&)rootIndexPage ); rootIndexPage->init( rootPageId); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); assert( st == OK); rootIndexPage->setLeftLink( headerPage->root ); RID dummyRid; st = rootIndexPage->insertKey( (void*)(&newRootEntryPtr->key), headerPage->key_type , newRootEntryPtr->data.pageNo, dummyRid); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); // headerPage->root = newRootEntryPtr->data.pageNo; headerPage->root = rootPageId; st = MINIBASE_BM->unpinPage( rootIndexPage->page_no(), TRUE ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); fprintf(stdout, "end of new index first!!!\n"); } return OK; }
Status Sort::firstPass( char *inFile, int bufferNum, int& tempHFnum ) { /* Variables which are required to be passed as parameters to different functions */ Status s; RID rid; char res; //Used to pass values to the getNext method of scan int len; // Used to pass values to the getNext method of scan and also used to move the recPtr run_no=0; char file_name[25]; int buffer_size=PAGESIZE * bufferNum; int available_memory= buffer_size; int rec_count_tracker=0; //cout <<"\n Buffer size is : " <<buffer_size; char temp_buffer[buffer_size]; //Temp_buffer to store all the records /* Pointers to the buffer array used for keeping track of the records that need to be */ char *recptr; char *outPtr; char *heapPtr; recptr=temp_buffer; outPtr=temp_buffer; heapPtr=temp_buffer; HeapFile f(inFile,s); //Creating HeapFile object and calling th constructor if(s != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); // initiate a sequential scan Scan *sc= f.openScan(s); if (s != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); int record_count=f.getRecCnt(); if (record_count==0) // File to be sorted has no records. Simply return OK return OK; int max_no_records_in_buffer=record_count/bufferNum; bool isEqual_dist = (record_count%bufferNum == 0); for (int i=0;i < record_count;i++) { s = sc->getNext(rid, recptr, len); if (s != OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); if (available_memory > len and rec_count_tracker != record_count -1) //Read the record into the temp buffer, decrement the available memory, increment the record count tracker { recptr = recptr + len; available_memory = available_memory - len; rec_count_tracker=rec_count_tracker+1; if (available_memory - len < 0) { // Sort the records using qsort qsort(temp_buffer, rec_count_tracker, rec_len, tupleCmp); for (int i = 0; i < rec_count_tracker; i++) { //cout << temp_buffer[i] << " "; } //Increment the run no run_no = run_no + 1; // Write the records to a temporary heap file and as well as outFile makeHFname(file_name, 1, run_no); HeapFile w(file_name, s); if (s != OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, s); //Writing the sorted records to the temp heap file for (int i = 0; i < rec_count_tracker; i++) { s = w.insertRecord(heapPtr, rec_len, rid); heapPtr = heapPtr + rec_len; //cout << "\n Inserting record " << i + 1 << *heapPtr << " into temporary heap file"; if (s != OK) { return MINIBASE_CHAIN_ERROR(HEAPFILE, s); } } // Re-set the available memory to the initial limit and make the pointers to point to start of temp_buffer available_memory=PAGESIZE*bufferNum; recptr = temp_buffer; heapPtr = temp_buffer; outPtr = temp_buffer; rec_count_tracker=0; } } else if (available_memory > len and i==record_count-1) { recptr = recptr + len; available_memory = available_memory - len; rec_count_tracker=rec_count_tracker+1; qsort(temp_buffer,rec_count_tracker,rec_len,tupleCmp); run_no=run_no+1; tempHFnum=run_no; // Setting the value of tempHFnum which is passed as reference. makeHFname(file_name,1,run_no); HeapFile w(file_name, s); if (s!=OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); //Writing the sorted records to the temp heap file for (int i=0; i < rec_count_tracker ; i++) { //cout <<"\n Inserting record " <<i+1 << *heapPtr <<" into temporary heap file"; s = w.insertRecord(heapPtr, rec_len, rid); heapPtr=heapPtr+rec_len; if ( s!=OK) { return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); } } //Writing the sorted records to the outFile HeapFile o(outFileName, s); if (s!=OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); for (int i=0; i < rec_count_tracker ; i++) { //cout <<"\n Inserting record " <<i+1 << "\t" <<*outPtr <<" " <<*(outPtr+1)<<" into outFile"; s = o.insertRecord(outPtr, rec_len, rid); outPtr=outPtr+rec_len; if ( s!=OK) { return MINIBASE_CHAIN_ERROR( HEAPFILE, s ); } } //Destroy the output file object when we have more than one run because the actual output would be produced in the following pass. if(run_no > 1) { Status stat = o.deleteFile(); if (stat !=OK) return MINIBASE_CHAIN_ERROR( HEAPFILE, stat ); } delete(sc); return OK; } } }
Status DB::set_bits( PageId start_page, unsigned run_size, int bit ) { if ((start_page < 0) || (start_page+run_size > num_pages)) return MINIBASE_FIRST_ERROR( DBMGR, BAD_PAGE_NO ); #ifdef DEBUG printf("set_bits:: space_map_before \n"); dump_space_map(); #endif // Locate the run within the space map. int first_map_page = start_page / bits_per_page + 1; int last_map_page = (start_page+run_size-1) / bits_per_page + 1; unsigned first_bit_no = start_page % bits_per_page; // The outer loop goes over all space-map pages we need to touch. for ( PageId pgid=first_map_page; pgid <= last_map_page; ++pgid, first_bit_no=0 ) { Status status; // Pin the space-map page. char* pg; status = MINIBASE_BM->pinPage( pgid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // Locate the piece of the run that fits on this page. unsigned first_byte_no = first_bit_no / 8; unsigned first_bit_offset = first_bit_no % 8; int last_bit_no = first_bit_no + run_size - 1; if ( last_bit_no >= bits_per_page ) last_bit_no = bits_per_page - 1; unsigned last_byte_no = last_bit_no / 8; // Find the start of this page's piece of the run. char* p = pg + first_byte_no; char* end = pg + last_byte_no; // This loop actually flips the bits on the current page. for ( ; p <= end; ++p, first_bit_offset=0 ) { unsigned max_bits_this_byte = 8 - first_bit_offset; unsigned num_bits_this_byte = (run_size > max_bits_this_byte? max_bits_this_byte : run_size); unsigned mask = ((1 << num_bits_this_byte) - 1) << first_bit_offset; if ( bit ) *p |= mask; else *p &= ~mask; run_size -= num_bits_this_byte; } // Unpin the space-map page. status = MINIBASE_BM->unpinPage( pgid, true /*dirty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } #ifdef DEBUG printf("set_bits:: space_map_afterwards \n"); dump_space_map(); #endif return OK; }
Status BTreeFile::_insert (const void *key, const RID rid, KeyDataEntry **goingUp, int *goingUpSize, PageId currentPageId) { Status st; SortedPage* rpPtr; assert(currentPageId != INVALID_PAGE); assert(*goingUp != NULL); st = MINIBASE_BM->pinPage(currentPageId,(Page *&) rpPtr); if (st != OK) return MINIBASE_FIRST_ERROR(BTREE, CANT_PIN_PAGE); NodeType pageType = rpPtr->get_type(); cerr<< "currentPageId IN _INSERT "<< currentPageId<<" pageType "<< pageType<<endl; // TWO CASES: // - pageType == INDEX: // recurse and then split if necessary // - pageType == LEAF: // try to insert pair (key, rid), maybe split switch (pageType) { case INDEX: { // two cases: // - *goingUp == NULL: one level lower no split has occurred: // we are done. // - *goingUp != NULL: one of the children has split and // **goingUp is the new data entry which has // to be inserted on this index page // TODO: fill the body BTIndexPage* indexPage = (BTIndexPage*) rpPtr; RID myRid; KeyDataEntry* newEntry = new KeyDataEntry(); int newEntrySize; PageId pageId; indexPage->get_page_no( key, headerPage->key_type, pageId); printf("in index page insert to %d\n", pageId); fflush(stdout); Status returnStatus = _insert(key, rid, &newEntry , &newEntrySize, pageId); if (returnStatus != OK) MINIBASE_FIRST_ERROR(BTREE, INSERT_FAILED); if( newEntry != NULL){ if( indexPage->available_space() >= newEntrySize){ st = indexPage->insertKey( (void*)(&newEntry->key), headerPage->key_type, newEntry->data.pageNo, myRid); if(st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); } else{ //pageFUll: //new a Indexpage "RightSibling" cout<<"*************************index_split"<<endl; BTIndexPage* rightSiblingIndexPage; PageId rightPageId; Status st; st = MINIBASE_BM->newPage( rightPageId, (Page*&)rightSiblingIndexPage ); rightSiblingIndexPage->init( rightPageId); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); assert( st == OK); //chose a mediate_key to push up int numLeft = (indexPage->numberOfRecords()+1)/2; int numRight = indexPage->numberOfRecords()+1-numLeft; RID metaRid; Keytype iterKey; PageId iterPage; st = indexPage->get_first( metaRid, &iterKey, iterPage); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); assert( st == OK); RID dummyRid; RID leftLastRid; Keytype medKey; PageId medPage; bool entryInserted = false; for( int i = 0 ; i < numLeft-1 ; i++){ st = indexPage->get_next( metaRid, &iterKey, iterPage); } if( !entryInserted && keyCompare( &(newEntry->key), &iterKey, headerPage->key_type) <=0){ //newEntry is in the left half st = indexPage->insertKey( (void*)(&newEntry->key), headerPage->key_type, newEntry->data.pageNo, dummyRid ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); medKey = iterKey; medPage = iterPage; st = indexPage->deleteKey( &iterKey, headerPage->key_type, dummyRid); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); st = indexPage->get_next( metaRid, &iterKey, iterPage); entryInserted = true; } else{ // this is the middle key st = indexPage->get_next( metaRid, &iterKey, iterPage); if( !entryInserted && keyCompare( &(newEntry->key), &iterKey, headerPage->key_type) <=0){ medKey = newEntry->key; medPage = newEntry->data.pageNo; } else{ medKey = iterKey; medPage = iterPage; rightSiblingIndexPage->insertKey( (void*)&(newEntry->key), headerPage->key_type, newEntry->data.pageNo, dummyRid ); indexPage->deleteKey( &iterKey, headerPage->key_type, dummyRid); st = indexPage->get_next( metaRid, &iterKey, iterPage); entryInserted = true; } } while( st == OK){ st = indexPage->deleteKey( &iterKey, headerPage->key_type, dummyRid); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); st = rightSiblingIndexPage->insertKey( (void*)&iterKey, headerPage->key_type, iterPage, dummyRid ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); st = indexPage->get_next( metaRid, &iterKey, iterPage); } rightSiblingIndexPage->setLeftLink( medPage); KeyDataEntry newEntry; Datatype entryData; entryData.pageNo = rightSiblingIndexPage->page_no(); int entryLen; make_entry( &newEntry, headerPage->key_type, (void*)&medKey,INDEX, entryData, &entryLen); **goingUp = newEntry; *goingUpSize = entryLen; st = MINIBASE_BM->unpinPage( rightPageId, TRUE ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); } } else{ *goingUp = NULL; printf("index do not split\n"); } break; } case LEAF: { BTLeafPage* leafPage = (BTLeafPage*) rpPtr; RID myRid; if( leafPage->available_space() >= sizeof(KeyDataEntry)){ Status myst = leafPage->insertRec(key, headerPage->key_type, rid, myRid); if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); *goingUp = NULL; } else{ //split fprintf(stderr, "leaf split start >>>>>>>>"); cout<<"**************************leaf_split"<<endl; printPage(currentPageId); int numberRec = leafPage->numberOfRecords(); BTLeafPage* newRight; // BTIndexPage* newRoot; Status myst; PageId newRightID; void* currentKey; RID currentDataRID; if((myst = MINIBASE_BM->newPage(newRightID, (Page*&)newRight)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); newRight->init(newRightID); RID firstRID; RID tmp; void* middleKey; RID middleDataRID; if((myst = leafPage->get_first(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); int board = (numberRec)/2; for(int i = 1; i < board; i++){ if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); if((myst = leafPage->get_next(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } int k = 0; for(int j = board; j < numberRec; j++){ void* tmpKey = (void*) malloc(sizeof(currentKey)); memcpy(tmpKey, currentKey, sizeof(currentKey)); if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); if(j == board){ if((myst = leafPage->get_next(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } else{ leafPage->delUserRid(tmpKey, headerPage->key_type, currentDataRID); if((myst = leafPage->get_current(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } myst = newRight->insertRec(currentKey, headerPage->key_type, currentDataRID, tmp); if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } leafPage->delUserRid(currentKey, headerPage->key_type, currentDataRID); if((myst = newRight->get_first(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); middleKey = currentKey; middleDataRID = currentDataRID; if(keyCompare(key, middleKey, headerPage->key_type)>0){ myst = newRight->insertRec(key, headerPage->key_type, rid, tmp); if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } else if(keyCompare(key, currentKey, headerPage->key_type) == 0){ assert("key values equal!!"); } else{ myst = leafPage->insertRec(key, headerPage->key_type, rid, tmp); if(myst != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); } PageId pre = leafPage->getPrevPage(); PageId nex = leafPage->getNextPage(); fprintf(stdout, "pre = %d\nnex = %d\n", pre, nex); newRight->setPrevPage(currentPageId); leafPage->setNextPage(newRightID); // fprintf(stdout, "c = %d\nn = %d\n", currentPageId, newRightID); BTLeafPage* tmpPage; if(nex >= 0){ if((myst = MINIBASE_BM->pinPage(nex,(Page *&) tmpPage)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); // tmpPage->init(newRightID); ((BTLeafPage*)tmpPage)->setPrevPage(newRightID); newRight->setNextPage(nex); fprintf(stdout, "before unpin\n"); if((myst = MINIBASE_BM->unpinPage(nex, TRUE)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); fprintf(stdout, "afterpin\n"); } fflush(stdout); if((myst = newRight->get_first(firstRID, currentKey, currentDataRID)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); fprintf(stderr, "\nysysys\n"); middleKey = currentKey; middleDataRID = currentDataRID; // KeyDataEntry* newEntry = (KeyDataEntry*)malloc(sizeof(KeyDataEntry)); KeyDataEntry newEntry; Datatype entryData; Keytype entryKey; entryData.pageNo = newRightID; fprintf(stderr, "sure:[%d]\n", entryData.pageNo); int entryLen; make_entry( &newEntry, headerPage->key_type, middleKey,INDEX,entryData, &entryLen); // make_entry( &newEntry, headerPage->key_type, middleKey,INDEX, newRightID, &entryLen); // (newEntry->key).intkey = *(int*)middleKey; // (newEntry->data).pageNo = newRightId; newEntry.data.pageNo=newRightID; // fprintf(stderr, "in leaf dataentry:should be [%d] [%d] but: [%d] [%d]\n",*((int*)middleKey), newRightID , newEntry.key.intkey, newEntry.data.pageNo); **goingUp = newEntry; // newEntry.data.pageNo = 1; *goingUpSize = entryLen; if((myst = MINIBASE_BM->unpinPage(newRightID, TRUE)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, myst); fprintf(stderr,"\t leaf split end\n"); printPage(currentPageId); printPage(newRightID); } break; } default: // in case memory is scribbled upon & type is hosed fprintf(stderr, "currentPageId = (%d) pagetype%d\n", currentPageId, pageType ); assert(false); } if((st = MINIBASE_BM->unpinPage(currentPageId, TRUE)) != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); return OK; }
Status BTreeFile::findRunStart (const void *lo_key, BTLeafPage **pppage, RID *pstartrid) { BTLeafPage *ppage; BTIndexPage *ppagei; PageId pageno; PageId curpage; // iterator PageId prevpage; PageId nextpage; RID metaRid, curRid; Keytype curkey; Status st; AttrType key_type = headerPage->key_type; KeyDataEntry curEntry; pageno = headerPage->root; if (pageno == INVALID_PAGE){ // no pages in the BTREE *pppage = NULL; // should be handled by pstartrid = NULL; // the caller return OK; } st = MINIBASE_BM->pinPage(pageno, (Page *&) ppagei); if (st != OK) return MINIBASE_FIRST_ERROR(BTREE, CANT_PIN_PAGE); while (ppagei->get_type() == INDEX) { // TODO: fill the body if( lo_key == NULL) st = ppagei->get_first( metaRid, (void*)&curkey, nextpage ); else{ st = ppagei->get_page_no( (void*)&curkey, headerPage->key_type, nextpage); } assert( st ==OK); st = MINIBASE_BM->pinPage( nextpage, (Page*&) ppagei); assert( st ==OK); } assert(ppagei); assert(ppagei->get_type() == LEAF); ppage = (BTLeafPage *) ppagei; st = ppage->get_first(metaRid, &curkey, curRid); while (st == NOMORERECS) { // TODO: fill the body PageId nextPageId = ppage->getNextPage(); if( nextPageId == INVALID_PAGE){ *pppage = NULL; return OK; } st = MINIBASE_BM->unpinPage( ppage->page_no(), TRUE ); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); st = MINIBASE_BM->pinPage(nextPageId, (Page *&) ppage); if( st != OK) return MINIBASE_CHAIN_ERROR(BTREE, st); st = ppage->get_first(metaRid, &curkey, curRid); } if (lo_key == NULL) { *pppage = ppage; *pstartrid = metaRid; return OK; // note that pageno/ppage is still pinned; scan will unpin it when done } while (keyCompare(&curkey, lo_key, key_type) < 0) { // TODO: fill the body st = ppage->get_next( metaRid, &curkey, curRid); if( st == NOMORERECS) break; } *pppage = ppage; *pstartrid = metaRid; return OK; }
// merge. Status Sort::merge( Scan* scan[], int runNum, HeapFile* outHF ) { //Member variables declaration int len; RID rid; int runId; Status s; char record[runNum*rec_len]; char *recptr; recptr=record; int runflag[runNum]; /* By default setting all the runFlags to be 1 */ for (int i=0;i<runNum;i++) runflag[i]=1; char file[25]; // Construct the record array by using the pointers from the scan array for (int i=0;i <runNum;i++) { s = scan[i]->getNext(rid, recptr, len); //Create or set the run flags for each of the arrays if (s != OK) { //cout <<"\nNo more records.Setting run flag to 0"; runflag[i] = 0; } recptr = recptr + len; } int count=0; while(1) { //Call popup function after constructing the record array Status s1= popup(record,runflag,runNum,runId); if (s1==DONE) { //cout <<"\nIs this true ? Are we done ?"; break; } recptr=record+ runId*rec_len; count=count+1; //cout <<"\n Inserting record " << count<< "\t" <<*recptr<<" " <<*(recptr+1)<<" into outFile"; s = outHF->insertRecord(recptr, rec_len, rid); if (s!= OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, s); //Get the next record from the file which had the lowest record and so the pointer keeps moving. s = scan[runId]->getNext(rid, recptr, len); if (s!= OK) runflag[runId]=0; } return OK; }
DB::DB( const char* fname, unsigned num_pgs, Status& status ) { #ifdef DEBUG cout << "Creating database " << fname << " with pages " << num_pgs <<endl; #endif name = strcpy(new char[strlen(fname)+1],fname); num_pages = (num_pgs > 2) ? num_pgs : 2; // Create the file; fail if it's already there; open it in read/write // mode. fd = ::open( name, O_RDWR | O_CREAT | O_EXCL, 0666 ); if ( fd < 0 ) { status = MINIBASE_FIRST_ERROR( DBMGR, UNIX_ERROR ); return; } // Make the file num_pages pages long, filled with zeroes. char zero = 0; ::lseek( fd, (num_pages*MINIBASE_PAGESIZE)-1, SEEK_SET ); ::write( fd, &zero, 1 ); // Initialize space map and directory pages. MINIBASE_DB = this; //set the global variable to be this. Status s; first_page* fp; #ifdef BM_TRACE s = MINIBASE_BM->pinPage( 0, (Page*&)fp, true /*==empty*/, "*** DB admin ***" ); #else s = MINIBASE_BM->pinPage( 0, (Page*&)fp, true /*==empty*/ ); #endif if ( s != OK ) { status = MINIBASE_CHAIN_ERROR( DBMGR, s ); return; } fp->num_db_pages = num_pages; init_dir_page( &fp->dir, sizeof *fp ); s = MINIBASE_BM->unpinPage( 0, true /*==dirty*/ ); if ( s != OK ) { status = MINIBASE_CHAIN_ERROR( DBMGR, s ); return; } // Calculate how many pages are needed for the space map. Reserve pages // 0 and 1 and as many additional pages for the space map as are needed. unsigned num_map_pages = (num_pages + bits_per_page - 1) / bits_per_page; status = set_bits( 0, 1 + num_map_pages, 1 ); }
Status DB::add_file_entry(const char* fname, PageId start_page_num) { #ifdef DEBUG cout << "Adding a file entry: " << fname << " : " << start_page_num << endl; #endif // Is the info kosher? if ( strlen(fname) >= MAX_NAME ) return MINIBASE_FIRST_ERROR( DBMGR, FILE_NAME_TOO_LONG ); if ((start_page_num < 0) || (start_page_num >= (int) num_pages) ) return MINIBASE_FIRST_ERROR( DBMGR, BAD_PAGE_NO ); // Does the file already exist? PageId tmp; if ( get_file_entry(fname,tmp) == OK ) return MINIBASE_FIRST_ERROR( DBMGR, DUPLICATE_ENTRY ); char *pg = 0; Status status; directory_page* dp = 0; bool found = false; unsigned free_slot = 0; PageId hpid, nexthpid = 0; do { hpid = nexthpid; // Pin the header page. status = MINIBASE_BM->pinPage( hpid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // This complication is because the first page has a different // structure from that of subsequent pages. dp = (hpid == 0)? &((first_page*)pg)->dir : (directory_page*)pg; nexthpid = dp->next_page; unsigned entry = 0; while ( (entry < dp->num_entries) && (dp->entries[entry].pagenum != INVALID_PAGE)) ++entry; if ( entry < dp->num_entries ) { free_slot = entry; found = true; } else if ( nexthpid != INVALID_PAGE ) { // We only unpin if we're going to continue looping. status = MINIBASE_BM->unpinPage( hpid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } } while ( nexthpid != INVALID_PAGE && !found ); // Have to add a new header page if possible. if ( !found ) { status = allocate_page( nexthpid ); if ( status != OK ) { MINIBASE_BM->unpinPage( hpid ); return status; } // Set the next-page pointer on the previous directory page. dp->next_page = nexthpid; status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // Pin the newly-allocated directory page. hpid = nexthpid; status = MINIBASE_BM->pinPage( hpid, (Page*&)pg, true /*empty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); dp = (directory_page*)pg; init_dir_page( dp, sizeof(directory_page) ); free_slot = 0; } // At this point, "hpid" has the page id of the header page with the free // slot; "pg" points to the pinned page; "dp" has the directory_page // pointer; "free_slot" is the entry number in the directory where we're // going to put the new file entry. dp->entries[free_slot].pagenum = start_page_num; strcpy( dp->entries[free_slot].fname, fname ); status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) status = MINIBASE_CHAIN_ERROR( DBMGR, status ); return status; }
Status DB::allocate_page(PageId& start_page_num, int run_size_int) { #ifdef DEBUG cout << "Allocating a run of "<< run_size << " pages." << endl; #endif if ( run_size_int < 0 ) { cerr << "Allocating a negative run of pages.\n"; return MINIBASE_FIRST_ERROR ( DBMGR, NEG_RUN_SIZE ); } unsigned run_size = run_size_int; unsigned num_map_pages = (num_pages + bits_per_page - 1) / bits_per_page; unsigned current_run_start = 0, current_run_length = 0; // This loop goes over each page in the space map. Status status; for( unsigned i=0; i < num_map_pages; ++i ) { PageId pgid = 1 + i; // The space map starts at page #1. // Pin the space-map page. char* pg; status = MINIBASE_BM->pinPage( pgid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // How many bits should we examine on this page? int num_bits_this_page = num_pages - i*bits_per_page; if ( num_bits_this_page > bits_per_page ) num_bits_this_page = bits_per_page; // Walk the page looking for a sequence of 0 bits of the appropriate // length. The outer loop steps through the page's bytes, the inner // one steps through each byte's bits. for ( ; num_bits_this_page > 0 && current_run_length < run_size; ++pg ) for ( unsigned mask=1; (mask < 256) && (num_bits_this_page > 0) && (current_run_length < run_size); mask <<= 1, --num_bits_this_page ) if ( *pg & mask ) { current_run_start += current_run_length + 1; current_run_length = 0; } else ++current_run_length; // Unpin the space-map page. status = MINIBASE_BM->unpinPage( pgid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } if ( current_run_length >= run_size ) { start_page_num = current_run_start; #ifdef DEBUG cout<<"Page allocated in get_free_pages:: "<< start_page_num << endl; #endif return set_bits( start_page_num, run_size, 1 ); } return MINIBASE_FIRST_ERROR( DBMGR, DB_FULL ); }
Status SortedPage::insertRecord (AttrType key_type, char * recPtr, int recLen, RID& rid) { Status status; int i; // ASSERTIONS: // - the slot directory is compressed -> inserts will occur at the end // - slotCnt gives the number of slots used // general plan: // 1. Insert the record into the page, // which is then not necessarily any more sorted // 2. Sort the page by rearranging the slots (insertion sort) status = HFPage::insertRecord(recPtr, recLen, rid); //fprintf(stderr, "###sorted page start###\n"); //dumpPage(); if (status != OK) return MINIBASE_FIRST_ERROR(SORTEDPAGE, INSERT_REC_FAILED); assert(rid.slotNo == (slotCnt-1)); #ifdef MULTIUSER char tmp_buf[DPFIXED]; memcpy(tmp_buf,(void*)&slot[0], DPFIXED); #endif // performs a simple insertion sort for (i=slotCnt-1; i > 0; i--) { char *key_i = data + slot[-i].offset; char *key_iplus1 = data + slot[-(i-1)].offset; if (keyCompare((void*)key_i, (void*) key_iplus1, key_type) < 0) { // switch slots: slot_t tmp_slot; tmp_slot = slot[-i]; slot[-i] = slot[-(i-1)]; slot[-(i-1)] = tmp_slot; } else { // end insertion sort break; } } // ASSERTIONS: // - record keys increase with increasing slot number (starting at slot 0) // - slot directory compacted rid.slotNo = i; #ifdef MULTIUSER status = MINIBASE_RECMGR->WriteUpdateLog(DPFIXED, curPage,sizeof data, tmp_buf,(char*)&slot[0], (Page*) this); if (status != OK) return MINIBASE_CHAIN_ERROR(BTREE,status); #endif //fprintf(stderr, "###sorted page end ###\n"); //dumpPage(); return OK; }
// pass after the first. Status Sort::followingPass( int passNum, int oldHFnum, int bufferNum, int& newHFnum ) { int no_of_input_buffers = bufferNum -1; int no_of_output_buffer = 1; int oldpassNum=passNum; int iterative_hfnum; int run_no; Scan *scan[no_of_input_buffers]; int scan_count; int heap_files_processed; char file[25]; Status s1; //Setting the newHFnum initially to zero ans then updating it accordingly inside the function. newHFnum=0; //Read in bufferNum -1 files and open scans on each of them if (oldHFnum <=1) return OK; while(newHFnum != 1) { scan_count= 0; heap_files_processed=0; run_no=0; for (int i = 0; i < oldHFnum; i++) { makeHFname(file,passNum,i+1); HeapFile f1(file, s1); if (s1 != OK) { cout << "\n Error here in opening heap file"; return MINIBASE_CHAIN_ERROR(HEAPFILE, s1); } //Open scans on each of them Scan *sc1 = f1.openScan(s1); if (s1 != OK) { cout << "\n Error here in opening scan"; return MINIBASE_CHAIN_ERROR(HEAPFILE, s1); } scan[scan_count] = sc1; scan_count = scan_count + 1; heap_files_processed = heap_files_processed + 1; if (scan_count < bufferNum - 1 && heap_files_processed != oldHFnum) continue; //After setting up scan array and run number call the merge function if(scan_count==bufferNum-1 && newHFnum==bufferNum-1) { run_no = run_no + 1; //cout <<"\n Run no is:" <<run_no; HeapFile o(outFileName,s1); if(s1!=OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, s1); merge(scan,scan_count,&o); //Re-set the scan_count for processing the next set of (numBuffer-1) heap files scan_count = 0; return OK; } if(scan_count == bufferNum-1) { //Set up a name for the heap file //cout<<"\nWriting the results to temp heapfile"; run_no = run_no + 1; makeHFname(file,passNum+1,run_no); //cout <<"\nRun no is:" <<run_no; HeapFile w(file,s1); if(s1!=OK) return MINIBASE_CHAIN_ERROR(HEAPFILE, s1); merge(scan,scan_count,&w); //Re-set the scan_count for processing the next set of (numBuffer-1) heap files scan_count = 0; } } //The end of for-loop indicates the processing of all the files for that pass. The run count now will tell us the number //of runs produced from the following pass. We should set that to the newHFnum variable. passNum = passNum + 1; newHFnum = run_no; oldHFnum=run_no; //cout <<"\nPass no is: " <<passNum; //cout << "\nFinal Number of runs produced:" << newHFnum; } return OK; }