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
/***************************************************************
 * 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;
}
Beispiel #12
0
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;
}
Beispiel #15
0
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;

}
Beispiel #16
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();
}
Beispiel #19
0
/*
 * 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;
}
Beispiel #20
0
void 
readAndCheckDummyPage(BM_BufferPool *bm, int pageNum)
{
  BM_PageHandle *h = MAKE_PAGE_HANDLE();
  char *expected = malloc(sizeof(char) * 512);

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

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

  free(expected);
  free(h);
}
// 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);
}
Beispiel #23
0
/*
 * 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;
}
Beispiel #24
0
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);
}
Beispiel #28
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();  
}
/**
 * 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;
}
Beispiel #30
0
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;
}