void 
checkDummyPages(BM_BufferPool *bm, int num)
{
  int i;
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  char *expected = malloc(sizeof(char) * 512);

  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));

  for (i = 0; i < num; i++)
    {
      CHECK(pinPage(bm, h, i));

      sprintf(expected, "%s-%i", "Page", h->pageNum);

      ASSERT_EQUALS_STRING(expected, h->data, "reading back dummy page content");
	 
      CHECK(unpinPage(bm,h));
    }

  CHECK(shutdownBufferPool(bm));

  free(expected);
  free(h);
}
void 
createDummyPages(BM_BufferPool *bm, int num)
{
  int i;
  BM_PageHandle *h = MAKE_PAGE_HANDLE();

  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));

  for (i = 0; i < num; i++)
    {
      CHECK(pinPage(bm, h, i));
	
	  sprintf(h->data, "%s-%i", "Page", h->pageNum);

	  CHECK(markDirty(bm, h));
	
	  CHECK(unpinPage(bm,h));

    }

  CHECK(shutdownBufferPool(bm));

  free(h);

}
void
testReadPage ()
{
  BM_BufferPool *bm = MAKE_POOL();
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  testName = "Reading a page";

  CHECK(createPageFile("testbuffer.bin"));
  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
  
  CHECK(pinPage(bm, h, 0));
  CHECK(pinPage(bm, h, 0));

  CHECK(markDirty(bm, h));

  CHECK(unpinPage(bm,h));
  CHECK(unpinPage(bm,h));

  CHECK(forcePage(bm, h));

  CHECK(shutdownBufferPool(bm));
  CHECK(destroyPageFile("testbuffer.bin"));

  free(bm);
  free(h);

  TEST_DONE();
}
/*
 * This function is used to update a Record,
 * updating on a deleted page is not possible
 */
RC updateRecord (RM_TableData *rel, Record *record)
{
	//Find the data to be updated
	if(record->id.page > 0 && record->id.page <=  totalPages)
	{
		BM_PageHandle *page = MAKE_PAGE_HANDLE();

		int pageNum, slotNum;

		// Setting record id and slot number
		pageNum = record->id.page;
		slotNum = record->id.slot;

		//Compare if the record is a deleted Record,
		//return update not possible for deleted records (EC 401)

		if(strncmp(record->data, "DELETED_RECORD", 14) == 0)
			return RC_RM_UPDATE_NOT_POSSIBLE_ON_DELETED_RECORD;

		//Take the serailized updated record data
		char *record_str = serializeRecord(record, rel->schema);

		//pin page
		pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, record->id.page);

		//set the new fields, or the entire modified page
		memset(page->data, '\0', strlen(page->data));
		sprintf(page->data, "%s", record_str);

		//free the temp data
		free(record_str);

		//mark the page as dirty
		markDirty(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//unpin the page, after use
		unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//force write onto the page, as it is modified page now
		forcePage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//printf("record data in update: %s\n", page->data);

		free(page);		//free page, avoid leaks
		return RC_OK;
	}
	else
	{
		return RC_RM_NO_MORE_TUPLES;	//return the data to be modfied not found
	}

	return RC_OK;
}
void
testClock(void)
{
    // expected results
    const char *poolContents[]= {
        
    "[3x0],[-1 0],[-1 0],[-1 0]",
    "[3x0],[2 0],[-1 0],[-1 0]",
    "[3x0],[2 0],[0 0],[-1 0]",
    "[3x0],[2 0],[0 0],[8 0]",
    "[4 0],[2 0],[0 0],[8 0]",
    "[4 0],[2 0],[0 0],[8 0]",
    "[4 0],[2 0],[5 0],[8 0]",
    "[4 0],[2 0],[5 0],[0 0]",
    "[9 0],[2 0],[5 0],[0 0]",
    "[9 0],[8 0],[5 0],[0 0]",
    "[9 0],[8 0],[3x0],[0 0]",
    "[9 0],[8 0],[3x0],[2 0]"
    };
    const int orderRequests[]= {3,2,0,8,4,2,5,0,9,8,3,2};
        
    int i;
    int snapshot = 0;
    BM_BufferPool *bm = MAKE_POOL();
    BM_PageHandle *h = MAKE_PAGE_HANDLE();
    testName = "Testing CLOCK page replacement";

    CHECK(createPageFile("testbuffer.bin"));
    createDummyPages(bm, 100);
    CHECK(initBufferPool(bm, "testbuffer.bin", 4, RS_CLOCK, NULL));
    
    for (i=0;i<11;i++)
    {
        pinPage(bm,h,orderRequests[i]);
	if(orderRequests[i] == 3)
		markDirty(bm,h);
        unpinPage(bm,h);
        ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content using pages");
    }
    
    forceFlushPool(bm);
    // check number of write IOs
    ASSERT_EQUALS_INT(2, getNumWriteIO(bm), "check number of write I/Os");
    ASSERT_EQUALS_INT(10, getNumReadIO(bm), "check number of read I/Os");
    
    CHECK(shutdownBufferPool(bm));
    CHECK(destroyPageFile("testbuffer.bin"));
    
    free(bm);
    free(h);
    TEST_DONE();
}
/*
 * This function is used to Delete the Record from the Table
 * BONUS IMPLEMENTATION - TOMBSTONE IS USED IN DELETION PROCESS
 */
RC deleteRecord (RM_TableData *rel, RID id)
{
	/*A TOMBSTONE FLAG is set to mark it as a Deleted Record, but actual delete is not done
	 * The Record is Prefixed with DELETED_RECORD string
	 * ex. consider the record to be deleted be
	 * (a:1,b:aaaa,c:45), the serializer store it as [1-0](a:1,b:aaaa,c:45)
	 * deleted will be marked as DELETED RECORD[1-0](a:1,b:aaaa,c:45)
	 */

	char deleteTombStomeFlag[14] = "DELETED_RECORD";	//Tombstone flag

	char *temp = (char*)malloc(sizeof(char*));			//temp memory allocation to preappend the flag

	if(id.page > 0 && id.page <=  totalPages)
	{
		BM_PageHandle *page = MAKE_PAGE_HANDLE();

		//Pin page, to mark it in USE
		pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, id.page);

		//attach the flag to deletedRecord
		strcpy(temp, deleteTombStomeFlag);
		strcat(temp, page->data);

		//set pageNum
		page->pageNum = id.page;

		//copy the new data onto the Page i.e. modify the page->data
		memset(page->data, '\0', strlen(page->data));
		sprintf(page->data, "%s", temp);

		//marking the page dirty, as new data has been written, i.e. tombstone data
		markDirty(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//unpin page, after use
		unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//write the new data onto the page, in the pageFile
		forcePage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		page = NULL;
		free(page);		//free page, avoid leaks
		return RC_OK;
	}
	else
	{
		return RC_RM_NO_MORE_TUPLES;
	}

	return RC_OK;
}
/*
 * This function is used to Open a Created Table,
 * for any operation to be performed, the table has to be opened first
 * Also store the Schema related info by deserializing the schema,
 * in the Table Data
 */
RC openTable (RM_TableData *rel, char *name)
{
	//Record Management to store record attributes
	RM_RecordMgmt *rm_mgmt = (RM_RecordMgmt*)malloc(sizeof(RM_RecordMgmt));

	FILE *fptr;	//FILE pointer
	fptr = fopen(name, "r+");	//Open the PageFile (Table)

	//Get the total Number of Pages in the page File
	char* readHeader;
	readHeader = (char*)calloc(PAGE_SIZE,sizeof(char));

	fgets(readHeader,PAGE_SIZE,fptr);

	char* totalPage;
	totalPage = readHeader;
	totalPages = atoi(totalPage);	//convert to integer

	//Make a Buffer Pool
	rm_mgmt->bm = MAKE_POOL();

	//Make a Page Handle
	BM_PageHandle *page = MAKE_PAGE_HANDLE();

	//Initialize the BufferPool
	initBufferPool(rm_mgmt->bm,name,6,RS_FIFO,NULL);

	//Pin the Page = 0, which has the Schema Information
	pinPage(rm_mgmt->bm,page,0);

	//FreePages are stored in an array
	rm_mgmt->freePages = (int*)malloc(sizeof(int));
	rm_mgmt->freePages[0] = totalPages;

	//initialize the table data attributes

	//Deserialzing the Schema gives us the Relation information (i.e. Schema info)
	rel->schema = deserializeSchema(page->data);

	//store the name of the schema
	rel->name = name;

	//store the record management details
	rel->mgmtData = rm_mgmt;

	//Free the temp. memory allocations
	free(readHeader);
	free(page);

	return RC_OK;
}
Exemple #8
0
void 
readAndCheckDummyPage(BM_BufferPool *bm, int pageNum)
{
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  char *expected = malloc(sizeof(char) * 512);

  CHECK(pinPage(bm, h, pageNum));

  sprintf(expected, "%s-%i", "Page", h->pageNum);
  ASSERT_EQUALS_STRING(expected, h->data, "check read page dummy page content");
  CHECK(unpinPage(bm,h));

  free(expected);
  free(h);
}
/*
 * This function is used to get the Record from the Table
 * using the RID details
 */
RC getRecord (RM_TableData *rel, RID id, Record *record)
{

	//find the record in the record table
	if(id.page > 0 && id.page <=  totalPages)
	{
		//make a page handle
		BM_PageHandle *page = MAKE_PAGE_HANDLE();

		//pin page, and mark it for use
		pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, id.page);

		//temp, to store the record data
		char *record_data = (char*)malloc(sizeof(char) * strlen(page->data));

		//copy the data
		strcpy(record_data,page->data);

		//printf("Page data is: %s",record_data);

		//store the record data and id
		record->id = id;

		//deSerialze the data
		Record* deSerializedRecord = deserializeRecord(record_data,rel->schema);

		//unpin the page, after fetching the record
		unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

		//return the new data
		record->data = deSerializedRecord->data;

		//printf("Record Data in getRecord: %s\n",record->data);

		//free temp. allocations to avoid memory leaks
		free(deSerializedRecord);
		free(page);

		return RC_OK;
	}
	else		//if record not found return RC_RM_NO_MORE_TUPLES
	{
		return RC_RM_NO_MORE_TUPLES;
	}

	return RC_OK;
}
/**************************************************************************************
 * Function Name: initPageList
 *
 * Description:
 *		Initialize the PageList to store pages in the Buffer Pool
 *
 * Parameters:
 *		BM_BufferPool * const bm: Buffer Pool Handler
 *
 * Return:
 *		void
 *
 * Author:
 *		Xin Su <*****@*****.**>
 *
 * History:
 *		Date        Name                                Content
 *		----------  ----------------------------------  ------------------------
 *		2015-03-15  Xin Su <*****@*****.**>         Initialization
 **************************************************************************************/
void initPageList(BM_BufferPool * const bm) {
	PageList *queue = (PageList *) bm->mgmtData;
	PageFrame *pf[bm->numPages];

	int i;
	for (i = 0; i < bm->numPages; i++) {
		// init PageFrame -> position 3
		// Free them in shutdownBufferPool -> position 2
		pf[i] = (PageFrame *) malloc(sizeof(PageFrame));

		// Initialize the content in the PageFrame
		pf[i]->page = MAKE_PAGE_HANDLE();

		// init page->data -> position 4
		// Free them in shutdownBufferPool -> position 1
		pf[i]->page->data = (char *) malloc(PAGE_SIZE * sizeof(char));
		pf[i]->page->pageNum = NO_PAGE;
		pf[i]->frameNum = i;
		pf[i]->numReadIO = 0;
		pf[i]->numWriteIO = 0;
		pf[i]->fixCount = 0;
		pf[i]->dirtyFlag = FALSE;
		pf[i]->clockFlag = FALSE;

		// Add this new PageFrame to the tail of pf

		// if pf has only one node (i = 0), then add this new PageFrame as the head
		// else, add this new PageFrame to the tail
		if (i == 0) {
			pf[i]->previous = NULL;
			pf[i]->next = NULL;
		} else {
			pf[i - 1]->next = pf[i];
			pf[i]->previous = pf[i - 1];
			pf[i]->next = NULL;
		}
	}

	// Reset all pointers and queue's size to the initial state
	queue->head = pf[0];
	queue->tail = queue->head;
	queue->current = queue->head;
	queue->clock = queue->head;
	queue->size = 0;

	return;
} // initPageList
// test error cases
void
testError (void)
{
    BM_BufferPool *bm = MAKE_POOL();
    BM_PageHandle *h = MAKE_PAGE_HANDLE();
    testName = "ERROR TEST";
    
    CHECK(createPageFile("testbuffer.bin"));
    
    // pinpage until buffer pool is full and then request additional page.
    CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
    CHECK(pinPage(bm, h, 0));
    CHECK(pinPage(bm, h, 1));
    CHECK(pinPage(bm, h, 2));
    
    ASSERT_ERROR(pinPage(bm, h, 3), "try to pin page when pool is full of pinned pages with fix-count > 0");
    
    CHECK(shutdownBufferPool(bm));
    
    // try to pin page with negative page number.
    CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
    ASSERT_ERROR(pinPage(bm, h, -10), "try to pin page with negative page number");
    CHECK(shutdownBufferPool(bm));
    
    
    // try to use uninitialized buffer pool
    ASSERT_ERROR(initBufferPool(bm, "unavailable.bin", 3, RS_FIFO, NULL), "try to init buffer pool for non existing page file");
    ASSERT_ERROR(shutdownBufferPool(bm), "shutdown buffer pool that is not open");
    ASSERT_ERROR(forceFlushPool(bm), "flush buffer pool that is not open");
    ASSERT_ERROR(pinPage(bm, h, 1), "pin page in buffer pool that is not open");
    
    
    // try to unpin, mark, or force page that is not in pool
    CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
    ASSERT_ERROR(unpinPage(bm, h), "Try to unpin a page which is not available in framelist.");
    ASSERT_ERROR(forcePage(bm, h), "Try to forceflush a page which is not available in framelist.");
    ASSERT_ERROR(markDirty(bm, h), "Try to markdirty a page which is not available in framelist.");  
    CHECK(shutdownBufferPool(bm));
    
    // done remove page file
    CHECK(destroyPageFile("testbuffer.bin"));
    
    free(bm);
    free(h);
    TEST_DONE();  
}
// test error cases
void
testError (void)
{
  int i;
  BM_BufferPool *bm = MAKE_POOL();
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  testName = "Testing LRU page replacement";

  CHECK(createPageFile("testbuffer.bin"));

  // pin until buffer pool is full and request additional page
  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
  CHECK(pinPage(bm, h, 0));
  CHECK(pinPage(bm, h, 1));
  CHECK(pinPage(bm, h, 2));
  ASSERT_ERROR(pinPage(bm, h, 3), "try to pin page when pool is full of pinned pages");
  CHECK(shutdownBufferPool(bm));

  // try to ready page with negative page number
  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
  ASSERT_ERROR(pinPage(bm, h, -1), "try to pin page with negative page number");
  CHECK(shutdownBufferPool(bm));

  // try to use uninitialized buffer pool  
  ASSERT_ERROR(shutdownBufferPool(bm), "shutdown buffer pool that is not open");
  ASSERT_ERROR(forceFlushPool(bm), "flush buffer pool that is not open");
  ASSERT_ERROR(pinPage(bm, h, 1), "pin page in buffer pool that is not open");
  ASSERT_ERROR(initBufferPool(bm, "xxx.bin", 3, RS_FIFO, NULL), "try to init buffer pool for non existing page file");

  // try to unpin, mark, or force page that is not in pool
  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));
  ASSERT_ERROR(unpinPage(bm, h), "unpin page not in buffer pool");  
  ASSERT_ERROR(forcePage(bm, h), "unpin page not in buffer pool");  
  ASSERT_ERROR(markDirty(bm, h), "mark page dirty that is not in buffer pool");  
  CHECK(shutdownBufferPool(bm));

  // done remove page file
  CHECK(destroyPageFile("testbuffer.bin"));

  free(bm);
  free(h);
  TEST_DONE();  
}
void
testsimpleFIFO ()
{
printf("FIFO Execution in new thread : \n " );
// expected results
  const char *poolContents[] = {
    "[0 0],[-1 0],[-1 0]" ,
    "[0 0],[1 0],[-1 0]",
    "[0 0],[1 0],[2 0]",
    "[3 0],[1 0],[2 0]"
  };
  const int requests[] = {0,1,2,3,4,4,5,6,0};
  const int numLinRequests = 4;

  int i;
  BM_BufferPool *bm = MAKE_POOL();
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  testName = "Testing FIFO page replacement";

  CHECK(createPageFile("testbuffer.bin"));

  createDummyPages(bm, 100);

  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));

  // reading some pages linearly with direct unpin and no modifications
  for(i = 0; i < numLinRequests; i++)
    {
      pinPage(bm, h, requests[i]);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[i], bm, "check pool content");
    }

  CHECK(shutdownBufferPool(bm));
  CHECK(destroyPageFile("testbuffer.bin"));

  free(bm);
  free(h);
  TEST_DONE();
}
// test the CLOCK page replacement strategy
void
testClock (void)
{
    // expected results
    const char *poolContents[] = {
        // read first five pages and directly unpin them
        "[0 0],[-1 0],[-1 0]" ,
        "[0 0],[1 0],[-1 0]" ,
        "[2 0],[1 0],[-1 0]" ,
        "[2 0],[1 0],[3 0]" ,
        
        // pin the page 2 again
        "[2 0],[1 0],[3 0]" ,
        
        // read other pages use pin_CLOCK
        "[2 0],[4 0],[3 0]" ,
        "[5 0],[4 0],[3 0]" ,
        "[6 0],[4 0],[3 0]",
        "[6 0],[7 0],[3 0]"
    };
    const int orderRequests[] = {2};
    const int numrfChange = 1;
    
    int i;
    int snapshot = 0;
    BM_BufferPool *bm = MAKE_POOL();
    BM_PageHandle *h = MAKE_PAGE_HANDLE();
    testName = "Testing CLOCK page replacement";
    
    CHECK(createPageFile("testbuffer.bin"));
    createDummyPages(bm, 100);
    CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_CLOCK, NULL));
    
    // reading first five pages linearly with direct unpin and no modifications
    for(i = 0; i <4; i++)
    {
        pinPage(bm, h, i);
        unpinPage(bm, h);
        ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content reading in pages");
    }
    // read pages to rf of the frames
    for(i = 0; i < numrfChange; i++)
    {
        pinPage(bm, h, orderRequests[i]);
        unpinPage(bm, h);
        ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content using pages");
    }
    
    // replace pages and check that it happens in LRU_K order
    for(i = 0; i < 4; i++)
    {
        pinPage(bm, h, 4 + i);
        unpinPage(bm, h);
        ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content using pages");
        
    }
    
    // check number of write IOs
    ASSERT_EQUALS_INT(0, getNumWriteIO(bm), "check number of write I/Os");
    ASSERT_EQUALS_INT(8, getNumReadIO(bm), "check number of read I/Os");
    
    CHECK(shutdownBufferPool(bm));
    CHECK(destroyPageFile("testbuffer.bin"));
    
    free(bm);
    free(h);
    TEST_DONE();
}
//Clock[START]
void testClock()
{
	// expected results
	  const char *poolContents[] = {
			  "[0 0],[-1 0],[-1 0]",
			  	  "[0 0],[4 0],[-1 0]",
			  	  "[0 0],[4 0],[1 0]",
			  	  "[0 0],[4 0],[1 0]",
			  	  "[2 0],[4 0],[1 0]",
			  	  "[2 0],[4 0],[1 0]",
			  	  "[2 0],[4 0],[3 0]",
			  	  "[2 0],[4 0],[3 0]",
			  	  "[2 0],[4 0],[3 0]",
			  	  "[2 0],[4 0],[3 0]",
			  	  "[2 0],[4 0],[0 0]",
			  	  "[2 0],[4 0],[0 0]",
			  	  "[1 0],[4 0],[0 0]",
			  	  "[1 0],[4 0],[0 0]",
			  	  "[1 0],[4 0],[2 0]",
			  	  "[1 0],[4 0],[2 0]",
			  	  "[3 0],[4 0],[2 0]",
			  	  "[3 0],[4 0],[2 0]",
				  "[3 0],[4 0],[2 0]",
	  };
	  const int requests[] = {0,4,1,4,2,4,3,4,2,4,0,4,1,4,2,4,3,4};


	  int i;
	  BM_BufferPool *bm = MAKE_POOL();
	  BM_PageHandle *h = MAKE_PAGE_HANDLE();
	  testName = "Testing CLOCK page replacement";

	  CHECK(createPageFile("testbuffer.bin"));

	  createDummyPages(bm, 100);

	  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_CLOCK, NULL));

	  // reading some pages linearly with direct unpin and no modifications
	  for(i = 0; i < 18; i++)
	    {
	      pinPage(bm, h, requests[i]);
	      unpinPage(bm, h);
	      ASSERT_EQUALS_POOL(poolContents[i], bm, "check pool content");
	    }


 	  forceFlushPool(bm);
	  ASSERT_EQUALS_POOL(poolContents[i],bm,"pool content after flush");

	  // check number of write IOs
	  //0 writes because no dirty pages were present
	  ASSERT_EQUALS_INT(0, getNumWriteIO(bm), "check number of write I/Os");


	  ASSERT_EQUALS_INT(9, getNumReadIO(bm), "check number of read I/Os");

	  CHECK(shutdownBufferPool(bm));
	  CHECK(destroyPageFile("testbuffer.bin"));

	  free(bm);
	  free(h);
	  TEST_DONE();

}
void
testFIFO ()
{
  // expected results
  const char *poolContents[] = { 
    "[0 0],[-1 0],[-1 0]" , 
    "[0 0],[1 0],[-1 0]", 
    "[0 0],[1 0],[2 0]", 
    "[3 0],[1 0],[2 0]", 
    "[3 0],[4 0],[2 0]",
    "[3 0],[4 1],[2 0]",
    "[3 0],[4 1],[5x0]",
    "[6x0],[4 1],[5x0]",
    "[6x0],[4 1],[0x0]",
    "[6x0],[4 0],[0x0]",
    "[6 0],[4 0],[0 0]"
  };
  const int requests[] = {0,1,2,3,4,4,5,6,0};
  const int numLinRequests = 5;
  const int numChangeRequests = 3;

  int i;
  BM_BufferPool *bm = MAKE_POOL();
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  testName = "Testing FIFO page replacement";

  CHECK(createPageFile("testbuffer.bin"));

  createDummyPages(bm, 100);

  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_FIFO, NULL));

  // reading some pages linearly with direct unpin and no modifications
  for(i = 0; i < numLinRequests; i++)
    {
      pinPage(bm, h, requests[i]);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[i], bm, "check pool content");
    }

  // pin one page and test remainder
  i = numLinRequests;
  pinPage(bm, h, requests[i]);
  ASSERT_EQUALS_POOL(poolContents[i],bm,"pool content after pin page");

  // read pages and mark them as dirty
  for(i = numLinRequests + 1; i < numLinRequests + numChangeRequests + 1; i++)
    {
      pinPage(bm, h, requests[i]);
      markDirty(bm, h);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[i], bm, "check pool content");
    }

  // flush buffer pool to disk
  i = numLinRequests + numChangeRequests + 1;
  h->pageNum = 4;
  unpinPage(bm, h);
  ASSERT_EQUALS_POOL(poolContents[i],bm,"unpin last page");
  
  i++;
  forceFlushPool(bm);
  ASSERT_EQUALS_POOL(poolContents[i],bm,"pool content after flush");

  // check number of write IOs
  ASSERT_EQUALS_INT(3, getNumWriteIO(bm), "check number of write I/Os");
  ASSERT_EQUALS_INT(8, getNumReadIO(bm), "check number of read I/Os");

  CHECK(shutdownBufferPool(bm));
  CHECK(destroyPageFile("testbuffer.bin"));

  free(bm);
  free(h);
  TEST_DONE();
}
Exemple #17
0
/*
 * This function is used to insert a new Record into the table
 * while inserting, the record Manager assigns a RID to the record
 * and update the "record" parameter too
 */
RC insertRecord (RM_TableData *rel, Record *record)
{
	//Create a record variable
	Record *r = (Record *)malloc(sizeof(Record));

	RID rid;
	rid.page = 1;
	rid.slot = 0;

	//Find the next place of insertion of a record
	while(rid.page > 0 && rid.page < totalPages)
	{
		rid.page = rid.page + 1;
		rid.slot = 0;

		/*getRecord(rel, rid, r); //obtaining the record from the table
		//checking for soft delete record in the table space for insertion
		if(strncmp(r->data, "DELETED_RECORD", 14) == 0)
			break;*/
	}


	r = NULL;
	free(r); //free the memory of r which was just a temporary allocation

	//mark the page as free page
	((RM_RecordMgmt *)rel->mgmtData)->freePages[0] = rid.page;

	//create a page handle
	BM_PageHandle *page = MAKE_PAGE_HANDLE();

	//assign the record, its RID and slot number
	record->id.page = ((RM_RecordMgmt *)rel->mgmtData)->freePages[0];
	record->id.slot = 0;

	//Serialize the Record to be inserted
	char * serializedRecord = serializeRecord(record, rel->schema);

	//Pin the record page, to mark that it is in use
	pinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page, ((RM_RecordMgmt *)rel->mgmtData)->freePages[0]);

	//insert the new record data, into the Table i.e. Pages of the PageFile
	memset(page->data, '\0', strlen(page->data));
	sprintf(page->data, "%s", serializedRecord);

	//mark the page as Dirty Page, as now there is a new record entry on that page
	markDirty(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

	//Unpin the page as now it has been used
	unpinPage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

	//Force Page to push entire data onto the page
	forcePage(((RM_RecordMgmt *)rel->mgmtData)->bm, page);

	//printf("record data: %s\n", page->data);

	free(page);		//free page, avoid memory leaks

	((RM_RecordMgmt *)rel->mgmtData)->freePages[0] += 1;

	totalPages++;
	return RC_OK;
}
// test the LRU page replacement strategy
void
testLRU (void)
{
  // expected results
  const char *poolContents[] = { 
    // read first five pages and directly unpin them
    "[0 0],[-1 0],[-1 0],[-1 0],[-1 0]" , 
    "[0 0],[1 0],[-1 0],[-1 0],[-1 0]", 
    "[0 0],[1 0],[2 0],[-1 0],[-1 0]",
    "[0 0],[1 0],[2 0],[3 0],[-1 0]",
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    // use some of the page to create a fixed LRU order without changing pool content
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    "[0 0],[1 0],[2 0],[3 0],[4 0]",
    // check that pages get evicted in LRU order
    "[0 0],[1 0],[2 0],[5 0],[4 0]",
    "[0 0],[1 0],[2 0],[5 0],[6 0]",
    "[7 0],[1 0],[2 0],[5 0],[6 0]",
    "[7 0],[1 0],[8 0],[5 0],[6 0]",
    "[7 0],[9 0],[8 0],[5 0],[6 0]"
  };
  const int orderRequests[] = {3,4,0,2,1};
  const int numLRUOrderChange = 5;

  int i;
  int snapshot = 0;
  BM_BufferPool *bm = MAKE_POOL();
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  testName = "Testing LRU page replacement";

  CHECK(createPageFile("testbuffer.bin"));
  createDummyPages(bm, 100);
  CHECK(initBufferPool(bm, "testbuffer.bin", 5, RS_LRU, NULL));

  // reading first five pages linearly with direct unpin and no modifications
  for(i = 0; i < 5; i++)
  {
      pinPage(bm, h, i);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content reading in pages");
  }

  // read pages to change LRU order
  for(i = 0; i < numLRUOrderChange; i++)
  {
      pinPage(bm, h, orderRequests[i]);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content using pages");
  }

  // replace pages and check that it happens in LRU order
  for(i = 0; i < 5; i++)
  {
      pinPage(bm, h, 5 + i);
      unpinPage(bm, h);
      ASSERT_EQUALS_POOL(poolContents[snapshot++], bm, "check pool content using pages");
  }

  // check number of write IOs
  ASSERT_EQUALS_INT(0, getNumWriteIO(bm), "check number of write I/Os");
  ASSERT_EQUALS_INT(10, getNumReadIO(bm), "check number of read I/Os");

  CHECK(shutdownBufferPool(bm));
  CHECK(destroyPageFile("testbuffer.bin"));

  free(bm);
  free(h);
  TEST_DONE();
}
void testLFU()
{
	// expected results
	  const char *poolContents[] = {
		//Pin and Unpin 3 pages
	    "[0 0],[-1 0],[-1 0]" ,
	    "[0 0],[1 0],[-1 0]",
	    "[0 0],[1 0],[2 0]",

		//Pin the 0th page thrice,1st page twice
		"[0 3],[1 2],[2 0]",

		//Now pin a new page say 4. 4 should replace page 2 as page 2 has been Least Freq Used.
		"[0 3],[1 2],[4 1]",

		//Pin the 4th page thrice
		"[0 3],[1 2],[4 4]",

		//Now pin a new page 5. 5 should replace page 1 as page 1 has been Least Freq Used.
		"[0 3],[5 1],[4 4]",

		//Unpin page 0 thrice, page 5 once and page 4 four times.
		"[0 0],[5 0],[4 0]",
	  };
	  const int requests[] = {0,1,2,3,4,5,6};
	  const int numLinRequests = 3;

	  int i;
	  BM_BufferPool *bm = MAKE_POOL();
	  BM_PageHandle *h = MAKE_PAGE_HANDLE();
	  testName = "Testing LFU page replacement";

	  CHECK(createPageFile("testbuffer.bin"));

	  createDummyPages(bm, 100);

	  CHECK(initBufferPool(bm, "testbuffer.bin", 3, RS_LFU, NULL));

	  // reading some pages linearly with direct unpin and no modifications
	  for(i = 0; i < numLinRequests; i++)
	    {
	      pinPage(bm, h, requests[i]);
	      unpinPage(bm, h);
	      ASSERT_EQUALS_POOL(poolContents[i], bm, "check pool content");
	    }


	  pinPage(bm, h, 0);
	  pinPage(bm, h, 0);
	  pinPage(bm, h, 0);
	  pinPage(bm, h, 1);
	  pinPage(bm, h, 1);
	  ASSERT_EQUALS_POOL(poolContents[i++],bm,"pool content after pin page");

	  pinPage(bm, h, 4);
	  ASSERT_EQUALS_POOL(poolContents[i++],bm,"pool content after pin page");

	  pinPage(bm,h,4);
	  pinPage(bm,h,4);
	  pinPage(bm,h,4);
	  ASSERT_EQUALS_POOL(poolContents[i++],bm,"pool content after pin page");

	  pinPage(bm,h,5);
	  ASSERT_EQUALS_POOL(poolContents[i++],bm,"pool content after pin page");


	  h->data = "Page-0";
	  h->pageNum = 0;
	  unpinPage(bm,h);
	  unpinPage(bm,h);
	  unpinPage(bm,h);

	  h->data = "Page-5";
	  h->pageNum = 5;
	  unpinPage(bm,h);

	  h->data = "Page-4";
	  h->pageNum = 4;
	  unpinPage(bm,h);
	  unpinPage(bm,h);
	  unpinPage(bm,h);
	  unpinPage(bm,h);
 	  forceFlushPool(bm);
	  ASSERT_EQUALS_POOL(poolContents[i],bm,"pool content after flush");

	  // check number of write IOs
	  //0 writes because no dirty pages were present
	  ASSERT_EQUALS_INT(0, getNumWriteIO(bm), "check number of write I/Os");


	  ASSERT_EQUALS_INT(5, getNumReadIO(bm), "check number of read I/Os");

	  CHECK(shutdownBufferPool(bm));
	  CHECK(destroyPageFile("testbuffer.bin"));

	  free(bm);
	  free(h);
	  TEST_DONE();

}