Node* LeafNode::grow() { /* * Ya tiene agregado en elements el record que causo el overflow * ordenado por la key levelActual * * instancia 2 nuevos nodos, uno interno otro hoja * a la hoja le pasa la mitad mayor de su contenido * al interno le pasa el promedio por la key levelActual de * todos los registros */ InnerNode* newInner = new InnerNode(level); //New Leafs in next level //Half the elements in each this->level++; Node* newLeaf = NULL; Key* parentKey = this->split(newLeaf); //Assigns new number on serialization unsigned parentLeft = NodeSerializer::serializeNode(this); unsigned parentRight = NodeSerializer::serializeNode(newLeaf); newInner->setLeft(parentLeft); newInner->addPair(new PairKeyNode(parentKey, parentRight)); return newInner; }
inline void BTree<KeyType, KeyComparator>::insert(KeyType key, TID tid) { size_t currHeight = 0; uint64_t currPageId = rootPageId; BufferFrame *parentFrame = nullptr; BufferFrame *currFrame = nullptr; InnerNode<KeyType, KeyComparator> *parentNode = nullptr; InnerNode<KeyType, KeyComparator> *currNode = nullptr; while (!isLeafHeight(currHeight)) { if (parentFrame != nullptr) { bufferManager.unfixPage(*parentFrame, true); } parentFrame = currFrame; parentNode = currNode; currFrame = &bufferManager.fixPage(this->segmentId, currPageId, true); currNode = reinterpret_cast<InnerNode<KeyType, KeyComparator> *>(currFrame->getData()); if (!currNode->hasSpaceForOneMoreEntry()) { if (parentNode == nullptr) { auto newNode = createEmptyNode(currPageId); parentFrame = newNode.first; parentNode = newNode.second; currHeight++; } auto splitResult = splitInnerNode(currNode, currFrame, currPageId, parentNode, key); currFrame = splitResult.first; currNode = splitResult.second; } currPageId = currNode->getNextNode(key, this->smallerComparator); currHeight++; } // we are now at leaf height - the currPageId points to a leaf if (parentFrame != nullptr) { bufferManager.unfixPage(*parentFrame, true); } parentFrame = currFrame; parentNode = currNode; currNode = nullptr; currFrame = &bufferManager.fixPage(this->segmentId, currPageId, true); auto leaf = reinterpret_cast<Leaf<KeyType, KeyComparator> *>(currFrame->getData()); if (!leaf->hasSpaceForOneMoreEntry()) { if (parentNode == nullptr) { auto newNode = createEmptyNode(currPageId); parentFrame = newNode.first; parentNode = newNode.second; } auto splitResult = splitLeaf(leaf, currFrame, currPageId, parentNode, key); currFrame = splitResult.first; leaf = splitResult.second; } if (parentFrame != nullptr) { bufferManager.unfixPage(*parentFrame, true); } leaf->insertDefiniteFit(key, tid, smallerComparator); bufferManager.unfixPage(*currFrame, true); treeSize++; }
bool Tree::put(Slice key, Slice value) { assert(root_); InnerNode *root = root_; root->inc_ref(); bool ret = root->put(key, value); root->dec_ref(); return ret; }
bool Tree::del(Slice key) { assert(root_); InnerNode *root = root_; root->inc_ref(); bool ret = root->del(key); root->dec_ref(); return ret; }
bool Tree::get(Slice key, Slice& value) { assert(root_); InnerNode *root = root_; root->inc_ref(); bool ret = root->find(key, value, NULL); root->dec_ref(); return ret; }
void Tree::lock_path(Slice key, std::vector<DataNode*>& path) { assert(root_); InnerNode *root = root_; root->inc_ref(); root->write_lock(); path.push_back(root); root->lock_path(key, path); }
void LeafNode::merge(Slice anchor) { if (balancing_) { unlock(); return; } balancing_ = true; assert(records_.size() == 0); // release the write lock unlock(); // acquire write locks from root to leaf vector<DataNode*> path; tree_->lock_path(anchor, path); assert(path.back() == this); // may have insertions during this period if (records_.size() > 0) { while (path.size()) { path.back()->unlock(); path.back()->dec_ref(); path.pop_back(); } return; } if (left_sibling_ >= NID_LEAF_START) { LeafNode *ll = (LeafNode*)tree_->load_node(left_sibling_, false); assert(ll); ll->write_lock(); ll->right_sibling_ = right_sibling_; ll->set_dirty(true); ll->unlock(); ll->dec_ref(); } if (right_sibling_ >= NID_LEAF_START) { LeafNode *rl = (LeafNode*)tree_->load_node(right_sibling_, false); assert(rl); rl->write_lock(); rl->left_sibling_ = left_sibling_; rl->set_dirty(true); rl->unlock(); rl->dec_ref(); } dead_ = true; balancing_ = false; path.pop_back(); unlock(); dec_ref(); // propagation InnerNode *parent = (InnerNode*) path.back(); assert(parent); parent->rm_pivot(nid_, path); }
void InnerNode::split() { // this function is called only when THIS is the only descendent // of the root node, and THIS needs to be split. // assumes that idx of THIS in Parent is 0. InnerNode* newnode = new InnerNode( parent ); CHECK( newnode != 0 ); parent->append( getKey(last), newnode ); newnode->appendFrom( this, last, last ); last--; parent->incNofKeys( 1, newnode->getNofKeys(0) ); parent->decNofKeys( 0, newnode->getNofKeys(0) ); balanceWithRight( newnode, 1 ); }
BufferFrame *BTree<KeyType, KeyComparator>::findFrameForKey(KeyType key, bool exclusive) { BufferFrame *currentFrame = &bufferManager.fixPage(this->segmentId, rootPageId, exclusive); int currentDepth = 0; BufferFrame *parentFrame = nullptr; while (!isLeafHeight(currentDepth)) { InnerNode<KeyType, KeyComparator> *curNode = reinterpret_cast<InnerNode<KeyType, KeyComparator> *> (currentFrame->getData()); if (parentFrame != nullptr) { bufferManager.unfixPage(*parentFrame, false); } int nextPageId = curNode->getNextNode(key, smallerComparator); parentFrame = currentFrame; currentFrame = &bufferManager.fixPage(this->segmentId, nextPageId, exclusive); currentDepth++; } if (parentFrame != nullptr) { bufferManager.unfixPage(*parentFrame, false); } //frame is fixed and has to be unfixed by the caller!! return currentFrame; }
Node* BPlusTree::hidratateNode(int numeroDeNodo) { ByteString byteStr = this->fileBlockManager->readBlock(numeroDeNodo); if (byteStr.isEmpty()) { return NULL; } else { int nivel = byteStr.readAsInt(0); if (nivel == 0) { LeafNode *nuevoNodoHoja = createLeafNode(); nuevoNodoHoja->Hidratate(byteStr); nuevoNodoHoja->number = numeroDeNodo; return nuevoNodoHoja; } else { InnerNode *nuevoNodoInterior = createInnerNode(nivel); nuevoNodoInterior->Hidratate(byteStr); nuevoNodoInterior->number = numeroDeNodo; return nuevoNodoInterior; } } }
inline bool BTree<KeyType, KeyComparator>::searchForKey( KeyType key, TID &tid, uint64_t pageId, size_t currentHeight) { BufferFrame *currentFrame = &bufferManager.fixPage(this->segmentId, pageId, false); bool result; if (isLeafHeight(currentHeight)) { Leaf<KeyType, KeyComparator> *leaf = reinterpret_cast<Leaf<KeyType, KeyComparator> *>( currentFrame->getData()); result = leaf->lookup(key, smallerComparator, &tid); } else { //we haven't reached the leaves yet InnerNode<KeyType, KeyComparator> *currNode = reinterpret_cast<InnerNode<KeyType, KeyComparator> *> ( currentFrame->getData()); pageId = currNode->getNextNode(key, smallerComparator); result = searchForKey(key, tid, pageId, currentHeight + 1); } //return page as result was received and page is no longer required bufferManager.unfixPage(*currentFrame, false); return result; }
Node* ClassifBPlusTree::hidratateNode(int nodeNumber) { int block = fileBlockNodeMapper->getBlock(nodeNumber); ByteString byteStr = this->fileBlockManager->readBlock(block); if (byteStr.isEmpty()) { return NULL; } else { int nivel = byteStr.readAsInt(0); if (nivel == 0) { LeafNode *nuevoNodoHoja = createLeafNode(); nuevoNodoHoja->Hidratate(byteStr); nuevoNodoHoja->number = nodeNumber; return nuevoNodoHoja; } else { InnerNode *nuevoNodoInterior = createInnerNode(nivel); nuevoNodoInterior->Hidratate(byteStr); nuevoNodoInterior->number = nodeNumber; return nuevoNodoInterior; } } }
void InnerNode::isFull(Node *that) { // the child node THAT is full. We will either redistribute elements // or create a new node and then redistribute. // In an attempt to minimize the number of splits, we adopt the following // strategy: // * redistribute if possible // * if not possible, then split with a sibling if( that->isLeaf ) { LeafNode *leaf = (LeafNode *)that; LeafNode *left, *right; // split LEAF only if both sibling nodes are full. int leafidx = indexOf(leaf); int hasRightSib = (leafidx < last) && ((right=(LeafNode*)getTree(leafidx+1)) != 0); int hasLeftSib = (leafidx > 0) && ((left=(LeafNode*)getTree(leafidx-1)) != 0); int rightSibFull = (hasRightSib && right->isAlmostFull()); int leftSibFull = (hasLeftSib && left->isAlmostFull()); if( rightSibFull ) { if( leftSibFull ) { // both full, so pick one to split with left->splitWith( leaf, leafidx ); } else if( hasLeftSib ) { // left sib not full, so balance with it leaf->balanceWithLeft( left, leafidx ); } else { // there is no left sibling, so split with right leaf->splitWith( right, leafidx+1 ); } } else if( hasRightSib ) { // right sib not full, so balance with it leaf->balanceWithRight( right, leafidx+1 ); } else if( leftSibFull ) { // no right sib, and left sib is full, so split with it left->splitWith( leaf, leafidx ); } else if( hasLeftSib ) { // left sib not full so balance with it leaf->balanceWithLeft( left, leafidx ); } else { // neither a left or right sib; should never happen CHECK(0); } } else { InnerNode *inner = (InnerNode *)that; // split INNER only if both sibling nodes are full. int inneridx = indexOf(inner); InnerNode *left, *right; int hasRightSib = (inneridx < last) && ((right=(InnerNode*)getTree(inneridx+1)) != 0); int hasLeftSib = (inneridx > 0) && ((left=(InnerNode*)getTree(inneridx-1)) != 0); int rightSibFull = (hasRightSib && right->isAlmostFull()); int leftSibFull = (hasLeftSib && left->isAlmostFull()); if( rightSibFull ) { if( leftSibFull ) { left->splitWith( inner, inneridx ); } else if( hasLeftSib ) { inner->balanceWithLeft( left, inneridx ); } else { // there is no left sibling inner->splitWith(right, inneridx+1); } } else if( hasRightSib ) { inner->balanceWithRight( right, inneridx+1 ); } else if( leftSibFull ) { left->splitWith( inner, inneridx ); } else if( hasLeftSib ) { inner->balanceWithLeft( left, inneridx ); } else { CHECK(0); } } }
void BPlusTree::exportNode(ofstream& salida, Node* unNodo, int tabulacion,bool keyText,bool textContent) { if (unNodo->isLeaf()) { LeafNode *unNodoHoja = static_cast<LeafNode*> (unNodo); salida << endl; for(int i = 0 ; i < tabulacion ; i++) salida << " "; salida << "Numero: " << unNodoHoja->number << " Nivel: " << unNodoHoja->level << " Cant.Elem: " << unNodoHoja->keyMount << " Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoHoja->occupiedSpace << " Hoja.Sig: " << unNodoHoja->nextLeaf << endl; for (int posicion = 0; posicion < unNodoHoja->keyMount; ++posicion) { for(int i = 0 ; i < tabulacion + 4 ; i++) salida << " "; salida << "("; Key unaClave = unNodoHoja->keys[posicion]; if(keyText) { salida << unaClave.toString(); } else { ByteString clave(unaClave.toString()); salida << Utility::toString(clave.readAsInt(0)); } salida << ";"; ByteString unDato = unNodoHoja->byteData[posicion]; if(textContent) { salida << unDato.toString(); } else { salida << Utility::intToString(unDato.readAsInt(0)); } salida << ")"; salida << (unaClave.getSize() + unDato.getSize() + TreeConstraits::getControlSizeRecord()) << endl; } salida << endl; } else { InnerNode *unNodoInterior = static_cast<InnerNode*> (unNodo); salida << endl << endl; for(int i=0; i<tabulacion ; i++) salida << " "; salida << "Numero: " << unNodoInterior->number << " Nivel: " << unNodoInterior->level << " Cant.Elem: " << unNodoInterior->keyMount << " Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoInterior->occupiedSpace << endl; for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) { if (posicion < unNodoInterior->keyMount) { Key unaClave = unNodoInterior->keys[posicion]; for(int i=0; i<(tabulacion+1) ; i++) salida << " "; salida << "("; if(keyText) { salida << unaClave.toString(); } else { ByteString clave(unaClave.toString()); salida << Utility::toString(clave.readAsInt(0)); } salida << ")"; salida << unaClave.getSize(); salida << " "; salida << unNodoInterior->getSons()[posicion] << " "; } } for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) { Node *hijo = hidratateNode(unNodoInterior->sons[posicion]); exportNode(salida, hijo, tabulacion + 2,keyText,textContent); if (hijo) freeNodeMemory(hijo); } for(int i=0; i<tabulacion ; i++) salida << " "; salida << endl; } }
Result BPlusTree::recursiveRemove(Key clave, Node *nodoCorriente, Node *nodoIzquierda, Node *nodoDerecha, InnerNode *nodoPadreIzquierda, InnerNode *nodoPadreDerecha, InnerNode *nodoPadre, int posicionPadre) { if (nodoCorriente->isLeaf()) { LeafNode *nodoHojaCorriente = static_cast<LeafNode*> (nodoCorriente); LeafNode *nodoHojaIzquierda = static_cast<LeafNode*> (nodoIzquierda); LeafNode *nodoHojaDerecha = static_cast<LeafNode*> (nodoDerecha); int posicion = getPosition(nodoHojaCorriente, clave); if (posicion >= nodoHojaCorriente->keyMount || !equalKey(clave, nodoHojaCorriente->keys[posicion])) { return Result::NO_ENCONTRADO; } nodoHojaCorriente->occupiedSpace -= (nodoHojaCorriente->byteData[posicion].getSize() + nodoHojaCorriente->keys[posicion].getSize() + TreeConstraits::getControlSizeRecord()); nodoHojaCorriente->keyMount--; for (int i = posicion; i < nodoHojaCorriente->keyMount; i++) { nodoHojaCorriente->keys[i] = nodoHojaCorriente->keys[i + 1]; nodoHojaCorriente->byteData[i] = nodoHojaCorriente->byteData[i + 1]; } Result resultado = Result::OK; // si se borro el elemento de la ultima posicion y no es la raiz if (posicion == nodoHojaCorriente->keyMount && nodoPadre) { if (posicionPadre < nodoPadre->keyMount) { if (nodoHojaCorriente->keyMount >= 1) { nodoPadre->occupiedSpace -= nodoPadre->keys[posicionPadre].getSize(); nodoPadre->occupiedSpace += nodoHojaCorriente->keys[nodoHojaCorriente->keyMount - 1].getSize(); nodoPadre->keys[posicionPadre] = nodoHojaCorriente->keys[nodoHojaCorriente->keyMount - 1]; } } else { if (nodoHojaCorriente->keyMount >= 1) { resultado |= Result (Result::ACTUALIZAR_ULTIMA_CLAVE, nodoHojaCorriente->keys[nodoHojaCorriente->keyMount - 1]); } else { resultado |= Result (Result::ACTUALIZAR_ULTIMA_CLAVE, nodoHojaIzquierda->keys[nodoHojaIzquierda->keyMount - 1]); } } } if (nodoHojaCorriente->isUnderflow() && !(nodoHojaCorriente == root && nodoHojaCorriente->keyMount >= 1)) { if (nodoHojaIzquierda == NULL && nodoHojaDerecha == NULL) { persistNode(root); if (root) freeNodeMemory(root); root = nodoHojaCorriente = NULL; firstLeaf = 0; string archivoConfiguracion = fileBlockManager->getPath() + ".cnf"; remove(archivoConfiguracion.c_str()); return Result::OK; // @fusion } else if (( (nodoHojaIzquierda == NULL || !nodoHojaIzquierda->elementsCanTransfer()) && (nodoHojaDerecha == NULL || !nodoHojaDerecha->elementsCanTransfer())) || nodoHojaCorriente->keyMount == 0) { if (nodoPadreIzquierda == nodoPadre) { // cte e izq son hermanos. resultado |= leafNodeFusion(nodoHojaIzquierda, nodoHojaCorriente); }else { resultado |= leafNodeFusion(nodoHojaCorriente, nodoHojaDerecha); } // si la derecha mas cargada redistribuyo } else if ((nodoHojaIzquierda != NULL && !nodoHojaIzquierda->elementsCanTransfer()) && (nodoHojaDerecha != NULL && nodoHojaDerecha->elementsCanTransfer())) { if (nodoPadreDerecha == nodoPadre) { resultado |= redistributeLeftLeaf(nodoHojaCorriente, nodoHojaDerecha, nodoPadreDerecha, posicionPadre); } else { resultado |= leafNodeFusion(nodoHojaIzquierda, nodoHojaCorriente); } // si la izquierda mas cargada redistribuyo } else if ((nodoHojaIzquierda != NULL && nodoHojaIzquierda->elementsCanTransfer()) && (nodoHojaDerecha != NULL && !nodoHojaDerecha->elementsCanTransfer())) { if (nodoPadreIzquierda == nodoPadre) { redistributeRightLeaf(nodoHojaIzquierda, nodoHojaCorriente, nodoPadreIzquierda, posicionPadre - 1); } else { resultado |= leafNodeFusion(nodoHojaCorriente, nodoHojaDerecha); } // izq cte y der son todos hermanos, me fijo cual tiene mas carga y redistribuyo } else if (nodoPadreIzquierda == nodoPadreDerecha) { if (nodoHojaIzquierda->occupiedSpace <= nodoHojaDerecha->occupiedSpace) { resultado |= redistributeLeftLeaf(nodoHojaCorriente, nodoHojaDerecha, nodoPadreDerecha, posicionPadre); } else { redistributeRightLeaf(nodoHojaIzquierda, nodoHojaCorriente, nodoPadreIzquierda, posicionPadre - 1); } } else { if (nodoPadreIzquierda == nodoPadre) { redistributeRightLeaf(nodoHojaIzquierda, nodoHojaCorriente, nodoPadreIzquierda, posicionPadre - 1); } else { resultado |= redistributeLeftLeaf(nodoHojaCorriente, nodoHojaDerecha, nodoPadreDerecha, posicionPadre); } } } else { persistNode(nodoHojaCorriente); } return resultado; } else { InnerNode *nodoInteriorCorriente = static_cast<InnerNode*> (nodoCorriente); InnerNode *nodoInteriorIzquierda = static_cast<InnerNode*> (nodoIzquierda); InnerNode *nodoInteriorDerecha = static_cast<InnerNode*> (nodoDerecha); Node *auxNodoIzquierda, *auxNodoDerecha; InnerNode *auxPadreIzquierda, *auxPadreDerecha; int posicion = getPosition(nodoInteriorCorriente, clave); if (posicion == 0) { auxNodoIzquierda = (nodoIzquierda == NULL) ? NULL : hidratateNode((static_cast<InnerNode*> (nodoIzquierda))->sons[nodoIzquierda->keyMount]); auxPadreIzquierda = nodoPadreIzquierda; } else { auxNodoIzquierda = hidratateNode(nodoInteriorCorriente->sons[posicion - 1]); auxPadreIzquierda = nodoInteriorCorriente; } if (posicion == nodoInteriorCorriente->keyMount) { auxNodoDerecha = (nodoDerecha == NULL) ? NULL : hidratateNode((static_cast<InnerNode*> (nodoDerecha))->sons[0]); auxPadreDerecha = nodoPadreDerecha; } else { auxNodoDerecha = hidratateNode(nodoInteriorCorriente->sons[posicion + 1]); auxPadreDerecha = nodoInteriorCorriente; } // if(clave.getKey().compare("438") == 0) // std::cout << "llamada recursiva: nodointeriorcorriente: " << nodoInteriorCorriente->number << "posicion: " << posicion << endl; Node* auxNodoCorriente = hidratateNode(nodoInteriorCorriente->sons[posicion]); Result resultadoParcial = recursiveRemove(clave, auxNodoCorriente, auxNodoIzquierda, auxNodoDerecha, auxPadreIzquierda, auxPadreDerecha, nodoInteriorCorriente, posicion); Result resultado = Result::OK; if (auxNodoIzquierda) freeNodeMemory(auxNodoIzquierda); if (auxNodoDerecha) freeNodeMemory(auxNodoDerecha); if (auxNodoCorriente) freeNodeMemory(auxNodoCorriente); if (resultadoParcial.contains(Result::NO_ENCONTRADO)) { return resultadoParcial; } if (resultadoParcial.contains(Result::ACTUALIZAR_ULTIMA_CLAVE)) { if (nodoPadre && posicionPadre < nodoPadre->keyMount) { nodoPadre->occupiedSpace -= nodoPadre->keys[posicionPadre].getSize(); nodoPadre->occupiedSpace += resultadoParcial.ultimaClave.getSize(); nodoPadre->keys[posicionPadre] = resultadoParcial.ultimaClave; } else { resultado |= Result(Result::ACTUALIZAR_ULTIMA_CLAVE, resultadoParcial.ultimaClave); } } if (resultadoParcial.contains(Result::FUSION_NODOS)) { Node* nodoHijo = hidratateNode(nodoInteriorCorriente->sons[posicion]); if (nodoHijo->keyMount != 0) posicion++; Key claveInteriorBorrada = nodoInteriorCorriente->keys[posicion - 1]; for (int i = posicion; i < nodoInteriorCorriente->keyMount; i++) { nodoInteriorCorriente->keys[i - 1] = nodoInteriorCorriente->keys[i]; nodoInteriorCorriente->sons[i] = nodoInteriorCorriente->sons[i + 1]; } nodoInteriorCorriente->keyMount--; nodoInteriorCorriente->occupiedSpace -= (claveInteriorBorrada.getSize() + TreeConstraits::getControlSizeRecord()); nodoInteriorCorriente->occupiedSpace -= nodoInteriorCorriente->keys[nodoInteriorCorriente->keyMount].getSize(); if (nodoHijo) freeNodeMemory(nodoHijo); if (nodoInteriorCorriente->level == 1) { posicion--; nodoHijo = hidratateNode(nodoInteriorCorriente->sons[posicion]); nodoInteriorCorriente->occupiedSpace -= nodoInteriorCorriente->keys[posicion].getSize(); nodoInteriorCorriente->occupiedSpace += nodoHijo->keys[nodoHijo->keyMount - 1].getSize(); nodoInteriorCorriente->keys[posicion] = nodoHijo->keys[nodoHijo->keyMount - 1]; if (nodoHijo) freeNodeMemory(nodoHijo); } } if (resultadoParcial.contains(Result::FUSION_NODOS) && nodoInteriorCorriente->isUnderflow() && !(nodoInteriorCorriente == root && nodoInteriorCorriente->keyMount >= 1)) { if (nodoInteriorIzquierda == NULL && nodoInteriorDerecha == NULL) { root = hidratateNode(nodoInteriorCorriente->sons[0]); root->number = 0; persistNode(root); freeNodes.push_back(nodoInteriorCorriente->sons[0]); serializeDataConfig(); return Result::OK; } else if ((nodoInteriorIzquierda == NULL || !nodoInteriorIzquierda->elementsCanTransfer()) && (nodoInteriorDerecha == NULL || !nodoInteriorDerecha->elementsCanTransfer())) { if (nodoPadreIzquierda == nodoPadre) { resultado |= innerNodeFusion(nodoInteriorIzquierda, nodoInteriorCorriente, nodoPadreIzquierda, posicionPadre - 1); } else { resultado |= innerNodeFusion(nodoInteriorCorriente, nodoInteriorDerecha, nodoPadreDerecha, posicionPadre); } } else if ((nodoInteriorIzquierda != NULL && !nodoInteriorIzquierda->elementsCanTransfer()) && (nodoInteriorDerecha != NULL && nodoInteriorDerecha->elementsCanTransfer())) { if (nodoPadreDerecha == nodoPadre) { redistributeLeftInner(nodoInteriorCorriente, nodoInteriorDerecha, nodoPadreDerecha, posicionPadre); } else { resultado |= innerNodeFusion(nodoInteriorIzquierda, nodoInteriorCorriente, nodoPadreIzquierda, posicionPadre - 1); } } else if ((nodoInteriorIzquierda != NULL && nodoInteriorIzquierda->elementsCanTransfer()) && (nodoInteriorDerecha != NULL && !nodoInteriorDerecha->elementsCanTransfer())) { if (nodoPadreIzquierda == nodoPadre) { redistributeRightInner(nodoInteriorIzquierda, nodoInteriorCorriente, nodoPadreIzquierda, posicionPadre - 1); } else { resultado |= innerNodeFusion(nodoInteriorCorriente, nodoInteriorDerecha, nodoPadreDerecha, posicionPadre); } } else if (nodoPadreIzquierda == nodoPadreDerecha) { if (nodoInteriorIzquierda->keyMount <= nodoInteriorDerecha->keyMount) { redistributeLeftInner(nodoInteriorCorriente, nodoInteriorDerecha, nodoPadreDerecha, posicionPadre); } else { redistributeRightInner(nodoInteriorIzquierda, nodoInteriorCorriente, nodoPadreIzquierda, posicionPadre - 1); } } else { if (nodoPadreIzquierda == nodoPadre) { redistributeRightInner(nodoInteriorIzquierda, nodoInteriorCorriente, nodoPadreIzquierda, posicionPadre - 1); } else { redistributeLeftInner(nodoInteriorCorriente, nodoInteriorDerecha, nodoPadreDerecha, posicionPadre); } } } else { persistNode(nodoInteriorCorriente); } return resultado; } }
bool BPlusTree::recursiveInsert(Node* nodoCorriente, Key clave, ByteString dato, Key* clavePromocion, Node** nuevoNodo) { if (!nodoCorriente->isLeaf()) { InnerNode *nodoInteriorCorriente = static_cast<InnerNode*> (nodoCorriente); Key nuevaClave; Node* nuevoNodoHijo = NULL; int posicion = getPosition(nodoInteriorCorriente, clave); Node* nodoHijo = hidratateNode(nodoInteriorCorriente->sons[posicion]); bool resultado = recursiveInsert(nodoHijo, clave, dato, &nuevaClave, &nuevoNodoHijo); if (nuevoNodoHijo) { if (nodoInteriorCorriente->isOverflow(nuevaClave.getSize() + TreeConstraits::getControlSizeRecord() + keyTopSize)) { splitInnerNode(nodoInteriorCorriente, clavePromocion, nuevoNodo, posicion); if (posicion == nodoInteriorCorriente->keyMount + 1 && nodoInteriorCorriente->keyMount < (*nuevoNodo)->keyMount) { InnerNode *nuevoNodoInterior = static_cast<InnerNode*> (*nuevoNodo); nodoInteriorCorriente->keys[nodoInteriorCorriente->keyMount] = *clavePromocion; nodoInteriorCorriente->sons[nodoInteriorCorriente->keyMount + 1] = nuevoNodoInterior->sons[0]; nodoInteriorCorriente->keyMount++; nodoInteriorCorriente->occupiedSpace += (*clavePromocion).getSize() + TreeConstraits::getControlSizeRecord(); nuevoNodoInterior->sons[0] = nuevoNodoHijo->number; *clavePromocion = nuevaClave; persistNode(nuevoNodoHijo); freeNodeMemory(nuevoNodoHijo); persistNode(nodoHijo); freeNodeMemory(nodoHijo); return resultado; } else { if (posicion >= nodoInteriorCorriente->keyMount + 1) { posicion -= (nodoInteriorCorriente->keyMount + 1); nodoInteriorCorriente = static_cast<InnerNode*> (*nuevoNodo); } } } int i = nodoInteriorCorriente->keyMount; while (i > posicion) { nodoInteriorCorriente->keys[i] = nodoInteriorCorriente->keys[i - 1]; nodoInteriorCorriente->sons[i + 1] = nodoInteriorCorriente->sons[i]; i--; } nodoInteriorCorriente->keys[posicion] = nuevaClave; nodoInteriorCorriente->sons[posicion + 1] = nuevoNodoHijo->number; nodoInteriorCorriente->keyMount++; nodoInteriorCorriente->occupiedSpace += nuevaClave.getSize() + TreeConstraits::getControlSizeRecord(); persistNode(nuevoNodoHijo); freeNodeMemory(nuevoNodoHijo); } persistNode(nodoHijo); freeNodeMemory(nodoHijo); return resultado; } else { LeafNode *nodoHojaCorriente = static_cast<LeafNode*> (nodoCorriente); int posicion = getPosition(nodoHojaCorriente, clave); // chequea que no exista la clave if (posicion < nodoHojaCorriente->keyMount && equalKey(clave, nodoHojaCorriente->keys[posicion])) { return false; } int i = nodoHojaCorriente->keyMount - 1; while (i >= 0 && minorKey(clave, nodoHojaCorriente->keys[i])) { nodoHojaCorriente->keys[i + 1] = nodoHojaCorriente->keys[i]; nodoHojaCorriente->byteData[i + 1] = nodoHojaCorriente->byteData[i]; i--; } nodoHojaCorriente->keys[i + 1] = clave; nodoHojaCorriente->byteData[i + 1] = dato; nodoHojaCorriente->keyMount++; nodoHojaCorriente->occupiedSpace += dato.getSize() + clave.getSize() + TreeConstraits::getControlSizeRecord(); if (nodoHojaCorriente->isOverflow(keyTopSize)) { splitLeafNode(nodoHojaCorriente, clavePromocion, nuevoNodo); if (posicion >= nodoHojaCorriente->keyMount) { posicion -= nodoHojaCorriente->keyMount; nodoHojaCorriente = static_cast<LeafNode*> (*nuevoNodo); } } if (nuevoNodo && nodoHojaCorriente != *nuevoNodo && posicion == nodoHojaCorriente->keyMount - 1) { *clavePromocion = clave; } return true; } }
/*! This is called by parseSourceFile() to do the actual parsing and tree building. It only processes qdoc comments. It skips everything else. */ bool PureDocParser::processQdocComments() { QSet<QString> topicCommandsAllowed = topicCommands(); QSet<QString> otherMetacommandsAllowed = otherMetaCommands(); QSet<QString> metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed; while (tok != Tok_Eoi) { if (tok == Tok_Doc) { /* lexeme() returns an entire qdoc comment. */ QString comment = lexeme(); Location start_loc(location()); readToken(); Doc::trimCStyleComment(start_loc,comment); Location end_loc(location()); /* Doc parses the comment. */ Doc doc(start_loc,end_loc,comment,metacommandsAllowed); QString topic; ArgList args; QSet<QString> topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed(); /* There should be one topic command in the set, or none. If the set is empty, then the comment should be a function description. */ if (topicCommandsUsed.count() > 0) { topic = *topicCommandsUsed.begin(); args = doc.metaCommandArgs(topic); } NodeList nodes; QList<Doc> docs; if (topic.isEmpty()) { doc.location().warning(tr("This qdoc comment contains no topic command " "(e.g., '\\%1', '\\%2').") .arg(COMMAND_MODULE).arg(COMMAND_PAGE)); } else { /* There is a topic command. Process it. */ if ((topic == COMMAND_QMLPROPERTY) || (topic == COMMAND_QMLATTACHEDPROPERTY)) { Doc nodeDoc = doc; Node* node = processTopicCommandGroup(nodeDoc,topic,args); if (node != 0) { nodes.append(node); docs.append(nodeDoc); } } else { ArgList::ConstIterator a = args.begin(); while (a != args.end()) { Doc nodeDoc = doc; Node* node = processTopicCommand(nodeDoc,topic,*a); if (node != 0) { nodes.append(node); docs.append(nodeDoc); } ++a; } } } Node* treeRoot = QDocDatabase::qdocDB()->treeRoot(); NodeList::Iterator n = nodes.begin(); QList<Doc>::Iterator d = docs.begin(); while (n != nodes.end()) { processOtherMetaCommands(*d, *n); (*n)->setDoc(*d); checkModuleInclusion(*n); if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast<InnerNode *>(*n); while (m->parent() && m->parent() != treeRoot) m = m->parent(); if (m == *n) ((InnerNode *)*n)->addInclude((*n)->name()); else ((InnerNode *)*n)->setIncludes(m->includes()); } ++d; ++n; } } else { readToken(); } } return true; }
void LeafNode::split(Slice anchor) { if (balancing_) { unlock(); return; } balancing_ = true; assert(records_.size() > 1); // release the write lock unlock(); // need to search from root to leaf again // since the path may be modified vector<DataNode*> path; tree_->lock_path(anchor, path); assert(path.back() == this); // may have deletions during this period if (records_.size() <= 1 || (records_.size() <= (tree_->options_.leaf_node_record_count / 2) && size() <= (tree_->options_.leaf_node_page_size / 2) )) { while (path.size()) { path.back()->unlock(); path.back()->dec_ref(); path.pop_back(); } return; } // create new leaf LeafNode *nl = tree_->new_leaf_node(); assert(nl); // set siblings nl->left_sibling_ = nid_; nl->right_sibling_ = right_sibling_; if(right_sibling_ >= NID_LEAF_START) { LeafNode *rl = (LeafNode*)tree_->load_node(right_sibling_, false); assert(rl); rl->write_lock(); rl->left_sibling_ = nl->nid_; rl->set_dirty(true); rl->unlock(); rl->dec_ref(); } right_sibling_ = nl->nid_; Slice k = records_.split(nl->records_); refresh_buckets_info(); nl->refresh_buckets_info(); set_dirty(true); nl->set_dirty(true); nl->dec_ref(); balancing_ = false; path.pop_back(); unlock(); dec_ref(); // propagation InnerNode *parent = (InnerNode*) path.back(); assert(parent); parent->add_pivot(k, nl->nid_, path); }
void InnerNode::split(std::vector<DataNode*>& path) { assert(pivots_.size() > 1); size_t n = pivots_.size()/2; size_t n1 = pivots_.size() - n - 1; Slice k = pivots_[n].key; InnerNode *ni = tree_->new_inner_node(); ni->bottom_ = IS_LEAF(pivots_[n].child); assert(ni); ni->first_child_ = pivots_[n].child; ni->first_msgbuf_ = pivots_[n].msgbuf; ni->pivots_.resize(n1); std::copy(pivots_.begin() + n + 1, pivots_.end(), ni->pivots_.begin()); pivots_.resize(n); size_t pivots_sz1 = 0; size_t msgcnt1 = 0; size_t msgbufsz1 = 0; msgcnt1 += ni->first_msgbuf_->count(); msgbufsz1 += ni->first_msgbuf_->size(); for(size_t i = 0; i < ni->pivots_.size(); i++) { pivots_sz1 += pivot_size(ni->pivots_[i].key); msgcnt1 += ni->pivots_[i].msgbuf->count(); msgbufsz1 += ni->pivots_[i].msgbuf->size(); } ni->pivots_sz_ = pivots_sz1; ni->msgcnt_ = msgcnt1; ni->msgbufsz_ = msgbufsz1; pivots_sz_ -= (pivots_sz1 + pivot_size(k)); msgcnt_ -= msgcnt1; msgbufsz_ -= msgbufsz1; ni->set_dirty(true); ni->dec_ref(); path.pop_back(); unlock(); dec_ref(); // propagation if( path.size() == 0) { // i'm root InnerNode *nr = tree_->new_inner_node(); assert(nr); nr->bottom_ = false; nr->first_child_ = nid_; MsgBuf* mb0 = new MsgBuf(tree_->options_.comparator); nr->first_msgbuf_ = mb0; nr->msgbufsz_ += mb0->size(); nr->pivots_.resize(1); MsgBuf* mb1 = new MsgBuf(tree_->options_.comparator); nr->pivots_[0] = Pivot(k.clone(), ni->nid_, mb1); nr->pivots_sz_ += pivot_size(k); nr->msgbufsz_ += mb1->size(); nr->set_dirty(true); tree_->pileup(nr); // need not do nr->dec_ref() here } else { // propagation InnerNode* parent = (InnerNode*) path.back(); assert(parent); parent->add_pivot(k, ni->nid_, path); } }
void InnerNode::rm_pivot(bid_t nid, std::vector<DataNode*>& path) { // todo free memory of pivot key assert(path.back() == this); if (status_ == kSkeletonLoaded) { load_all_msgbuf(); } if (first_child_ == nid) { /// @todo this is true only for single thread, fix me assert(first_msgbuf_->count() == 0); msgbufsz_ -= first_msgbuf_->size(); delete first_msgbuf_; if (pivots_.size() == 0) { first_msgbuf_ = NULL; dead_ = true; path.pop_back(); unlock(); dec_ref(); if (path.size() == 0) { // reach root tree_->collapse(); } else { // propagation InnerNode* parent = (InnerNode*) path.back(); assert(parent); parent->rm_pivot(nid_, path); } return; } // shift pivots first_child_ = pivots_[0].child; first_msgbuf_ = pivots_[0].msgbuf; pivots_sz_ -= pivot_size(pivots_[0].key); pivots_.erase(pivots_.begin()); // TODO adjst size } else { vector<Pivot>::iterator it; for (it = pivots_.begin(); it != pivots_.end(); it ++) { if (it->child == nid) { break; } } assert(it != pivots_.end()); /// @todo this is true only for single thread, fix me assert(it->msgbuf->count() == 0); msgbufsz_ -= it->msgbuf->size(); delete it->msgbuf; pivots_sz_ -= pivot_size(it->key); pivots_.erase(it); // TODO adjust size } set_dirty(true); // unlock all parents while (path.size()) { path.back()->unlock(); path.back()->dec_ref(); path.pop_back(); } }
void InnerNode::splitWith( InnerNode *rightsib, int keyidx ) { // THIS and SIB are too full; create a NEWnODE, and balance // the number of keys between the three of them. // // picture: (also see Knuth Vol 3 pg 478) // keyidx keyidx+1 // +--+--+--+--+--+--... // | | | | | | // parent--->| | | | // | | | | // +*-+*-+*-+--+--+--... // | | | // +----+ | +-----+ // | +-----+ | // V | V // +----------+ | +----------+ // | | | | | // this->| | | | |<--sib // +----------+ | +----------+ // V // data // // keyidx is the index of where the sibling is, and where the // newly created node will be recorded (sibling will be moved to // keyidx+1) // PRECONDITION( keyidx > 0 && keyidx <= parent->last ); // I would like to be able to prove that the following assertion // is ALWAYS true, but it is beyond my time limits. If this assertion // ever comes up False, then the code to make it so must be inserted // here. // assert(parent->getKey(keyidx) == rightsib->getKey(0)); // During debugging, this came up False, so rightsib->setKey(0,parent->getKey(keyidx)); int nofKeys = Psize() + rightsib->Vsize(); int newSizeThis = nofKeys / 3; int newSizeNew = (nofKeys - newSizeThis) / 2; int newSizeSib = (nofKeys - newSizeThis - newSizeNew); int noFromThis = Psize() - newSizeThis; int noFromSib = rightsib->Vsize() - newSizeSib; // because of their smaller size, this InnerNode may not have to // give up any elements to the new node. I.e., noFromThis == 0. // This will not happen for LeafNodes. // We handle this by pulling an item from the rightsib. CHECK( noFromThis >= 0 ); CHECK( noFromSib >= 1 ); InnerNode* newNode = new InnerNode(parent); CHECK( newNode != 0 ); if( noFromThis > 0 ) { newNode->append( getItem(last) ); parent->addElt( keyidx, getKey(last--), newNode ); if( noFromThis > 2 ) this->pushRight( noFromThis-1, newNode, keyidx ); rightsib->pushLeft( noFromSib, newNode, keyidx+1 ); } else { // pull an element from the rightsib newNode->append( rightsib->getItem(0) ); parent->addElt( keyidx+1, rightsib->getKey(1), rightsib); rightsib->shiftLeft(1); parent->setTree( keyidx, newNode ); rightsib->pushLeft( noFromSib-1, newNode, keyidx+1 ); } parent->setNofKeys( keyidx-1, this->nofKeys() ); parent->setNofKeys( keyidx, newNode->nofKeys() ); parent->setNofKeys( keyidx+1, rightsib->nofKeys() ); if( parent->isFull() ) parent->informParent(); }
void InnerNode::isLow( Node *that ) { // the child node THAT is <= half full. We will either redistribute // elements between children, or THAT will be merged with another child. // In an attempt to minimize the number of mergers, we adopt the following // strategy: // * redistribute if possible // * if not possible, then merge with a sibling if( that->isLeaf ) { LeafNode *leaf = (LeafNode *)that; LeafNode *left, *right; // split LEAF only if both sibling nodes are full. int leafidx = indexOf(leaf); int hasRightSib = (leafidx < last) && ((right=(LeafNode*)getTree(leafidx+1)) != 0); int hasLeftSib = (leafidx > 0) && ((left=(LeafNode*)getTree(leafidx-1)) != 0); if( hasRightSib && (leaf->Psize() + right->Vsize()) >= leaf->maxPsize()) { // then cannot merge, // and balancing this and rightsib will leave them both // more than half full leaf->balanceWith( right, leafidx+1 ); } else if( hasLeftSib && (leaf->Vsize() + left->Psize()) >= leaf->maxPsize()) { // ditto left->balanceWith( leaf, leafidx ); } else if( hasLeftSib ) { // then they should be merged left->mergeWithRight( leaf, leafidx ); } else if( hasRightSib ) { leaf->mergeWithRight( right, leafidx+1 ); } else { CHECK(0); // should never happen } } else { InnerNode *inner = (InnerNode *)that; // int inneridx = indexOf(inner); InnerNode *left, *right; int hasRightSib = (inneridx < last) && ((right=(InnerNode*)getTree(inneridx+1)) != 0); int hasLeftSib = (inneridx > 0) && ((left=(InnerNode*)getTree(inneridx-1)) != 0); if( hasRightSib && (inner->Psize() + right->Vsize()) >= inner->maxPsize()) { // cannot merge inner->balanceWith( right, inneridx+1 ); } else if( hasLeftSib && (inner->Vsize() + left->Psize()) >= inner->maxPsize()) { // cannot merge left->balanceWith( inner, inneridx ); } else if( hasLeftSib ) { left->mergeWithRight( inner, inneridx ); } else if( hasRightSib ) { inner->mergeWithRight( right, inneridx+1 ); } else { CHECK(0); } } }
void ClassifBPlusTree::exportNode(ofstream& salida, Node* unNodo, int tabulacion,bool keytext, bool textContent) { if (unNodo->isLeaf()) { LeafNode *unNodoHoja = static_cast<LeafNode*> (unNodo); salida << endl; for(int i = 0 ; i < tabulacion ; i++) salida << " "; salida << "Numero: " << unNodoHoja->number << " Nivel: " << unNodoHoja->level << " Cant.Elem: " << unNodoHoja->keyMount << " Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoHoja->occupiedSpace << " Hoja.Sig: " << unNodoHoja->nextLeaf << endl; for (int posicion = 0; posicion < unNodoHoja->keyMount; ++posicion) { for(int i = 0 ; i < tabulacion + 4 ; i++) salida << " "; salida << "("; Key unaClave = unNodoHoja->keys[posicion]; if(keytext) { salida << unaClave.toString(); } else { ByteString clave(unaClave.toString()); if(clave.getSize()==(2*sizeof(int))) { salida << Utility::toString(clave.readAsInt(0)); salida << "-"; salida << Utility::toString(clave.readAsInt(sizeof(int))); } else salida << Utility::toString(clave.readAsInt(0)); } salida << ";"; ByteString unDato = unNodoHoja->byteData[posicion]; int idBlock = unDato.readAsInt(0); string datoString = Utility::intToString(idBlock); salida << datoString; salida << ")"; salida << (unaClave.getSize() + unDato.getSize() + TreeConstraits::getControlSizeRecord()) << endl; for(int i = 0 ; i < tabulacion + 4 ; i++) salida << " "; ListofID listOfID(this->fileBlockManager,idBlock); list<int> listOfInt = listOfID.getListID(); list<int>::iterator it; int id; //int count = 0; ByteString bs; unsigned int i = 0; for(it=listOfInt.begin();it!=listOfInt.end();++it) { i++; id = *it; bs.insertLast(Utility::intToString(id)); bs.insertLast(" "); if((i == listOfInt.size()) || (bs.toString().size() >80)) { salida << bs.toString(); salida << endl; if(i != listOfInt.size()) { for(int i = 0 ; i < tabulacion + 4 ; i++) salida << " "; } bs.clean(); } } } } else { InnerNode *unNodoInterior = static_cast<InnerNode*> (unNodo); salida << endl << endl; for(int i=0; i<tabulacion ; i++) salida << " "; salida << "Numero: " << unNodoInterior->number << " Nivel: " << unNodoInterior->level << " Cant.Elem: " << unNodoInterior->keyMount << " Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoInterior->occupiedSpace << endl; for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) { if (posicion < unNodoInterior->keyMount) { Key unaClave = unNodoInterior->keys[posicion]; for(int i=0; i<(tabulacion+1) ; i++) salida << " "; salida << "("; if(keytext) { salida << unaClave.toString(); } else { ByteString clave(unaClave.toString()); salida << Utility::toString(clave.readAsInt(0)); } salida << ")"; salida << unaClave.getSize(); salida << " "; salida << unNodoInterior->getSons()[posicion] << " "; } } for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) { Node *hijo = hidratateNode(unNodoInterior->sons[posicion]); exportNode(salida, hijo, tabulacion + 2,keytext,textContent); if (hijo) freeNodeMemory(hijo); } for(int i=0; i<tabulacion ; i++) salida << " "; salida << endl; } }