📄 ndx.cpp
字号:
memcpy( FieldName, TempNode->NodeText, TempNode->Len ); Type = dbf->GetFieldType( dbf->GetFieldNo( FieldName )); if( Type == 'N' || Type == 'F' ) return -8; } if(( rc = dbf->xbase->ProcessExpression( ExpressionTree )) != XB_NO_ERROR ) return 0; // dbf->xbase->DumpExpressionTree(ExpressionTree); TempNode = (xbExpNode *) dbf->xbase->Pop(); if( !TempNode ) return 0; rc = TempNode->DataLen; if( !TempNode->InTree ) delete TempNode;// dbf->xbase->FreeExpNode( TempNode );//printf("CalcKeyLen returning %d\n", rc); return rc;}/***********************************************************************///! Short description/*! \param IxName \param Exp \param Unique \param Overlay*/xbShort xbNdx::CreateIndex(const char * IxName, const char * Exp, xbShort Unique, xbShort Overlay ){ xbShort i, NameLen, KeyLen, rc; IndexStatus = XB_CLOSED; if( strlen( Exp ) > 488 ) xb_error(XB_INVALID_KEY_EXPRESSION); if( dbf->GetDbfStatus() == 0 ) xb_error(XB_NOT_OPEN); /* Get the index file name and store it in the class */ NameLen = strlen( IxName ) + 1; if(( rc = dbf->NameSuffixMissing( 2, IxName )) > 0 ) NameLen +=4; IndexName = IxName; if( rc == 1 ) IndexName += ".ndx"; else if( rc == 2 ) IndexName += ".NDX"; /* check if the file already exists */ if (((indexfp = fopen( IndexName, "r" )) != NULL ) && !Overlay ) { fclose( indexfp ); xb_io_error(XB_FILE_EXISTS, IndexName); } if (indexfp) fclose(indexfp); if(( indexfp = fopen( IndexName, "w+b" )) == NULL ) xb_open_error(IndexName);#ifdef XB_LOCKING_ON /* ** Must turn off buffering when multiple programs may be accessing ** index files. */ setbuf( indexfp, NULL );#endif #ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) if((rc = LockIndex(F_SETLKW, F_WRLCK)) != 0) return rc;#endif /* parse the expression */ if(( rc = dbf->xbase->BuildExpressionTree( Exp, strlen( Exp ), dbf )) != XB_NO_ERROR ) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return rc; } ExpressionTree = dbf->xbase->GetTree(); dbf->xbase->SetTreeToNull(); /* build the header record */ memset( &HeadNode, 0x00, sizeof( xbNdxHeadNode )); HeadNode.StartNode = 1L; HeadNode.TotalNodes = 2L; HeadNode.NoOfKeys = 1L; KeyLen = CalcKeyLen(); if( KeyLen == 0 || KeyLen > 100 ) /* 100 byte key length limit */ xb_error(XB_INVALID_KEY) else if( KeyLen == -8 ) { HeadNode.KeyType = 1; /* numeric key */ HeadNode.KeyLen = 8; } else { HeadNode.KeyType = 0; /* character key */ HeadNode.KeyLen = KeyLen; }// HeadNode.KeysPerNode = (xbUShort) ( XB_NDX_NODE_SIZE - (2*sizeof( xbLong ))) /// (HeadNode.KeyLen + 8 );// HeadNode.KeySize = HeadNode.KeyLen + 8;// while(( HeadNode.KeySize % 4 ) != 0 ) HeadNode.KeySize++; /* multiple of 4*//* above code replaced with following by Paul Koufalis pkoufalis@cogicom.com */// while(( HeadNode.KeyLen % 4 ) != 0 ) HeadNode.KeyLen++; /* multiple of 4*/// HeadNode.KeySize = HeadNode.KeyLen + 8;/* above two lines commented out by gary 4/14/99 and replaced w/ following For compatibilyt with other Xbase tools KeyLen is the length of the key data KeySize = KeyLen+8, rounded up until divisible by 4*/ HeadNode.KeySize = HeadNode.KeyLen + 8; while(( HeadNode.KeySize % 4 ) != 0 ) HeadNode.KeySize++; /* multiple of 4*/ HeadNode.KeysPerNode = (xbUShort) (XB_NDX_NODE_SIZE - (2*sizeof( xbLong ))) / HeadNode.KeySize; HeadNode.Unique = Unique; strncpy( HeadNode.KeyExpression, Exp, 488 ); KeyBuf = (char *) malloc( HeadNode.KeyLen + 1 ); KeyBuf2 = (char *) malloc( HeadNode.KeyLen + 1 ); memset( KeyBuf, 0x00, HeadNode.KeyLen + 1 ); memset( KeyBuf2, 0x00, HeadNode.KeyLen + 1 ); if(( rc = PutHeadNode( &HeadNode, indexfp, 0 )) != 0 ) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return rc; } /* write node #1 all 0x00 */ for( i = 0; i < XB_NDX_NODE_SIZE; i++ ) { if ((fwrite("\x00", 1, 1, indexfp)) != 1) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif fclose( indexfp ); xb_io_error(XB_WRITE_ERROR, IndexName); } } IndexStatus = XB_OPEN;#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return dbf->AddIndexToIxList( index, IndexName ); }/***********************************************************************///! Short description/*! \param RecNo \param n \param NodeNo*/xbShort xbNdx::PutLeftNodeNo( xbShort RecNo, xbNdxNodeLink *n, xbLong NodeNo ){ /* This routine sets n node's leftnode number */ xbNdxLeafNode *temp; char *p; if( !n ) xb_error(XB_INVALID_NODELINK); temp = &n->Leaf; if( RecNo < 0 || RecNo > HeadNode.KeysPerNode) xb_error(XB_INVALID_KEY); p = temp->KeyRecs; p+= RecNo * ( 8 + HeadNode.KeyLen ); dbf->xbase->PutLong( p, NodeNo ); return XB_NO_ERROR;}/***********************************************************************///! Short description/*! \param RecNo \param n \param DbfNo*/xbShort xbNdx::PutDbfNo( xbShort RecNo, xbNdxNodeLink *n, xbLong DbfNo ){ /* This routine sets n node's dbf number */ xbNdxLeafNode *temp; char *p; if( !n ) xb_error(XB_INVALID_NODELINK); temp = &n->Leaf; if( RecNo < 0 || RecNo > (HeadNode.KeysPerNode-1)) xb_error(XB_INVALID_KEY); p = temp->KeyRecs + 4; p+= RecNo * ( 8 + HeadNode.KeyLen ); dbf->xbase->PutLong( p, DbfNo ); return XB_NO_ERROR;}/************************************************************************///! Short description/*! \param l \param n*/xbShort xbNdx::PutLeafNode( xbLong l, xbNdxNodeLink *n ){ if ((fseek(indexfp, l * XB_NDX_NODE_SIZE , SEEK_SET)) != 0) { fclose( indexfp ); xb_io_error(XB_SEEK_ERROR, IndexName); } dbf->xbase->PutLong( Node, n->Leaf.NoOfKeysThisNode ); if(( fwrite( Node, 4, 1, indexfp )) != 1 ) { fclose( indexfp ); xb_io_error(XB_WRITE_ERROR, IndexName); } if(( fwrite( &n->Leaf.KeyRecs, XB_NDX_NODE_SIZE-4, 1, indexfp )) != 1 ) { fclose( indexfp ); xb_io_error(XB_WRITE_ERROR, IndexName); } return 0; }/************************************************************************///! Short description/*! \param Head \param f \param UpdateOnly*/xbShort xbNdx::PutHeadNode( xbNdxHeadNode * Head, FILE * f, xbShort UpdateOnly ){ char buf[4]; if(( fseek( f, 0L, SEEK_SET )) != 0 ) { fclose( f ); xb_io_error(XB_SEEK_ERROR, IndexName); } memset( buf, 0x00, 4 ); dbf->xbase->PutLong( buf, Head->StartNode ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 4 ); dbf->xbase->PutLong( buf, Head->TotalNodes ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 4 ); dbf->xbase->PutLong( buf, Head->NoOfKeys ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } if( UpdateOnly ) return XB_NO_ERROR; memset( buf, 0x00, 2 ); dbf->xbase->PutLong( buf, Head->KeyLen ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 2 ); dbf->xbase->PutLong( buf, Head->KeysPerNode ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 2 ); dbf->xbase->PutLong( buf, Head->KeyType ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 4 ); dbf->xbase->PutLong( buf, Head->KeySize ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); }// if(( fwrite( &Head->Unknown2, 490, 1, f )) != 1 ) if(( fwrite( &Head->Unknown2, XB_NDX_NODE_SIZE - 22, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } return 0; }/************************************************************************///! Short description/*! \param RecNo \param n*/xbShort xbNdx::PutKeyData( xbShort RecNo, xbNdxNodeLink *n ){ /* This routine copies the KeyBuf data into xbNdxNodeLink n */ xbNdxLeafNode *temp; char *p; xbShort i; if( !n ) xb_error(XB_INVALID_NODELINK); temp = &n->Leaf; if( RecNo < 0 || RecNo > (HeadNode.KeysPerNode-1)) xb_error(XB_INVALID_KEY); p = temp->KeyRecs + 8; p+= RecNo * ( 8 + HeadNode.KeyLen ); for( i = 0; i < HeadNode.KeyLen; i++ ) { *p = KeyBuf[i]; p++; } return XB_NO_ERROR;}/************************************************************************///! Short description/*! \param n \param pos \param d \param l \param w*/xbShort xbNdx::PutKeyInNode( xbNdxNodeLink * n, xbShort pos, xbLong d, xbLong l, xbShort w ){ xbShort i; /* check the node */ if (!n) xb_error(XB_INVALID_NODELINK); if(pos < 0 || pos > HeadNode.KeysPerNode) xb_error(XB_INVALID_RECORD); if(n->Leaf.NoOfKeysThisNode >= HeadNode.KeysPerNode) xb_error(XB_NODE_FULL); /* if key movement, save the original key */ if( pos < n->Leaf.NoOfKeysThisNode ) memcpy( KeyBuf2, KeyBuf, HeadNode.KeyLen + 1); /* if interior node, handle the right most left node no */ if( GetLeftNodeNo( 0, n )) PutLeftNodeNo( n->Leaf.NoOfKeysThisNode+1, n, GetLeftNodeNo( n->Leaf.NoOfKeysThisNode, n )); for( i = n->Leaf.NoOfKeysThisNode; i > pos; i-- ) { memcpy( KeyBuf, GetKeyData(i-1,n), HeadNode.KeyLen ); PutKeyData( i, n ); PutDbfNo( i, n, GetDbfNo(i-1,n)); PutLeftNodeNo(i, n, GetLeftNodeNo(i-1,n)); } /* put new key in node */ if( pos < n->Leaf.NoOfKeysThisNode ) memcpy( KeyBuf, KeyBuf2, HeadNode.KeyLen + 1); PutKeyData( pos, n ); PutDbfNo( pos, n, d ); PutLeftNodeNo( pos, n, l ); n->Leaf.NoOfKeysThisNode++; if( w ) return PutLeafNode( n->NodeNo, n ); else return 0;}/************************************************************************///! Short description/*! \param n1 \param n2 \param pos \param d*/xbShort xbNdx::SplitLeafNode( xbNdxNodeLink *n1, xbNdxNodeLink *n2, xbShort pos, xbLong d ){ xbShort i,j,rc; if( !n1 || !n2 ) xb_error(XB_INVALID_NODELINK); if( pos < 0 || pos > HeadNode.KeysPerNode ) xb_error(XB_INVALID_NODELINK); if( pos < HeadNode.KeysPerNode ) /* if it belongs in node */ { /* save the original key */ memcpy( KeyBuf2, KeyBuf, HeadNode.KeyLen + 1); PutKeyData( HeadNode.KeysPerNode, n2 ); for( j = 0,i = pos; i < n1->Leaf.NoOfKeysThisNode; j++,i++ ) { memcpy( KeyBuf, GetKeyData( i, n1 ), HeadNode.KeyLen ); PutKeyData ( j, n2 ); PutDbfNo ( j, n2, GetDbfNo ( i, n1 )); n2->Leaf.NoOfKeysThisNode++; } /* restore original key */ memcpy( KeyBuf, KeyBuf2, HeadNode.KeyLen + 1); /* update original leaf */ PutKeyData( pos, n1 ); PutDbfNo ( pos, n1, d ); n1->Leaf.NoOfKeysThisNode = pos+1; } else /* put the key in a new node because it doesn't fit in the CurNode*/ { PutKeyData ( 0, n2 ); PutDbfNo ( 0, n2, d ); n2->Leaf.NoOfKeysThisNode++; } 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 t*/xbShort xbNdx::SplitINode( xbNdxNodeLink *n1, xbNdxNodeLink *n2, xbLong t ) /* parent, tempnode, tempnodeno */{ xbShort i,j,rc; xbNdxNodeLink * SaveNodeChain; xbNdxNodeLink * SaveCurNode; /* if not at the end of the node shift everthing to the right */ if( n1->CurKeyNo+1 < HeadNode.KeysPerNode ) /* this clause appears to work */ { if( CurNode->NodeNo == HeadNode.StartNode ) cout << "\nHead node "; for( j = 0,i = n1->CurKeyNo+1; i < n1->Leaf.NoOfKeysThisNode; i++,j++ ) { memcpy( KeyBuf, GetKeyData( i, n1 ), HeadNode.KeyLen ); PutKeyData( j, n2 ); PutLeftNodeNo( j, n2, GetLeftNodeNo( i, n1 )); } PutLeftNodeNo( j, n2, GetLeftNodeNo( i, n1 )); n2->Leaf.NoOfKeysThisNode = n1->Leaf.NoOfKeysThisNode - n1->CurKeyNo - 1; n1->Leaf.NoOfKeysThisNode = n1->Leaf.NoOfKeysThisNode - n2->Leaf.NoOfKeysThisNode; /* attach the new leaf to the original parent */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -