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();
}
Beispiel #2
0
// create pages 100 with content "Page X" and perform 10000 random reads of these pages and check that the correct pages are read
void
testCreatingAndRandomReadingDummyPages (void)
{
  int i;
  BM_BufferPool *bm = MAKE_POOL();
  testName = "Creating and Dummy Pages and reading them in random order";

  CHECK(createPageFile("testbuffer.bin"));
  createDummyPages(bm, 100);

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

  srand(time(0));
  for(i = 0; i < 10000; i++)
    {
      int page = rand() % NUM_DUMMY_PAGES;
      readAndCheckDummyPage(bm, page);
    }

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

  free(bm);
  TEST_DONE();
}
Beispiel #3
0
//Append Empty Block
RC appendEmptyBlock(SM_FileHandle *fHandle)
{
FILE *myfile;
myfile = fopen(fHandle->fileName,"r");
if(myfile!=NULL)
{
createPageFile(fHandle->fileName);
}
}
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;
}
/* Initialize the BTreeHandle 
   Initialize the variables for BTree datastructure
*/
RC createBtree (char *idxId, DataType keyType, int n)
{
	BTreeHandle *data=(BTreeHandle *)malloc(sizeof(BTreeHandle)*size_n);
	/* 
	bptree root =(Bptree*) malloc(sizeof(BPtree));
	root=NULL;
	*/
	//printf("\n File Name %s",idxId);
	data->keyType=keyType;
	createPageFile(idxId);
	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();
}
Beispiel #7
0
/*
 * This function is used to Create a Table,
 * and also used to store the Information about the schema
 */
RC createTable (char *name, Schema *schema)
{
	//File handle from Storage Manager
	SM_FileHandle fh;

	char *serializedData;	//data is stored in a serialized format in this variable

	/*
	 * using access to check whether a Table can be accessed,
	 * this access is specified with a existence test F_OK,
	 * Checks whether Table with "name" alread exists
	 * If yes, it returns RC_TABLE_ALREADY_EXISTS
	 */
	if(access(name,F_OK)!= -1)
	{
		return RC_TABLE_ALREADY_EXISTS;
	}

	//Creating a PageFile with name as given in createTable (name, schema)
	if(createPageFile(name)!=RC_OK)
	{
		return RC_FILE_NOT_FOUND;
	}

	//Open the pageFile
	if(openPageFile(name,&fh)!=RC_OK)
	{
		return RC_FILE_NOT_FOUND;
	}

	//Store the table Information & initialize its attributes
	RM_TableInfo *tableInfo = (RM_TableInfo *)malloc(sizeof(RM_TableInfo));

	tableInfo->schemaSize = 0;

	/*The schema is now serialized using serializeSchema() function
	 * The first page of the file is used to store the entire Formatted (Serialized Schema)
	 */
	serializedData = serializeSchema(schema);

	//Write the serialized data ontot Page = 0
	if(writeBlock(0,&fh,serializedData)!=RC_OK)
	{
		return RC_WRITE_FAILED;
	}

	return RC_OK;	//all steps executed correctly, and Table is created, return RC_OK
}
//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;
    
    

    
}
// 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();  
}
// create n pages with content "Page X" and read them back to check whether the content is right
void testCreatingAndReadingDummyPages(void) {
	BM_BufferPool *bm = MAKE_POOL();
	testName = "Creating and Reading Back Dummy Pages";

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

	createDummyPages(bm, 22);
	checkDummyPages(bm, 20);

	createDummyPages(bm, 10000);
	checkDummyPages(bm, 10000);

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

	free(bm);
	TEST_DONE()
	;
}
Beispiel #11
0
// 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();  
}
/* Try to create, open, and close a page file */
void
testSinglePageContent(void)
{
  SM_FileHandle fh;
  SM_PageHandle ph;
  int i;

  testName = "test single page content";

  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");
  
  // read first page into handle
  TEST_CHECK(readFirstBlock (&fh, ph));
  // the page should be empty (zero bytes)
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == 0), "expected zero byte in first page of freshly initialized page");
  printf("first block was empty\n");
    
  // change ph to be a string and write that one to disk
  for (i=0; i < PAGE_SIZE; i++)
    ph[i] = (i % 10) + '0';
  TEST_CHECK(writeBlock (0, &fh, ph));
  printf("writing first block\n");

  // read back the page containing the string and check that it is correct
  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.");
  printf("reading first block\n");

  // destroy new page file
  TEST_CHECK(destroyPageFile (TESTPF));  
  
  free(ph);
  ph=NULL;
  
  TEST_DONE();
}
Beispiel #13
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();
}
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();
}
Beispiel #15
0
/* Try to create, open, and close a page file */
void testWrite(void)
{
  SM_FileHandle fh;
  SM_PageHandle ph;
  int i;

  testName = "test single page content";

  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");
  
  
   TEST_CHECK(ensureCapacity(5,&fh)); 
  for (i=0; i < PAGE_SIZE; i++)
    ph[i] = (i % 10) + '0';
    
  
  ASSERT_TRUE((fh.totalNumPages == 5), "expect 5 pages in new file");

  TEST_CHECK(writeBlock (5, &fh, ph));
   
  // read back the page containing the string and check that it is correct
  TEST_CHECK(readBlock (5,&fh, ph));
  
  printf("\nreading :");
  
  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.");

  // destroy new page file
  TEST_CHECK(destroyPageFile (TESTPF));  
  
  TEST_DONE();
}
Beispiel #16
0
RC createBtree (char *idxId, DataType keyType, int n){
    SM_FileHandle *fHandle = (SM_FileHandle *)calloc(1, sizeof(SM_FileHandle));
    char *metadata = (char *)calloc(1, PAGE_SIZE);

    int rootPage;
    int nodeNum;
    int entryNum;

    createPageFile(idxId);
    openPageFile(idxId, fHandle);
    ensureCapacity(1, fHandle);

    rootPage = -1;
    nodeNum = 0;
    entryNum = 0;

    /*
     * root page number
     * the number of node
     * the number of entry
     * n
     * key type
     */
    memcpy(metadata, &rootPage, sizeof(int));
    memcpy(metadata + sizeof(int), &nodeNum, sizeof(int));
    memcpy(metadata + 2*sizeof(int), &entryNum, sizeof(int));
    memcpy(metadata + 3*sizeof(int), &n, sizeof(int));
    memcpy(metadata + 4*sizeof(int), &keyType, sizeof(DataType));

    writeBlock(0, fHandle, metadata);

    free(fHandle);
    free(metadata);

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

}
Beispiel #19
0
/* Try to create, open, and close a multi-page file */
void
testMultiPageContent(void)
{
  SM_FileHandle fh;
  SM_PageHandle ph;
  int i;

  testName = "test multi-page content";

  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");
  
  //ensure the capacity of the file with 4 pages
  TEST_CHECK(ensureCapacity(4,&fh));
  // read the current page into handle
  TEST_CHECK(readCurrentBlock(&fh, ph));
  // the page should be empty (zero bytes)
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == 0), "expected zero byte in current page of freshly initialized page");
  printf("current block was empty with the page number =%d\n", getBlockPos(&fh));
    
  // read the next page into handle
  TEST_CHECK(readNextBlock(&fh, ph));
  // the page should be empty (zero bytes)
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == 0), "expected zero byte in next page of freshly initialized page");
  printf("the next block was empty\n");
  printf("the updated page number is =%d\n",getBlockPos(&fh));
	
  // change ph to be a string and write that one to disk
  for (i=0; i < PAGE_SIZE; i++)
    ph[i] = (i % 10) + '0';
  TEST_CHECK(writeCurrentBlock(&fh, ph));
  printf("writing current block with the page number =%d\n", getBlockPos(&fh));

  // read back the page containing the string and check that it is correct
  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.");
  printf("reading back current block into memory with page number =%d\n", getBlockPos(&fh));
 
  // read the last page into handle
  TEST_CHECK(readLastBlock(&fh, ph));
  // the page should be empty (zero bytes)
  for (i=0; i < PAGE_SIZE; i++)
    ASSERT_TRUE((ph[i] == 0), "expected zero byte in last page of freshly initialized page");
  printf("last block was empty with the page number =%d\n", getBlockPos(&fh));


  // change ph to be a string and write that one to disk
  for (i=0; i < PAGE_SIZE; i++)
    ph[i] = (i % 10) + '0';
  TEST_CHECK(writeCurrentBlock(&fh, ph));
  printf("writing current block with the page number =%d\n", getBlockPos(&fh));

  // read back the page containing the string and check that it is correct
  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.");
  printf("reading back current block into memory with page number =%d\n", getBlockPos(&fh));



  // destroy new page file
  TEST_CHECK(destroyPageFile (TESTPF));  
  
  TEST_DONE();
}
/**************************************************************************************
 * Function Name: createBtree
 *
 * Description:
 *		Create a B+ Tree with given name, DataType and number of elements in a node
 *
 * Parameters:
 * 		char *idxId: name of the B+ Tree
 * 		DataType keyType: data type of the tree
 * 		int n: number of elements in one node
 *
 * Return:
 *		RC: return code
 *
 * Author:
 *		Xiaolang Wang <*****@*****.**>
 *
 * History:
 *		Date        Name                                      Content
 *		----------  ----------------------------------------  ------------------------
 *		2015-04-27  Xiaolang Wang <*****@*****.**>     Initialization.
 **************************************************************************************/
RC createBtree(char *idxId, DataType keyType, int n) {
	BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle));
	RC rc;

	// Check if the file exists
	rc = -99;
	rc = access(idxId, F_OK);

	// if the file does not exist (rc == -1), create it by calling createPageFile(),
	// else if the file exists (rc == 0), then return error code to report it
	// else, some error happens, return rc
	if (rc == -1) {
		rc = createPageFile(idxId);

		if (rc != RC_OK) {
			return rc;
		}
	} else if (rc == 0) {
		return RC_TABLE_EXISTS;
	} else {
		return rc;
	}

	// pin page 0, and write NUM_NODES, NUM_ENTRIES, KEY_TYPE = 0 (4 bytes each)
	rc = -99;
	rc = pinPage(BM, page, INDEX_INFO_PAGE);

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

	int typeLength;
	switch (keyType) {
	case DT_INT:
		typeLength = sizeof(int);
		break;
	case DT_FLOAT:
		typeLength = sizeof(float);
		break;
	case DT_BOOL:
		typeLength = sizeof(bool);
		break;
	case DT_STRING:
		typeLength = 10 * sizeof(char);
	}

	// Store the following info:
	// ip[0] # OF NODES - sizeof(int)
	// ip[1] # OF ENTRIES - sizeof(int)
	// ip[2] KEY_TYPE - sizeof(int)
	// ip[3] TYPE_LENGTH - sizeof(int)
	// ip[4] MAX_KEY PER NODE - sizeof(int)
	// ip[5] ROOT PAGE - sizeof(int)
	// ip[6] TOTAL PAGES - sizeof(int)
	int *ip = (int *) page->data;
	ip[0] = 0;
	ip[1] = 0;
	ip[2] = keyType;
	ip[3] = typeLength;
	ip[4] = n;
	ip[5] = 0;
	ip[6] = 1;

	// unpin page 0
	rc = -99;
	rc = unpinPage(BM, page);

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

	BTREE_HANDLE->keyType = keyType;

	free(page);

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

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