📄 ntx.cpp
字号:
temp = n1->offsets[end]; for( i = end; i > start; i--) { n1->offsets[i] = n1->offsets[i-1]; } n1->offsets[start] = temp; // Insert new key PutKeyData( start , n1 ); PutDbfNo ( start , n1, d ); } else { // If the passed-in key IS median key, just copy it. if (pos == HeadNode.HalfKeysPerNode) { memcpy(PushItem.Key, KeyBuf, HeadNode.KeyLen); PushItem.RecordNumber = d; start = pos; end = pos; } else { // Otherwise, the median key will be middle key becasue the // new key will be inserted somewhere above the middle. memcpy(PushItem.Key, GetKeyData(HeadNode.HalfKeysPerNode, n1), HeadNode.KeyLen); PushItem.RecordNumber = GetDbfNo(HeadNode.HalfKeysPerNode, n1); start = HeadNode.HalfKeysPerNode ; end = pos -1; } temp = n1->offsets[start]; for( i = start; i < end; i++) { n1->offsets[i] = n1->offsets[i+1]; } n1->offsets[end] = temp; // Insert new key PutKeyData( pos -1 , n1 ); PutDbfNo ( pos -1 , n1, d ); } // Dup the node data memcpy(n2->Leaf.KeyRecs, n1->Leaf.KeyRecs, XB_NTX_NODE_SIZE); // Dup the offsets for ( i = 0; i < HeadNode.KeysPerNode +1; i++) { n2->offsets[i] = n1->offsets[i]; } // Setup the second node for (j = 0, i = HeadNode.HalfKeysPerNode; i < HeadNode.KeysPerNode; i++, j++ ) { temp = n2->offsets[j]; n2->offsets[j] = n2->offsets[i]; n2->offsets[i] = temp; } // Get the last offset for both nodes temp = n2->offsets[j]; n2->offsets[j] = n2->offsets[HeadNode.KeysPerNode]; n2->offsets[HeadNode.KeysPerNode] = temp; // Set the new count of both nodes n2->Leaf.NoOfKeysThisNode = HeadNode.HalfKeysPerNode; n1->Leaf.NoOfKeysThisNode = HeadNode.HalfKeysPerNode; if(( rc = PutLeafNode( n1->NodeNo, n1 )) != 0 ) return rc; if(( rc = PutLeafNode( n2->NodeNo, n2 )) != 0 ) return rc; return 0;}/************************************************************************///! Short description./*! \param n1 \param n2 \param*/xbShort xbNtx::SplitINode( xbNodeLink *n1, xbNodeLink *n2, xbLong ) /* parent, tempnode, tempnodeno */{ xbShort i,j,rc; xbShort temp; xbShort pos = n1->CurKeyNo; xbShort start; xbShort end; xbLong n1LastNodeNo = 0; NtxItem oldPushItem; oldPushItem.Node = PushItem.Node; oldPushItem.RecordNumber = PushItem.RecordNumber; memcpy(oldPushItem.Key, PushItem.Key, sizeof(PushItem.Key)); // n2->NodeNo = HeadNode.TotalNodes++; n2->NodeNo = GetNextNodeNo(); // If the new key goes in the first node. if (pos < HeadNode.HalfKeysPerNode) { // Setup key to insert into parent memcpy(PushItem.Key, GetKeyData(HeadNode.HalfKeysPerNode -1, n1), HeadNode.KeyLen); PushItem.RecordNumber = GetDbfNo(HeadNode.HalfKeysPerNode -1, n1); PushItem.Node = n2->NodeNo; n1LastNodeNo = GetLeftNodeNo(HeadNode.HalfKeysPerNode -1, n1); start = pos; end = HeadNode.HalfKeysPerNode - 1; // Insert the new key. temp = n1->offsets[end]; for( i = end; i > start; i--) { n1->offsets[i] = n1->offsets[i-1]; } n1->offsets[start] = temp; } else { // If the passed-in key IS median key, just copy it. if (pos == HeadNode.HalfKeysPerNode) { PutLeftNodeNo(0, n2, oldPushItem.Node); // PushItem should remain the same, except for its left pointer PushItem.Node = n2->NodeNo; start = pos; end = pos; } else { // Otherwise, the median key will be middle key becasue the // new key will be inserted somewhere above the middle. memcpy(PushItem.Key, GetKeyData(HeadNode.HalfKeysPerNode, n1), HeadNode.KeyLen); PushItem.RecordNumber = GetDbfNo(HeadNode.HalfKeysPerNode, n1); PushItem.Node = n2->NodeNo; n1LastNodeNo = GetLeftNodeNo(HeadNode.HalfKeysPerNode, n1); // start = HeadNode.HalfKeysPerNode + 1; start = HeadNode.HalfKeysPerNode; end = pos -1; // Insert the new key. temp = n1->offsets[start]; for( i = start; i < end; i++) { n1->offsets[i] = n1->offsets[i+1]; } n1->offsets[end] = temp; pos--; } } /* restore original key */ memcpy( KeyBuf, oldPushItem.Key, HeadNode.KeyLen + 1); // Insert new key PutKeyData( pos, n1 ); PutDbfNo ( pos, n1, oldPushItem.RecordNumber); PutLeftNodeNo( pos, n1, GetLeftNodeNo (pos + 1, n1)); PutLeftNodeNo( pos + 1 /* +1 ?*/, n1, oldPushItem.Node /* t */ ); // Dup the node data into the new page memcpy(n2->Leaf.KeyRecs, n1->Leaf.KeyRecs, XB_NTX_NODE_SIZE); // Dup the offsets for ( i = 0; i < HeadNode.KeysPerNode +1; i++) { n2->offsets[i] = n1->offsets[i]; } // Setup the second node for (j = 0, i = HeadNode.HalfKeysPerNode; i < HeadNode.KeysPerNode; i++, j++ ) { temp = n2->offsets[j]; n2->offsets[j] = n2->offsets[i]; n2->offsets[i] = temp; } // Get the last offset for both nodes temp = n2->offsets[j]; n2->offsets[j] = n2->offsets[HeadNode.KeysPerNode]; n2->offsets[HeadNode.KeysPerNode] = temp; PutLeftNodeNo(HeadNode.HalfKeysPerNode, n1, n1LastNodeNo); // Set the new count of both nodes n2->Leaf.NoOfKeysThisNode = HeadNode.HalfKeysPerNode; n1->Leaf.NoOfKeysThisNode = HeadNode.HalfKeysPerNode; if((rc = PutLeafNode( n1->NodeNo,n1 )) != 0) return rc; if((rc = PutLeafNode( n2->NodeNo,n2 )) != 0) return rc; return 0;}/************************************************************************///! Short description./*! \param RecBufSw \param KeyBufSw*/xbShort xbNtx::CreateKey( xbShort RecBufSw, xbShort KeyBufSw ){ /* RecBufSw 0 Use RecBuf */ /* 1 Use RecBuf2 */ /* KeyBufSw 0 Use KeyBuf */ /* 1 Use KeyBuf2 */ xbShort rc; xbExpNode * TempNode; if(( rc = dbf->xbase->ProcessExpression( ExpressionTree, RecBufSw )) != XB_NO_ERROR ) return rc; TempNode = (xbExpNode *) dbf->xbase->Pop(); if( !TempNode ) xb_error( XB_INVALID_KEY ); if( KeyBufSw ) { memset( KeyBuf2, 0x00, HeadNode.KeyLen + 1 ); memcpy( KeyBuf2, TempNode->StringResult, TempNode->DataLen ); } else { memset( KeyBuf, 0x00, HeadNode.KeyLen + 1 ); memcpy( KeyBuf, TempNode->StringResult, TempNode->DataLen ); }// if( !TempNode->InTree ) dbf->xbase->FreeExpNode( TempNode ); if( !TempNode->InTree ) delete TempNode; return 0;}/************************************************************************///! Short description./*! \param key*/xbShort xbNtx::GetCurrentKey(char *key){ CreateKey(0, 0); memcpy(key, KeyBuf, HeadNode.KeyLen + 1); return 0;}/************************************************************************///! Short description./*! \param DbfRec*/xbShort xbNtx::AddKey( xbLong DbfRec ){ /* This routine assumes KeyBuf contains the contents of the index to key */ xbShort i,rc; xbNodeLink * TempNode; xbNodeLink * Tparent; xbLong TempNodeNo = 0L; /* new, unattached leaf node no */ /* find node key belongs in */ rc = FindKey( KeyBuf, HeadNode.KeyLen, 0 ); if( rc == XB_FOUND && HeadNode.Unique ) xb_error(XB_KEY_NOT_UNIQUE);// 9/29/98// these lines commented out - compatibity wins over efficiency for this library// /* 1.02 next statement moves to key match w/ space in nodes to reduce splits */// if( !HeadNode.Unique && rc == XB_FOUND &&// HeadNode.KeysPerNode == CurNode->Leaf.NoOfKeysThisNode )// {// if(( rc = CloneNodeChain()) != XB_NO_ERROR ) return rc;// if(( rc = GetNextKey( 0 )) != XB_NO_ERROR )// UncloneNodeChain();// while( HeadNode.KeysPerNode == CurNode->Leaf.NoOfKeysThisNode &&// rc == XB_NO_ERROR && // (CompareKey( KeyBuf, GetKeyData( CurNode->CurKeyNo, CurNode ),// HeadNode.KeyLen ) == 0 )// )// if(( rc = GetNextKey( 0 )) != XB_NO_ERROR )// UncloneNodeChain();// } /************************************************/ /* section A - if room in node, add key to node */ /************************************************/ if( CurNode->Leaf.NoOfKeysThisNode < HeadNode.KeysPerNode ) { if(( rc = PutKeyInNode( CurNode,CurNode->CurKeyNo,DbfRec,0L,1)) != 0) return rc; if(( rc = PutHeadNode( &HeadNode, indexfp, 1 )) != 0) return rc; return XB_NO_ERROR; } /***********************************************************************/ /* section B - split leaf node if full and put key in correct position */ /***********************************************************************/ TempNode = GetNodeMemory(); // Create a new page TempNode->NodeNo = GetNextNodeNo(); rc = SplitLeafNode( CurNode, TempNode, CurNode->CurKeyNo, DbfRec ); if( rc ) return rc; /* TempNode is on disk, now we have to point someone above to that node. Keep the NodeNo of the on disk new node. */ TempNodeNo = TempNode->NodeNo; ReleaseNodeMemory( TempNode ); /* PushItem also contains the key to put into the parent PushItem should point at TempNode */ PushItem.Node = TempNodeNo; /*****************************************************/ /* section C go up tree splitting nodes as necessary */ /*****************************************************/ Tparent = CurNode->PrevNode; while( Tparent && Tparent->Leaf.NoOfKeysThisNode >= HeadNode.KeysPerNode ) { TempNode = GetNodeMemory(); if( !TempNode )#ifdef HAVE_EXCEPTIONS throw xbOutOfMemoryException();#else return XB_NO_MEMORY;#endif rc = SplitINode( Tparent, TempNode, TempNodeNo ); if( rc ) return rc; TempNodeNo = TempNode->NodeNo; ReleaseNodeMemory( TempNode ); ReleaseNodeMemory( CurNode ); CurNode = Tparent; CurNode->NextNode = NULL; Tparent = CurNode->PrevNode; } /************************************************************/ /* Section D if CurNode is split root, create new root */ /************************************************************/ /* at this point CurNode = The node that was just split TempNodeNo = The new node split off from CurNode */ if(CurNode->NodeNo == HeadNode.StartNode ) { TempNode = GetNodeMemory(); if( !TempNode )#ifdef HAVE_EXCEPTIONS throw xbOutOfMemoryException();#else return XB_NO_MEMORY;#endif memcpy( KeyBuf, PushItem.Key, HeadNode.KeyLen ); PutKeyData( 0, TempNode ); PutDbfNo ( 0, TempNode, PushItem.RecordNumber ); PutLeftNodeNo( 0, TempNode, CurNode->NodeNo ); PutLeftNodeNo( 1, TempNode, PushItem.Node ); TempNode->NodeNo = GetNextNodeNo(); TempNode->Leaf.NoOfKeysThisNode++; HeadNode.StartNode = TempNode->NodeNo; rc = PutLeafNode( TempNode->NodeNo, TempNode ); if( rc ) return rc; rc = PutHeadNode( &HeadNode, indexfp, 1 ); if( rc ) return rc; ReleaseNodeMemory( TempNode ); return XB_NO_ERROR; } /**********************************/ /* Section E make room in parent */ /**********************************/ InsertKeyOffset(Tparent->CurKeyNo, Tparent); /* put key in parent */ i = Tparent->CurKeyNo; memcpy( KeyBuf, PushItem.Key, HeadNode.KeyLen); PutKeyData( i, Tparent ); PutDbfNo( i, Tparent, PushItem.RecordNumber); PutLeftNodeNo( i , Tparent, CurNode->NodeNo ); PutLeftNodeNo( i + 1 , Tparent, TempNodeNo ); Tparent->Leaf.NoOfKeysThisNode++; rc = PutLeafNode( Tparent->NodeNo, Tparent ); if( rc ) return rc; rc = PutHeadNode( &HeadNode, indexfp, 1 ); if( rc ) return rc; return XB_NO_ERROR;}/***********************************************************************///! Short description./*! \param n*/xbShort xbNtx::UpdateParentKey( xbNodeLink * n ){/* this routine goes backwards thru the node chain looking for a parent node to update */ xbNodeLink * TempNode; if( !n ) return XB_INVALID_NODELINK; if( !GetDbfNo( 0, n )) { cout << "Fatal index error - Not a leaf node" << n->NodeNo << "\n";// exit(0); return XB_NOT_LEAFNODE; } TempNode = n->PrevNode; while( TempNode ) { if( TempNode->CurKeyNo < TempNode->Leaf.NoOfKeysThisNode ) { memcpy(KeyBuf,GetKeyData(n->Leaf.NoOfKeysThisNode-1,n),HeadNode.KeyLen); PutKeyData( TempNode->CurKeyNo, TempNode ); return PutLeafNode( TempNode->NodeNo, TempNode ); } TempNode = TempNode->PrevNode; } return XB_NO_ERROR;}/***********************************************************************///! Short description./*! \param n*//* This routine queues up a list of nodes which have been emptied */void xbNtx::UpdateDeleteList( xbNodeLink *n ){ n->NextNode = DeleteChain; DeleteChain = n;}/***********************************************************************///! Short description./*!*//* Delete nodes from the node list - for now we leave the empty nodes *//* dangling in the file. Eventually we will remove nodes from the file */void xbNtx::ProcessDeleteList( void ){ if( DeleteChain ) { ReleaseNodeMemory( DeleteChain ); DeleteChain = NULL; }}/***********************************************************************///! Short description./*!*/xbShort xbNtx::KeyWasChanged( void ){ CreateKey( 0, 0 ); /* use KeyBuf, RecBuf */ CreateKey( 1, 1 ); /* use KeyBuf2, RecBuf2 */ if( CompareKey( KeyBuf, KeyBuf2, HeadNode.KeyLen ) != 0 ) return 1; else return 0;}// /******************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -