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;

}
예제 #2
0
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++;
}
예제 #3
0
파일: tree.cpp 프로젝트: BohuTANG/cascadb
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;
}
예제 #4
0
파일: tree.cpp 프로젝트: BohuTANG/cascadb
bool Tree::del(Slice key)
{
    assert(root_);
    InnerNode *root = root_;
    root->inc_ref();
    bool ret = root->del(key);
    root->dec_ref();
    return ret;
}
예제 #5
0
파일: tree.cpp 프로젝트: BohuTANG/cascadb
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;
}
예제 #6
0
파일: tree.cpp 프로젝트: BohuTANG/cascadb
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);
}
예제 #7
0
파일: node.cpp 프로젝트: jameswei/cascadb
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 );
}
예제 #9
0
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;
}
예제 #10
0
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;
		}
	}
}
예제 #11
0
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);
            }
        }
}
예제 #14
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;
	}
}
예제 #15
0
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;
	}
}
예제 #16
0
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;
	}
}
예제 #17
0
파일: puredocparser.cpp 프로젝트: cedrus/qt
/*!
  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;
}
예제 #18
0
파일: node.cpp 프로젝트: jameswei/cascadb
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);
}
예제 #19
0
파일: node.cpp 프로젝트: jameswei/cascadb
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);
    }
}
예제 #20
0
파일: node.cpp 프로젝트: jameswei/cascadb
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;
	}
}