Exemplo n.º 1
0
int RM_FileHandle::InsertRec(RID &rid, RM_Record &rec) {		//这里的RID是插入后返回一个RID,其余成员函数都是需要一个RID

	int first_index;
	BufType first_head = bpm->getPage(fileid, 0, first_index);
	int empty_rid_offset = EMPTY_RID_OFFSET_BYTE;			//获取下一可插入项的偏移
	int next_page_offset = NEXT_EMPTY_PAGE_BYTE;			//获取下一个含空项页页码的偏移
	int slots_offset = SLOT_OFFSET_BYTE;					//获取slot偏移位置
	if (*(int*)(first_head + EMPTY_PAGE_OFFSET_4BYTE) != -1) {			//存在下一个空记录

		int insert_page_index;
		Bytes insert_page_head = (Bytes)bpm->getPage(fileid, first_head[EMPTY_PAGE_OFFSET_4BYTE], insert_page_index);
		bpm->markDirty(insert_page_index);						//肯定要修改,所以提前标记为脏页
		RID* current_empty_rid = (RID*)(insert_page_head + empty_rid_offset);	//下一可插入项
		int next_page = *(int*)(insert_page_head + next_page_offset);			//下一个含空项页页码
		Bits* slots = new Bits(insert_page_head + slots_offset, pernum);		//slots

		int offset = PAGE_HEAD_BYTE;
		offset = offset + recordsize * current_empty_rid->GetSlotid();
		Bytes rlocation = insert_page_head + offset;			//获取相应偏移后的地址
		memcpy(rlocation, rec.GetRdata(), rec.GetSize());			//插入该记录
		slots->bit_setone(current_empty_rid->GetSlotid());		//slot相应位子置1
		rid = *current_empty_rid;								//rid返回

		bool isfull = true;									//标记用,true表示当前页满
		for (int current_slot = current_empty_rid->GetSlotid() + 1; current_slot < pernum; current_slot++) {
			if (!slots->bit_get(current_slot)) {					//寻找下一个current_empty_rid,当slots[i]为0时说明该位为空
				isfull = false;
				current_empty_rid->SetSlotid(current_slot);		//修改下一个空项的位置
				break;
			}
		}
		if (isfull) {											//如果页满了
			first_head[EMPTY_PAGE_OFFSET_4BYTE] = next_page;	//当前数据页的下一页给第一页的含空项页
			bpm->markDirty(first_index);						//标记脏页
			current_empty_rid->SetSlotid(-1);					//slotid为-1表示没有下一项
			*(int*)(insert_page_head + next_page_offset) = -1;	//下一个含空项页页码表示当前页为满页
		}
	} else {													//均为满页,新建一页
		pagesum++;												//总页数新增一页
		first_head[PSIZE_OFFSET_4BYTE] = pagesum;				//修改总页数
		bpm->markDirty(first_index);							//标记为脏页
		int new_index;											//新建一个页,并将slot清零
		Bytes new_head = (Bytes)bpm->getPage(fileid, pagesum - 1, new_index);
		Bits* new_slots = new Bits(new_head + slots_offset, pernum);
		new_slots->all_zero();

		int new_offset = PAGE_HEAD_BYTE;						//slot[0]即为第一条记录,存储insert的记录
		Bytes rlocation = new_head + new_offset;
		memcpy(rlocation, rec.GetRdata(), rec.GetSize());
		new_slots->bit_setone(0);
		bpm->markDirty(new_index);								//标记为脏页

		RID new_rid;
		new_rid.SetFileid(-1);
		new_rid.SetPageid(pagesum - 1);
		new_rid.SetSlotid(1);
		*(RID*)(new_head + empty_rid_offset) = new_rid;			//下一可插入项更新为第1项
		rid = new_rid;
		rid.SetSlotid(0);
		first_head[EMPTY_PAGE_OFFSET_4BYTE] = pagesum - 1;		//第一页的含空项页设为当下的新增页
		*(int*)(new_head + next_page_offset) = -1;				//由于之前都是满页,这页显然没有后继页面,设为-1
	}
	return 0;
}
Exemplo n.º 2
0
int RM_FileScan::NextRec(RM_Record &rec, RID &rid) {
	if (isclose) {
		//cout << "[RM_FileScan]GetNextRec error: This filescan has been closed!" << endl;
		return 2;
	}
	//NULL1:当comparevalue为NULL且op为大小于中的一个时为用假,返回为空
	if(op <= GE && op >= LT && comparevalue == NULL)	return 1;

	bool get_flag = false;
	int index;
	Bytes head = (Bytes)filehandle->bpm->getPage(currentRid->GetFileid(), currentRid->GetPageid(), index);
	Bits* slots = new Bits(head, filehandle->GetPnum());
	Bytes record_head;
	int current_slotid = currentRid->GetSlotid();
	int current_pageid = currentRid->GetPageid();

	int offset = PAGE_HEAD_BYTE;
	while (!get_flag) {
//		cout << "fuck1" << endl;
		while ( current_slotid < filehandle->GetPnum() && slots->bit_get(current_slotid) == false) {
			current_slotid++;
		}
//		cout << "fuck2" << endl;
		if (current_slotid == filehandle->GetPnum()) {		//该页记录已全部遍历
			current_pageid++;
			current_slotid = 0;
			if (current_pageid == filehandle->GetPsum()) {	//说明该文件下所有页的所有记录都已遍历过.此时返回0表示已遍历完
				currentRid->SetPageid(current_pageid);
				currentRid->SetSlotid(current_slotid);
				return 1;
			}
			head = (Bytes)filehandle->bpm->getPage(currentRid->GetFileid(), current_pageid, index);
			slots->setData(head);
			offset = PAGE_HEAD_BYTE;
		} else {	//得到一个记录
//			cout << "fuck3" << endl;
			offset = PAGE_HEAD_BYTE;
			offset = offset + filehandle->GetRsize() * current_slotid;
			record_head = head + offset;
			int nullbits_offset = RECORD_NULLBITS_OFFSET_BYTE;
			Bits* nullbits = new Bits(record_head + nullbits_offset, attrcol+1);		//获取相应记录的null位图(一定长度)
			//NULL2.1:左边NULL且需要判等(不等),则直接通过null位图来判别
			//NULL2.2:左边NULL且op为大小于,直接返回true
//			cout << "fuck3.1" << endl;
			if(nullbits->bit_get(attrcol) == 0) {//左边为NULL
				if(op == NO) {
					get_flag = true;
				}
				if(op <= GE && op >= LT) {		//为理解方便写出来,实际没什么用
					get_flag = false;
				}
				if(op == EQ) {
					get_flag = (comparevalue == NULL);
				}
				if(op == NE) {
					get_flag = !(comparevalue == NULL);
				}
			} else /*if (comparevalue != 0)*/{//其他情况,进行相应比较
//				cout << "fuck3.2" << endl;
				char* value_head = record_head + attroffset;
//				enum AttrType{INTEGER,FLOAT,STRING};
//				enum CompOp{EQ,LT,GT,LE,GE,NE,NO};
//				cout << "11" << endl;
				const char* cmp1 = value_head;
				const char* cmp2 = (char*)comparevalue;
				const CompOp cmpop = op;
				const AttrType cmptype = type;
//				cout << "22" << endl;
				if  (comparevalue != 0 || op == NO){
//					cout << "33" << endl;
					get_flag = compareData(cmp1, cmpop, cmp2, cmptype);
				}
				else
					get_flag = false;

			}
//			cout << "fuck4" << endl;
			if (get_flag) {
				rec.SetSize(filehandle->GetRsize());
//				cout << "get_data: " << &get_data << " " << "head: " << &record_head << endl;
				rec.SetData(record_head);
			} else {
				current_slotid++;
			}
//			cout << "fuck5" << endl;
		}
	}
	//设置RID
	rid.SetFileid(-1);
	rid.SetPageid(current_pageid);
	rid.SetSlotid(current_slotid);
	//设置下一条记录的位置
	currentRid->SetPageid(current_pageid);
	currentRid->SetSlotid(current_slotid + 1);
	return 0;
}