Esempio n. 1
0
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;
}
Esempio n. 2
0
Leaf<KeyType, KeyComparator> &BTree<KeyType, KeyComparator>::getLeaf(KeyType key) {
  BufferFrame *frame = findFrameForKey(key, false);
  Leaf<KeyType, KeyComparator> *leaf = reinterpret_cast<Leaf<KeyType, KeyComparator> *>(frame->getData());
  bufferManager.unfixPage(*frame, false);
  return *leaf;
}
Esempio n. 3
0
bool BTree<K, Comp>::insert(K key, uint64_t tid) {
  //latch the root
  BufferFrame* curFrame = &bufferManager.fixPage(rootPID, true);
  Node<K, Comp>* curNode = reinterpret_cast<Node<K, Comp>*>(curFrame->getData());
  BufferFrame* parFrame = NULL;
  while (!curNode->isLeaf()) {
    if (curNode->count >= maxNodeSize) {
      // --> split to safe inner pages
      if (parFrame == NULL) {
        //Need to create a new root (parent) first
        parFrame = createNewRoot();
      }
      BufferFrame* newFrame = &bufferManager.fixPage(nextFreePage++, true);
      K splitKey = curNode->split(curFrame->pageId, newFrame, parFrame, smaller);

      //determine correct node and release the other one
      if (smaller(key, splitKey)) {
        bufferManager.unfixPage(*newFrame, true);
      } else {
        curNode = reinterpret_cast<Node<K, Comp>*>(newFrame->getData());
        bufferManager.unfixPage(*curFrame, true);
        curFrame = newFrame;
      }
    }

    //release the parent node
    if (parFrame != NULL) {
      bufferManager.unfixPage(*parFrame, true); //TODO only set true when parent is really dirty?
    }
    parFrame = curFrame;

    //latch the next level
    uint64_t pos = curNode->findKeyPos(key, smaller);
    uint64_t nextPID =
        (pos == curNode->count) ?
            curNode->next : curNode->keyValuePairs[pos].second;
    curFrame = &bufferManager.fixPage(nextPID, true);
    curNode = reinterpret_cast<Node<K, Comp>*>(curFrame->getData());
  }

  Node<K, Comp>* leaf = reinterpret_cast<Node<K, Comp>*>(curNode);
  if (leaf->count >= maxNodeSize) {
    if (parFrame == NULL) {
      parFrame = createNewRoot();
    }

    BufferFrame* newFrame = &bufferManager.fixPage(nextFreePage++, true);
    K splitKey = leaf->split(curFrame->pageId, newFrame, parFrame, smaller);
    if (smaller(key, splitKey)) {
      bufferManager.unfixPage(*newFrame, true);
    } else {
      leaf = reinterpret_cast<Node<K, Comp>*>(newFrame->getData());
      bufferManager.unfixPage(*curFrame, true);
      curFrame = newFrame;
    }
  }
  if (parFrame != NULL) {
    bufferManager.unfixPage(*parFrame, true); //TODO: only mark dirty when parent was actually updated
  }

  bool insertSuccessful = leaf->insertKey(key, tid, smaller);
  if (insertSuccessful) {
    elements++;
  }
  bufferManager.unfixPage(*curFrame, true);
  return insertSuccessful;
}