RC FIFO(BM_BufferPool *const bm, BM_PageHandle *const page, const PageNumber pageNum) {
    int ret, i;
    struct BM_PageFrame *frameListHead, *curFrame, *selectedFrame;
    SM_FileHandle fh;
    
    ret = openPageFile(bm->pageFile, &fh);
    if (RC_OK != ret){
        printf("%s, %d, Open Page File Fail\n", __func__,__LINE__);
        return RC_FILE_HANDLE_NOT_INIT;
    }
    frameListHead = (BM_PageFrame *)bm->mgmtData;
     
    selectedFrame = findEmpPage(frameListHead);
   
        // No Empty page, fetch suitable position to replace the page
    if (NULL == selectedFrame) { 
        selectedFrame = pinPosition(frameListHead);
    }

    // Do not have usable frame in memory 
    if (NULL == selectedFrame) { 
        printf("%s All frame cannot be used\n", __func__);
        return RC_BM_BP_NO_FRAME_TO_REP;
    }
  
    //Prepare to read the page from disk to memory
    if (fh.totalNumPages < pageNum +1) {
        ret = ensureCapacity(pageNum +1, &fh);
        NumWriteIO += pageNum +1 - fh.totalNumPages;
        if (RC_OK != ret) {
            closePageFile(&fh);
            printf("%s, %d ensurecapacity fail\n",__func__, __LINE__ );
            return RC_READ_NON_EXISTING_PAGE;
        }
    }

    //Write framepage to disk if page is dirty
    if(selectedFrame->flags & Frame_dirty) {
        writeBlock(selectedFrame->pageHandle.pageNum,  &fh, selectedFrame->pageHandle.data); 
        selectedFrame->flags &= ~Frame_dirty;
        NumWriteIO++;
    }

    ret  = readBlock(pageNum, &fh, selectedFrame->pageHandle.data);
    NumReadIO++;
     
    page->pageNum = pageNum;
    page->data = selectedFrame->pageHandle.data;
    
    selectedFrame->fixCount += 1; 
    selectedFrame->pageHandle.pageNum = pageNum;
    selectedFrame->flags |=Frame_cached;
    
    maintainSortedFrameList(bm, selectedFrame);

    closePageFile(&fh);

    return ret;    
}
예제 #2
0
RC forceFlushPool(BM_BufferPool *const bm)
{
    //write all dirty pages (fix count 0) to disk
    //do pinned check
    buffer *bf = bm->mgmtData;
    
    SM_FileHandle fHandle;
    RC rt_value = openPageFile(bm->pageFile, &fHandle);
    if (rt_value!=RC_OK) return rt_value;

    frame *pt = bf->head;
    do
    {
        if (pt->dirty)
        {
            rt_value = writeBlock(pt->currpage, &fHandle, pt->data);
            if (rt_value!=RC_OK) return rt_value;
            pt->dirty = false;
            bf->numWrite++;
        }
        pt = pt->next;
    }while (pt!=bf->head);
    
    closePageFile(&fHandle);
    return RC_OK;
}
예제 #3
0
int pinThispage(BM_BufferPool *const bm, frame *pt, PageNumber pageNum)
/*pin page pointed by pt with pageNum-th page. If do not have, create one*/
{
    buffer *bf = bm->mgmtData;
    SM_FileHandle fHandle; //cheating: should malloc then free
    RC rt_value = openPageFile(bm->pageFile, &fHandle);
    if (rt_value!=RC_OK) return rt_value;
    rt_value = ensureCapacity(pageNum, &fHandle); //你不说谁知道啊
    if (rt_value!=RC_OK) return rt_value;
    
    if (pt->dirty)
    {
        rt_value = writeBlock(pt->currpage, &fHandle, pt->data);
        if (rt_value!=RC_OK) return rt_value;
        pt->dirty = false;
        bf->numWrite++;
    }
    
    rt_value = readBlock(pageNum, &fHandle, pt->data);
    if (rt_value!=RC_OK) return rt_value;
    bf->numRead++;
    pt->currpage = pageNum;
    pt->fixCount++;
    closePageFile(&fHandle);
    
    return 0;
}
예제 #4
0
RC shutdownBufferPool (BM_BufferPool *const bm)
{
  SM_FileHandle fh;
  RC code = openPageFile(bm->pageFile, &fh);
  if (code != RC_OK)
    return code;

  resetPages();
  int i = 0;
  for(i = 0; i < bm->numPages; i++){
    if (pages->isMark && pages->fixCount > 0){
      code = writeBlock(pages->pageNum, &fh, pages->pageData);
      if(code != RC_OK)
	return code;
      metaData.numWriteIO++;
    }
    
    pages->isMark = false;
    pages->pageData = malloc(PAGE_SIZE);
    strcpy(pages->pageData, "");
    pages->pageNum = -1;
    pages->fixCount = 0;
    pages->repStrat = -1;

    if(i < bm->numPages-1){
      pages = pages->nextPage;
    }
  }
  closePageFile(&fh);

  return RC_OK;

}
RC shutdownBufferPool(BM_BufferPool *const bm){
    forceFlushPool(bm);         //store data into memory
    free(bm->mgmtData);
    closePageFile(fh);
    return RC_OK;
    
}
예제 #6
0
RC createTable(char *name, Schema *schema) {
	SM_FileHandle fh;
	char data[PAGE_SIZE];
	char *offset = data;

	// Prepare schema for writing to block header
	memset(offset, 0, PAGE_SIZE);
	*(int*)offset = 0;
	offset = offset + sizeof(int);
	*(int*)offset = 0;
	offset = offset + sizeof(int);
	*(int*)offset = schema->numAttr;
	offset = offset + sizeof(int);
	*(int*)offset = schema->keySize;
	offset = offset + sizeof(int);

	// Copy everything from schema to be written to block
	int i;
	for (i = 0; i < schema->numAttr; i++) {
		strncpy(offset, schema->attrNames[i], NAME_SIZE);
		offset = offset + NAME_SIZE;

		*(int*)offset = (int)schema->dataTypes[i];
		offset = offset + TYPE_SIZE;

		*(int*)offset = (int)schema->typeLength[i];
		offset = offset + LENGTH_SIZE;

		if (i < schema->keySize) {
			*(int*)offset = (int)schema->keyAttrs[i];
		}
		offset = offset + KEY_SIZE;
	}

	// Write the table and schema information to file
	RC createPageFileResult;
	if ((createPageFileResult = createPageFile(name)) != RC_OK) {
		return createPageFileResult;
	}
	RC openPageFileResult;
	if ((openPageFileResult = openPageFile(name, &fh)) != RC_OK) {
		return openPageFileResult;
	}
	RC writeBlockResult;
	if ((writeBlockResult = writeBlock(0, &fh, data)) != RC_OK) {
		return writeBlockResult;
	}
	RC closePageFileResult;
	if ((closePageFileResult = closePageFile(&fh)) != RC_OK) {
		return closePageFileResult;
	}

	return RC_OK;
}
예제 #7
0
RC forcePage (BM_BufferPool *const bm, BM_PageHandle *const page)
{
    //current frame2file
    buffer *bf = bm->mgmtData;
    SM_FileHandle fHandle;
    RC rt_value;
    
    rt_value = openPageFile(bm->pageFile, &fHandle);
    if (rt_value!=RC_OK) return RC_FILE_NOT_FOUND;
    
    rt_value = writeBlock(page->pageNum, &fHandle, page->data);
    if (rt_value!=RC_OK)
    {
        closePageFile(&fHandle);
        return RC_FILE_NOT_FOUND;
    }
    
    bf->numWrite++;
    closePageFile(&fHandle);
    return RC_OK;
}
예제 #8
0
RC shutdownBufferPool(BM_BufferPool *const bm) {
    // Flush the pool
    RC flushResult = forceFlushPool(bm);
    if (flushResult != RC_OK) {
        return flushResult;
    }

    // Retrieve management data
    BM_MgmtData *mgmtData = bm->mgmtData;
    BM_Frame *frame = &mgmtData->framePool[0];

    // Check for pinned pages
    int i;
    for (i = 0; i < bm->numPages; i++) {
        if (frame->fixCount != 0) {
            return RC_FRAME_PINNED_PAGE;
        }

        frame++;
    }

    // Close storage manager details
    RC pageCloseResult = closePageFile(&mgmtData->fh);
    if (pageCloseResult != RC_OK) {
        return pageCloseResult;
    }

    // Free memory and lists
    // Free frames
    for (i = 0; i < bm->numPages; i++) {
        free(mgmtData->framePool[i].memPage);
    }

    // Free frame pool
    free(mgmtData->framePool);

    // Free linked list nodes
    BM_Node *freeHead = mgmtData->head;
    while (freeHead != NULL) {
        freeHead = removeFromHead(&mgmtData->head);
        if (freeHead != NULL) {
            free(freeHead);
        }
    }

    // Free mgmt data
    free(bm->mgmtData);

    // Free buffer pool 
    free(bm->pageFile);
    
    return RC_OK;
}
예제 #9
0
RC shutdownBufferPool(BM_BufferPool *const bm) {

	RC retCode;
	// Get the head node of the linked list.
	BM_PageReplaceList *current = bm->mgmtData->last;

	while(current != NULL) {
		if(current->pageFrameHandle->fixCount == 0) {
			// If fix count is 0, then proceed, else throw error.
			if(current->pageFrameHandle->dirtyFlag) {
                                // If dirty flag is set, write page back to the disk.
				BM_PageHandle *const page = current->pageFrameHandle->pageHandle;
				if(forcePage(bm, page) != RC_OK) {
					return RC_FORCE_FLUSH_FAILED;
				}
			}
                        current = current->prevFrame;
		} else {
                        // Throw error as buffer pool is still in use.
			return RC_POOL_IN_USE;
		}
	}

	int i;
        // Deallocate memory allocated for frame data and page handle.
        for(i=0; i < bm->numPages; i++) {
                free(bm->mgmtData->hashT->hashArray[i]->pageHandle->data);	// Char *
                free(bm->mgmtData->hashT->hashArray[i]->pageHandle);		// BM_PageHandle
                free(bm->mgmtData->hashT->hashArray[i]);			// PageInfo
        }

//        free(bm->mgmtData->hashT->hashArray);
        // Close file and deallocate memory assigned to file handle.
        closePageFile(bm->mgmtData->fh);

        // Deallocate memory assigned for each link in the linked list.
        current = bm->mgmtData->last;
        while(current->prevFrame != NULL) {
                free(current->nextFrame);
                current = current->prevFrame;
        }
        free(current);

        free(bm->mgmtData->fh);		// Deallocate memory for SM_FileHandle
        free(bm->mgmtData->hashT);	// Deallocation of PageInfo **
        free(bm->mgmtData);		// Deallocation of BM_MgmtData
        free(bm->pageFile);		// Deallocation of page file

	return RC_OK;
}
/* Name: ShutDown BufferPool
 * Behavior:Would shutdown an existing buffer pool.
 * Version: 1.0.0 */
RC shutdownBufferPool(BM_BufferPool *const bm)
{
    RC ret=RC_WRITE_FAILED;
    int i ,*pgnums, *fixounts;
    bool ispinned=FALSE;
    Buffer_page_Dtl *pg_dtl;
    BufferPool_Node *bufnode;
    char *frame;
    int currentaccessed;
//    pthread_mutex_lock(&work_mutex_shutdown);//1st Incoming thread hold a lock.
    fixounts=getFixCounts(bm);
    pgnums=getFrameContents(bm);
    for(i=0 ; i < bm->numPages ; i++)
    {
        if(fixounts[i] > 0)
        {
            ispinned=TRUE;//Condition to check for pinned pages before shut down.
        }
    }
    free(fixounts);
    if(ispinned==FALSE)
    {
        ret=RC_OK;
        bufnode=search_data(BP_StNode_ptr,bm);//Get the active buffer pool from collection of pools.
        currentaccessed=getfilebeingused(BP_StNode_ptr,bm->pageFile);//Check if the same pool is being shared.
        if(bufnode!=NULL)
        {
            pg_dtl=bufnode->buffer_page_dtl;
            if(pg_dtl!=NULL)
            for(i=0;i<bm->numPages;i++)
            {
                frame=pg_dtl[i].pageframes;
                if(pg_dtl[i].isdirty==TRUE)
                {
                   ret=writeBlock(pg_dtl[i].pagenums,bm->mgmtData,frame)==RC_OK?RC_OK:RC_WRITE_FAILED;//Write the content with dirty to disk.
                }
                currentaccessed == 1 ?free(frame):' ';
            }
            currentaccessed == 1 ?free(pg_dtl):' ';
            pg_dtl=NULL;
            delete_node(&BP_StNode_ptr,bm);
        }
    currentaccessed == 1 ?closePageFile(bm->mgmtData):' ';
    currentaccessed == 1 ?free(bm->mgmtData):' ';

  }
//  pthread_mutex_unlock(&work_mutex_shutdown);//1st Incoming thread release a lock.
    free(pgnums);
    return ret;
}
//Creating a table should create the underlying page file and store information about the schema, free-space, ... and so on in the Table Information pages
RC createTable (char *name, Schema *schema){
    createPageFile(name);
    SM_PageHandle ph;
    openPageFile(name, &fh);
    ensureCapacity(1, &fh);
    ph=schemaToString(schema);
    writeCurrentBlock(&fh,ph);
    calSlotSize(schema);
    calPageHeader(schema);
    closePageFile(&fh);
    return RC_OK;
    
    

    
}
예제 #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
파일: buffer_mgr.c 프로젝트: iypearun001/DB
// Close buffer pool
RC shutdownBufferPool(BM_BufferPool *const bm)
{
  RC rc= RC_OK;
  int frmNo;
  BM_PageFrame *pf;
  BM_Pool_MgmtData *mgmtData= bm->mgmtData;

  // Flush dirty pages
  rc= forceFlushPool(bm);
  if (rc != RC_OK)
    RETURN(rc);

  BM_LOCK();
  // Check if we have pinned pages,
  pf= &mgmtData->pool[0];
  for (frmNo=0; frmNo < bm->numPages; frmNo++)
  {
    if (pf->fixCount)
    {
      BM_UNLOCK();
      RETURN(RC_HAVE_PINNED_PAGE);
    }

    // Also reset page table
    if (pf->pn != NO_PAGE)
      resetPageFrame(&mgmtData->pt_head, pf->pn);
    pf++;
  }
  
  rc= closePageFile(&mgmtData->fh);
  if (rc != RC_OK)
  {
    BM_UNLOCK();
    RETURN(rc);
  }

  cleanLRUlist(&mgmtData->stratData);
  free(mgmtData->pool);
  free(bm->pageFile);
  BM_UNLOCK();
  pthread_mutex_destroy(&mgmtData->bm_mutex);
  free(mgmtData);

  RETURN(RC_OK);
}
/**************************************************************************************
 * Function Name: shutdownBufferPool
 *
 * Description:
 *		Shut down the buffer pool
 *
 * Parameters:
 *		BM_BufferPool *const bm: buffer pool that users try to shut down
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Chengnan Zhao <*****@*****.**>
 *
 * History:
 *		Date        Name									Content
 *		----------  --------------------------------------	------------------------
 *		2015-03-14  Chengnan Zhao <*****@*****.**>	Initialization
 *		2015-03-20	Xin Su <*****@*****.**>				Add judgment of the rc returned by forceFlushPool
 *															Modify the logic of freeing the PageList
 *															Add comments
 *															Add judgment of the rc returned by closePageFile
 *															Add the free code of F_HANDLE and MEM_PAGE
 **************************************************************************************/
RC shutdownBufferPool(BM_BufferPool * const bm) {
	// Force to flush all pages updated in the Buffer Pool back to the disk
	RC rc = -99; // init return code
	rc = forceFlushPool(bm);

	if (rc != RC_OK) {
		// TO DO
	}

	// Free allocated memory blocks (PageFrame) of the PageList
	PageList *queue = (PageList *) bm->mgmtData;
	queue->current = queue->tail;

	// if the capacity is 1, simply free the only block
	// else (the capacity > 1), free the PageFrame from the tail back to the head
	if (bm->numPages == 1) {
		free(bm->mgmtData);
	} else {
		while (queue->current != queue->head) {
			queue->current = queue->current->previous;
			free(queue->current->next);
		}

		// After the while loop, the current pointer points to the head,
		// then free the only left block
		free(queue->head);
	}

	// Turn off the Storage Manager by closing the page file
	rc = -99; // reset return code
	rc = closePageFile(F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// Then free the F_HANDLE and MEM_PAGE
	free(F_HANDLE);
	free(MEM_PAGE);

	return RC_OK;
}
예제 #15
0
/* Try to create, open, and close a page file */
void testCreateOpenClose(void) {
    SM_FileHandle fh;

    testName = "test create open and close methods";

    TEST_CHECK(createPageFile (TESTPF));

    TEST_CHECK(openPageFile (TESTPF, &fh));
    ASSERT_TRUE(strcmp(fh.fileName, TESTPF) == 0, "filename correct");
    ASSERT_TRUE((fh.totalNumPages == 1), "expect 1 page in new file");
    ASSERT_TRUE((fh.curPagePos == 0), "freshly opened file's page position should be 0");

    TEST_CHECK(closePageFile (&fh));
    TEST_CHECK(destroyPageFile (TESTPF));

    // after destruction trying to open the file should cause an error
    ASSERT_TRUE((openPageFile(TESTPF, &fh) != RC_OK), "opening non-existing file should return an error.");

    TEST_DONE();
}
예제 #16
0
/*Purpose: when buffer pool is to be shut down, this function will write the pages which are dirty to the memory */
RC forceFlushPool(BM_BufferPool *const bm)
{

BufferManager *mgmtDataInfo=(BufferManager *)bm->mgmtData;
PageFrames *TempTraverseNode=mgmtDataInfo->HeadNode;
RC msg;
if(TempTraverseNode==NULL){return RC_FRAME_NOT_INIT;} 
mgmtDataInfo->Total_WriteIO=getNumWriteIO(bm);

while(TempTraverseNode!=NULL)
{
	if(TempTraverseNode->Pining==0){
	if(TempTraverseNode->DirtyCount==1)
	{
		if((msg = ensureCapacity(TempTraverseNode->PageNumberValue, &mgmtDataInfo->fileHandler_StorageMgr)) != RC_OK){
            return msg;
        }
		if((msg=writeBlock(TempTraverseNode->PageNumberValue,&mgmtDataInfo->fileHandler_StorageMgr,TempTraverseNode->Data_Value))==RC_OK)
		{
            TempTraverseNode->DirtyCount=0;
            mgmtDataInfo->DirtyValue[(TempTraverseNode->PageNumberValue)-1]=false;
            mgmtDataInfo->Total_WriteIO+=1;
		}
        else
        {
            RC_message = "forceFlushPool";
            RC_WRITE_FAILED;
        }
    }
}
else return RC_PINED_PAGE_FOUND;

TempTraverseNode=TempTraverseNode->next;
}

closePageFile(&mgmtDataInfo->fileHandler_StorageMgr);
free(TempTraverseNode);
return RC_OK;
}
RC forceFlushPool(BM_BufferPool *const bm){     //function used to store data into memory
    BufferPageNode *tem;
    int result;
    tem=g_queue->front;
    while (tem!=NULL) //loop to check dirty files
    {
        result=-1;
        if(tem->dirty==1)   //check file if it is dirty
        {
        result=writeBlock(tem->PageNum,fh, tem->data);
        countWrite++;
        tem->dirty=0;   //after storing set the dirty flag into 0
        if (result!=0)
            {
                closePageFile(fh);
                return RC_WRITE_FAILED;
            }
        }

        tem=tem->next;
    }
    return RC_OK;
}
예제 #18
0
RC forceFlushPool (BM_BufferPool *const bm)
{  
  int i = 0;
  resetPages();

  SM_FileHandle fh;
  RC code = openPageFile(bm->pageFile, &fh);
  if (code != RC_OK)
    return code;

  for(i = 0; i < bm->numPages; i++){
    if (pages->isMark && pages->pageNum > -1){
      pages->isMark = false;
    }
    if(i < bm->numPages-1){
      pages = pages->nextPage;
    }
  }
  resetPages();
  closePageFile(&fh);

  return RC_OK;
}
/**************************************************************************************
 * Function Name: forcePage
 *
 * Description:
 *		Write the requested page back to the page file on disk
 *
 * Parameters:
 *		BM_BufferPool * const bm: Buffer Pool Handler
 *		BM_PageHandle * const page: Buffer Page Handler
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Jie Zhou <*****@*****.**>
 *
 * History:
 *		Date        Name								Content
 *		----------  ----------------------------------	----------------------------
 *		2015-03-13  Jie Zhou <*****@*****.**>		Initialization
 *		2015-03-20	Xin Su <*****@*****.**>			Modify the logic of forcing to write the requested page back
 *														Add comments
 **************************************************************************************/
RC forcePage(BM_BufferPool * const bm, BM_PageHandle * const page) {
	PageList *queue = (PageList *) bm->mgmtData;
	RC rc = -99;

	// Require lock
	pthread_rwlock_init(&rwlock, NULL);
	pthread_rwlock_wrlock(&rwlock);

	// Open file
	rc = -99;
	rc = openPageFile(bm->pageFile, F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// First set numWriteIO
	queue->current->numWriteIO = 1;

	// Write the requested page back to the disk
	rc = -99;
	rc = writeBlock(page->pageNum, F_HANDLE, page->data);
	NUM_WRITE_IOS++;

	if (rc != RC_OK) {
		// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

		// Close file
		rc = -99;
		rc = closePageFile(F_HANDLE);

		if (rc != RC_OK) {
			return rc;
		}

		// Release unlock
		pthread_rwlock_unlock(&rwlock);
		pthread_rwlock_destroy(&rwlock);

		return rc;
	}

	// Set the page back to clean
	queue->current->dirtyFlag = FALSE;

	// The write completes without error, then set numWriteIO back
	queue->current->numWriteIO = 0;

	// Close file
	rc = -99;
	rc = closePageFile(F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// Release lock
	pthread_rwlock_unlock(&rwlock);
	pthread_rwlock_destroy(&rwlock);

	return RC_OK;
} // forcePage
예제 #20
0
//adding one to the fix for the pin page in the buffer pool
//And adding one to each time of mgmtDataLRU in the buffer pool
RC LRU_pinPage(BM_BufferPool *const bm, BM_PageHandle *const page, PageNumber pageNum){
    //printf("pin: %d\n", pageNum);
    int i;
    int ind = LRU_findByPageNumber(bm, pageNum);
    //get the system time at pinPage;
    clock_t c = clock();
    
    mgmtDataLRU * nodes = (mgmtDataLRU *)bm->mgmtData;
    
    RC _rc;
    SM_FileHandle fHandle;
    //if the page is in buffer, return the pagehandle
    if (ind >= 0){
        page->pageNum = pageNum;
        page->data = nodes[ind].pagehandle->data;
        nodes[ind].time = c;
        nodes[ind].fix++;
        //printf("page found in buffer: %d\n", ind);
        return RC_OK;
    }
    
    //if there are free page in the buffer
    for(i=0; i<bm->numPages; i++){
        if ( nodes[i].pagehandle->pageNum == NO_PAGE){
            //printf("%dth page is free\n", i);
            nodes[i].pagehandle->pageNum = pageNum;
            free(nodes[i].pagehandle->data);
            nodes[i].pagehandle->data = (char *)calloc(1, PAGE_SIZE);
            _rc = openPageFile(bm->pageFile, &fHandle);
            if(_rc != RC_OK){
                return _rc;
            }
            _rc = readBlock(pageNum, &fHandle, nodes[i].pagehandle->data);
            closePageFile(&fHandle);
            if(_rc == RC_OK){
                //printf("page # %d is in disk\n", pageNum);
                bm->numOfRead++;
            }
            nodes[i].fix++;
            nodes[i].time = c;
            nodes[i].dirty = false;
            
            page->pageNum = pageNum;
            page->data = nodes[i].pagehandle->data;
            //printf("pinpage succeed, %dth page become page# %d\n", i, page->pageNum);
            return RC_OK;
        }
    }
    //if all buffers have data
    i = LRU_findTheEariestUnfixedNode(bm);
    if (i == -1){
        //all buffers are full and occupied
        return RC_BM_ALL_PAGE_PINNED;
    }
    else{
        //write the content to disk
        if(nodes[i].dirty){
            _rc = forcePage(bm,nodes[i].pagehandle);
            //bm->numOfWrite++;
        }
        nodes[i].pagehandle->pageNum = pageNum;
        free(nodes[i].pagehandle->data);
        nodes[i].pagehandle->data = (char *)calloc(1, PAGE_SIZE);
        
        _rc = openPageFile(bm->pageFile, &fHandle);
        if(_rc != RC_OK){
            return _rc;
        }
        _rc = readBlock(pageNum, &fHandle, nodes[i].pagehandle->data);
        closePageFile(&fHandle);
        if(_rc == RC_OK){
            bm->numOfRead++;
        }
        nodes[i].fix++;
        nodes[i].time = c;
        nodes[i].dirty = false;
        //            nodes[i].time  = (double)seconds;
        page->pageNum = pageNum;
        page->data = nodes[i].pagehandle->data;
        
        return RC_OK;
    }
    
}
예제 #21
0
RC pinPage (BM_BufferPool *const bm, BM_PageHandle *const page, const PageNumber pageNum)
{ 
  int i; 
  resetPages();
 
  int spotFound = -1;
  for(i = 0; i < bm->numPages; i++){
    if(pages->pageNum == -1){
      spotFound = i;
      break;
    }

    if(pages->pageNum == pageNum){
      spotFound = i;
      break;
    }
    
    if(i < bm->numPages-1){
      pages = pages->nextPage;
    }
  }

  int min = 999999;
  if (spotFound == -1) {
    resetPages();
    for (i = 0; i < bm->numPages; i++) {
      if (pages->fixCount == 0 && pages->repStrat < min) {
	min = pages->repStrat;
	spotFound = i;
      }

      if(i < bm->numPages-1){
	pages = pages->nextPage;
      }
    }
  }
  resetPages();
  for(i = 0; i < bm->numPages; i++){
    if(i == spotFound)
      break;
    if(i < bm->numPages-1){
      pages = pages->nextPage;
    }
  }
  
  SM_FileHandle fH;
  openPageFile(bm->pageFile, &fH);
 
  if(pages->pageNum == pageNum){
    if(bm->strategy == RS_LRU)
      pages->repStrat = ++(metaData.totalRepStrat);
    pages->fixCount++;
    page->pageNum = pageNum;
    strcpy(page->data, pages->pageData);
  }else {
    page->data = malloc(PAGE_SIZE);
    page->pageNum = pageNum;
    readBlock(pageNum, &fH, page->data);
    metaData.numReadIO++;
          
    pages->pageNum = pageNum;

    pages->fixCount = 1;
    pages->repStrat = ++(metaData.totalRepStrat);
    pages->isMark = false;
  }
  closePageFile(&fH);
  
  return RC_OK; 
}
/**************************************************************************************
 * Function Name: appendPage
 *
 * Description:
 *		Read the requested page from the disk and append it to the tail of the PageList
 *
 * Parameters:
 *		BM_BufferPool * const bm: Buffer Pool Handler
 *		BM_PageHandle * const page: Buffer Page Handler
 *		PageNumber pageNum: the page number of the requested page
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Xin Su <*****@*****.**>
 *
 * History:
 *		Date        Name                                Content
 *		----------  ----------------------------------  ------------------------
 *		2015-03-15  Xin Su <*****@*****.**>         Initialization
 *		2015-03-26	Xin Su <*****@*****.**>			Add thread read-write lock
 **************************************************************************************/
RC appendPage(BM_BufferPool * const bm, BM_PageHandle * const page,
		PageNumber pageNum) {
	PageList *queue = (PageList *) bm->mgmtData;
	RC rc; // init return code

	// Require lock
	pthread_rwlock_init(&rwlock, NULL);
	pthread_rwlock_wrlock(&rwlock);

	// Open File
	rc = -99;
	rc = openPageFile(bm->pageFile, F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// if the size of the PageList = 0, then the PageList is empty, add this requested page as the head
	// else, the PageList is neither empty nor full, add the requested page to next of the tail of the PageList
	if (queue->size == 0) {
		queue->head->fixCount = 1;
		queue->head->numWriteIO = 1;

		// if the page does not exist, then call ensureCapacity to add the requested page to the file
		if (F_HANDLE->totalNumPages < pageNum + 1) {
			int totalPages = F_HANDLE->totalNumPages;
			rc = -99;
			rc = ensureCapacity(pageNum + 1, F_HANDLE);
			NUM_WRITE_IOS += pageNum + 1 - totalPages;

			if (rc != RC_OK) {
				// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

				// Close file
				rc = -99;
				rc = closePageFile(F_HANDLE);

				if (rc != RC_OK) {
					return rc;
				}

				// Release lock
				pthread_rwlock_unlock(&rwlock);
				pthread_rwlock_destroy(&rwlock);

				return rc;
			}
		}
		queue->head->numWriteIO = 0;

		// After ensureCapacity, now we can read the requested page from the file
		queue->head->numReadIO++;
		rc = -99;
		rc = readBlock(pageNum, F_HANDLE, queue->head->page->data);
		NUM_READ_IOS++;
		queue->head->numReadIO--;

		if (rc != RC_OK) {
			// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

			// Close file
			rc = -99;
			rc = closePageFile(F_HANDLE);

			if (rc != RC_OK) {
				return rc;
			}

			// Release lock
			pthread_rwlock_unlock(&rwlock);
			pthread_rwlock_destroy(&rwlock);

			return rc;
		}

		// Now the fixCount = 1, the numReadIO = 0, and the numWriteIO = 0
		queue->head->page->pageNum = pageNum;
		queue->head->dirtyFlag = FALSE;
		queue->head->clockFlag = FALSE;

		// Now there is only 1 page in the PageList, and all pointers , including the current pointer, are pointing to it
	} else {
		queue->tail->next->fixCount = 1;
		queue->tail->next->numWriteIO = 1;

		// if the page does not exist, then call ensureCapacity to add the requested page to the file
		if (F_HANDLE->totalNumPages < pageNum + 1) {
			int totalPages = F_HANDLE->totalNumPages;
			rc = -99;
			rc = ensureCapacity(pageNum + 1, F_HANDLE);
			NUM_WRITE_IOS += pageNum + 1 - totalPages;

			if (rc != RC_OK) {
				// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

				// Close file
				rc = -99;
				rc = closePageFile(F_HANDLE);

				if (rc != RC_OK) {
					return rc;
				}

				// Release lock
				pthread_rwlock_unlock(&rwlock);
				pthread_rwlock_destroy(&rwlock);

				return rc;
			}
		}
		queue->tail->next->numWriteIO = 0;

		// After ensureCapacity, now we can read the requested page from the file
		queue->tail->next->numReadIO++;
		rc = -99;
		rc = readBlock(pageNum, F_HANDLE, queue->tail->next->page->data);
		NUM_READ_IOS++;
		queue->tail->next->numReadIO--;

		if (rc != RC_OK) {
			// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

			// Close file
			rc = -99;
			rc = closePageFile(F_HANDLE);

			if (rc != RC_OK) {
				return rc;
			}

			// Release lock
			pthread_rwlock_unlock(&rwlock);
			pthread_rwlock_destroy(&rwlock);

			return rc;
		}

		// Now the fixCount = 1, the numReadIO = 0, and the numWriteIO = 0
		queue->tail->next->page->pageNum = pageNum;
		queue->tail->next->dirtyFlag = FALSE;
		queue->tail->next->clockFlag = FALSE;

		queue->tail = queue->tail->next;

		// Set the current pointer to the requested page, that is the tail of the PageList
		queue->current = queue->tail;
	}

	// After appending the requested page, Increment the size of the PageList
	queue->size++;

	// Load the requested page into BM_PageHandle
	page->data = queue->current->page->data;
	page->pageNum = queue->current->page->pageNum;

	// Close file
	rc = -99;
	rc = closePageFile(F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// Release lock
	pthread_rwlock_unlock(&rwlock);
	pthread_rwlock_destroy(&rwlock);

	return RC_OK;
} // appendPage
void testReadWrite(void) {
	SM_FileHandle fh;
	SM_PageHandle ph;

	int i;

	ph = (SM_PageHandle) malloc(PAGE_SIZE);

	testName = "test read and write methods";

	TEST_CHECK(createPageFile (TESTPF));

	TEST_CHECK(openPageFile (TESTPF, &fh));
	ASSERT_TRUE(strcmp(fh.fileName, TESTPF) == 0, "filename correct");
	ASSERT_TRUE((fh.totalNumPages == 1), "expect 1 page in new file");
	ASSERT_TRUE((fh.curPagePos == 0), "freshly opened file's page position should be 0");

	//Writes A, B, C, D, E, F, G, H from 0th page to 7th page
	for(i = 0; i < 8; i ++) {
		memset(ph, 'A' + i, PAGE_SIZE);
		TEST_CHECK(writeBlock (i, &fh, ph));
		printf("writing %d th block\n", fh.curPagePos);
	}

	// read first page into handle  i.e. A
	TEST_CHECK(readFirstBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 'A'), "expected A");
	printf("first block contains A\n");

	// read last page into handle   i.e. H
	TEST_CHECK(readLastBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 'H'), "expected H");
	printf("last block contains H\n");

	// read first page into handle  i.e. A
	readFirstBlock (&fh, ph);

	// read next page into handle   i.e. B
	TEST_CHECK(readNextBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 'B'), "expected B");
	printf("block contains B\n");

	readNextBlock (&fh, ph);        //C
	readNextBlock (&fh, ph);        //D

	// read previous page into handle	i.e. C
	TEST_CHECK(readPreviousBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 'C'), "expected C");
	printf("block contains C\n");

	readNextBlock (&fh, ph);        //D
	readNextBlock (&fh, ph);        //E

	// read current page into handle       i.e. E
	TEST_CHECK(readCurrentBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++)
		ASSERT_TRUE((ph[i] == 'E'), "expected E");
	printf("block contains E\n");

	readPreviousBlock (&fh, ph);        //D

	//Replace D with Z
	memset(ph, 'Z', PAGE_SIZE);
	TEST_CHECK(writeCurrentBlock (&fh, ph));
	printf("writing D with Z\n");

	// read current page into handle        i.e. Z
	TEST_CHECK(readCurrentBlock (&fh, ph));
	for (i=0; i < PAGE_SIZE; i++){
		ASSERT_TRUE((ph[i] == 'Z'), "expected Z");
	}
	printf("block contains Z\n");

	TEST_CHECK(closePageFile (&fh));
	TEST_CHECK(destroyPageFile (TESTPF));

	free(ph);


	TEST_DONE();
}
/**************************************************************************************
 * Function Name: replacePage
 *
 * Description:
 *		Replace the current page with the requested page read from the disk
 *
 * Parameters:
 *		BM_BufferPool * const bm: Buffer Pool Handler
 *		BM_PageHandle * const page: Buffer Page Handler
 *		PageNumber pageNum: the page number of the requested page
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Xin Su <*****@*****.**>
 *
 * History:
 *		Date        Name                                Content
 *		----------  ----------------------------------  ------------------------
 *		2015-03-15  Xin Su <*****@*****.**>         Initialization
 *		2015-03-26	Xin Su <*****@*****.**>			Add thread read-write lock
 **************************************************************************************/
RC replacePage(BM_BufferPool * const bm, BM_PageHandle * const page,
		PageNumber pageNum) {
	PageList *queue = (PageList *) bm->mgmtData;
	RC rc; // init return code

	// Require lock
	pthread_rwlock_init(&rwlock, NULL);
	pthread_rwlock_wrlock(&rwlock);

	// Open file
	rc = -99;
	rc = openPageFile(bm->pageFile, F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// If the removable page is dirty, then write it back to the disk before remove it.
	// Now the fixCount = 0, and the numReadIO = 0 and the numWriteIO = 0
	queue->current->fixCount = 1;
	queue->current->numWriteIO = 1;

	// if the removable page is dirty, then write it back to the file
	if (queue->current->dirtyFlag == TRUE) {
		rc = -99;
		rc = writeBlock(queue->current->page->pageNum, F_HANDLE,
				queue->current->page->data);
		NUM_WRITE_IOS++;

		if (rc != RC_OK) {
			// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

			// Close file
			rc = -99;
			rc = closePageFile(F_HANDLE);

			if (rc != RC_OK) {
				return rc;
			}

			// Release unlock
			pthread_rwlock_unlock(&rwlock);
			pthread_rwlock_destroy(&rwlock);

			return rc;
		}

		// After writeBlock, set the PageFrame back to clean
		queue->current->dirtyFlag = FALSE;
	}

	// if the page does not exist, then call ensureCapacity to add the requested page to the file
	if (F_HANDLE->totalNumPages < pageNum + 1) {
		int totalPages = F_HANDLE->totalNumPages;
		rc = -99;
		rc = ensureCapacity(pageNum + 1, F_HANDLE);
		NUM_WRITE_IOS += pageNum + 1 - totalPages;

		if (rc != RC_OK) {
			// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

			// Close file
			rc = -99;
			rc = closePageFile(F_HANDLE);

			if (rc != RC_OK) {
				return rc;
			}

			// Release unlock
			pthread_rwlock_unlock(&rwlock);
			pthread_rwlock_destroy(&rwlock);

			return rc;
		}
	}
	queue->current->numWriteIO = 0;

	// After ensureCapacity, now we can read the requested page from the file
	queue->current->numReadIO++;
	rc = -99;
	rc = readBlock(pageNum, F_HANDLE, queue->current->page->data);
	NUM_READ_IOS++;
	queue->current->numReadIO--;

	if (rc != RC_OK) {
		// Do not change fixCount and NumWriteIO back, for this indicates write IO error and need more info to proceed

		// Close file
		rc = -99;
		rc = closePageFile(F_HANDLE);

		if (rc != RC_OK) {
			return rc;
		}

		// Release lock
		pthread_rwlock_unlock(&rwlock);
		pthread_rwlock_destroy(&rwlock);

		return rc;
	}

	// Load the requested page to the current PageFrame in the BM_BufferPool
	// Now the fixCount = 1, the numReadIO = 0, and the numWriteIO = 0
	queue->current->page->pageNum = pageNum;
	queue->current->clockFlag = FALSE;

	// Load the requested into BM_PageHandle
	page->data = queue->current->page->data;
	page->pageNum = queue->current->page->pageNum;

	// Close file
	rc = -99;
	rc = closePageFile(F_HANDLE);

	if (rc != RC_OK) {
		return rc;
	}

	// Release lock
	pthread_rwlock_unlock(&rwlock);
	pthread_rwlock_destroy(&rwlock);

	return RC_OK;
} // replacePage
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();
}