/* Name: applyLRU
 * Expected arguments: BM_BufferPool
 * Behavior: Would apply LRU as page replacement strategy on the buffer pool and return us the appropriate
 * 			 page to be replaced.
 * Returns: Success/failure flag.
 * Version: 1.0.0 */
int applyLRU(BM_BufferPool * const bm, BM_PageHandle * const page,
		const PageNumber pageNum) {
	BufferPool_Node *bf_node;
	bf_node = search_data(BP_StNode_ptr, bm);
	Buffer_page_Dtl *lowestPossiblePage;
	lowestPossiblePage = sortWeights(bm, bf_node);
	char *replacementAddress;
	replacementAddress = lowestPossiblePage->pageframes;

	RC writeVal = RC_OK;
	RC readVal = RC_OK;
	if (lowestPossiblePage->isdirty == TRUE) {
		writeVal = writeBlock(page->pageNum, bm->mgmtData, replacementAddress);
		lowestPossiblePage->isdirty=FALSE;
		bf_node->numwriteIO++;
	}
	readVal = readBlock(pageNum, bm->mgmtData, replacementAddress);
	if(readVal==RC_READ_NON_EXISTING_PAGE)
    {
        readVal =appendEmptyBlock(bm->mgmtData);
        readVal = readBlock(pageNum, bm->mgmtData, replacementAddress);
    }
	page->pageNum  = pageNum;
	page->data = lowestPossiblePage->pageframes;
    lowestPossiblePage->pagenums = pageNum;
    lowestPossiblePage->fixcounts+=1;
	lowestPossiblePage->replacementWeight =
    lowestPossiblePage->replacementWeight + 1;
	lowestPossiblePage->timeStamp =(long double)univtime++;
    bf_node->numreadIO++;
	if (readVal == RC_OK && writeVal == RC_OK)
		return 1; //success flag
	else
		return 0;
}
示例#2
0
/*
 * If the file has less than numberOfPages pages then increase the size to given number of pages.
 */
RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
{
    /*
     * Checks if file handler is already initialized
     * If yes, increases pages to size of given number of pages
     * If not, returns appropriate error of file not initialized
     */
	if(fHandle->fileName == NULL)
		return RC_FILE_HANDLE_NOT_INIT;

	else if(fHandle->mgmtInfo == NULL)
		return RC_FILE_HANDLE_NOT_INIT;

	else
	{
		if(fHandle->totalNumPages == numberOfPages)
			return RC_OK;

		else if(fHandle->totalNumPages < numberOfPages)
		{
			while((fHandle->totalNumPages)!=numberOfPages)
			{
				appendEmptyBlock(fHandle);
			}
		}
	}
	return RC_OK;
}
RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)

{
  int numNewPages; 	                                          	/*to ensure capacity add the new number of pages*/ 

     
  if (fHandle->mgmtInfo == NULL)                                /*check the fhandle is initialized*/
 
    return RC_FILE_NOT_FOUND;	                 		  		/*return error*/

  else
  {

     if (numberOfPages > fHandle->totalNumPages){                 /*if number of pages required is more than total pages*/
      
       numNewPages = numberOfPages - fHandle->totalNumPages;      /*newpages will be added to the fhandle*/

       while(numNewPages > 0)                                     /*Ierate using while loop until we get the empty block*/
        {
          appendEmptyBlock(fHandle);                              /*perform appendEmptyBlock operations*/

          numNewPages=numNewPages - 1 ;
        }
      }

  }
  return RC_OK;													/*return as 0*/
    
  
 }
extern RC writeBlock(int pageNum, SM_FileHandle *fHandle, SM_PageHandle memPage)
{
    FILE *fp = ((SM_FileMgmtInfo*)fHandle->mgmtInfo)->file;

    if (pageNum < fHandle->totalNumPages) { //check if pageNum is a legal value
        //change curPagePos to specified pageNum
        fHandle->curPagePos = pageNum;
        fseek(fp, fHandle->curPagePos*PAGE_SIZE, SEEK_SET);
        //now write memPage to file
        int input_size = strlen(memPage);

        int check = 0, i = 0;
        for (i = 0; i < input_size; i++){
            //fprintf(fp, "%s", memPage); //assumes memPage is <= PAGE_SIZE
            putc(memPage[i], fp);
            check++;

            int currentPage = fHandle->curPagePos;
            int totalPages = fHandle->totalNumPages;
            if (check == PAGE_SIZE) {
                if (currentPage == totalPages - 1) { //ran out of pages to write to
                    appendEmptyBlock(fHandle);
                }
                fHandle->curPagePos = currentPage++;
                check = 0;
            }
        }
        return RC_OK; //done writing, no errors
    }
    return RC_WRITE_FAILED; //failed because pageNum is too large
}
/*function to write block to the Page File on the Disk starts from here*/
RC writeBlock (int pageNum, SM_FileHandle *fHandle, SM_PageHandle memPage)
{
	/*required variables declarations for writeBlock function starts here*/
	FILE *filePointer; // define FILE pointer to point to the file opened
	int blockSize =0;// to check the size of the block written to disk
	int offset_write=0; //to calculate the offset to write to correct page
	int offset_initial = (fHandle->totalNumPages) * PAGE_SIZE;
	int i=0;
	char buffer[PAGE_SIZE]={'\0'};
	/*required variables declarations for writeBlock function ends here*/
	
	/*Check if the pageNum in the referring file has atleast one page*/
	if(pageNum>=0){
		/*If the pageNum value exceeds the totalNumPages, call ensureCapacity function*/
		if(pageNum+1>(fHandle->totalNumPages))
		{
			for (i=0;i<=(pageNum+1)-fHandle->totalNumPages;i++)
			{
					appendEmptyBlock(fHandle);
			}
		}
		/*function to open the file in read Binary mode*/
		filePointer = fopen(fHandle->fileName,"rb+"); // open the binary file in write mode
		/*seek the file pointer to the end of the file*/
		printf("The page number passed in writeBlock is %d\n",pageNum);
		fseek(filePointer,0,SEEK_SET);
		int position = ftell(filePointer);
		
		/*Find the offset to seek to from the end of the file to the desired location to do the write operation*/
			offset_initial = pageNum * PAGE_SIZE;
		/*seek the file pointer to the calculated value as above*/
		fseek(filePointer,offset_initial,SEEK_SET); //seek to the end of the file -> to set total number of pages of the file
		int pos = ftell(filePointer);

		/*write the file at the position pointed to by the file pointer using fwrite function*/
		for (i=0;i<PAGE_SIZE;i++)
		{
			if (i<strlen (memPage))
			{
				buffer[i] = *(memPage+i);
			}
			else
			{
				buffer[i] = '\0';
			}
		}
		blockSize = fwrite(buffer,1,PAGE_SIZE,filePointer);//write the data pointed to by memPage to file on disk pointed by filePointer
		int pos1 = ftell(filePointer);
		fHandle->curPagePos=pageNum;//update the current page position
	}
	if(blockSize>0)
	{
		return RC_OK;
	}
	else{
		printError(RC_WRITE_FAILED);
		return RC_WRITE_FAILED;
	}
}
//append the file and increase totoal number of pages if needed
RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle){
    int rt = 0;
    int i;
    if(fHandle->totalNumPages<numberOfPages+1){
        for(i=0; i<numberOfPages+1-fHandle->totalNumPages; i++){
            if((rt=appendEmptyBlock(fHandle)) != 0){
                return rt;
            }
        }
    }
    return RC_OK;
}
示例#7
0
/* A function to update the fifo page information when needed. 
 * The function finds and updates the oldest page and replace it.
 */
RC readPageFIFO(BM_PoolInfo *const pi, BM_PageHandle *const page, 
      const PageNumber pageNum) {
  RC rc_code = RC_OK;

  int max_index = pi->numPages - 1;
  int index = pi->fifo_old;

  while(pi->fixCounter[index] > 0) {
    if (index >= max_index) {
      index = 0;
    } else {
      index++;
    }
  }

  SM_FileHandle *fh = pi->fh;
  SM_PageHandle memPage = pi->frames[index];

  if (pi->dirtys[index]) {
    writeBlock(pi->map[index], fh, memPage);
    NumWriteIO++;
    pi->dirtys[index] = false;
  }

  // printf("buffer_mgr.readPageFIFO: before any returning code\n");

  if (pageNum >= fh->totalNumPages) {
    // printf("buffer_mgr.readPageFIFO: appending... pageNum (%d) fh->totalNumPages (%d)\n", pageNum, fh->totalNumPages);
    rc_code = appendEmptyBlock(fh);
    // NumWriteIO++;
    // printf("buffer_mgr.readPageFIFO: appended returned (%d)\n", rc_code);

    if (rc_code != RC_OK) return rc_code;
  }

  // printf("READING FROM DISK PAGE %i\n", pageNum);
  rc_code = readBlock(pageNum, fh, memPage);
  NumReadIO++;

  page->data = memPage;
  // update control variables
  pi->map[index] = pageNum;
  pi->fixCounter[index]++; // should go from 0 to 1...
  if (pi->fifo_old >= max_index) {
    pi->fifo_old = 0;
  } else {
    pi->fifo_old++;
  }

  return rc_code;
}
/**************************************************************************************
 * Function Name: ensureCapacity
 *
 * Description:
 *		If the file has less than numberOfPages pages then increase the size to numberOfPages.
 *
 * Parameters:
 *		int numberOfPages: the number of the pages that the file needs to be increased to
 *		SM_FileHandle *fHandle: the file handle that contains the file info
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Xin Su <*****@*****.**>
 *
 * History:
 *		Date        Name                                Content
 *		----------  ----------------------------------  ------------------------
 *		2015-02-09  Xin Su <*****@*****.**>         Initialization.
 *		2015-02-15	Xin Su <*****@*****.**>			Add validation for appendEmptyBlock inside the for loop.
 **************************************************************************************/
RC ensureCapacity(int numberOfPages, SM_FileHandle *fHandle) {
	if (fHandle->totalNumPages < numberOfPages) {
		int i;
		for (i = 0; i < (numberOfPages - fHandle->totalNumPages); i++) {
			RC rc = appendEmptyBlock(fHandle);

			// TODO - what should I do to clean the unfinished write of the empty block?
			if (rc != RC_OK) {
				return rc;
			}
		}
	}
	return RC_OK;
}
示例#9
0
RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
{
        int numPages,total=fHandle->totalNumPages,i;

	if (total < numberOfPages)
	{
		numPages = numberOfPages - total;           // Find Difference 
        	for (i=0; i < numPages; i++)
        	{
			appendEmptyBlock(fHandle); 
		}
    	}
    return RC_OK;
}
示例#10
0
/**************************************************************************************
 * Function Name: If the file has less than numberOfPages pages then increase the size to numberOfPages.
 *
 * Description:
 *            increase number of pages so that the file have the same page numbers as claimed.
 * Parameters:
 *
 *            SM_FileHandle *fHandle: a structure that contains informations of a file(including pointer to this file)
 *            memPage:a buffer that stores data of block
 * Return:
 *            RC: return a status of success or fail
 * Author:
 *            Qi Yang
 * History:
 *            Date                  Name                                Content
 *            ----------            ------------------------------      ---------------
 *            2016-01-23             Qi Yang<*****@*****.**>        self-create
 **************************************************************************************/
RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
{
    if (fHandle->totalNumPages<numberOfPages)
    {
        //how many pages need to be appended.
        int pages,i;
        pages=numberOfPages-fHandle->totalNumPages;
        //appendEmptyBlock for "pages" times
        for (i=0;i<pages;i++)
        {
            appendEmptyBlock(fHandle);
        }
        return RC_OK;
    }
    else return RC_READ_NON_EXISTING_PAGE;
}
示例#11
0
 RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
{
    RC ret = RC_WRITE_FAILED;
    
    if (numberOfPages > fHandle->totalNumPages) {
        int addPageNum = numberOfPages - fHandle->totalNumPages;
        for (int i = 0; i < addPageNum; i++) {
            ret = appendEmptyBlock(fHandle);
            if(ret == RC_OK) fHandle->totalNumPages ++;
        }
         
    }else{
        ret = RC_OK;
    }
    return ret;
}
示例#12
0
RC forcePage (BM_BufferPool *const bm, BM_PageHandle *const page)
{
  SM_FileHandle fH; 
  int code = openPageFile(bm->pageFile, &fH); 
  if(code != RC_OK) 
    return code; 
  
  appendEmptyBlock(&fH);
  code = writeBlock(page->pageNum, &fH, page->data);
  
  if(code != RC_OK) 
    return code;
  closePageFile(&fH);
  metaData.numWriteIO++;
  
  return RC_OK; 
}
示例#13
0
 /****************************************************************
 * Function Name: ensureCapacity
 * 
 * Description: Increase the file size to numberOfPages if the file 
 *              has less than numberOfPages pages.
 * 
 * Parameter: int, SM_FileHandle
 * 
 * Return: RC (int)
 * 
 * Author: Monika Priyadarshani ([email protected])
 ****************************************************************/
 extern RC ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
 {
     RC error;
	 if(fHandle == NULL)
	 {
		return RC_FILE_HANDLE_NOT_INIT;
	 }
	 if(fHandle->totalNumPages < numberOfPages) 
	 {
		 while((numberOfPages - fHandle->totalNumPages)!=0)
		 {
			error = appendEmptyBlock(fHandle);
			if(!error){
			  continue;
		    }
			return error;
		 }	 
	 }
	 return RC_OK;
}
示例#14
0
/* A function to update the lru page information when needed. 
 */
RC readPageLRU(BM_PoolInfo *const pi, BM_PageHandle *const page, 
      const PageNumber pageNum) {
  RC rc_code;

  int index = searchLowest(pi->lru_stamp, pi->numPages);

  SM_FileHandle *fh = pi->fh;
  SM_PageHandle memPage = pi->frames[index];

  if (pi->fixCounter[index] > 0) return RC_PINNED_LRU;

  if (pi->dirtys[index]) {
    writeBlock(pi->map[index], fh, memPage);
    NumWriteIO++;
    pi->dirtys[index] = false;
  }

  if (pageNum >= fh->totalNumPages) {
    // printf("Append for (%d) when total is (%d)\n", pageNum, fh->totalNumPages);
    rc_code = appendEmptyBlock(fh);
    // NumWriteIO++;
    if (rc_code != RC_OK) return rc_code;
  }

  rc_code = readBlock(pageNum, fh, memPage);
  NumReadIO++;
  page->data = memPage;
 
  // update fix count and lru array
  pi->map[index] = pageNum;
  pi->fixCounter[index]++;

  update_lru(index, pi->lru_stamp, pi->numPages);

  return rc_code;
  
}
示例#15
0
/* If the file has less than numberOfPages pages, then increase the size to numberOfPages. 
 * The increasing is done by appending (numberOfPages - totalNumPages) empty blocks 
 * at the end of file.
 */
RC
ensureCapacity (int numberOfPages, SM_FileHandle *fHandle)
{
    
    FILE *fp;
    int totalNumPages, i;
    char *buff;
    
    if (access(fHandle->fileName, R_OK) < 0) return RC_FILE_NOT_FOUND;
    
    fp = fopen(fHandle->fileName, "r+");
    
    buff = (char*)malloc(sizeof(char)*PAGE_SIZE);
    
    if ((totalNumPages = readHeader(fp)) < 1) return RC_FILE_R_W_ERROR;
    
    if (numberOfPages > totalNumPages) {
        for (i = 0; i < (numberOfPages - totalNumPages); i++) {
            appendEmptyBlock(fHandle);
        }
    }
    
    // log file info to console
    struct stat fileStat;
    if(stat(fHandle->fileName,&fileStat) < 0)
        return RC_FILE_R_W_ERROR;
    // printf("\n\n**ENSURE LOG**\n");
    // printf("************************************\n");
    // printf("File Name: \t\t%s\n",fHandle->fileName);
    // printf("File Size: \t\t%lld bytes\n",fileStat.st_size);
    // printf("Total # Pages: \t%d\n",fHandle->totalNumPages);
    
    free(buff);
    fclose(fp);

    return RC_OK;
}
void testAppendEnsureCapMetaData()
{
	SM_FileHandle fh;
	SM_PageHandle ph;
	ph = (SM_PageHandle) malloc(PAGE_SIZE);

	TEST_CHECK(createPageFile (TESTPF));
	TEST_CHECK(openPageFile (TESTPF, &fh));

	//Append an empty block to the file.
	appendEmptyBlock(&fh);
	//Check whether the appended block has only 4096 '\0' in the currentBlock.
	readBlock(getBlockPos(&fh),&fh,ph);
	int i;
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 0), "expected zero byte in first page of freshly initialized page");
	printf("Appended Block was empty\n");

	//Page File should contain only 2 blocks.first block during createPage and second during appendBlock
	ASSERT_TRUE((fh.totalNumPages == 2), "Number of Blocks : 2");

	 //Current Block postion should be 1
	ASSERT_TRUE((fh.curPagePos == 1), "Current Page Position is 1");

	//add 3 more blocks to the Page File.
	ensureCapacity(5,&fh);

	//Verify whether the freshly added 3 blocks are of '\0' characters
	//[START]
	readBlock(2,&fh,ph);
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 0), "expected zero byte in first page of freshly initialized page");

	readBlock(3,&fh,ph);
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 0), "expected zero byte in first page of freshly initialized page");

	readBlock(4,&fh,ph);
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 0), "expected zero byte in first page of freshly initialized page");
	printf("Freshly appended 3 blocks are empty\n");
	//[END]

	//Page File should contain only 5 blocks, as we have called ensureCapacity(5)
	ASSERT_TRUE((fh.totalNumPages == 5), "Number of Blocks : 5");

	//Current Block postion should be 4
	ASSERT_TRUE((fh.curPagePos == 4), "Current Page Position is 4");

	//Store the metaData into the file and close the pagefile.
	int totalNoOfPages = fh.totalNumPages;
	char fileName[100];
	memset(fileName,'\0',100);
	strcpy(fileName,fh.fileName);
	char metaDataFromFile[100];
	memset(metaDataFromFile,'\0',100);
	closePageFile(&fh);

	//Verify whether the written  MetaData is correct or not
	//[START]
	char metaDataToBeVerified[100];
	memset(metaDataToBeVerified,'\0',100);
	char returnData[100];
	memset(returnData,'\0',100);
	metaDataToBeVerified[0]= 'P';metaDataToBeVerified[1]= 'S';metaDataToBeVerified[2]= ':';metaDataToBeVerified[3]= '\0';
	getString(PAGE_SIZE,returnData);
	strcat(metaDataToBeVerified,returnData);
	strcat(metaDataToBeVerified,";");
	memset(returnData,'\0',100);
	strcat(metaDataToBeVerified,"NP:");
	getString(totalNoOfPages,returnData);
	strcat(metaDataToBeVerified,returnData);
	strcat(metaDataToBeVerified,";");
	readMetaDataFromFile(fileName,metaDataFromFile);
	ASSERT_TRUE((strcmp(metaDataToBeVerified, metaDataFromFile) == 0), "MetaData read from file is correct");
	printf("Read Meta Data from file is :: %s\n",metaDataToBeVerified);
	//[END]
	TEST_CHECK(destroyPageFile(TESTPF));
	free(ph);
	TEST_DONE();
}
示例#17
0
/****************************************************************
 * Function Name: myTestAssign1
 *  
 * Description: Additional tests for Storage Manager.
 * 
 * Parameter: void
 * 
 * Return: void
 * 
 * Author: Dhruvit Modi ([email protected])
 *         Monika Priyadarshani ([email protected])
 ****************************************************************/
void
myTestAssign1(void)
{
  SM_FileHandle fh;
  SM_PageHandle ph;
  int i;
  
  ph = (SM_PageHandle) malloc(PAGE_SIZE);

  // create a new page file
  TEST_CHECK(createPageFile (TESTPF));
  TEST_CHECK(openPageFile (TESTPF, &fh));
  printf("created and opened file\n");
  
    
  for (i=0; i < PAGE_SIZE; i++)
    ph[i] = (i % 10) + '0';
  
  // write on the first block  
  TEST_CHECK(writeCurrentBlock (&fh, ph));
  printf("writing first block\n");
  
  // append empty block
  TEST_CHECK(appendEmptyBlock(&fh));
  printf("append Empty block\n");
   
   // write on the second block 
  TEST_CHECK(writeBlock (1, &fh, ph));
  printf("writing second block\n");
  
  TEST_CHECK(appendEmptyBlock(&fh));
  printf("append Empty block\n");
  
    // write to the third block
  TEST_CHECK(writeBlock (2, &fh, ph));
  printf("writing third block\n");
  
  // read back the page containing the string and check that it is correct
  printf("reading first block\n");
  TEST_CHECK(readFirstBlock (&fh, ph));
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == (i % 10) + '0'), "character in page read from disk is the one we expected.");
  
  
  // read back the page containing the string and check that it is correct
  printf("reading last block\n");
  TEST_CHECK(readLastBlock (&fh, ph));
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == (i % 10) + '0'), "character in page read from disk is the one we expected.");
  
  
  // read back the page containing the string and check that it is correct
  printf("reading previous block\n");
  TEST_CHECK(readPreviousBlock (&fh, ph));
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == (i % 10) + '0'), "character in page read from disk is the one we expected.");
  
  
  // read back the page containing the string and check that it is correct
  printf("reading current block\n");
  TEST_CHECK(readCurrentBlock (&fh, ph));
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == (i % 10) + '0'), "character in page read from disk is the one we expected.");
  
  
  // read back the page containing the string and check that it is correct
  printf("reading next block\n");
  TEST_CHECK(readNextBlock (&fh, ph));
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == (i % 10) + '0'), "character in page read from disk is the one we expected.");
  
  // append empty block
  TEST_CHECK(appendEmptyBlock(&fh));
  printf("append Empty block\n");
  
  // ensure capacity
  TEST_CHECK(ensureCapacity(6, &fh));
  printf("ensure capacity\n");
  
    // destroy new page file
  TEST_CHECK(destroyPageFile (TESTPF));  
  
  TEST_DONE();
}
示例#18
0
// Bulk of work will be here 
// handling records in a table
RC insertRecord(RM_TableData *rel, Record *record) {
	RM_TableMgmtData *tableMgmtData = rel->mgmtData;
	BM_MgmtData *bufferMgmtData = tableMgmtData->bufferPool.mgmtData;
	RID *rid = &record->id;
	RM_Page *page;
	char *slotOffset;

	//  Do we have a free slot?
	if (tableMgmtData->nextFreeSlot > 0) {
		// We have a free slot for the record
		rid->page = tableMgmtData->nextFreeSlot;
		// Pin page to insert record
		RC pinPageResult;
		if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, rid->page) != RC_OK) {
			return pinPageResult;
		}

		page = (RM_Page*)tableMgmtData->pageHandle.data;

		// Find the free slot for the record and save it
		rid->slot = findFreeSlot(page, rel->schema);

		if (rid->slot == NO_SLOT) { // Append new page, out of space
			RC unpinPageResult;
			if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) {
				return unpinPageResult;
			}

			if (appendEmptyBlock(&bufferMgmtData->fh) != RC_OK) {
				return RC_RM_INSERT_RECORD_FAIL;
			}

			rid->page = bufferMgmtData->fh.totalNumPages - 1;

			RC pinPageResult;
			if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, rid->page) != RC_OK) {
				return pinPageResult;
			}
			
			//new page, set slot to 0 (first slot)
			page = (RM_Page*)tableMgmtData->pageHandle.data;
			rid->slot = 0;
		}
	}
	else {
	// No free slot so make new page for record
		RC appendEmptyBlockResult;
		if (appendEmptyBlock(&bufferMgmtData->fh) != RC_OK) {
			return RC_RM_INSERT_RECORD_FAIL;
		}

		rid->page = bufferMgmtData->fh.totalNumPages - 1;

		RC pinPageResult;
		if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, rid->page) != RC_OK) {
			return pinPageResult;
		}
		page = (RM_Page*)tableMgmtData->pageHandle.data;

		rid->slot = 0;
	
	}

	// Finish writing the record now that we have slot information
	RC markDirtyResult;
	if (markDirtyResult = markDirty(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) {
		return markDirtyResult;
	}
	
	// Add header offset to slot position for slot offset
	slotOffset = ((char*)&page->data) + (rid->slot * getRecordSize(rel->schema));

	int recordSize = getRecordSize(rel->schema);
	memcpy(slotOffset + 1, record->data, recordSize);

	// Mark first byte of slot with tombstone information info
	*(char*)slotOffset = 1;

	// Update free slot information
	if (findFreeSlot(page, rel->schema) != NO_SLOT) {
		int pageNum = rid->page;
		addFreeSlot(tableMgmtData, page, rid->page);
	}

	RC unpinPageResult;
	if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) {
		return unpinPageResult;
	}
	tableMgmtData->numTuples++;

	return RC_OK;
}
/* Name: pinPage
 * Expected arguments: BM_BufferPool *const bm, BM_PageHandle *const page, covnst PageNumber pageNum
 * Behavior: Would perform the applicable page replacement strategy on the buffer pool and pin the page from
 * 			 file at the appropriate position.
 * Version: 1.0.0
 * Algorithm:   1) Check if the page is already present in buffer
 * 				2) Add a replcementWeight to each page.
 * 				2) Get the appropriate replacement page by invoking the corresponding strategy
 * 				2) Replace that page with the new page.
 * 				3) The newly added page should have the maximum weight. */
RC pinPage(BM_BufferPool * const bm, BM_PageHandle * const page,
		const PageNumber pageNum) {
	int replacementFrameNum, totalPages, i;
	int statusFlag;
	ReplacementStrategy strategy = bm->strategy;
	Buffer_page_Dtl *lowestPossiblePage;
	totalPages = bm->numPages;
	BufferPool_Node *bf_node;
//	pthread_mutex_lock(&work_mutex_pin);//Hold the mutex lock for thread in pin block.
	bf_node = search_data(BP_StNode_ptr, bm);
	Buffer_page_Dtl *pg_dtl;
	pg_dtl = bf_node->buffer_page_dtl;
	RC writeVal=1, readVal=1;
	int emptyFlag = 1;
	if (pg_dtl != NULL) {

		/*This for loop checks if the page is already present in the buffer*/
		for (i = 0; i < totalPages; i++) {
			/*In order to make sure that all the elements of the array are empty, I am not breaking the loop*/
			if ((pg_dtl + i)->pagenums > -1) { //I assume that pagenums will be a mandatory field for any pg_dtl.
				emptyFlag = 0;
				/*To check if the page is already present in buffer.*/
				if ((pg_dtl + i)->pagenums == pageNum) {
                    (pg_dtl + i)->timeStamp=univtime++;//timestamp used in LRU
                    page->pageNum = pageNum;
					page->data = (pg_dtl + i)->pageframes;
					(pg_dtl + i)->fixcounts+=1;
//					pthread_mutex_unlock(&work_mutex_pin);//Unlock the mutex lock for thread in pin block.
					return RC_OK; // If there is a hit, return OK. There is no need to pin it since it is already present.
				}

			}
		} //end of 1st for loop

		/*This loop gets the first lowestPossible page and assigns it.*/
		for (i = 0; i < totalPages; i++) {
			if ((pg_dtl + i)->pagenums == -1){
				lowestPossiblePage = ((pg_dtl + i)); //After the loop, lowestPossiblePage would be last page for which pg_dtl was empty
				emptyFlag = 1;
				break;
			}
		}//end of 2nd for loop

	} else { /*This also means that the page detail has not been initialized at all since the array itself is null. This block might never be reached*/
		lowestPossiblePage = (pg_dtl + 0); // I assign the first frame itself as the lowestPossiblePage which is fit to be replaced.
		lowestPossiblePage->replacementWeight =
				lowestPossiblePage->replacementWeight + 1;

		(pg_dtl + i)->timeStamp=univtime++;
		emptyFlag = 1;
	}

	/*Even if there is one empty frame, emptyFlag would be 1. And we could make use of that page.*/
	if (emptyFlag == 1) {
		page->pageNum = pageNum;
		page->data = lowestPossiblePage->pageframes;
		/*If you find a free frame, just write the contents to that frame*/
		writeVal = RC_OK;
		/*This if condition is not mandatory. Infact this might never become true*/
		if (lowestPossiblePage->isdirty == TRUE) {
			writeVal = writeBlock(pageNum, bm->mgmtData,
					lowestPossiblePage->pageframes);
					bf_node->numwriteIO++;
		}
		if(readBlock(pageNum, bm->mgmtData,lowestPossiblePage->pageframes)==RC_READ_NON_EXISTING_PAGE)
				{
				    readVal=appendEmptyBlock(bm->mgmtData);//If page requested in pin not available in the file , do append it.
				}
				else
                    readVal=RC_OK;
        bf_node->numreadIO++;
		lowestPossiblePage->fixcounts += 1;
		lowestPossiblePage->pagenums = pageNum;

	} else { /*If no frame is free, call the appropriate page replacement algorithm to do the job*/
		if (strategy == RS_FIFO) {
			statusFlag = applyFIFO(bm, page, pageNum);
		} else if (strategy == RS_LRU) {
			statusFlag = applyLRU(bm, page, pageNum);
		} else if (strategy == RS_CLOCK) {
//			statusFlag = applyCLOCK(bm, page, pageNum);
		} else if (strategy == RS_LRU_K) {
//			statusFlag = applyLRU_k(bm, page, pageNum);
		} else {
			return RC_WRITE_FAILED; // should probably return "Invalid strategy"
		}
	} //end of outer else block

	/*Status flag indicates the success of the page replacement algorithm when no frame is free
	 * writeVal indicates the success of writelock call when a frame is dirty*/
//   	 pthread_mutex_unlock(&work_mutex_pin);
	if (statusFlag == 1 || (writeVal == RC_OK && readVal == RC_OK)) {
		return RC_OK;
	} else {
		return RC_WRITE_FAILED;
	}
}
示例#20
0
RC insertKey (BTreeHandle *tree, Value *key, RID rid){
    BT_Node *node = NULL, *newnode = NULL, *root = NULL, *point = NULL;
    int i, intKey, left, right, k=0, maxsize=2*(tree->n+2);
    BT_Element *element = (BT_Element *)malloc(maxsize * sizeof(BT_Element));
    
    // If root does not exist, create root.
    if(tree->entryNum==0 || tree->rootPage==-1 || getNode(tree, tree->rootPage, &node) != RC_OK){   
        node = (BT_Node *)calloc(1, sizeof(BT_Node));
        node->isValid = 1;
        node->parent = -1;
        node->current = tree->fileHandle->totalNumPages;
        appendEmptyBlock(tree->fileHandle);
        node->nodeType = 1;
        node->size = 2;
        node->element = (BT_Element *)malloc(sizeof(BT_Element) * maxsize);
        (*(node->element)).id = rid;
        (*(node->element+1)).node = key->v.intV;
        tree->nodeNum++;
        tree->rootPage = node->current;
        setNode(tree, node->current, node);
    } else {
        // Find the target node to insert
        while(node->nodeType == 0){     // While not leaf
            for(i=1; ; i+=2){
                if((*(node->element+i)).node > key->v.intV || i>=node->size){
                    k = (*(node->element+i-1)).node;
                    getNode(tree, k, &node);
                    break;
                }
            }
        }
        
        intKey = key->v.intV;
        do {
            // Insert rid and key into node
            for(i=1; i < node->size+4; i+=2){
                if((*(node->element+i)).node > intKey || i>=node->size){
                    if(i > 1 && (*(node->element+i-2)).node == intKey){
                        freeNode(node);
                        return RC_IM_KEY_ALREADY_EXISTS;
                    }
                    if(node->nodeType == 0){        // if not leaf.
                        memcpy(element, node->element, sizeof(BT_Element) * (i-1));
                        (*(element+i-1)).node = left;
                        (*(element+i)).node = intKey;
                        (*(element+i+1)).node = right;
                        memcpy(element + i+2, node->element+ i, sizeof(BT_Element) * (node->size-i));
                    } else {                        // if leaf node
                        memcpy(element, node->element, sizeof(BT_Element) * (i-1));
                        (*(element+i-1)).id = rid;
                        (*(element+i)).node = intKey;
                        memcpy(element + i+1, node->element+ i-1, sizeof(BT_Element) * (node->size+1-i));
                    }
                    node->size+=2;
                    memcpy(node->element, element, sizeof(BT_Element) * node->size);
                    break;
                }
            }
            
            if(node->size >= 2*(tree->n+1)){       // If node overflow, then split into 2 nodes.
                if(newnode == NULL){
                    newnode = (BT_Node *)malloc(sizeof(BT_Node));
                    newnode->element = (BT_Element *)calloc(maxsize, sizeof(BT_Element));  
                }
                newnode->size = node->size/4*2 + node->size%2;
                newnode->isValid = 1;
                newnode->current = tree->fileHandle->totalNumPages;
                appendEmptyBlock(tree->fileHandle);
                newnode->nodeType = node->nodeType;
                newnode->parent = node->parent;
                memcpy(newnode->element, node->element + node->size - newnode->size, 
                    sizeof(BT_Element)*newnode->size);

                node->size = (node->size/2 - node->size/4)*2 + 1;
                (*(node->element+node->size-1)).node =  newnode->current;   //Point to new node.

                tree->nodeNum++; 
                if(node->parent == -1){     // Create new root if corrent node do not have parent
                    left = node->current;  
                    if(root == NULL){
                        root = (BT_Node *)malloc(sizeof(BT_Node));
                        root->size = 3;
                        root->isValid = 1;
                        root->parent = -1;
                        root->nodeType = 0;
                        root->element = (BT_Element *)malloc(sizeof(BT_Element) * 3);
                    }

                    root->current = tree->fileHandle->totalNumPages;
                    appendEmptyBlock(tree->fileHandle);
                    (*(root->element)).node = left;
                    (*(root->element+1)).node = (*(newnode->element+1)).node;
                    (*(root->element+2)).node = newnode->current;
                    
                    tree->rootPage = root->current;
                    tree->nodeNum++;
                    node->parent = root->current;
                    newnode->parent = root->current;
                    setNode(tree, node->current, node);
                    setNode(tree, newnode->current, newnode);
                    setNode(tree, root->current, root);
                    break;
                } else {                    // Insert into root if corrent node have parent
                    setNode(tree, node->current, node);
                    setNode(tree, newnode->current, newnode);
                    intKey = (*(newnode->element+1)).node;
                    left = node->current;      
                    right = newnode->current;
                    getNode(tree, node->parent, &node);
                }
            } else {                        // If node not overflow, then save node and break loop
                setNode(tree, node->current, node);
                break;
            }
        } while (true);
    }
    
    tree->entryNum++;
    free(element);
    freeNode(node);
    freeNode(newnode);
    freeNode(root);
    return RC_OK;
}