/* 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; }
/* * 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; }
/* 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; }
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; }
/************************************************************************************** * 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; }
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; }
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; }
/**************************************************************** * 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; }
/* 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; }
/* 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(); }
/**************************************************************** * 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(); }
// 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; } }
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; }