示例#1
0
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;

}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
文件: scan.C 项目: cloudhit/DBsystem
// *******************************************
// 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;
}
示例#5
0
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;
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
文件: scan.C 项目: cloudhit/DBsystem
// *******************************************
// 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;
}
示例#11
0
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;
}
示例#12
0
文件: scan.C 项目: cloudhit/DBsystem
// *******************************************
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;
}
示例#13
0
文件: scan.C 项目: cloudhit/DBsystem
// *******************************************
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;
}
示例#14
0
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;
}
示例#15
0
文件: SMJTester.C 项目: skyrain/dbms
//-------------------------------------------------------------
// 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;
}
示例#16
0
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;
}
示例#17
0
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;
}
示例#18
0
文件: scan.C 项目: cloudhit/DBsystem
// *******************************************
// 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;
}
示例#19
0
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;

		}
	}

}
示例#21
0
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;
}
示例#22
0
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;
}
示例#23
0
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;

}
示例#25
0
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 );
}
示例#26
0
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;
}
示例#27
0
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;


}