⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tabindnode.cpp

📁 linux下一款GIS程序源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                assert(m_poCurChildNode);                assert(m_nSubTreeDepth > 1);                return m_poCurChildNode->AddEntry(pKeyValue, nRecordNo,                                                  bAddInThisNodeOnly,                                                  bInsertAfterCurChild,                                                  bMakeNewEntryCurChild);            }            else            {                /*-----------------------------------------------------                 * Splitting a regular node will leave it 50% full.                 *----------------------------------------------------*/                if (SplitNode() != 0)                    return -1;             }        }        /*-------------------------------------------------------------         * Insert new key/value at the right position in node.         *------------------------------------------------------------*/        if (InsertEntry(pKeyValue, nRecordNo,                         bInsertAfterCurChild, bMakeNewEntryCurChild) != 0)            return -1;    }    return 0;}/********************************************************************** *                   TABINDNode::InsertEntry() * * (private method) * * Insert a key/value pair in the current node buffer. * * Returns 0 on success, -1 on error **********************************************************************/int TABINDNode::InsertEntry(UGKByte *pKeyValue, UGKInt32 nRecordNo,                            UGKBool bInsertAfterCurChild /*=FALSE*/,                            UGKBool bMakeNewEntryCurChild /*=FALSE*/){    int iInsertAt=0;    if (GetNumEntries() >= GetMaxNumEntries())    {           UGKError(ET_Failure, UGKErr_AssertionFailed,                  "Node is full!  Cannot insert key!");        return -1;    }    /*-----------------------------------------------------------------     * Find the spot where the key belongs     *----------------------------------------------------------------*/    if (bInsertAfterCurChild)    {        iInsertAt = m_nCurIndexEntry+1;    }    else    {        while(iInsertAt < m_numEntriesInNode)        {            int nCmpStatus = IndexKeyCmp(pKeyValue, iInsertAt);            if (nCmpStatus <= 0)            {                break;            }            iInsertAt++;        }    }    m_poDataBlock->GotoByteInBlock(12 + iInsertAt*(m_nKeyLength+4));    /*-----------------------------------------------------------------     * Shift all entries that follow in the array     *----------------------------------------------------------------*/    if (iInsertAt < m_numEntriesInNode)    {        // Since we use memmove() directly, we need to inform         // m_poDataBlock that the upper limit of the buffer will move        m_poDataBlock->GotoByteInBlock(12 + (m_numEntriesInNode+1)*                                                        (m_nKeyLength+4));        m_poDataBlock->GotoByteInBlock(12 + iInsertAt*(m_nKeyLength+4));        memmove(m_poDataBlock->GetCurDataPtr()+(m_nKeyLength+4),                m_poDataBlock->GetCurDataPtr(),                (m_numEntriesInNode-iInsertAt)*(m_nKeyLength+4));    }    /*-----------------------------------------------------------------     * Write new entry     *----------------------------------------------------------------*/    m_poDataBlock->WriteBytes(m_nKeyLength, pKeyValue);    m_poDataBlock->WriteInt32(nRecordNo);    m_numEntriesInNode++;    m_poDataBlock->GotoByteInBlock(0);    m_poDataBlock->WriteInt32(m_numEntriesInNode);    if (bMakeNewEntryCurChild)        m_nCurIndexEntry = iInsertAt;    else if (m_nCurIndexEntry >= iInsertAt)        m_nCurIndexEntry++;    /*-----------------------------------------------------------------     * If we replaced the first entry in the node, then this node's key     * changes and we have to update the reference in the parent node.     *----------------------------------------------------------------*/    if (iInsertAt == 0 && m_poParentNodeRef)    {        if (m_poParentNodeRef->UpdateCurChildEntry(GetNodeKey(),                                                   GetNodeBlockPtr()) != 0)            return -1;    }    return 0;}/********************************************************************** *                   TABINDNode::UpdateCurChildEntry() * * Update the key for the current child node.  This method is called by * the child when its first entry (defining its node key) is changed. * * Returns 0 on success, -1 on error **********************************************************************/int TABINDNode::UpdateCurChildEntry(UGKByte *pKeyValue, UGKInt32 nRecordNo){    /*-----------------------------------------------------------------     * Update current child entry with the info for the first node.     *     * For some reason, the key for first entry of the first node of each     * level has to be set to 0 except for the leaf level.     *----------------------------------------------------------------*/    m_poDataBlock->GotoByteInBlock(12 + m_nCurIndexEntry*(m_nKeyLength+4));    if (m_nCurIndexEntry == 0 && m_nSubTreeDepth > 1 && m_nPrevNodePtr == 0)    {        m_poDataBlock->WriteZeros(m_nKeyLength);    }    else    {        m_poDataBlock->WriteBytes(m_nKeyLength, pKeyValue);    }    m_poDataBlock->WriteInt32(nRecordNo);    return 0;}/********************************************************************** *                   TABINDNode::UpdateSplitChild() * * Update the key and/or record ptr information corresponding to the  * current child node. * * Returns 0 on success, -1 on error **********************************************************************/int TABINDNode::UpdateSplitChild(UGKByte *pKeyValue1, UGKInt32 nRecordNo1,                                 UGKByte *pKeyValue2, UGKInt32 nRecordNo2,                                 int nNewCurChildNo /* 1 or 2 */){    /*-----------------------------------------------------------------     * Update current child entry with the info for the first node.     *     * For some reason, the key for first entry of the first node of each     * level has to be set to 0 except for the leaf level.     *----------------------------------------------------------------*/    m_poDataBlock->GotoByteInBlock(12 + m_nCurIndexEntry*(m_nKeyLength+4));    if (m_nCurIndexEntry == 0 && m_nSubTreeDepth > 1 && m_nPrevNodePtr == 0)    {        m_poDataBlock->WriteZeros(m_nKeyLength);    }    else    {        m_poDataBlock->WriteBytes(m_nKeyLength, pKeyValue1);    }    m_poDataBlock->WriteInt32(nRecordNo1);    /*-----------------------------------------------------------------     * Add an entry for the second node after the current one and ask      * AddEntry() to update m_nCurIndexEntry if the new node should      * become the new current child.     *----------------------------------------------------------------*/    if (AddEntry(pKeyValue2, nRecordNo2,                  TRUE, /* bInThisNodeOnly */                 TRUE, /* bInsertAfterCurChild */                 (nNewCurChildNo==2)) != 0)    {            return -1;    }    return 0;}/********************************************************************** *                   TABINDNode::SplitNode() * * (private method) * * Split a node, update the references in the parent node, etc. * Note that Root Nodes cannot be split using this method... SplitRootNode() * should be used instead. * * The node is split in a way that the current child stays inside this * node object, and a new node is created for the other half of the * entries.  This way, the object references in this node's parent and in its  * current child all remain valid.  The new node is not kept in memory,  * it is written to disk right away. * * Returns 0 on success, -1 on error **********************************************************************/int TABINDNode::SplitNode(){    TABINDNode *poNewNode=NULL;    int numInNode1, numInNode2;    assert(m_numEntriesInNode >= 2);    assert(m_poParentNodeRef);  // This func. does not work for root nodes    /*-----------------------------------------------------------------     * Prepare new node     *----------------------------------------------------------------*/    numInNode1 = (m_numEntriesInNode+1)/2;    numInNode2 = m_numEntriesInNode - numInNode1;    poNewNode = new TABINDNode(m_eAccessMode);    if (m_nCurIndexEntry < numInNode1)    {        /*-------------------------------------------------------------         * We will move the second half of the array to a new node.         *------------------------------------------------------------*/        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength,                                 m_nSubTreeDepth, m_bUnique,                                 m_poBlockManagerRef, m_poParentNodeRef,                                 GetNodeBlockPtr(), m_nNextNodePtr)!= 0 ||            poNewNode->SetFieldType(m_eFieldType) != 0 )        {            return -1;        }        // We have to update m_nPrevNodePtr in the node that used to follow        // the current node and will now follow the new node.        if (m_nNextNodePtr)        {            TABINDNode *poTmpNode = new TABINDNode(m_eAccessMode);            if (poTmpNode->InitNode(m_fp, m_nNextNodePtr,                                     m_nKeyLength, m_nSubTreeDepth,                                    m_bUnique, m_poBlockManagerRef,                                     m_poParentNodeRef) != 0 ||                poTmpNode->SetPrevNodePtr(poNewNode->GetNodeBlockPtr()) != 0 ||                poTmpNode->CommitToFile() != 0)            {                return -1;            }            delete poTmpNode;        }        m_nNextNodePtr = poNewNode->GetNodeBlockPtr();        // Move half the entries to the new block        m_poDataBlock->GotoByteInBlock(12 + numInNode1*(m_nKeyLength+4));        if (poNewNode->SetNodeBufferDirectly(numInNode2,                                         m_poDataBlock->GetCurDataPtr()) != 0)            return -1;#ifdef DEBUG        // Just in case, reset space previously used by moved entries        memset(m_poDataBlock->GetCurDataPtr(), 0, numInNode2*(m_nKeyLength+4));#endif        // And update current node members        m_numEntriesInNode = numInNode1;        // Update parent node with new children info        if (m_poParentNodeRef)        {            if (m_poParentNodeRef->UpdateSplitChild(GetNodeKey(),                                                    GetNodeBlockPtr(),                                                    poNewNode->GetNodeKey(),                                        poNewNode->GetNodeBlockPtr(), 1) != 0)                return -1;        }    }    else    {        /*-------------------------------------------------------------         * We will move the first half of the array to a new node.         *------------------------------------------------------------*/        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength,                                 m_nSubTreeDepth, m_bUnique,                                 m_poBlockManagerRef, m_poParentNodeRef,                                 m_nPrevNodePtr, GetNodeBlockPtr())!= 0 ||            poNewNode->SetFieldType(m_eFieldType) != 0 )        {            return -1;        }        // We have to update m_nNextNodePtr in the node that used to precede        // the current node and will now precede the new node.        if (m_nPrevNodePtr)        {            TABINDNode *poTmpNode = new TABINDNode(m_eAccessMode);            if (poTmpNode->InitNode(m_fp, m_nPrevNodePtr,                                     m_nKeyLength, m_nSubTreeDepth,                                    m_bUnique, m_poBlockManagerRef,                                     m_poParentNodeRef) != 0 ||                poTmpNode->SetNextNodePtr(poNewNode->GetNodeBlockPtr()) != 0 ||                poTmpNode->CommitToFile() != 0)            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -