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