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(); }
/*************************************************************** * Function Name: getNode * * Description:get node from tree * * Parameters:BTreeHandle *tree, int nodeNum, BT_Node **node * * Return: RC * * Author:Xincheng Yang * * History: * Date Name Content * 04/9/2016 Xincheng Yang finish this function ***************************************************************/ RC getNode (BTreeHandle *tree, int nodeNum, BT_Node **node) { BM_PageHandle *pg = (BM_PageHandle *)calloc(1, sizeof(BM_PageHandle)); RC rv = RC_OK; bool isNull = false; int maxsize=2*(tree->n+2); if(*node == NULL){ isNull = true; *node = (BT_Node *)calloc(1, sizeof(BT_Node)); } if((rv = pinPage(tree->bufferPool, pg, nodeNum)) == RC_OK){ memcpy(&(*node)->isValid, pg->data, sizeof(int)); if((*node)->isValid == 0){ unpinPage(tree->bufferPool, pg); rv = RC_IM_NODE_NOT_EXIST; } else { memcpy(&(*node)->parent, pg->data + sizeof(int), sizeof(int)); memcpy(&(*node)->current, pg->data + 2*sizeof(int) , sizeof(int)); memcpy(&(*node)->size, pg->data + 3*sizeof(int), sizeof(int)); memcpy(&(*node)->nodeType, pg->data + 4*sizeof(int), sizeof(int)); if(isNull || (*node)->element == NULL){ (*node)->element = (BT_Element *)malloc(sizeof(BT_Element) * maxsize); } memcpy((*node)->element, pg->data + 5*sizeof(int), sizeof(BT_Element) * (*node)->size); rv = unpinPage(tree->bufferPool, pg); } } free(pg); return rv; }
RC setPageInfo(BTreeHandle *tree, int value, PageNumber pageNum, int pos) { BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle)); RC rc; // pin page 0, page 0 is the information page of b+ tree rc = -99; rc = pinPage(BM, page, pageNum); if (rc != RC_OK) { return rc; } // set the first # of page value int *ip = (int *) page->data; ip[pos] = value; // unpin page 0 rc = -99; rc = unpinPage(BM, page); if (rc != RC_OK) { return rc; } free(page); return RC_OK; }
// Simply marks tombstones, doesn't physically delete or allow for records to overwrite RC deleteRecord(RM_TableData *rel, RID id) { RM_TableMgmtData *tableMgmtData = rel->mgmtData; RM_Page *page; RC pinPageResult; if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, id.page) != RC_OK) { return pinPageResult; } page = (RM_Page*)tableMgmtData->pageHandle.data; char *slotOffset = ((char*)&page->data) + (id.slot*getRecordSize(rel->schema)); // Update tombstone *(char*)slotOffset = -1; RC markDirtyResult; if (markDirtyResult = markDirty(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return markDirtyResult; } RC unpinPageResult; if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return unpinPageResult; } tableMgmtData->numTuples--; return RC_OK; }
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); }
RC updateRecord(RM_TableData *rel, Record *record) { RID *rid = &record->id; RM_TableMgmtData *tableMgmtData = rel->mgmtData; RM_Page *page; // Check to see if feasible record if (rid->page == NO_PAGE || rid->slot == NO_SLOT) { return RC_RM_NO_RECORD; } RC pinPageResult; if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, rid->page) != RC_OK) { return pinPageResult; } page = (RM_Page*)tableMgmtData->pageHandle.data; char *slotOffset = ((char*)&page->data) + (rid->slot * getRecordSize(rel->schema)); int recordSize = getRecordSize(rel->schema); memcpy(slotOffset + 1, record->data, recordSize); RC markDirtyResult; if (markDirtyResult = markDirty(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return markDirtyResult; } RC unpinPageResult; if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return unpinPageResult; } return RC_OK; }
void addFreeSlot(RM_TableMgmtData *tableMgmtData, RM_Page *page, int pageNum) { // Am I the free slot? if (tableMgmtData->nextFreeSlot < 1) { page->next = page->prev = pageNum; tableMgmtData->nextFreeSlot = pageNum; } // Add the slot to the list else { BM_PageHandle pageHandle; RM_Page *firstPage; RC pinPageResult; if (pinPageResult = pinPage(&tableMgmtData->bufferPool, &pageHandle, tableMgmtData->nextFreeSlot) != RC_OK) { return; } firstPage = (RM_Page*)pageHandle.data; RC markDirtyResult; if (markDirtyResult = markDirty(&tableMgmtData->bufferPool, &pageHandle) != RC_OK) { return; } firstPage->prev = pageNum; RC unpinPageResult; if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &pageHandle) != RC_OK) { return; } page->next = tableMgmtData->nextFreeSlot; tableMgmtData->nextFreeSlot = pageNum; page->prev = 0; } }
RC getPageInfo(BTreeHandle *tree, PageNumber pageNum, int pos, int *result) { BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle)); RC rc; // pin page 0, page 0 is the information page of b+ tree rc = -99; rc = pinPage(BM, page, pageNum); if (rc != RC_OK) { return rc; } // get the first # of page 0, is # of nodes int *ip = (int *) page->data; *result = ip[pos]; // unpin page 0 rc = -99; rc = unpinPage(BM, page); if (rc != RC_OK) { return rc; } free(page); return RC_OK; }
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 updateOperationDetails(RM_TableData *rel, recordTableInfo *rec, BM_PageHandle *pageHandle, int recordId) { char *data; recordId = 0; markDirty(rec->bufferManager, pageHandle); unpinPage(rec->bufferManager, pageHandle); forcePage(rec->bufferManager, pageHandle); tableInfoDetailsToFileData(rel->name, data, rec); }
RC getRecord (RM_TableData *rel, RID id, Record *record){ int offset=0; pinPage(bm, page, id.page); offset=numPageHeader+id.slot*slotSize+sizeof(RID); record->id=id; record->data=page->data+offset; unpinPage(bm, page); return RC_OK; }
void removeFromMiddle(TableManager *tableManager, Pager *dp, int pageno){ BM_PageHandle pageHandler2; BM_PageHandle pageHandler; Pager *pagerData; Pager *tmp_dp2; pinPage(&tableManager->pool, &pageHandler, (PageNumber)dp->prev); pinPage(&tableManager->pool, &pageHandler2, (PageNumber)dp->next); pagerData= (Pager*) pageHandler.data; tmp_dp2= (Pager*) pageHandler2.data; markDirty(&tableManager->pool, &pageHandler); markDirty(&tableManager->pool, &pageHandler2); pagerData->next= dp->next; tmp_dp2->prev= dp->prev; unpinPage(&tableManager->pool, &pageHandler); unpinPage(&tableManager->pool, &pageHandler2); dp->next=dp->prev= 0; }
RC updateRecord (RM_TableData *rel, Record *record){ int offset=0; pinPage(bm, page, record->id.page); offset=numPageHeader+record->id.slot*slotSize; offset+=sizeof(RID); memcpy(page->data+offset,record->data, slotSize-sizeof(RID)); markDirty(bm, page); unpinPage(bm, page); return RC_OK; }
RC insertLeafNode(BTreeHandle *tree, BT_KeyPosition *kp, Value *key, RID *rid) { BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle)); RC rc; // get N int n; rc = -99; rc = getN(tree, &n); if (rc != RC_OK) { return rc; } // pin the page rc = pinPage(BM, page, kp->nodePage); if (rc != RC_OK) { return rc; } int *ip = (int *) page->data; // get current keys int currentKeys = ip[1]; // i is the index of key and key pointer, starts from 0 int i; for (i = currentKeys - 1; i > kp->keyPos - 1; i--) { ip[4 + i + 1] = ip[4 + i]; ip[4 + n + 2 * (i + 1)] = ip[4 + n + 2 * i]; ip[4 + n + 2 * (i + 1) + 1] = ip[4 + n + 2 * i + 1]; } // After the for loop, the i is pointing the left of the key position // put the key and RID into the right slot ip[4 + i + 1] = key->v.intV; ip[4 + n + 2 * (i + 1)] = rid->page; ip[4 + n + 2 * (i + 1) + 1] = rid->slot; // increment current ip[1]++; // unpin the page rc = -99; rc = unpinPage(BM, page); if (rc != RC_OK) { return rc; } free(page); return RC_OK; }
void removeFromTail(TableManager *tableManager, Pager *dp, int pageno){ BM_PageHandle pageHandler; Pager *pagerData; pinPage(&tableManager->pool, &pageHandler, (PageNumber)dp->prev); pagerData= (Pager*) pageHandler.data; markDirty(&tableManager->pool, &pageHandler); pagerData->next= 0; unpinPage(&tableManager->pool, &pageHandler); dp->next=dp->prev= 0; }
/* * 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; }
RC deleteOldKey(BTreeHandle *tree, BT_KeyPosition *kp) { BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle)); RC rc; // get N int n; rc = -99; rc = getN(tree, &n); if (rc != RC_OK) { return rc; } // pin the page rc = pinPage(BM, page, kp->nodePage); if (rc != RC_OK) { return rc; } int *ip = (int *) page->data; // get current keys int currentKeys = ip[1]; int i; for (i = kp->keyPos + 1; i < currentKeys; i++) { ip[4 + i] = ip[4 + i + 1]; ip[4 + n + 2 * i] = ip[4 + n + 2 * (i + 1)]; ip[4 + n + 2 * i + 1] = ip[4 + n + 2 * (i + 1) + 1]; } // After the for loop, the i is pointing the currentKeys position // unset the key and keyPointer of currentKeys position ip[4 + i] = 0; ip[4 + n + 2 * i] = 0; ip[4 + n + 2 * i + 1] = 0; // decrement current ip[1]--; // unpin the page rc = -99; rc = unpinPage(BM, page); if (rc != RC_OK) { return rc; } free(page); 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; }
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); }
// handling records in a table RC insertRecord (RM_TableData *rel, Record *record){ int offset=0; currentPage=page->pageNum; if(currentPage==0) { count=0; currentPage++; } pinPage(bm, page,currentPage); if(*(bool *)page->data==true) //if the page is full, open the next page { unpinPage(bm, page); count=0; currentPage++; pinPage(bm, page, currentPage); } offset+=sizeof(bool)+count*sizeof(bool); // skip the first bool space to locate the address *((bool *)(page->data+offset))=true; // set the slot's representive bool to be full(true) if(count>=numSlots) return EXIT_FAILURE; if(count==numSlots-1) //if this is the last slot in the page. set the page to be full. *(bool*)page->data=true; offset = count*slotSize+numPageHeader; //set the offset to the spicific slot position record->id.page=currentPage; record->id.slot=count; memcpy(page->data+offset,&record->id.page,sizeof(int)); offset+=sizeof(int); memcpy(page->data+offset,&record->id.slot,sizeof(int)); offset+=sizeof(int); memcpy(page->data+offset,record->data,slotSize-sizeof(RID)); //copy the content to the memory of page. if((page->data+offset-2*sizeof(int)+slotSize)!=(page->data+(count+1)*slotSize+numPageHeader)) //test its space allocation correctness return EXIT_FAILURE; count++; markDirty(bm, page); unpinPage(bm, page); return RC_OK; }
void getRecordPageOperDtls(RM_TableData *rel, Record *rec, recordTableInfo *table, BM_PageHandle *ph, int pageNum, int slot) { char *stringRecord = NULL; Record *recCopy = NULL; stringRecord = (char *) calloc(table->slotSize, sizeof(char)); if (true) if (pinPage(table->bufferManager, ph, pageNum) == RC_OK) strncpy(stringRecord, ph->data + ((slot) * table->slotSize), sizeof(char) * table->slotSize); unpinPage(table->bufferManager, ph); recCopy = delRecord(rel, stringRecord, 0); rec->data = recCopy->data; free(recCopy); free(ph); }
/* * 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; }
void removeFromHead(TableManager *tableManager, Pager *dp, int pageno){ BM_PageHandle pageHandler; Pager *pagerData; if (dp->next == 0){ dp->prev= 0; tableManager->pageNo= 0; } else{ pinPage(&tableManager->pool, &pageHandler, (PageNumber)dp->next); pagerData= (Pager*) pageHandler.data; markDirty(&tableManager->pool, &pageHandler); pagerData->prev= 0; unpinPage(&tableManager->pool, &pageHandler); tableManager->pageNo= dp->next; dp->next=dp->prev= 0; } }
// 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(); }
RC closeTable(RM_TableData *rel) { RM_TableMgmtData *tableMgmtData; tableMgmtData = rel->mgmtData; // Read page and prepare schema RC pinPageResult; if ((pinPageResult = pinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle, 0)) != RC_OK) { return pinPageResult; } char *offset; offset = (char*)tableMgmtData->pageHandle.data; RC markDirtyResult; if (markDirtyResult = markDirty(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return markDirtyResult; } // Update table data *(int*)offset = tableMgmtData->numTuples; RC unpinPageResult; if (unpinPageResult = unpinPage(&tableMgmtData->bufferPool, &tableMgmtData->pageHandle) != RC_OK) { return unpinPageResult; } // Free buffer pool shutdownBufferPool(&tableMgmtData->bufferPool); // Free schema memory free(rel->name); free(rel->schema->attrNames); free(rel->schema->dataTypes); free(rel->schema->typeLength); free(rel->schema->keyAttrs); free(rel->schema); rel->schema = NULL; // Free mgmt info free(rel->mgmtData); rel->mgmtData = NULL; return RC_OK; }
void pageOperations(recordTableInfo *table, int pageNum, int slot, RM_TableData *rel, Record *record) { BM_PageHandle *pageHandle=NULL; pageHandle = getBuffPageHandle(); char *strRecord,*tempData; strRecord = serializeRecord(record, rel->schema); if(pinPage(table->bufferManager, pageHandle, pageNum)==RC_OK) strncpy(pageHandle->data + (slot * table->slotSize), strRecord, strlen(strRecord)); markDirty(table->bufferManager, pageHandle); unpinPage(table->bufferManager, pageHandle); if(forcePage(table->bufferManager, pageHandle)==RC_OK) record->id.tombS = false; table->numOfRecords = table->numOfRecords + 1; tableInfoDetailsToFileData(rel->name, tempData, table); free(pageHandle); free(strRecord); }
// 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(); }
/** * Writes record to the underlying physical storage file. * It is first serialized and then written. * */ PRIVATE RC writeRecord(RM_TableData *rel, Record *record) { SerBuffer *ss = malloc(sizeof(SerBuffer)); ss->next = 0; ss->size = 0; ss->data = malloc(((RM_TableMgmtData *) rel->mgmtData)->physicalRecordSize); //Serialize the record into binary format serializeRecordBin(record, ((RM_TableMgmtData *) rel->mgmtData)->recordSize, ss); //Calculate offset of the slow in page file where record is to be written unsigned int slotOffset = ((RM_TableMgmtData *) rel->mgmtData)->physicalRecordSize * record->id.slot; BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle)); if (page == NULL) { THROW(RC_NOT_ENOUGH_MEMORY, "Not enough memory available for resource allocation"); } //Pin the page where record is to be written pinPage(((RM_TableMgmtData *) rel->mgmtData)->bPool, page, record->id.page); //Copy serialized record to page slot memcpy(page->data + slotOffset, ss->data, ((RM_TableMgmtData *) rel->mgmtData)->physicalRecordSize); //Mark page as dirty as record has been written to it markDirty(((RM_TableMgmtData *) rel->mgmtData)->bPool, page); unpinPage(((RM_TableMgmtData *) rel->mgmtData)->bPool, page); // free(page->data); free(page); free(ss->data); free(ss); //All OK return RC_OK; }
RC setNode (BTreeHandle *tree, int nodeNum, BT_Node *node) { BM_PageHandle *pg = (BM_PageHandle *)malloc(sizeof(BM_PageHandle)); RC rv = RC_OK; if( (rv = ensureCapacity(nodeNum+1, tree->fileHandle)) == RC_OK && (rv = pinPage(tree->bufferPool, pg, nodeNum)) == RC_OK){ memcpy(pg->data, &node->isValid, sizeof(int)); memcpy(pg->data + sizeof(int), &node->parent, sizeof(int)); memcpy(pg->data + 2*sizeof(int), &node->current, sizeof(int)); memcpy(pg->data + 3*sizeof(int), &node->size, sizeof(int)); memcpy(pg->data + 4*sizeof(int), &node->nodeType, sizeof(int)); memcpy(pg->data + 5*sizeof(int), node->element, sizeof(BT_Element) * node->size); markDirty(tree->bufferPool, pg); rv = unpinPage(tree->bufferPool, pg); } free(pg); return rv; }