/tags/build45/harbour/source/rdd/dbfcdx/dbfcdx1.c
C | 2260 lines | 1798 code | 203 blank | 259 comment | 405 complexity | 2912bbf7e57df90e6526cd4746abad3c MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, CC-BY-SA-3.0, LGPL-3.0, GPL-2.0, LGPL-2.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /*
- * $Id: dbfcdx1.c 6462 2005-01-30 21:11:50Z druzus $
- */
- /*
- * xHarbour Project source code:
- * DBFCDX RDD (ver.2)
- *
- * Copyright 1999-2002 Bruno Cantero <bruno@issnet.net>
- * Copyright 2000-2003 Horacio Roldan <harbour_ar@yahoo.com.ar> (portions)
- * Copyright 2003 Przemyslaw Czerpak <druzus@priv.onet.pl> - all code except
- * hb_cdxTagDoIndex and related hb_cdxSort* rewritten.
- * Copyright 2004 Przemyslaw Czerpak <druzus@priv.onet.pl> - rest of code rewritten
- * www - http://www.xharbour.org
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
- *
- * As a special exception, the Harbour Project gives permission for
- * additional uses of the text contained in its release of Harbour.
- *
- * The exception is that, if you link the Harbour libraries with other
- * files to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the Harbour library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the Harbour
- * Project under the name Harbour. If you copy code from other
- * Harbour Project or Free Software Foundation releases into a copy of
- * Harbour, as the General Public License permits, the exception does
- * not apply to the code that you add in this way. To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
- *
- * If you write modifications of your own for Harbour, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
- *
- */
- #define HB_CDX_CLIP_AUTOPEN
- #define HB_CDX_PACKTRAIL
- #define HB_CDX_NEW_SORT
- #define HB_CDX_DBGCODE
- /*
- #define HB_CDX_DBGCODE_EXT
- #define HB_CDX_DSPDBG_INFO
- #define HB_CDP_SUPPORT_OFF
- #define HB_CDX_DBGTIME
- #define HB_CDX_DBGUPDT
- */
- #include "hbapi.h"
- #include "hbinit.h"
- #include "hbapierr.h"
- #include "hbapilng.h"
- #include "hbvm.h"
- #include "hbset.h"
- #include "hbrddcdx.h"
- #ifdef __XHARBOUR__
- #include "regex.h"
- #endif
- #define __PRG_SOURCE__ __FILE__
- #ifdef HB_PCODE_VER
- #undef HB_PRG_PCODE_VER
- #define HB_PRG_PCODE_VER HB_PCODE_VER
- #endif
- #ifndef HB_CDP_SUPPORT_OFF
- /* for nation sorting support */
- #include "hbapicdp.h"
- #define hb_cdpcharcmp( c1, c2, cdpage ) \
- ( ( cdpage && cdpage->lSort ) ? \
- hb_cdpchrcmp( c1, c2, cdpage ) : \
- ( (BYTE)(c1) - (BYTE)(c2) ) )
- /*
- #define hb_cdpcharcmp( c1, c2, cdpage ) ( (BYTE)(c1) - (BYTE)(c2) )
- */
- #endif
- /*
- * Tag->fRePos = TURE means that rootPage->...->childLeafPage path is
- * bad and has to be reloaded
- * CurKey->rec == 0 means that there is no correct CurKey
- */
- /* create a new Tag (make index) */
- static void hb_cdxTagDoIndex( LPCDXTAG pTag );
- /* Close Tag */
- static void hb_cdxTagClose( LPCDXTAG pTag );
- /* free Tag pages from cache */
- static void hb_cdxTagPoolFree( LPCDXTAG pTag, int nPagesLeft );
- /* Store tag header to index files */
- static void hb_cdxTagHeaderStore( LPCDXTAG pTag );
- /* write all changed pages in tag cache */
- static void hb_cdxTagPoolFlush( LPCDXTAG pTag );
- /* Discard all pages in cache (TagClose and TagPoolFree for all Tags) */
- static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex );
- /* write all changed pages in cache (pagePool and Tag Header) */
- static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex );
- /* free cached pages of index file */
- static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft );
- /* split Root Page */
- static int hb_cdxPageRootSplit( LPCDXPAGE pPage );
- /* free create index structur */
- static void hb_cdxSortFree( LPCDXSORTINFO pSort );
- static RDDFUNCS cdxSuper;
- static RDDFUNCS cdxTable =
- {
- /* Movement and positioning methods */
- ( DBENTRYP_BP ) hb_cdxBof,
- ( DBENTRYP_BP ) hb_cdxEof,
- ( DBENTRYP_BP ) hb_cdxFound,
- ( DBENTRYP_V ) hb_cdxGoBottom,
- ( DBENTRYP_UL ) hb_cdxGoTo,
- ( DBENTRYP_I ) hb_cdxGoToId,
- ( DBENTRYP_V ) hb_cdxGoTop,
- ( DBENTRYP_BIB ) hb_cdxSeek,
- ( DBENTRYP_L ) hb_cdxSkip,
- ( DBENTRYP_L ) hb_cdxSkipFilter,
- ( DBENTRYP_L ) hb_cdxSkipRaw,
- /* Data management */
- ( DBENTRYP_VF ) hb_cdxAddField,
- ( DBENTRYP_B ) hb_cdxAppend,
- ( DBENTRYP_I ) hb_cdxCreateFields,
- ( DBENTRYP_V ) hb_cdxDeleteRec,
- ( DBENTRYP_BP ) hb_cdxDeleted,
- ( DBENTRYP_SP ) hb_cdxFieldCount,
- ( DBENTRYP_VF ) hb_cdxFieldDisplay,
- ( DBENTRYP_SSI ) hb_cdxFieldInfo,
- ( DBENTRYP_SVP ) hb_cdxFieldName,
- ( DBENTRYP_V ) hb_cdxFlush,
- ( DBENTRYP_PP ) hb_cdxGetRec,
- ( DBENTRYP_SI ) hb_cdxGetValue,
- ( DBENTRYP_SVL ) hb_cdxGetVarLen,
- ( DBENTRYP_V ) hb_cdxGoCold,
- ( DBENTRYP_V ) hb_cdxGoHot,
- ( DBENTRYP_P ) hb_cdxPutRec,
- ( DBENTRYP_SI ) hb_cdxPutValue,
- ( DBENTRYP_V ) hb_cdxRecall,
- ( DBENTRYP_ULP ) hb_cdxRecCount,
- ( DBENTRYP_ISI ) hb_cdxRecInfo,
- ( DBENTRYP_I ) hb_cdxRecNo,
- ( DBENTRYP_S ) hb_cdxSetFieldExtent,
- /* WorkArea/Database management */
- ( DBENTRYP_P ) hb_cdxAlias,
- ( DBENTRYP_V ) hb_cdxClose,
- ( DBENTRYP_VP ) hb_cdxCreate,
- ( DBENTRYP_SI ) hb_cdxInfo,
- ( DBENTRYP_V ) hb_cdxNewArea,
- ( DBENTRYP_VP ) hb_cdxOpen,
- ( DBENTRYP_V ) hb_cdxRelease,
- ( DBENTRYP_SP ) hb_cdxStructSize,
- ( DBENTRYP_P ) hb_cdxSysName,
- ( DBENTRYP_VEI ) hb_cdxEval,
- ( DBENTRYP_V ) hb_cdxPack,
- ( DBENTRYP_LSP ) hb_cdxPackRec,
- ( DBENTRYP_VS ) hb_cdxSort,
- ( DBENTRYP_VT ) hb_cdxTrans,
- ( DBENTRYP_VT ) hb_cdxTransRec,
- ( DBENTRYP_V ) hb_cdxZap,
- /* Relational Methods */
- ( DBENTRYP_VR ) hb_cdxChildEnd,
- ( DBENTRYP_VR ) hb_cdxChildStart,
- ( DBENTRYP_VR ) hb_cdxChildSync,
- ( DBENTRYP_V ) hb_cdxSyncChildren,
- ( DBENTRYP_V ) hb_cdxClearRel,
- ( DBENTRYP_V ) hb_cdxForceRel,
- ( DBENTRYP_SVP ) hb_cdxRelArea,
- ( DBENTRYP_VR ) hb_cdxRelEval,
- ( DBENTRYP_SVP ) hb_cdxRelText,
- ( DBENTRYP_VR ) hb_cdxSetRel,
- /* Order Management */
- ( DBENTRYP_OI ) hb_cdxOrderListAdd,
- ( DBENTRYP_V ) hb_cdxOrderListClear,
- ( DBENTRYP_VP ) hb_cdxOrderListDelete,
- ( DBENTRYP_OI ) hb_cdxOrderListFocus,
- ( DBENTRYP_V ) hb_cdxOrderListRebuild,
- ( DBENTRYP_VOI ) hb_cdxOrderCondition,
- ( DBENTRYP_VOC ) hb_cdxOrderCreate,
- ( DBENTRYP_OI ) hb_cdxOrderDestroy,
- ( DBENTRYP_OII ) hb_cdxOrderInfo,
- /* Filters and Scope Settings */
- ( DBENTRYP_V ) hb_cdxClearFilter,
- ( DBENTRYP_V ) hb_cdxClearLocate,
- ( DBENTRYP_V ) hb_cdxClearScope,
- ( DBENTRYP_VPLP ) hb_cdxCountScope,
- ( DBENTRYP_I ) hb_cdxFilterText,
- ( DBENTRYP_SI ) hb_cdxScopeInfo,
- ( DBENTRYP_VFI ) hb_cdxSetFilter,
- ( DBENTRYP_VLO ) hb_cdxSetLocate,
- ( DBENTRYP_VOS ) hb_cdxSetScope,
- ( DBENTRYP_VPL ) hb_cdxSkipScope,
- /* Miscellaneous */
- ( DBENTRYP_P ) hb_cdxCompile,
- ( DBENTRYP_I ) hb_cdxError,
- ( DBENTRYP_I ) hb_cdxEvalBlock,
- /* Network operations */
- ( DBENTRYP_VSP ) hb_cdxRawLock,
- ( DBENTRYP_VL ) hb_cdxLock,
- ( DBENTRYP_UL ) hb_cdxUnLock,
- /* Memofile functions */
- ( DBENTRYP_V ) hb_cdxCloseMemFile,
- ( DBENTRYP_VP ) hb_cdxCreateMemFile,
- ( DBENTRYP_SVPB ) hb_cdxGetValueFile,
- ( DBENTRYP_VP ) hb_cdxOpenMemFile,
- ( DBENTRYP_SVP ) hb_cdxPutValueFile,
- /* Database file header handling */
- ( DBENTRYP_V ) hb_cdxReadDBHeader,
- ( DBENTRYP_V ) hb_cdxWriteDBHeader,
- /* non WorkArea functions */
- ( DBENTRYP_I0 ) hb_cdxExit,
- ( DBENTRYP_I1 ) hb_cdxDrop,
- ( DBENTRYP_I2 ) hb_cdxExists,
- /* Special and reserved methods */
- ( DBENTRYP_SVP ) hb_cdxWhoCares
- };
- HB_FUNC( _DBFCDX ) {;}
- HB_FUNC( DBFCDX_GETFUNCTABLE )
- {
- RDDFUNCS * pTable;
- USHORT * uiCount;
- uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) );
- pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) );
- HB_TRACE(HB_TR_DEBUG, ("DBFCDX_GETFUNCTABLE(%i, %p)", uiCount, pTable));
- if ( pTable )
- {
- SHORT iRet;
- if ( uiCount )
- * uiCount = RDDFUNCSCOUNT;
- iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFFPT" );
- if ( iRet == FAILURE )
- iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFDBT" );
- if ( iRet == FAILURE )
- iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" );
- hb_retni( iRet );
- }
- else
- hb_retni( FAILURE );
- }
- HB_INIT_SYMBOLS_BEGIN( dbfcdx1__InitSymbols )
- { "_DBFCDX", HB_FS_PUBLIC, {HB_FUNCNAME( _DBFCDX )}, NULL },
- { "DBFCDX_GETFUNCTABLE", HB_FS_PUBLIC, {HB_FUNCNAME( DBFCDX_GETFUNCTABLE )}, NULL }
- HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols )
- #if defined(HB_PRAGMA_STARTUP)
- #pragma startup dbfcdx1__InitSymbols
- #elif defined(_MSC_VER)
- #if _MSC_VER >= 1010
- #pragma data_seg( ".CRT$XIY" )
- #pragma comment( linker, "/Merge:.CRT=.data" )
- #else
- #pragma data_seg( "XIY" )
- #endif
- static HB_$INITSYM hb_vm_auto_dbfcdx1__InitSymbols = dbfcdx1__InitSymbols;
- #pragma data_seg()
- #endif
- #ifdef HB_CDX_DSPDBG_INFO
- static void hb_cdxDspTags( LPCDXINDEX pIndex )
- {
- LPCDXTAG pTag = NULL;
- printf( "\r\n*TAGS*" );
- while ( pIndex )
- {
- printf( "\r\nBAG: [%s] ->", pIndex->szFileName );
- pTag = pIndex->TagList;
- while ( pTag )
- {
- printf( " {%s}", pTag->szName );
- pTag = pTag->pNext;
- }
- pIndex = pIndex->pNext;
- }
- printf( "\r\n*END*\r\n" ); fflush( stdout );
- }
- #endif
- #ifdef HB_CDX_DBGTIME
- #include <sys/time.h>
- typedef LONGLONG CDXDBGTIME;
- static CDXDBGTIME cdxTimeIntBld = 0;
- static CDXDBGTIME cdxTimeExtBld = 0;
- static CDXDBGTIME cdxTimeIntBlc = 0;
- static CDXDBGTIME cdxTimeExtBlc = 0;
- static CDXDBGTIME cdxTimeGetKey = 0;
- static CDXDBGTIME cdxTimeFreeKey = 0;
- static CDXDBGTIME cdxTimeIdxBld = 0;
- static CDXDBGTIME hb_cdxGetTime()
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return ( (CDXDBGTIME) tv.tv_sec * 1000000 + (CDXDBGTIME) tv.tv_usec );
- }
- #endif
- #ifdef HB_CDX_DBGUPDT
- static ULONG cdxWriteNO = 0;
- static ULONG cdxReadNO = 0;
- static SHORT cdxStackSize = 0;
- static SHORT cdxTmpStackSize = 0;
- #endif
- /*
- * internal DBFCDX function
- */
- static void hb_cdxErrInternal( char * szMsg )
- {
- hb_errInternal( 9201, szMsg ? szMsg : "hb_cdxErrInternal: data integrity error.", "", "" );
- }
- static ERRCODE hb_cdxErrorRT( CDXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char * filename, USHORT uiOsCode, USHORT uiFlags )
- {
- PHB_ITEM pError;
- ERRCODE iRet;
- pError = hb_errNew();
- hb_errPutGenCode( pError, uiGenCode );
- hb_errPutSubCode( pError, uiSubCode );
- hb_errPutOsCode( pError, uiOsCode );
- hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) );
- if ( filename )
- hb_errPutFileName( pError, filename );
- if ( uiFlags )
- hb_errPutFlags( pError, uiFlags );
- iRet = SELF_ERROR( ( AREAP ) pArea, pError );
- hb_itemRelease( pError );
- return iRet;
- }
- /*
- * create index sort table
- */
- static void hb_cdxMakeSortTab( CDXAREAP pArea )
- {
- #ifndef HB_CDP_SUPPORT_OFF
- if ( pArea->cdPage && pArea->cdPage->lSort && !pArea->bCdxSortTab )
- {
- int i, j, l;
- BYTE * pbSort;
- BYTE b;
- pArea->bCdxSortTab = ( BYTE * ) hb_xgrab( 256 );
- pbSort = ( BYTE * ) hb_xgrab( 256 );
- /* this table should be allready quite good sorted so this simple
- algorithms will be one of the most efficient one. */
- for ( i = 0; i <= 255; i++ )
- pbSort[i] = ( BYTE ) i;
- l = 255;
- do
- {
- j = l;
- for( i = 0; i < j; i++ )
- {
- if ( hb_cdpchrcmp( pbSort[i], pbSort[i+1], pArea->cdPage ) > 0 )
- {
- b = pbSort[i+1];
- pbSort[i+1] = pbSort[i];
- pbSort[i] = b;
- l = i;
- }
- }
- } while ( j != l );
- for ( i = 0; i <= 255; i++ )
- pArea->bCdxSortTab[pbSort[i]] = i;
- hb_xfree( pbSort );
- }
- #endif
- }
- /*
- * create new index key
- */
- static LPCDXKEY hb_cdxKeyNew( void )
- {
- LPCDXKEY pKey;
- pKey = ( LPCDXKEY ) hb_xgrab( sizeof( CDXKEY ) );
- memset( pKey, 0, sizeof( CDXKEY ) );
- return pKey;
- }
- /*
- * Free index key
- */
- static void hb_cdxKeyFree( LPCDXKEY pKey )
- {
- if ( pKey->val )
- hb_xfree( pKey->val );
- hb_xfree( pKey );
- }
- /*
- * copy index key, if dst is null create new dst key else destroy dst
- */
- static LPCDXKEY hb_cdxKeyCopy( LPCDXKEY pKeyDest, LPCDXKEY pKey )
- {
- if ( !pKeyDest )
- pKeyDest = hb_cdxKeyNew();
- else
- {
- pKeyDest->rec = 0;
- if ( pKeyDest->val && pKeyDest->len != pKey->len )
- {
- hb_xfree( pKeyDest->val );
- pKeyDest->val = NULL;
- pKeyDest->len = 0;
- }
- }
- if ( pKey )
- {
- if ( pKey->len )
- {
- if ( !pKeyDest->val )
- pKeyDest->val = (BYTE *) hb_xgrab( pKey->len + 1 );
- memcpy( pKeyDest->val, pKey->val, pKey->len );
- pKeyDest->len = pKey->len;
- pKeyDest->val[ pKeyDest->len ] = '\0';
- }
- pKeyDest->rec = pKey->rec;
- }
- return pKeyDest;
- }
- /*
- * store bytes value in inkdex key
- */
- static LPCDXKEY hb_cdxKeyPut( LPCDXKEY pKey, BYTE * pbVal, USHORT uiLen, ULONG ulRec )
- {
- if ( !pKey )
- pKey = hb_cdxKeyNew();
- else
- {
- if ( pKey->val && pKey->len != uiLen )
- {
- hb_xfree( pKey->val );
- pKey->val = NULL;
- pKey->len = 0;
- }
- }
- if ( pbVal && uiLen )
- {
- pKey->len = (BYTE) uiLen;
- if ( !pKey->val )
- pKey->val = ( BYTE * ) hb_xgrab( uiLen + 1 );
- memcpy( pKey->val, pbVal, uiLen );
- pKey->val[ uiLen ] = '\0';
- }
- pKey->rec = ulRec;
- return pKey;
- }
- /*
- * store string0 value in index key
- */
- static LPCDXKEY hb_cdxKeyPutC( LPCDXKEY pKey, char * szText, USHORT uiRealLen, ULONG ulRec )
- {
- USHORT uiLen;
- if ( !pKey )
- pKey = hb_cdxKeyNew();
- else
- {
- if ( pKey->val )
- {
- hb_xfree( pKey->val );
- pKey->val = NULL;
- pKey->len = 0;
- }
- }
- uiLen = (USHORT) ( szText ? strlen( szText ) : 0 );
- if ( uiLen > uiRealLen )
- uiLen = uiRealLen;
- pKey->len = ( BYTE ) uiRealLen;
- pKey->val = ( BYTE * ) hb_xgrab( uiRealLen + 1 );
- if ( uiLen )
- memcpy( pKey->val, szText, uiLen );
- if ( uiLen < uiRealLen )
- memset( &pKey->val[ uiLen ], ' ', uiRealLen - uiLen );
- pKey->val[ uiRealLen ] = '\0';
- pKey->rec = ulRec;
- return pKey;
- }
- /*
- * compare two values using Tag conditions (len & type)
- */
- static int hb_cdxValCompare( LPCDXTAG pTag, BYTE * val1, BYTE len1,
- BYTE * val2, BYTE len2, BOOL fExact )
- {
- int iLimit, iResult = 0;
- iLimit = (len1 > len2) ? len2 : len1;
- if ( pTag->uiType == 'C' )
- {
- #ifndef HB_CDP_SUPPORT_OFF
- if ( pTag->pIndex->pArea->bCdxSortTab )
- {
- BYTE * pSort = pTag->pIndex->pArea->bCdxSortTab;
- int iPos = 0;
- while ( iResult == 0 && iPos < iLimit )
- {
- iResult = pSort[ val1[ iPos ] ] - pSort[ val2[ iPos ] ];
- iPos++;
- }
- }
- else
- #endif
- if ( iLimit > 0 )
- iResult = memcmp( val1, val2, iLimit );
- if ( iResult == 0 )
- {
- if ( len1 > len2 )
- iResult = 1;
- else if ( len1 < len2 && fExact )
- iResult = -1;
- }
- }
- else
- {
- if ( iLimit == 0 || (iResult = memcmp( val1, val2, iLimit )) == 0 )
- {
- if ( len1 > len2 )
- iResult = 1;
- else if ( len1 < len2 )
- iResult = -1;
- }
- }
- return iResult;
- }
- /*
- * store Item in index key
- * TODO: uiType check and generate RT error if necessary
- */
- static LPCDXKEY hb_cdxKeyPutItem( LPCDXKEY pKey, PHB_ITEM pItem, ULONG ulRec, LPCDXTAG pTag, BOOL fTrans, BOOL fSize )
- {
- BYTE buf[CDX_MAXKEY], *ptr;
- BYTE len = 0;
- double d;
- ptr = &buf[0];
- switch ( hb_itemType( pItem ) )
- {
- case HB_IT_STRING:
- case HB_IT_STRING | HB_IT_MEMO:
- len = (BYTE) HB_MIN( pItem->item.asString.length, (ULONG) pTag->uiLen );
- if ( fSize && len < pTag->uiLen )
- {
- memcpy( ptr, pItem->item.asString.value, len );
- memset( ptr + len, pTag->uiType == 'C' ? ' ' : '\0', pTag->uiLen - len );
- len = ( BYTE ) pTag->uiLen;
- }
- else
- {
- ptr = ( BYTE * ) pItem->item.asString.value;
- }
- break;
- case HB_IT_INTEGER:
- case HB_IT_LONG:
- case HB_IT_DOUBLE:
- d = hb_itemGetND( pItem );
- HB_DBL2ORD( &d, ptr );
- len = 8;
- break;
- case HB_IT_DATE:
- d = (double) pItem->item.asDate.value;
- HB_DBL2ORD( &d, ptr );
- len = 8;
- break;
- case HB_IT_LOGICAL:
- *ptr = (BYTE) ( hb_itemGetL( pItem ) ? 'T' : 'F' );
- len = 1;
- break;
- default:
- ptr = NULL;
- #ifdef HB_CDX_DBGCODE
- /* TODO: RTerror */
- printf( "hb_cdxKeyPutItem( invalid item type: %i )", hb_itemType( pItem ) );
- #endif
- break;
- }
- pKey = hb_cdxKeyPut( pKey, ptr, len, ulRec );
- #ifndef HB_CDP_SUPPORT_OFF
- if ( fTrans && pTag->uiType == 'C' )
- hb_cdpnTranslate( ( char * ) pKey->val, hb_cdp_page, pTag->pIndex->pArea->cdPage, pKey->len );
- #endif
- return pKey;
- }
- /*
- * get Item from index key (TODO: add pTag param)
- */
- static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEY pKey, PHB_ITEM pItem, USHORT uiType )
- {
- double d;
- if ( pKey )
- {
- switch( uiType )
- {
- case 'C':
- pItem = hb_itemPutCL( pItem, ( char * ) pKey->val, pKey->len );
- break;
- case 'N':
- HB_ORD2DBL( pKey->val, &d );
- pItem = hb_itemPutND( pItem, d );
- break;
- case 'D':
- HB_ORD2DBL( pKey->val, &d );
- pItem = hb_itemPutDL( pItem, ( LONG ) d );
- break;
- case 'L':
- pItem = hb_itemPutL( pItem, pKey->val[0] == 'T' );
- break;
- default:
- pItem = hb_itemNew( pItem );
- #ifdef HB_CDX_DBGCODE
- printf( "hb_cdxKeyGetItem() ??? (%x)\n", uiType );
- #endif
- }
- }
- else if ( pItem )
- hb_itemClear( pItem );
- else
- pItem = hb_itemNew( NULL );
- return pItem;
- }
- /*
- * evaluate key expression and create new Key from the result
- */
- static LPCDXKEY hb_cdxKeyEval( LPCDXKEY pKey, LPCDXTAG pTag, BOOL fSetWA )
- {
- HB_MACRO_PTR pMacro;
- int iCurrArea = 0;
- CDXAREAP pArea = pTag->pIndex->pArea;
- #ifndef HB_CDP_SUPPORT_OFF
- /* TODO: this hack is not thread safe, hb_cdp_page has to be thread specific */
- PHB_CODEPAGE cdpTmp = hb_cdp_page;
- hb_cdp_page = pArea->cdPage;
- #endif
- if ( fSetWA && !pTag->nField )
- {
- iCurrArea = hb_rddGetCurrentWorkAreaNumber();
- if ( iCurrArea != pArea->uiArea )
- hb_rddSelectWorkAreaNumber( pArea->uiArea );
- else
- iCurrArea = 0;
- }
- if ( pTag->nField )
- {
- PHB_ITEM pItem = hb_itemNew( NULL );
- SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem );
- pKey = hb_cdxKeyPutItem( pKey, pItem, pArea->ulRecNo, pTag, FALSE, TRUE );
- hb_itemRelease( pItem );
- }
- else if ( HB_IS_BLOCK( pTag->pKeyItem ) )
- {
- pKey = hb_cdxKeyPutItem( pKey, hb_vmEvalBlock( pTag->pKeyItem ), pArea->ulRecNo, pTag, FALSE, TRUE );
- }
- else
- {
- pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
- hb_macroRun( pMacro );
- pKey = hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( -1 ), pArea->ulRecNo, pTag, FALSE, TRUE );
- hb_stackPop();
- }
- if ( iCurrArea )
- hb_rddSelectWorkAreaNumber( iCurrArea );
- #ifndef HB_CDP_SUPPORT_OFF
- hb_cdp_page = cdpTmp;
- #endif
- return pKey;
- }
- /*
- * evaluate macro expression
- * the result is on the stack hb_stackItemFromTop(-1)
- * TODO: eliminate it by implementing macro evaluation
- * in SELF_EVALBLOCK( AREAP pArea, PHB_ITEM pExpr)
- */
- static void hb_cdxMacroRun( CDXAREAP pArea, HB_MACRO_PTR pMacro )
- {
- int iCurrArea;
- iCurrArea = hb_rddGetCurrentWorkAreaNumber();
- if ( iCurrArea != pArea->uiArea )
- hb_rddSelectWorkAreaNumber( pArea->uiArea );
- else
- iCurrArea = 0;
- hb_macroRun( pMacro );
- if ( iCurrArea )
- hb_rddSelectWorkAreaNumber( iCurrArea );
- }
- /*
- * evaluate conditional expression and return the result
- */
- static BOOL hb_cdxEvalCond( CDXAREAP pArea, PHB_ITEM pCondItem, BOOL fSetWA )
- {
- HB_MACRO_PTR pMacro;
- int iCurrArea = 0;
- BOOL fRet;
- if ( !pCondItem )
- return TRUE;
- if ( fSetWA ) {
- iCurrArea = hb_rddGetCurrentWorkAreaNumber();
- if ( iCurrArea != pArea->uiArea )
- hb_rddSelectWorkAreaNumber( pArea->uiArea );
- else
- iCurrArea = 0;
- }
- if ( HB_IS_BLOCK( pCondItem ) )
- {
- fRet = hb_itemGetL( hb_vmEvalBlock( pCondItem ) );
- }
- else
- {
- pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pCondItem );
- hb_macroRun( pMacro );
- fRet = hb_itemGetL( hb_stackItemFromTop( -1 ) );
- hb_stackPop();
- }
- if ( iCurrArea )
- hb_rddSelectWorkAreaNumber( iCurrArea );
- return fRet;
- }
- /*
- * evaluate seek/skip block: {|key, rec| ... }
- */
- static BOOL hb_cdxEvalSeekCond( LPCDXTAG pTag, PHB_ITEM pCondItem )
- {
- BOOL fRet;
- HB_ITEM ItemKey;
- if ( ! HB_IS_BLOCK( pCondItem ) )
- return TRUE;
- ItemKey.type = HB_IT_NIL;
- hb_cdxKeyGetItem( pTag->CurKey, &ItemKey, pTag->uiType );
- hb_vmPushSymbol( &hb_symEval );
- hb_vmPush( pCondItem );
- hb_vmPush( &ItemKey );
- hb_vmPushLong( ( LONG ) pTag->CurKey->rec );
- hb_vmDo( 2 );
- fRet = hb_itemGetL( hb_stackReturnItem() );
- hb_itemClear( &ItemKey );
- return fRet;
- }
- /*
- * find field index for single field expressions
- */
- static USHORT hb_cdxFieldIndex( CDXAREAP pArea, char * cExpr )
- {
- char szKeyExpr[ CDX_MAXKEY + 1 ],
- szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ];
- int i, j, l, n = 0;
- if ( SELF_ALIAS( ( AREAP ) pArea, ( BYTE * ) szAlias ) == SUCCESS )
- l = strlen( szAlias );
- else
- l = 0;
- hb_strncpyUpperTrim( szKeyExpr, cExpr, CDX_MAXKEY );
- /*
- * strip the _FIELD-> and FIELD-> prefix, it could be nested so repeat
- * this process until all prefixes will be removed
- */
- do
- {
- j = n;
- if ( strncmp( &szKeyExpr[ n ], "FIELD", 5 ) == 0 )
- i = 5;
- else if ( strncmp( &szKeyExpr[ n ], "_FIELD", 6 ) == 0 )
- i = 6;
- else if ( l > 0 && strncmp( &szKeyExpr[ n ], szAlias, l ) == 0 )
- i = l;
- else
- i = 0;
- if ( i > 0 )
- {
- i = n + 5;
- while ( szKeyExpr[ i ] == ' ' )
- i++;
- if ( szKeyExpr[ i ] == '-' && szKeyExpr[ i + 1 ] == '>' )
- {
- n = i + 2;
- while ( szKeyExpr[ n ] == ' ' )
- n++;
- }
- }
- }
- while ( n != j );
- return hb_rddFieldIndex( ( AREAP ) pArea, &szKeyExpr[ n ] );
- }
- /*
- * check if Key is in top scope
- */
- static BOOL hb_cdxTopScope( LPCDXTAG pTag )
- {
- LPCDXKEY pKey;
- if ( pTag->UsrAscend )
- {
- pKey = pTag->topScopeKey;
- return !pKey || !pKey->len ||
- hb_cdxValCompare( pTag, pKey->val, pKey->len,
- pTag->CurKey->val, pTag->CurKey->len, FALSE ) <= 0;
- }
- else
- {
- pKey = pTag->bottomScopeKey;
- return !pKey || !pKey->len ||
- hb_cdxValCompare( pTag, pKey->val, pKey->len,
- pTag->CurKey->val, pTag->CurKey->len, FALSE ) >= 0;
- }
- }
- /*
- * check if Key is in bottom scope
- */
- static BOOL hb_cdxBottomScope( LPCDXTAG pTag )
- {
- LPCDXKEY pKey;
- if ( pTag->UsrAscend )
- {
- pKey = pTag->bottomScopeKey;
- return !pKey || !pKey->len ||
- hb_cdxValCompare( pTag, pKey->val, pKey->len,
- pTag->CurKey->val, pTag->CurKey->len, FALSE ) >= 0;
- }
- else
- {
- pKey = pTag->topScopeKey;
- return !pKey || !pKey->len ||
- hb_cdxValCompare( pTag, pKey->val, pKey->len,
- pTag->CurKey->val, pTag->CurKey->len, FALSE ) <= 0;
- }
- }
- /*
- * clear scopes
- */
- static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope )
- {
- PHB_ITEM *pScope;
- LPCDXKEY *pScopeKey;
- HB_TRACE(HB_TR_DEBUG, ("hb_cdxTagClearScope(%p, %hu)", pTag, nScope));
- if ( pTag->UsrAscend ? nScope == 0 : nScope != 0 )
- {
- pScope = &pTag->topScope;
- pScopeKey = &pTag->topScopeKey;
- }
- else
- {
- pScope = &pTag->bottomScope;
- pScopeKey = &pTag->bottomScopeKey;
- }
- if ( *pScope )
- {
- hb_itemRelease( *pScope );
- *pScope = NULL;
- }
- if ( *pScopeKey )
- {
- hb_cdxKeyFree( *pScopeKey );
- *pScopeKey = NULL;
- pTag->curKeyState &= ~( CDX_CURKEY_RAWCNT | CDX_CURKEY_LOGCNT );
- if ( nScope == 0 )
- pTag->curKeyState &= ~( CDX_CURKEY_RAWPOS | CDX_CURKEY_LOGPOS );
- }
- }
- #ifdef HB_CDX_DBGCODE_EXT
- /*
- * check internal integrity of page pool
- */
- static void hb_cdxTagPoolCheck( LPCDXTAG pTag )
- {
- LPCDXPAGE pPage, pPrevPage;
- pPage = pTag->pagePool;
- pPrevPage = NULL;
- while ( pPage )
- {
- if ( pPage->pPoolPrev != pPrevPage || pPage->TagParent != pTag )
- hb_cdxErrInternal( "hb_cdxTagPoolCheck: data integrity error." );
- pPrevPage = pPage;
- pPage = pPage->pPoolNext;
- }
- }
- /*
- * check if the Tag buffers was not changed without write lock
- */
- static void hb_cdxTagCheckBuffers( LPCDXTAG pTag )
- {
- BOOL fChanged = FALSE;
- hb_cdxTagPoolCheck( pTag );
- if ( pTag->TagChanged )
- fChanged = TRUE;
- else
- {
- LPCDXPAGE pPage = pTag->pagePool;
- while ( pPage && !fChanged )
- {
- fChanged = pPage->fChanged;
- pPage = pPage->pPoolNext;
- }
- }
- if ( fChanged )
- hb_cdxErrInternal( "hb_cdxTagCheckBuffers: modification without write lock." );
- }
- /*
- * check if the Index buffers was not changed without write lock
- */
- static void hb_cdxIndexCheckBuffers( LPCDXINDEX pIndex )
- {
- LPCDXTAG pTag;
- if ( pIndex->fChanged || ( pIndex->freeLst && pIndex->freeLst->fStat ) )
- hb_cdxErrInternal( "hb_cdxIndexCheckBuffers: modification without write lock." );
- if ( pIndex->pCompound )
- hb_cdxTagCheckBuffers( pIndex->pCompound );
- pTag = pIndex->TagList;
- while ( pTag )
- {
- hb_cdxTagCheckBuffers( pTag );
- pTag = pTag->pNext;
- }
- }
- #endif
- /*
- * get free index page
- */
- static ULONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex, BOOL bHeader )
- {
- FHANDLE hFile = pIndex->hFile;
- BYTE byBuf[4];
- ULONG ulPos;
- if ( pIndex->fReadonly )
- {
- hb_errInternal( 9101, "hb_cdxIndexGetAvailPage on readonly database.", "", "" );
- }
- if ( pIndex->fShared && !pIndex->lockWrite )
- {
- hb_errInternal( 9102, "hb_cdxIndexGetAvailPage on not locked index file.", "", "" );
- }
- if ( pIndex->freePage != 0 && pIndex->freePage != CDX_DUMMYNODE && !bHeader )
- {
- ulPos = pIndex->freePage;
- if ( pIndex->freeLst != NULL )
- {
- LPCDXLIST pLst = pIndex->freeLst;
- pIndex->freePage = pLst->ulAddr;
- pIndex->freeLst = pLst->pNext;
- hb_xfree( pLst );
- }
- else
- {
- if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos ||
- hb_fsRead( hFile, (BYTE *) byBuf, 4 ) != 4 )
- hb_errInternal( EDBF_READ, "hb_cdxIndexGetAvailPage: Read index page failed.", "", "" );
- pIndex->freePage = HB_GET_LE_UINT32( byBuf );
- #ifdef HB_CDX_DBGUPDT
- cdxReadNO++;
- #endif
- }
- }
- else
- {
- int iCnt = ( bHeader ? CDX_HEADERPAGES : 1 );
- if ( pIndex->nextAvail != CDX_DUMMYNODE )
- ulPos = pIndex->nextAvail;
- else
- ulPos = hb_fsSeek( hFile, 0, FS_END );
- pIndex->nextAvail = ulPos + iCnt * CDX_PAGELEN;
- /* TODO: ### */
- if ( bHeader )
- {
- BYTE byBuf[CDX_PAGELEN];
- memset( byBuf, 0, CDX_PAGELEN );
- if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos )
- hb_errInternal( EDBF_WRITE, "Write in index page failed.(1)", "", "" );
- while ( iCnt-- )
- {
- if ( hb_fsWrite( hFile, byBuf, CDX_PAGELEN ) != CDX_PAGELEN )
- hb_errInternal( EDBF_WRITE, "Write in index page failed.(2)", "", "" );
- }
- pIndex->fChanged = TRUE;
- }
- }
- return ulPos;
- }
- /*
- * free index page
- */
- static void hb_cdxIndexPutAvailPage( LPCDXINDEX pIndex, ULONG ulPos, BOOL bHeader )
- {
- if ( ulPos != 0 && ulPos != CDX_DUMMYNODE )
- {
- int iCnt = ( bHeader ? CDX_HEADERPAGES : 1 );
- LPCDXLIST pLst;
- if ( pIndex->fReadonly )
- hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" );
- if ( pIndex->fShared && !pIndex->lockWrite )
- hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" );
- while ( iCnt-- )
- {
- pLst = (LPCDXLIST) hb_xgrab( sizeof( CDXLIST ) );
- pLst->ulAddr = pIndex->freePage;
- pIndex->freePage = ulPos;
- pLst->fStat = TRUE;
- pLst->pNext = pIndex->freeLst;
- pIndex->freeLst = pLst;
- ulPos += CDX_PAGELEN;
- }
- }
- }
- /*
- * flush list of free pages into index file
- */
- static void hb_cdxIndexFlushAvailPage( LPCDXINDEX pIndex )
- {
- LPCDXLIST pLst = pIndex->freeLst;
- BYTE byPageBuf[CDX_PAGELEN];
- ULONG ulPos;
- if ( pIndex->fReadonly )
- hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" );
- if ( pIndex->fShared && !pIndex->lockWrite )
- hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" );
- memset( byPageBuf, 0, CDX_PAGELEN );
- ulPos = pIndex->freePage;
- while ( pLst && pLst->fStat )
- {
- HB_PUT_LE_UINT32( byPageBuf, pLst->ulAddr );
- if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
- hb_fsWrite( pIndex->hFile, byPageBuf, CDX_PAGELEN ) != CDX_PAGELEN )
- {
- hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" );
- }
- pIndex->fChanged = TRUE;
- ulPos = pLst->ulAddr;
- pLst->fStat = FALSE;
- pLst = pLst->pNext;
- #ifdef HB_CDX_DBGUPDT
- cdxWriteNO++;
- #endif
- }
- }
- /*
- * drop list of free pages in index file
- */
- static void hb_cdxIndexDropAvailPage( LPCDXINDEX pIndex )
- {
- LPCDXLIST pLst;
- while ( pIndex->freeLst )
- {
- pLst = pIndex->freeLst->pNext;
- hb_xfree( pIndex->freeLst );
- pIndex->freeLst = pLst;
- }
- }
- /*
- * write index page
- */
- static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer,
- USHORT uiSize )
- {
- if ( pIndex->fReadonly )
- hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", "", "" );
- if ( pIndex->fShared && !pIndex->lockWrite )
- hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", "", "" );
- if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
- hb_fsWrite( pIndex->hFile, pBuffer, uiSize ) != uiSize )
- hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" );
- pIndex->fChanged = TRUE;
- #ifdef HB_CDX_DBGUPDT
- cdxWriteNO++;
- #endif
- }
- /*
- * read index page
- */
- static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer,
- USHORT uiSize )
- {
- if ( pIndex->fShared && !( pIndex->lockRead || pIndex->lockWrite ) )
- hb_errInternal( 9103, "hb_cdxIndexPageRead on not locked index file.", "", "" );
- if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
- hb_fsRead( pIndex->hFile, pBuffer, uiSize ) != uiSize )
- hb_errInternal( EDBF_READ, "hb_cdxIndexPageRead: Read index page failed.", "", "" );
- #ifdef HB_CDX_DBGUPDT
- cdxReadNO++;
- #endif
- }
- /*
- * check if index was updated by other process and if it was discard buffers
- */
- static void hb_cdxIndexCheckVersion( LPCDXINDEX pIndex )
- {
- BYTE byBuf[8];
- ULONG ulVer, ulFree;
- if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
- hb_fsRead( pIndex->hFile, byBuf, 8 ) != 8 )
- {
- if ( pIndex->lockWrite > 0 && hb_fsSeek( pIndex->hFile, 0, FS_END ) == 0 )
- memset( byBuf, 0, 8 );
- else
- hb_errInternal( 2155, "hb_cdxIndexCheckVersion: Read error on index heading page.", "", "" );
- }
- #ifdef HB_CDX_DBGUPDT
- cdxReadNO++;
- #endif
- ulFree = HB_GET_LE_UINT32( &byBuf[0] );
- ulVer = HB_GET_BE_UINT32( &byBuf[4] );
- if ( !pIndex->fShared )
- pIndex->ulVersion = pIndex->freePage;
- else if ( ulVer != pIndex->ulVersion || ulFree != pIndex->freePage )
- {
- pIndex->nextAvail = CDX_DUMMYNODE;
- pIndex->ulVersion = ulVer;
- pIndex->freePage = ulFree;
- hb_cdxIndexDiscardBuffers( pIndex );
- }
- /* TODO: !!! ## remove it it's for test only */
- /* hb_cdxIndexDiscardBuffers( pIndex ); */
- }
- /*
- * lock index for reading (shared lock)
- */
- static BOOL hb_cdxIndexLockRead( LPCDXINDEX pIndex )
- {
- BOOL ret;
- if ( pIndex->lockRead > 0 || pIndex->lockWrite > 0 ||
- !pIndex->pArea->fShared || !pIndex->fShared )
- {
- pIndex->lockRead++;
- return TRUE;
- }
- #ifdef HB_CDX_DBGCODE
- if ( pIndex->lockRead != 0 )
- hb_errInternal( 9105, "hb_cdxIndexLockRead: bad count of locks.", "", "" );
- if ( pIndex->WrLck || pIndex->RdLck )
- hb_errInternal( 9107, "hb_cdxIndexLockRead: lock failure (*)", "", "" );
- pIndex->RdLck = TRUE;
- #endif
- ret = hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType,
- FL_LOCK | FLX_SHARED | FLX_WAIT, &pIndex->ulLockPos );
- if ( !ret )
- hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0 );
- if ( ret )
- {
- pIndex->lockRead++;
- hb_cdxIndexCheckVersion( pIndex );
- }
- return ret;
- }
- /*
- * lock index for writing (exclusive lock)
- */
- static BOOL hb_cdxIndexLockWrite( LPCDXINDEX pIndex )
- {
- BOOL ret;
- if ( pIndex->lockRead )
- hb_errInternal( 9105, "hb_cdxIndexLockRead: writeLock after readLock.", "", "" );
- if ( pIndex->lockWrite > 0 )
- {
- pIndex->lockWrite++;
- return TRUE;
- }
- if ( pIndex->lockWrite != 0 )
- hb_errInternal( 9105, "hb_cdxIndexLockWrite: bad count of locks.", "", "" );
- if ( !pIndex->pArea->fShared || !pIndex->fShared )
- ret = TRUE;
- else
- {
- #ifdef HB_CDX_DBGCODE
- if ( pIndex->WrLck || pIndex->RdLck )
- hb_errInternal( 9107, "hb_cdxIndexLockWrite: lock failure (*)", "", "" );
- pIndex->WrLck = TRUE;
- #endif
- ret = hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType,
- FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, &pIndex->ulLockPos );
- }
- if ( !ret )
- hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0 );
- if ( ret )
- {
- pIndex->lockWrite++;
- if ( pIndex->fShared || pIndex->nextAvail == CDX_DUMMYNODE )
- hb_cdxIndexCheckVersion( pIndex );
- }
- return ret;
- }
- /*
- * remove index read lock (shared lock)
- */
- static BOOL hb_cdxIndexUnLockRead( LPCDXINDEX pIndex )
- {
- pIndex->lockRead--;
- if ( pIndex->lockRead < 0 )
- {
- hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" );
- }
- if ( pIndex->lockRead || pIndex->lockWrite )
- {
- return TRUE;
- }
- #ifdef HB_CDX_DBGCODE_EXT
- hb_cdxIndexCheckBuffers( pIndex );
- #endif
- hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE );
- if ( pIndex->pArea->fShared && pIndex->fShared )
- {
- #ifdef HB_CDX_DBGCODE
- if ( pIndex->WrLck || ! pIndex->RdLck )
- hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error (*)", "", "" );
- pIndex->RdLck = FALSE;
- #endif
- if ( !hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType, FL_UNLOCK, &pIndex->ulLockPos ) )
- {
- hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error.", "", "" );
- }
- }
- return TRUE;
- }
- /*
- * remove index write lock (exclusive lock)
- */
- static BOOL hb_cdxIndexUnLockWrite( LPCDXINDEX pIndex )
- {
- if ( pIndex->lockWrite > 1 )
- {
- pIndex->lockWrite--;
- return TRUE;
- }
- if ( pIndex->lockWrite < 1 )
- {
- hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" );
- }
- if ( pIndex->lockRead )
- {
- hb_errInternal( 9105, "hb_cdxIndexUnLockWrite: writeUnLock before readUnLock.", "", "" );
- }
- hb_cdxIndexFlushBuffers( pIndex );
- hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE );
- pIndex->lockWrite--;
- if ( pIndex->pArea->fShared && pIndex->fShared )
- {
- if ( pIndex->fChanged )
- {
- BYTE byBuf[8];
- (pIndex->ulVersion)++;
- HB_PUT_LE_UINT32( &byBuf[0], pIndex->freePage );
- HB_PUT_BE_UINT32( &byBuf[4], pIndex->ulVersion );
- if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
- hb_fsWrite( pIndex->hFile, byBuf, 8) != 8 )
- {
- hb_errInternal( EDBF_WRITE, "Write in index page failed (ver)", "", "" );
- }
- pIndex->fFlush = TRUE;
- pIndex->fChanged = FALSE;
- }
- #ifdef HB_CDX_DBGCODE
- if ( ! pIndex->WrLck || pIndex->RdLck )
- hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error (*)", "", "" );
- pIndex->WrLck = FALSE;
- #endif
- if ( !hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType, FL_UNLOCK, &pIndex->ulLockPos ) )
- {
- hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error.", "", "" );
- }
- }
- else
- {
- if ( pIndex->ulVersion != pIndex->freePage )
- {
- BYTE byBuf[4];
- HB_PUT_LE_UINT32( &byBuf[0], pIndex->freePage );
- if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
- hb_fsWrite( pIndex->hFile, byBuf, 4) != 4 )
- {
- hb_errInternal( EDBF_WRITE, "Write in index page failed (ver.ex)", "", "" );
- }
- pIndex->ulVersion = pIndex->freePage;
- pIndex->fFlush = TRUE;
- #ifdef HB_CDX_DBGUPDT
- cdxWriteNO++;
- #endif
- }
- else if ( pIndex->fChanged )
- {
- pIndex->fFlush = TRUE;
- }
- pIndex->fChanged = FALSE;
- }
- return TRUE;
- }
- /*
- * discard all pages in cache (TagClose and TagPoolFree for all Tags)
- */
- static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex )
- {
- LPCDXTAG pTag;
- #ifdef HB_CDX_DBGCODE_EXT
- hb_cdxIndexCheckBuffers( pIndex );
- #endif
- hb_cdxIndexDropAvailPage( pIndex );
- if ( pIndex->pCompound )
- {
- hb_cdxTagClose( pIndex->pCompound );
- hb_cdxTagPoolFree( pIndex->pCompound, 0 );
- pIndex->pCompound->fRePos = TRUE;
- pIndex->pCompound->curKeyState = 0;
- if ( pIndex->pCompound->CurKey )
- pIndex->pCompound->CurKey->rec = 0;
- }
- pTag = pIndex->TagList;
- while ( pTag )
- {
- hb_cdxTagClose( pTag );
- hb_cdxTagPoolFree( pTag, 0 );
- pTag->fRePos = TRUE;
- pTag->curKeyState = 0;
- if ( pTag->CurKey && !pTag->Custom )
- pTag->CurKey->rec = 0;
- pTag = pTag->pNext;
- }
- }
- /*
- * write all changed pages in cache (pagePool, pages in Tags and Tag Header)
- */
- static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex )
- {
- LPCDXTAG pTag;
- if ( pIndex->pCompound )
- {
- hb_cdxTagPoolFlush( pIndex->pCompound );
- if ( pIndex->pCompound->TagChanged )
- hb_cdxTagHeaderStore( pIndex->pCompound );
- }
- pTag = pIndex->TagList;
- while ( pTag )
- {
- hb_cdxTagPoolFlush( pTag );
- if ( pTag->TagChanged )
- hb_cdxTagHeaderStore( pTag );
- pTag = pTag->pNext;
- }
- hb_cdxIndexFlushAvailPage( pIndex );
- }
- /*
- * free cached pages of index file
- */
- static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft )
- {
- LPCDXTAG pTag;
- if ( pIndex->pCompound )
- {
- hb_cdxTagPoolFree( pIndex->pCompound, nPagesLeft );
- }
- pTag = pIndex->TagList;
- while ( pTag )
- {
- hb_cdxTagPoolFree( pTag, nPagesLeft );
- pTag = pTag->pNext;
- }
- }
- /*
- * get key value ptr from index page
- */
- static BYTE * hb_cdxPageGetKeyVal( LPCDXPAGE pPage, SHORT iKey )
- {
- #ifdef HB_CDX_DBGCODE
- if ( iKey < 0 || iKey >= pPage->iKeys )
- hb_cdxErrInternal( "hb_cdxPageGetKeyVal: wrong iKey index." );
- #endif
- if ( pPage->pKeyBuf )
- return &pPage->pKeyBuf[ iKey * ( pPage->TagParent->uiLen + 6 ) ];
- else if ( pPage->PageType & CDX_NODE_LEAF )
- {
- SHORT iPos, iLen, iTmp, iTrl, iDup;
- BYTE bTrail;
- iLen = pPage->TagParent->uiLen;
- bTrail = ( BYTE ) ( pPage->TagParent->uiType == 'C' ? ' ' : '\0' );
- if ( iKey < pPage->bufKeyNum - 1 )
- pPage->bufKeyNum = 0;
- if ( pPage->bufKeyNum == 0 )
- {
- pPage->bufKeyPos = CDX_EXT_FREESPACE;
- pPage->bufKeyLen = iLen;
- }
- while ( pPage->bufKeyNum <= iKey )
- {
- iPos = pPage->bufKeyNum * pPage->ReqByte;
- iTmp = HB_GET_LE_UINT16( &pPage->node.extNode.keyPool[ iPos + pPage->ReqByte - 2 ] ) >>
- ( 16 - pPage->TCBits - pPage->DCBits );
- iDup = ( pPage->bufKeyNum == 0 ) ? 0 : ( iTmp & pPage->DCMask );
- iTrl = ( iTmp >> pPage->DCBits ) & pPage->TCMask;
- if ( ( iTmp = iLen - iDup - iTrl ) > 0 )
- {
- pPage->bufKeyPos -= iTmp;
- memcpy( &pPage->bufKeyVal[ iDup ],
- &pPage->node.extNode.keyPool[ pPage->bufKeyPos ], iTmp );
- }
- #ifdef HB_CDX_DBGCODE
- else if ( iTmp < 0 )
- {
- printf("\r\npPage->Page=%lx, iLen=%d, iDup=%d, iTrl=%d", pPage->Page, iLen, iDup, iTrl); fflush(stdout);
- hb_cdxErrInternal( "hb_cdxPageGetKeyVal: index corrupted." );
- }
- #endif
- if ( iTrl > 0 && ( iTmp = pPage->bufKeyLen - iLen + iTrl ) > 0 )
- memset( &pPage->bufKeyVal[ iLen - iTrl ], bTrail, iTmp );
- pPage->bufKeyLen = iLen - iTrl;
- pPage->bufKeyNum++;
- }
- return pPage->bufKeyVal;
- }
- else
- return &pPage->node.intNode.keyPool[ iKey * ( pPage->TagParent->uiLen + 8 ) ];
- }
- /*
- * get record number from index page
- */
- static ULONG hb_cdxPageGetKeyRec( LPCDXPAGE pPage, SHORT iKey )
- {
- #ifdef HB_CDX_DBGCODE
- if ( iKey < 0 || iKey >= pPage->iKeys )
- hb_cdxErrInternal( "hb_cdxPageGetKeyRec: wrong iKey index." );
- #endif
- if ( pPage->pKeyBuf )
- return HB_GET_LE_UINT32( &pPage->pKeyBuf[ ( iKey + 1 ) * ( pPage->TagParent->uiLen + 6 ) - 6 ] );
- else if ( pPage->PageType & CDX_NODE_LEAF )
- return HB_GET_LE_UINT32( &pPage->node.extNode.keyPool[ iKey * pPage->ReqByte ] ) & pPage->RNMask;
- else
- return HB_GET_BE_UINT32( &pPage->node.intNode.keyPool[
- ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 8 ] );
- }
- /*
- * get child page number from interrior index page
- */
- static ULONG hb_cdxPageGetKeyPage( LPCDXPAGE pPage, SHORT iKey )
- {
- #ifdef HB_CDX_DBGCODE
- if ( iKey < 0 || iKey >= pPage->iKeys )
- hb_cdxErrInternal( "hb_cdxPageGetKeyPage: wrong iKey index." );
- if ( pPage->PageType & CDX_NODE_LEAF )
- hb_cdxErrInternal( "hb_cdxPageGetKeyPage: page is a leaf." );
- #endif
- return HB_GET_BE_UINT32( &pPage->node.intNode.keyPool[
- ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 4 ] );
- }
- #if 0
- /*
- * get key from uncompressed page
- */
- static LPCDXKEY hb_cdxPageGetKey( LPCDXPAGE pPage, SHORT iKey, LPCDXKEY pKey )
- {
- return hb_cdxKeyPut( pKey,
- hb_cdxPageGetKeyVal( pPage, iKey ),
- pPage->TagParent->uiLen,
- hb_cdxPageGetKeyRec( pPage, iKey ) );
- }
- #endif
- #ifdef HB_CDX_DBGCODE_EXT
- /*
- * check if keys are sorted in proper order
- */
- static void hb_cdxPageCheckKeys( LPCDXPAGE pPage )
- {
- SHORT i, K, iLen = pPage->TagParent->uiLen;
- ULONG ulRec, ulRecPrev;
- BYTE * pbVal, pbValPrev[CDX_MAXKEY];
- if ( pPage->iKeys > 1 )
- {
- pPage->bufKeyNum = 0;
- pbVal = hb_cdxPageGetKeyVal( pPage, 0 );
- ulRec = hb_cdxPageGetKeyRec( pPage, 0 );
- for ( i = 1; i < pPage->iKeys; i++ )
- {
- memcpy( pbValPrev, pbVal, iLen );
- ulRecPrev = ulRec;
- pbVal = hb_cdxPageGetKeyVal( pPage, i );
- ulRec = hb_cdxPageGetKeyRec( pPage, i );
- K = hb_cdxValCompare( pPage->TagParent,
- pbValPrev, iLen,
- pbVal, iLen, TRUE );
- if ( K > 0 || ( K == 0 && ulRecPrev >= ulRec ) )
- {
- printf( "\r\nikey=%d, pPage->iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld",
- i, pPage->iKeys, K, ulRecPrev, ulRec );fflush(stdout);
- printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pPage->pKeyBuf=%p, pPage->iCurKey=%d",
- pbValPrev, pbVal, memcmp( pbValPrev, pbVal, iLen ),
- pPage->pKeyBuf, pPage->iCurKey );fflush(stdout);
- hb_cdxErrInternal( "hb_cdxPageCheckKeys: index corrupted." );
- }
- }
- }
- }
- /*
- * Check decoded leaf page if all trailing and duplicate characters are set
- */
- static void hb_cdxPageCheckDupTrl( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys, BOOL fSpc )
- {
- SHORT iNum = pPage->TagParent->uiLen, iKey, iPos, iFree = CDX_EXT_FREESPACE;
- SHORT iLen = iNum + 6;
- BYTE bDup, bTrl;
- BYTE bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0';
- BOOL bErr = FALSE;
- for ( iKey = 0; iKey < iKeys; iKey++ )
- {
- iPos = iKey * iLen;
- bTrl = bDup = 0;
- while ( bTrl < iNum && pKeyBuf[ iPos + iNum - bTrl - 1 ] == bTrail )
- ++bTrl;
- if ( iKey > 0 )
- {
- #ifdef HB_CDX_PACKTRAIL
- SHORT iMax = iNum - bTrl;
- #else
- SHORT iMax = iNum - HB_MAX( pKeyBuf[ iPos - 1 ], bTrl );
- #endif
- while ( bDup < iMax && pKeyBuf[ iPos + bDup ] ==
- pKeyBuf[ iPos - iLen + bDup ] )
- ++bDup;
- }
- if ( bTrl != pKeyBuf[ iPos + iNum + 5 ] )
- {
- printf("\r\nbTrl=%d, keybuf->bTrl=%d, iKey=%d/%d\r\n", bTrl, pKeyBuf[ iPos + iNum + 5 ], iKey, iKeys );
- fflush(stdout);
- bErr = TRUE;
- }
- if ( bDup != ( iKey == 0 ? 0 : pKeyBuf[ iPos + iNum + 4 ] ) )
- {
- printf("\r\nbDup=%d, keybuf->bDup=%d (bTrl=%d), iKey=%d/%d\r\n", bDup, pKeyBuf[ iPos + iNum + 4 ], bTrl, iKey, iKeys );
- fflush(stdout);
- bErr = TRUE;
- }
- if ( iKey > 0 )
- {
- SHORT K;
- K = hb_cdxValCompare( pPage->TagParent,
- &pKeyBuf[ iPos - iLen ], iNum,
- &pKeyBuf[ iPos ], iNum, TRUE );
- if ( K > 0 || ( K == 0 &&
- HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum - iLen ] ) >=
- HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum ] ) ) )
- {
- printf( "\r\nikey=%d, iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld",
- iKey, iKeys, K,
- (ULONG) HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum - iLen ] ),
- (ULONG) HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum ] ) );
- printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pKeyBuf=%p",
- &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ],
- memcmp( &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ], iNum ),
- pKeyBuf );
- fflush(stdout);
- bErr = TRUE;
- }
- }
- iFree -= iNum + pPage->ReqByte - bDup - bTrl;
- }
- if ( fSpc && ( iFree != pPage->iFree /* || iFree < 0 */ ) )
- {
- printf( "\r\nFreeSpace calculated wrong! iFree=%d, pPage->iFree=%d",
- iFree, pPage->iFree );
- fflush(stdout);
- bErr = TRUE;
- }
- if ( bErr )
- {
- printf("\r\nPage=%lx, Page->iFree=%d, iLen=%d\r\n", pPage->Page, pPage->iFree, iNum );
- fflush(stdout);
- hb_cdxErrInternal( "hb_cdxPageCheckDupTrl: index corrupted." );
- }
- }
- static void hb_cdxPageLeafDecode( LPCDXPAGE pPage, BYTE * pKeyBuf );
- static void hb_cdxPageCheckDupTrlRaw( LPCDXPAGE pPage )
- {
- BYTE *pKeyBuf = (BYTE *) hb_xgrab( pPage->iKeys * ( pPage->TagParent->uiLen + 6 ) );
- hb_cdxPageLeafDecode( pPage, pKeyBuf );
- hb_cdxPageCheckDupTrl( pPage, pKeyBuf, pPage->iKeys, TRUE );
- hb_xfree( pKeyBuf );
- }
- #endif
- /*
- * put record and duplicate + trailing counters into leaf page
- */
- static void hb_cdxSetLeafRecord( BYTE *pDst, ULONG ulRec, int iDup, int iTrl,
- int iReq, int iDCbits, int iTCbits )
- {
- int i;
- USHORT usBit;
- usBit = ( ( iTrl << iDCbits ) | iDup ) << ( 16 - iTCbits - iDCbits );
- for ( i = 0; i < iReq; i++, ulRec >>= 8 )
- {
- if ( i < iReq - 2 )
- pDst[ i ] = ( BYTE ) ( ulRec & 0xff );
- else if ( i == iReq - 2 )
- pDst[ i ] = ( BYTE ) ( ulRec & 0xff ) | ( usBit & 0xff );
- else
- pDst[ i ] = ( BYTE ) ( ulRec & 0xff ) | ( ( usBit >> 8 ) & 0xff );
- }
- }
- /*
- * encode keys in buffer into cdx leaf node
- */
- static void hb_cdxPageLeafEncode( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys )
- {
- int iKey, iTrl, iDup, iReq, iTmp, iNum, iLen;
- BYTE *pKeyPos, *pRecPos, *pSrc;
- #ifdef HB_CDX_DBGCODE
- if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 )
- {
- printf("\r\npPage->Page=%lx. left=%lx, right=%lx",
- pPage->Page, pPage->Left, pPage->…
Large files files are truncated, but you can click here to view the full file