TID SPSegment::insert(const Record& r){ // Find page with enough space for r uint64_t pageId = this->lastPage + 1; for (auto it = this->fsi.rbegin(); it != this->fsi.rend(); it++) { if (it->second >= r.getLen()) { pageId = it->first; break; } } // If necessary, create new SlottedPage BufferFrame frame = bm->fixPage(pageId, true); SlottedPage* page = reinterpret_cast<SlottedPage*>(frame.getData()); if (pageId > this->lastPage) { *page = SlottedPage(); this->lastPage++; if (lastPage > 1l << 48) throw "Max page number reached."; } // TODO Reorder record ? // Write to page unsigned slotNum = page->insert(r); bm->unfixPage(frame, true); // Update lastTID TID newTID = TID(pageId, slotNum); if (newTID.tid > this->lastTID.tid) { this->lastTID = newTID; } // Update FSI this->fsi[newTID.getPage()] -= r.getLen() + (slotNum == page->getMaxSlot() ? sizeof(Slot) : 0); return newTID; }
bool SPSegment::update(TID tid, const Record& r){ Record r_old = this->lookup(tid); unsigned len_old = r_old.getLen(); unsigned len_new = r.getLen(); BufferFrame frame = bm->fixPage(tid.getPage(), true); SlottedPage* page = reinterpret_cast<SlottedPage*>(frame.getData()); if(len_old == len_new){ // If size doesn't change, use memcpy memcpy(page->getSlot(tid.getSlot())->getRecord(), &r, r.getLen()); } else if(len_old > len_new){ // Record has become smaller memcpy(page->getSlot(tid.getSlot())->getRecord(), &r, r.getLen()); // TODO Update freeSpace of page // TODO update FSI } else { // Record has become larger unsigned freeSpaceOnPage = page->remove(tid.getSlot()); this->fsi[tid.getPage()] = freeSpaceOnPage; if (freeSpaceOnPage >= len_new) { // It fits on the page after removal page->insert(r); } else { // Even after removal it is too large // Get another page uint64_t sndPageId = this->lastPage + 1; for (auto it = this->fsi.rbegin(); it != this->fsi.rend(); it++) { if (it->second >= r.getLen()) { sndPageId = it->first; break; } } BufferFrame sndFrame = bm->fixPage(sndPageId, true); // Create a new SlottedPage if necessary SlottedPage* sndPage = reinterpret_cast<SlottedPage*>(sndFrame.getData()); if (sndPageId > this->lastPage) { *sndPage = SlottedPage(); this->lastPage++; if (lastPage > 1l << 48) throw "Max page number reached."; } Slot* fstSlot = page->getSlot(tid.getSlot()); assert(fstSlot->isEmpty()); // Insert into new page unsigned sndSlotNum = sndPage->insert(r); this->fsi[sndPageId] -= r.getLen() + (sndSlotNum == sndPage->getMaxSlot() ? sizeof(Slot) : 0); // Update first slot to directo to second page. *fstSlot = Slot(TID(sndPageId, sndSlotNum)); bm->unfixPage(sndFrame, true); } } bm->unfixPage(frame, true); return true; }