📄 ntx.cpp
字号:
/*************************************************************************** ntx.cpp - description ------------------- begin : Thu Jan 17 2002 copyright : (C) 2002 by email : ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* $Id: ntx.cpp,v 1.6 2000/11/10 19:04:17 dbryson Exp $ Xbase project source code NTX (Clipper) indexing routines for X-Base Copyright (C) 1999 SynXis Corp., Bob Cotton email - bob@synxis.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Mail: Technology Associates, Inc. XBase Project 1455 Deming Way #11 Sparks, NV 89434 USA Email: xbase@techass.com See our website at: xdb.sourceforge.net V 1.0 10/10/97 - Initial release of software*/#ifdef __GNUG__ #pragma implementation "ntx.h"#endif#ifdef __WIN32__#include "xbconfigw32.h"#else#include "xbconfig.h"#endif#include "xbase.h"#ifdef XB_INDEX_NTX#ifdef HAVE_IO_H#include <io.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/stat.h>/* FIXME? Why <unistd.h> is there? Nothing bad happens if it isn't. -- willy */#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "xbexcept.h"/*! \file ntx.cpp*//***********************************************************************///! Short description./*!*/xbShort xbNtx::CloneNodeChain( void ){ xbNodeLink * TempNodeS; xbNodeLink * TempNodeT; xbNodeLink * TempNodeT2; xbUShort *sp; if( CloneChain ) ReleaseNodeMemory( CloneChain ); CloneChain = NULL; if( !NodeChain ) return XB_NO_ERROR; TempNodeS = NodeChain; TempNodeT2 = NULL; while( TempNodeS ) { if(( TempNodeT = GetNodeMemory()) == NULL )#ifdef HAVE_EXCEPTIONS throw xbOutOfMemoryException();#else return XB_NO_MEMORY;#endif sp = TempNodeT->offsets; memcpy( TempNodeT, TempNodeS, sizeof( struct xbNodeLink )); TempNodeT->offsets = sp; TempNodeT->NextNode = NULL; TempNodeT->PrevNode = TempNodeT2; if( !CloneChain ) { TempNodeT2 = TempNodeT; CloneChain = TempNodeT; } else { TempNodeT2->NextNode = TempNodeT; TempNodeT2 = TempNodeT2->NextNode; } TempNodeS = TempNodeS->NextNode; } return XB_NO_ERROR;}/***********************************************************************///! Short description./*!*/xbShort xbNtx::UncloneNodeChain( void ){ if( NodeChain ) ReleaseNodeMemory( NodeChain ); NodeChain = CloneChain; CloneChain = NULL; CurNode = NodeChain; while( CurNode->NextNode ) CurNode = CurNode->NextNode; return XB_NO_ERROR;}/***********************************************************************///! Short description./*!*//* This routine dumps the node chain to stdout */#ifdef XBASE_DEBUGvoid xbNtx::DumpNodeChain( void ){ xbNodeLink *n; cout << "\n*************************\n"; cout << "NodeLinkCtr = " << NodeLinkCtr; cout << "\nReused = " << ReusedNodeLinks << "\n"; n = NodeChain; while(n) { cout << "xbNodeLink Chain" << n->NodeNo << "\n"; n = n->NextNode; } n = FreeNodeChain; while(n) { cout << "FreeNodeLink Chain" << n->NodeNo << "\n"; n = n->NextNode; } n = DeleteChain; while(n) { cout << "DeleteLink Chain" << n->NodeNo << "\n"; n = n->NextNode; }}#endif/***********************************************************************///! Short description./*! \param n*//* This routine returns a chain of one or more index nodes back to the *//* free node chain */void xbNtx::ReleaseNodeMemory( xbNodeLink * n ){ xbNodeLink * temp; if( !FreeNodeChain ) FreeNodeChain = n; else /* put this list at the end */ { temp = FreeNodeChain; while( temp->NextNode ) temp = temp->NextNode; temp->NextNode = n; } return;}/***********************************************************************///! Short description./*!*//* This routine returns a node from the free chain if available, *//* otherwise it allocates new memory for the requested node */xbNodeLink * xbNtx::GetNodeMemory( void ){ xbNodeLink * temp; if( FreeNodeChain ) { temp = FreeNodeChain; temp->offsets = FreeNodeChain->offsets; FreeNodeChain = temp->NextNode; ReusedNodeLinks++; memset( temp->Leaf.KeyRecs, 0x00, XB_NTX_NODE_SIZE ); temp->Leaf.NoOfKeysThisNode = 0; temp->PrevNode = 0x00; temp->NextNode = 0x00; temp->CurKeyNo = 0L; temp->NodeNo = 0L; for (int i = 0; i < HeadNode.KeysPerNode + 1; i++) { temp->offsets[i] = 2 + ((HeadNode.KeysPerNode + 1) * 2) + (HeadNode.KeySize * i); } } else { temp = (xbNodeLink *) malloc( sizeof( xbNodeLink )); if(temp==NULL) return NULL; memset( temp, 0x00, sizeof( xbNodeLink )); temp->offsets = (xbUShort *)malloc( (HeadNode.KeysPerNode + 1) * sizeof(xbUShort)); if (temp->offsets==NULL) { free(temp); return NULL; }; NodeLinkCtr++; } return temp;}/***********************************************************************///! Short description./*!*/#ifdef XBASE_DEBUGvoid xbNtx::DumpHdrNode( void ){ cout << "\nSignature = " << HeadNode.Signature; cout << "\nVersion = " << HeadNode.Version; cout << "\nStartPahe = " << HeadNode.StartNode; cout << "\nUnusedOffset = " << HeadNode.UnusedOffset; cout << "\nKeySize = " << HeadNode.KeySize; cout << "\nKeyLen = " << HeadNode.KeyLen; cout << "\nDecimalCount = " << HeadNode.DecimalCount; cout << "\nKeysPerNode = " << HeadNode.KeysPerNode; cout << "\nHalfKeysPerPage = " << HeadNode.HalfKeysPerNode; cout << "\nKeyExpression = " << HeadNode.KeyExpression; cout << "\nUnique = " << HeadNode.Unique; cout << "\n";}#endif/***********************************************************************///! Short description./*! \param pdbf*/xbNtx::xbNtx( xbDbf * pdbf ) : xbIndex (pdbf){ memset( Node, 0x00, XB_NTX_NODE_SIZE ); memset( &HeadNode, 0x00, sizeof( NtxHeadNode )); NodeChain = NULL; CloneChain = NULL; FreeNodeChain = NULL; DeleteChain = NULL; CurNode = NULL; NodeLinkCtr = 0L; ReusedNodeLinks = 0L;}/***********************************************************************///! Short description./*!*/xbShortxbNtx::AllocKeyBufs(void){ KeyBuf = (char *) malloc( HeadNode.KeyLen + 1 ); if(KeyBuf==NULL) { return XB_NO_MEMORY; }; KeyBuf2 = (char *) malloc( HeadNode.KeyLen + 1); if(KeyBuf2==NULL) { free(KeyBuf); return XB_NO_MEMORY; }; memset( KeyBuf, 0x00, HeadNode.KeyLen + 1 ); memset( KeyBuf2, 0x00, HeadNode.KeyLen + 1 ); return XB_NO_ERROR;}/***********************************************************************///! Short description./*! \param FileName*/xbShort xbNtx::OpenIndex( const char * FileName ){ int NameLen, rc; NameLen = strlen( FileName ) + 1; if (( rc = dbf->NameSuffixMissing( 4, FileName )) > 0) NameLen += 4; IndexName = FileName; if( rc == 1 ) IndexName += ".ntx"; else if ( rc == 2 ) IndexName += ".NTX"; /* open the file */ if(( indexfp = fopen( IndexName, "r+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_RDLCK)) != 0) return rc;#endif IndexStatus = 1; if(( rc = GetHeadNode()) != 0) { #ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif fclose( indexfp ); return rc; } /* parse the expression */ if(( rc = dbf->xbase->BuildExpressionTree( HeadNode.KeyExpression, strlen( HeadNode.KeyExpression ), dbf )) != XB_NO_ERROR ) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif fclose( indexfp ); return rc; } ExpressionTree = dbf->xbase->GetTree(); dbf->xbase->SetTreeToNull(); rc=AllocKeyBufs(); if(rc) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif fclose(indexfp); return rc; }#ifdef XBASE_DEBUG// CheckIndexIntegrity( 0 );#endif#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return dbf->AddIndexToIxList( index, IndexName ); }/***********************************************************************///! Short description./*!*/xbShort xbNtx::CloseIndex( void ){ if( KeyBuf ) { free ( KeyBuf ); KeyBuf = NULL; } if( KeyBuf2 ) { free ( KeyBuf2 ); KeyBuf2 = NULL; } dbf->RemoveIndexFromIxList( index ); fclose( indexfp ); IndexStatus = 0; return 0;}/***********************************************************************///! Short description./*!*/xbShort xbNtx::GetHeadNode( void ){ char *p; if( !IndexStatus ) xb_error(XB_NOT_OPEN); if( fseek( indexfp, 0, SEEK_SET )) xb_io_error(XB_SEEK_ERROR, IndexName); if(( fread( Node, XB_NTX_NODE_SIZE, 1, indexfp )) != 1 ) xb_io_error(XB_READ_ERROR, IndexName); /* load the head node structure */ p = Node; HeadNode.Signature = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.Version = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.StartNode = dbf->xbase->GetULong( p ); p += sizeof(xbULong); HeadNode.UnusedOffset = dbf->xbase->GetULong( p ); p += sizeof(xbULong); HeadNode.KeySize = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.KeyLen = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.DecimalCount = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.KeysPerNode = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); HeadNode.HalfKeysPerNode = dbf->xbase->GetShort( p ); p += sizeof(xbUShort); strncpy(HeadNode.KeyExpression, p, 256); p+= 256; HeadNode.Unique = *p++; p = HeadNode.KeyExpression; while (*p) { *p = toupper(*p); p++; } return 0;}/***********************************************************************///! Short description./*! \param NodeNo \param SetNodeChain*//* This routine reads a leaf node from disk *//* *//* If SetNodeChain 2, then the node is not appended to the node chain *//* but the CurNode pointer points to the node read *//* If SetNodeChain 1, then the node is appended to the node chain *//* If SetNodeChain 0, then record is only read to Node memory */xbShort xbNtx::GetLeafNode( xbLong NodeNo, xbShort SetNodeChain ){ xbNodeLink *n; char *p; if( !IndexStatus ) xb_error(XB_NOT_OPEN); if( fseek( indexfp, NodeNo, SEEK_SET )) xb_io_error(XB_SEEK_ERROR, IndexName); if(( fread( Node, XB_NTX_NODE_SIZE, 1, indexfp )) != 1 ) xb_io_error(XB_READ_ERROR, IndexName); if( !SetNodeChain ) return 0; if(( n = GetNodeMemory()) == NULL ) xb_memory_error; n->NodeNo = NodeNo; n->CurKeyNo = 0L; n->NextNode = NULL; // The offsets at the head of each leaf are not necessarly in order. p = Node + 2; for (int i = 0; i < HeadNode.KeysPerNode + 1; i++) { n->offsets[i] = dbf->xbase->GetShort( p ); p += 2; } // Do the edian translation correctly n->Leaf.NoOfKeysThisNode = dbf->xbase->GetShort( Node ); memcpy( n->Leaf.KeyRecs, Node, XB_NTX_NODE_SIZE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -