Record SPSegment::inPlaceLookup(TID tid) { // TODO assert(tid.getPage() is part of this segment); BufferFrame frame = bm->fixPage(tid.getPage(), false); SlottedPage* page = reinterpret_cast<SlottedPage*>(frame.getData()); Slot* slot = page->getSlot(tid.getSlot()); if (slot->isMoved() || slot->isEmpty()) { // Slot is empty: Return empty record bm->unfixPage(frame, false); return Record(0, nullptr); } else { // Slot has content: Return record with content. bm->unfixPage(frame, false); return Record(slot->length(), slot->getRecord()->getData()); } }
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; }