int RM_FileHandle::UpdateRec(RID &rid, RM_Record &rec) { int index; Bytes head = (Bytes)bpm->getPage(fileid, rid.GetPageid(), index); Bits* slots = new Bits(head, pernum); if (!slots->bit_get(rid.GetSlotid())) { //cout << "[RM_FileHandle-Update]Warning: RID doesn't exist,Maybe need Insert" << endl; return 1; } int offset = PAGE_HEAD_BYTE; offset = offset + recordsize * rid.GetSlotid(); Bytes rlocation = (Bytes)head; rlocation = rlocation + offset; memcpy(rlocation, rec.GetRdata(), rec.GetSize()); slots->bit_setone(rid.GetSlotid()); bpm->markDirty(index); return 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; }