PageRenderTime 72ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/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

  1. /*
  2. * $Id: dbfcdx1.c 6462 2005-01-30 21:11:50Z druzus $
  3. */
  4. /*
  5. * xHarbour Project source code:
  6. * DBFCDX RDD (ver.2)
  7. *
  8. * Copyright 1999-2002 Bruno Cantero <bruno@issnet.net>
  9. * Copyright 2000-2003 Horacio Roldan <harbour_ar@yahoo.com.ar> (portions)
  10. * Copyright 2003 Przemyslaw Czerpak <druzus@priv.onet.pl> - all code except
  11. * hb_cdxTagDoIndex and related hb_cdxSort* rewritten.
  12. * Copyright 2004 Przemyslaw Czerpak <druzus@priv.onet.pl> - rest of code rewritten
  13. * www - http://www.xharbour.org
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2, or (at your option)
  18. * any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this software; see the file COPYING. If not, write to
  27. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  28. * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
  29. *
  30. * As a special exception, the Harbour Project gives permission for
  31. * additional uses of the text contained in its release of Harbour.
  32. *
  33. * The exception is that, if you link the Harbour libraries with other
  34. * files to produce an executable, this does not by itself cause the
  35. * resulting executable to be covered by the GNU General Public License.
  36. * Your use of that executable is in no way restricted on account of
  37. * linking the Harbour library code into it.
  38. *
  39. * This exception does not however invalidate any other reasons why
  40. * the executable file might be covered by the GNU General Public License.
  41. *
  42. * This exception applies only to the code released by the Harbour
  43. * Project under the name Harbour. If you copy code from other
  44. * Harbour Project or Free Software Foundation releases into a copy of
  45. * Harbour, as the General Public License permits, the exception does
  46. * not apply to the code that you add in this way. To avoid misleading
  47. * anyone as to the status of such modified files, you must delete
  48. * this exception notice from them.
  49. *
  50. * If you write modifications of your own for Harbour, it is your choice
  51. * whether to permit this exception to apply to your modifications.
  52. * If you do not wish that, delete this exception notice.
  53. *
  54. */
  55. #define HB_CDX_CLIP_AUTOPEN
  56. #define HB_CDX_PACKTRAIL
  57. #define HB_CDX_NEW_SORT
  58. #define HB_CDX_DBGCODE
  59. /*
  60. #define HB_CDX_DBGCODE_EXT
  61. #define HB_CDX_DSPDBG_INFO
  62. #define HB_CDP_SUPPORT_OFF
  63. #define HB_CDX_DBGTIME
  64. #define HB_CDX_DBGUPDT
  65. */
  66. #include "hbapi.h"
  67. #include "hbinit.h"
  68. #include "hbapierr.h"
  69. #include "hbapilng.h"
  70. #include "hbvm.h"
  71. #include "hbset.h"
  72. #include "hbrddcdx.h"
  73. #ifdef __XHARBOUR__
  74. #include "regex.h"
  75. #endif
  76. #define __PRG_SOURCE__ __FILE__
  77. #ifdef HB_PCODE_VER
  78. #undef HB_PRG_PCODE_VER
  79. #define HB_PRG_PCODE_VER HB_PCODE_VER
  80. #endif
  81. #ifndef HB_CDP_SUPPORT_OFF
  82. /* for nation sorting support */
  83. #include "hbapicdp.h"
  84. #define hb_cdpcharcmp( c1, c2, cdpage ) \
  85. ( ( cdpage && cdpage->lSort ) ? \
  86. hb_cdpchrcmp( c1, c2, cdpage ) : \
  87. ( (BYTE)(c1) - (BYTE)(c2) ) )
  88. /*
  89. #define hb_cdpcharcmp( c1, c2, cdpage ) ( (BYTE)(c1) - (BYTE)(c2) )
  90. */
  91. #endif
  92. /*
  93. * Tag->fRePos = TURE means that rootPage->...->childLeafPage path is
  94. * bad and has to be reloaded
  95. * CurKey->rec == 0 means that there is no correct CurKey
  96. */
  97. /* create a new Tag (make index) */
  98. static void hb_cdxTagDoIndex( LPCDXTAG pTag );
  99. /* Close Tag */
  100. static void hb_cdxTagClose( LPCDXTAG pTag );
  101. /* free Tag pages from cache */
  102. static void hb_cdxTagPoolFree( LPCDXTAG pTag, int nPagesLeft );
  103. /* Store tag header to index files */
  104. static void hb_cdxTagHeaderStore( LPCDXTAG pTag );
  105. /* write all changed pages in tag cache */
  106. static void hb_cdxTagPoolFlush( LPCDXTAG pTag );
  107. /* Discard all pages in cache (TagClose and TagPoolFree for all Tags) */
  108. static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex );
  109. /* write all changed pages in cache (pagePool and Tag Header) */
  110. static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex );
  111. /* free cached pages of index file */
  112. static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft );
  113. /* split Root Page */
  114. static int hb_cdxPageRootSplit( LPCDXPAGE pPage );
  115. /* free create index structur */
  116. static void hb_cdxSortFree( LPCDXSORTINFO pSort );
  117. static RDDFUNCS cdxSuper;
  118. static RDDFUNCS cdxTable =
  119. {
  120. /* Movement and positioning methods */
  121. ( DBENTRYP_BP ) hb_cdxBof,
  122. ( DBENTRYP_BP ) hb_cdxEof,
  123. ( DBENTRYP_BP ) hb_cdxFound,
  124. ( DBENTRYP_V ) hb_cdxGoBottom,
  125. ( DBENTRYP_UL ) hb_cdxGoTo,
  126. ( DBENTRYP_I ) hb_cdxGoToId,
  127. ( DBENTRYP_V ) hb_cdxGoTop,
  128. ( DBENTRYP_BIB ) hb_cdxSeek,
  129. ( DBENTRYP_L ) hb_cdxSkip,
  130. ( DBENTRYP_L ) hb_cdxSkipFilter,
  131. ( DBENTRYP_L ) hb_cdxSkipRaw,
  132. /* Data management */
  133. ( DBENTRYP_VF ) hb_cdxAddField,
  134. ( DBENTRYP_B ) hb_cdxAppend,
  135. ( DBENTRYP_I ) hb_cdxCreateFields,
  136. ( DBENTRYP_V ) hb_cdxDeleteRec,
  137. ( DBENTRYP_BP ) hb_cdxDeleted,
  138. ( DBENTRYP_SP ) hb_cdxFieldCount,
  139. ( DBENTRYP_VF ) hb_cdxFieldDisplay,
  140. ( DBENTRYP_SSI ) hb_cdxFieldInfo,
  141. ( DBENTRYP_SVP ) hb_cdxFieldName,
  142. ( DBENTRYP_V ) hb_cdxFlush,
  143. ( DBENTRYP_PP ) hb_cdxGetRec,
  144. ( DBENTRYP_SI ) hb_cdxGetValue,
  145. ( DBENTRYP_SVL ) hb_cdxGetVarLen,
  146. ( DBENTRYP_V ) hb_cdxGoCold,
  147. ( DBENTRYP_V ) hb_cdxGoHot,
  148. ( DBENTRYP_P ) hb_cdxPutRec,
  149. ( DBENTRYP_SI ) hb_cdxPutValue,
  150. ( DBENTRYP_V ) hb_cdxRecall,
  151. ( DBENTRYP_ULP ) hb_cdxRecCount,
  152. ( DBENTRYP_ISI ) hb_cdxRecInfo,
  153. ( DBENTRYP_I ) hb_cdxRecNo,
  154. ( DBENTRYP_S ) hb_cdxSetFieldExtent,
  155. /* WorkArea/Database management */
  156. ( DBENTRYP_P ) hb_cdxAlias,
  157. ( DBENTRYP_V ) hb_cdxClose,
  158. ( DBENTRYP_VP ) hb_cdxCreate,
  159. ( DBENTRYP_SI ) hb_cdxInfo,
  160. ( DBENTRYP_V ) hb_cdxNewArea,
  161. ( DBENTRYP_VP ) hb_cdxOpen,
  162. ( DBENTRYP_V ) hb_cdxRelease,
  163. ( DBENTRYP_SP ) hb_cdxStructSize,
  164. ( DBENTRYP_P ) hb_cdxSysName,
  165. ( DBENTRYP_VEI ) hb_cdxEval,
  166. ( DBENTRYP_V ) hb_cdxPack,
  167. ( DBENTRYP_LSP ) hb_cdxPackRec,
  168. ( DBENTRYP_VS ) hb_cdxSort,
  169. ( DBENTRYP_VT ) hb_cdxTrans,
  170. ( DBENTRYP_VT ) hb_cdxTransRec,
  171. ( DBENTRYP_V ) hb_cdxZap,
  172. /* Relational Methods */
  173. ( DBENTRYP_VR ) hb_cdxChildEnd,
  174. ( DBENTRYP_VR ) hb_cdxChildStart,
  175. ( DBENTRYP_VR ) hb_cdxChildSync,
  176. ( DBENTRYP_V ) hb_cdxSyncChildren,
  177. ( DBENTRYP_V ) hb_cdxClearRel,
  178. ( DBENTRYP_V ) hb_cdxForceRel,
  179. ( DBENTRYP_SVP ) hb_cdxRelArea,
  180. ( DBENTRYP_VR ) hb_cdxRelEval,
  181. ( DBENTRYP_SVP ) hb_cdxRelText,
  182. ( DBENTRYP_VR ) hb_cdxSetRel,
  183. /* Order Management */
  184. ( DBENTRYP_OI ) hb_cdxOrderListAdd,
  185. ( DBENTRYP_V ) hb_cdxOrderListClear,
  186. ( DBENTRYP_VP ) hb_cdxOrderListDelete,
  187. ( DBENTRYP_OI ) hb_cdxOrderListFocus,
  188. ( DBENTRYP_V ) hb_cdxOrderListRebuild,
  189. ( DBENTRYP_VOI ) hb_cdxOrderCondition,
  190. ( DBENTRYP_VOC ) hb_cdxOrderCreate,
  191. ( DBENTRYP_OI ) hb_cdxOrderDestroy,
  192. ( DBENTRYP_OII ) hb_cdxOrderInfo,
  193. /* Filters and Scope Settings */
  194. ( DBENTRYP_V ) hb_cdxClearFilter,
  195. ( DBENTRYP_V ) hb_cdxClearLocate,
  196. ( DBENTRYP_V ) hb_cdxClearScope,
  197. ( DBENTRYP_VPLP ) hb_cdxCountScope,
  198. ( DBENTRYP_I ) hb_cdxFilterText,
  199. ( DBENTRYP_SI ) hb_cdxScopeInfo,
  200. ( DBENTRYP_VFI ) hb_cdxSetFilter,
  201. ( DBENTRYP_VLO ) hb_cdxSetLocate,
  202. ( DBENTRYP_VOS ) hb_cdxSetScope,
  203. ( DBENTRYP_VPL ) hb_cdxSkipScope,
  204. /* Miscellaneous */
  205. ( DBENTRYP_P ) hb_cdxCompile,
  206. ( DBENTRYP_I ) hb_cdxError,
  207. ( DBENTRYP_I ) hb_cdxEvalBlock,
  208. /* Network operations */
  209. ( DBENTRYP_VSP ) hb_cdxRawLock,
  210. ( DBENTRYP_VL ) hb_cdxLock,
  211. ( DBENTRYP_UL ) hb_cdxUnLock,
  212. /* Memofile functions */
  213. ( DBENTRYP_V ) hb_cdxCloseMemFile,
  214. ( DBENTRYP_VP ) hb_cdxCreateMemFile,
  215. ( DBENTRYP_SVPB ) hb_cdxGetValueFile,
  216. ( DBENTRYP_VP ) hb_cdxOpenMemFile,
  217. ( DBENTRYP_SVP ) hb_cdxPutValueFile,
  218. /* Database file header handling */
  219. ( DBENTRYP_V ) hb_cdxReadDBHeader,
  220. ( DBENTRYP_V ) hb_cdxWriteDBHeader,
  221. /* non WorkArea functions */
  222. ( DBENTRYP_I0 ) hb_cdxExit,
  223. ( DBENTRYP_I1 ) hb_cdxDrop,
  224. ( DBENTRYP_I2 ) hb_cdxExists,
  225. /* Special and reserved methods */
  226. ( DBENTRYP_SVP ) hb_cdxWhoCares
  227. };
  228. HB_FUNC( _DBFCDX ) {;}
  229. HB_FUNC( DBFCDX_GETFUNCTABLE )
  230. {
  231. RDDFUNCS * pTable;
  232. USHORT * uiCount;
  233. uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) );
  234. pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) );
  235. HB_TRACE(HB_TR_DEBUG, ("DBFCDX_GETFUNCTABLE(%i, %p)", uiCount, pTable));
  236. if ( pTable )
  237. {
  238. SHORT iRet;
  239. if ( uiCount )
  240. * uiCount = RDDFUNCSCOUNT;
  241. iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFFPT" );
  242. if ( iRet == FAILURE )
  243. iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFDBT" );
  244. if ( iRet == FAILURE )
  245. iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" );
  246. hb_retni( iRet );
  247. }
  248. else
  249. hb_retni( FAILURE );
  250. }
  251. HB_INIT_SYMBOLS_BEGIN( dbfcdx1__InitSymbols )
  252. { "_DBFCDX", HB_FS_PUBLIC, {HB_FUNCNAME( _DBFCDX )}, NULL },
  253. { "DBFCDX_GETFUNCTABLE", HB_FS_PUBLIC, {HB_FUNCNAME( DBFCDX_GETFUNCTABLE )}, NULL }
  254. HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols )
  255. #if defined(HB_PRAGMA_STARTUP)
  256. #pragma startup dbfcdx1__InitSymbols
  257. #elif defined(_MSC_VER)
  258. #if _MSC_VER >= 1010
  259. #pragma data_seg( ".CRT$XIY" )
  260. #pragma comment( linker, "/Merge:.CRT=.data" )
  261. #else
  262. #pragma data_seg( "XIY" )
  263. #endif
  264. static HB_$INITSYM hb_vm_auto_dbfcdx1__InitSymbols = dbfcdx1__InitSymbols;
  265. #pragma data_seg()
  266. #endif
  267. #ifdef HB_CDX_DSPDBG_INFO
  268. static void hb_cdxDspTags( LPCDXINDEX pIndex )
  269. {
  270. LPCDXTAG pTag = NULL;
  271. printf( "\r\n*TAGS*" );
  272. while ( pIndex )
  273. {
  274. printf( "\r\nBAG: [%s] ->", pIndex->szFileName );
  275. pTag = pIndex->TagList;
  276. while ( pTag )
  277. {
  278. printf( " {%s}", pTag->szName );
  279. pTag = pTag->pNext;
  280. }
  281. pIndex = pIndex->pNext;
  282. }
  283. printf( "\r\n*END*\r\n" ); fflush( stdout );
  284. }
  285. #endif
  286. #ifdef HB_CDX_DBGTIME
  287. #include <sys/time.h>
  288. typedef LONGLONG CDXDBGTIME;
  289. static CDXDBGTIME cdxTimeIntBld = 0;
  290. static CDXDBGTIME cdxTimeExtBld = 0;
  291. static CDXDBGTIME cdxTimeIntBlc = 0;
  292. static CDXDBGTIME cdxTimeExtBlc = 0;
  293. static CDXDBGTIME cdxTimeGetKey = 0;
  294. static CDXDBGTIME cdxTimeFreeKey = 0;
  295. static CDXDBGTIME cdxTimeIdxBld = 0;
  296. static CDXDBGTIME hb_cdxGetTime()
  297. {
  298. struct timeval tv;
  299. gettimeofday(&tv, NULL);
  300. return ( (CDXDBGTIME) tv.tv_sec * 1000000 + (CDXDBGTIME) tv.tv_usec );
  301. }
  302. #endif
  303. #ifdef HB_CDX_DBGUPDT
  304. static ULONG cdxWriteNO = 0;
  305. static ULONG cdxReadNO = 0;
  306. static SHORT cdxStackSize = 0;
  307. static SHORT cdxTmpStackSize = 0;
  308. #endif
  309. /*
  310. * internal DBFCDX function
  311. */
  312. static void hb_cdxErrInternal( char * szMsg )
  313. {
  314. hb_errInternal( 9201, szMsg ? szMsg : "hb_cdxErrInternal: data integrity error.", "", "" );
  315. }
  316. static ERRCODE hb_cdxErrorRT( CDXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char * filename, USHORT uiOsCode, USHORT uiFlags )
  317. {
  318. PHB_ITEM pError;
  319. ERRCODE iRet;
  320. pError = hb_errNew();
  321. hb_errPutGenCode( pError, uiGenCode );
  322. hb_errPutSubCode( pError, uiSubCode );
  323. hb_errPutOsCode( pError, uiOsCode );
  324. hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) );
  325. if ( filename )
  326. hb_errPutFileName( pError, filename );
  327. if ( uiFlags )
  328. hb_errPutFlags( pError, uiFlags );
  329. iRet = SELF_ERROR( ( AREAP ) pArea, pError );
  330. hb_itemRelease( pError );
  331. return iRet;
  332. }
  333. /*
  334. * create index sort table
  335. */
  336. static void hb_cdxMakeSortTab( CDXAREAP pArea )
  337. {
  338. #ifndef HB_CDP_SUPPORT_OFF
  339. if ( pArea->cdPage && pArea->cdPage->lSort && !pArea->bCdxSortTab )
  340. {
  341. int i, j, l;
  342. BYTE * pbSort;
  343. BYTE b;
  344. pArea->bCdxSortTab = ( BYTE * ) hb_xgrab( 256 );
  345. pbSort = ( BYTE * ) hb_xgrab( 256 );
  346. /* this table should be allready quite good sorted so this simple
  347. algorithms will be one of the most efficient one. */
  348. for ( i = 0; i <= 255; i++ )
  349. pbSort[i] = ( BYTE ) i;
  350. l = 255;
  351. do
  352. {
  353. j = l;
  354. for( i = 0; i < j; i++ )
  355. {
  356. if ( hb_cdpchrcmp( pbSort[i], pbSort[i+1], pArea->cdPage ) > 0 )
  357. {
  358. b = pbSort[i+1];
  359. pbSort[i+1] = pbSort[i];
  360. pbSort[i] = b;
  361. l = i;
  362. }
  363. }
  364. } while ( j != l );
  365. for ( i = 0; i <= 255; i++ )
  366. pArea->bCdxSortTab[pbSort[i]] = i;
  367. hb_xfree( pbSort );
  368. }
  369. #endif
  370. }
  371. /*
  372. * create new index key
  373. */
  374. static LPCDXKEY hb_cdxKeyNew( void )
  375. {
  376. LPCDXKEY pKey;
  377. pKey = ( LPCDXKEY ) hb_xgrab( sizeof( CDXKEY ) );
  378. memset( pKey, 0, sizeof( CDXKEY ) );
  379. return pKey;
  380. }
  381. /*
  382. * Free index key
  383. */
  384. static void hb_cdxKeyFree( LPCDXKEY pKey )
  385. {
  386. if ( pKey->val )
  387. hb_xfree( pKey->val );
  388. hb_xfree( pKey );
  389. }
  390. /*
  391. * copy index key, if dst is null create new dst key else destroy dst
  392. */
  393. static LPCDXKEY hb_cdxKeyCopy( LPCDXKEY pKeyDest, LPCDXKEY pKey )
  394. {
  395. if ( !pKeyDest )
  396. pKeyDest = hb_cdxKeyNew();
  397. else
  398. {
  399. pKeyDest->rec = 0;
  400. if ( pKeyDest->val && pKeyDest->len != pKey->len )
  401. {
  402. hb_xfree( pKeyDest->val );
  403. pKeyDest->val = NULL;
  404. pKeyDest->len = 0;
  405. }
  406. }
  407. if ( pKey )
  408. {
  409. if ( pKey->len )
  410. {
  411. if ( !pKeyDest->val )
  412. pKeyDest->val = (BYTE *) hb_xgrab( pKey->len + 1 );
  413. memcpy( pKeyDest->val, pKey->val, pKey->len );
  414. pKeyDest->len = pKey->len;
  415. pKeyDest->val[ pKeyDest->len ] = '\0';
  416. }
  417. pKeyDest->rec = pKey->rec;
  418. }
  419. return pKeyDest;
  420. }
  421. /*
  422. * store bytes value in inkdex key
  423. */
  424. static LPCDXKEY hb_cdxKeyPut( LPCDXKEY pKey, BYTE * pbVal, USHORT uiLen, ULONG ulRec )
  425. {
  426. if ( !pKey )
  427. pKey = hb_cdxKeyNew();
  428. else
  429. {
  430. if ( pKey->val && pKey->len != uiLen )
  431. {
  432. hb_xfree( pKey->val );
  433. pKey->val = NULL;
  434. pKey->len = 0;
  435. }
  436. }
  437. if ( pbVal && uiLen )
  438. {
  439. pKey->len = (BYTE) uiLen;
  440. if ( !pKey->val )
  441. pKey->val = ( BYTE * ) hb_xgrab( uiLen + 1 );
  442. memcpy( pKey->val, pbVal, uiLen );
  443. pKey->val[ uiLen ] = '\0';
  444. }
  445. pKey->rec = ulRec;
  446. return pKey;
  447. }
  448. /*
  449. * store string0 value in index key
  450. */
  451. static LPCDXKEY hb_cdxKeyPutC( LPCDXKEY pKey, char * szText, USHORT uiRealLen, ULONG ulRec )
  452. {
  453. USHORT uiLen;
  454. if ( !pKey )
  455. pKey = hb_cdxKeyNew();
  456. else
  457. {
  458. if ( pKey->val )
  459. {
  460. hb_xfree( pKey->val );
  461. pKey->val = NULL;
  462. pKey->len = 0;
  463. }
  464. }
  465. uiLen = (USHORT) ( szText ? strlen( szText ) : 0 );
  466. if ( uiLen > uiRealLen )
  467. uiLen = uiRealLen;
  468. pKey->len = ( BYTE ) uiRealLen;
  469. pKey->val = ( BYTE * ) hb_xgrab( uiRealLen + 1 );
  470. if ( uiLen )
  471. memcpy( pKey->val, szText, uiLen );
  472. if ( uiLen < uiRealLen )
  473. memset( &pKey->val[ uiLen ], ' ', uiRealLen - uiLen );
  474. pKey->val[ uiRealLen ] = '\0';
  475. pKey->rec = ulRec;
  476. return pKey;
  477. }
  478. /*
  479. * compare two values using Tag conditions (len & type)
  480. */
  481. static int hb_cdxValCompare( LPCDXTAG pTag, BYTE * val1, BYTE len1,
  482. BYTE * val2, BYTE len2, BOOL fExact )
  483. {
  484. int iLimit, iResult = 0;
  485. iLimit = (len1 > len2) ? len2 : len1;
  486. if ( pTag->uiType == 'C' )
  487. {
  488. #ifndef HB_CDP_SUPPORT_OFF
  489. if ( pTag->pIndex->pArea->bCdxSortTab )
  490. {
  491. BYTE * pSort = pTag->pIndex->pArea->bCdxSortTab;
  492. int iPos = 0;
  493. while ( iResult == 0 && iPos < iLimit )
  494. {
  495. iResult = pSort[ val1[ iPos ] ] - pSort[ val2[ iPos ] ];
  496. iPos++;
  497. }
  498. }
  499. else
  500. #endif
  501. if ( iLimit > 0 )
  502. iResult = memcmp( val1, val2, iLimit );
  503. if ( iResult == 0 )
  504. {
  505. if ( len1 > len2 )
  506. iResult = 1;
  507. else if ( len1 < len2 && fExact )
  508. iResult = -1;
  509. }
  510. }
  511. else
  512. {
  513. if ( iLimit == 0 || (iResult = memcmp( val1, val2, iLimit )) == 0 )
  514. {
  515. if ( len1 > len2 )
  516. iResult = 1;
  517. else if ( len1 < len2 )
  518. iResult = -1;
  519. }
  520. }
  521. return iResult;
  522. }
  523. /*
  524. * store Item in index key
  525. * TODO: uiType check and generate RT error if necessary
  526. */
  527. static LPCDXKEY hb_cdxKeyPutItem( LPCDXKEY pKey, PHB_ITEM pItem, ULONG ulRec, LPCDXTAG pTag, BOOL fTrans, BOOL fSize )
  528. {
  529. BYTE buf[CDX_MAXKEY], *ptr;
  530. BYTE len = 0;
  531. double d;
  532. ptr = &buf[0];
  533. switch ( hb_itemType( pItem ) )
  534. {
  535. case HB_IT_STRING:
  536. case HB_IT_STRING | HB_IT_MEMO:
  537. len = (BYTE) HB_MIN( pItem->item.asString.length, (ULONG) pTag->uiLen );
  538. if ( fSize && len < pTag->uiLen )
  539. {
  540. memcpy( ptr, pItem->item.asString.value, len );
  541. memset( ptr + len, pTag->uiType == 'C' ? ' ' : '\0', pTag->uiLen - len );
  542. len = ( BYTE ) pTag->uiLen;
  543. }
  544. else
  545. {
  546. ptr = ( BYTE * ) pItem->item.asString.value;
  547. }
  548. break;
  549. case HB_IT_INTEGER:
  550. case HB_IT_LONG:
  551. case HB_IT_DOUBLE:
  552. d = hb_itemGetND( pItem );
  553. HB_DBL2ORD( &d, ptr );
  554. len = 8;
  555. break;
  556. case HB_IT_DATE:
  557. d = (double) pItem->item.asDate.value;
  558. HB_DBL2ORD( &d, ptr );
  559. len = 8;
  560. break;
  561. case HB_IT_LOGICAL:
  562. *ptr = (BYTE) ( hb_itemGetL( pItem ) ? 'T' : 'F' );
  563. len = 1;
  564. break;
  565. default:
  566. ptr = NULL;
  567. #ifdef HB_CDX_DBGCODE
  568. /* TODO: RTerror */
  569. printf( "hb_cdxKeyPutItem( invalid item type: %i )", hb_itemType( pItem ) );
  570. #endif
  571. break;
  572. }
  573. pKey = hb_cdxKeyPut( pKey, ptr, len, ulRec );
  574. #ifndef HB_CDP_SUPPORT_OFF
  575. if ( fTrans && pTag->uiType == 'C' )
  576. hb_cdpnTranslate( ( char * ) pKey->val, hb_cdp_page, pTag->pIndex->pArea->cdPage, pKey->len );
  577. #endif
  578. return pKey;
  579. }
  580. /*
  581. * get Item from index key (TODO: add pTag param)
  582. */
  583. static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEY pKey, PHB_ITEM pItem, USHORT uiType )
  584. {
  585. double d;
  586. if ( pKey )
  587. {
  588. switch( uiType )
  589. {
  590. case 'C':
  591. pItem = hb_itemPutCL( pItem, ( char * ) pKey->val, pKey->len );
  592. break;
  593. case 'N':
  594. HB_ORD2DBL( pKey->val, &d );
  595. pItem = hb_itemPutND( pItem, d );
  596. break;
  597. case 'D':
  598. HB_ORD2DBL( pKey->val, &d );
  599. pItem = hb_itemPutDL( pItem, ( LONG ) d );
  600. break;
  601. case 'L':
  602. pItem = hb_itemPutL( pItem, pKey->val[0] == 'T' );
  603. break;
  604. default:
  605. pItem = hb_itemNew( pItem );
  606. #ifdef HB_CDX_DBGCODE
  607. printf( "hb_cdxKeyGetItem() ??? (%x)\n", uiType );
  608. #endif
  609. }
  610. }
  611. else if ( pItem )
  612. hb_itemClear( pItem );
  613. else
  614. pItem = hb_itemNew( NULL );
  615. return pItem;
  616. }
  617. /*
  618. * evaluate key expression and create new Key from the result
  619. */
  620. static LPCDXKEY hb_cdxKeyEval( LPCDXKEY pKey, LPCDXTAG pTag, BOOL fSetWA )
  621. {
  622. HB_MACRO_PTR pMacro;
  623. int iCurrArea = 0;
  624. CDXAREAP pArea = pTag->pIndex->pArea;
  625. #ifndef HB_CDP_SUPPORT_OFF
  626. /* TODO: this hack is not thread safe, hb_cdp_page has to be thread specific */
  627. PHB_CODEPAGE cdpTmp = hb_cdp_page;
  628. hb_cdp_page = pArea->cdPage;
  629. #endif
  630. if ( fSetWA && !pTag->nField )
  631. {
  632. iCurrArea = hb_rddGetCurrentWorkAreaNumber();
  633. if ( iCurrArea != pArea->uiArea )
  634. hb_rddSelectWorkAreaNumber( pArea->uiArea );
  635. else
  636. iCurrArea = 0;
  637. }
  638. if ( pTag->nField )
  639. {
  640. PHB_ITEM pItem = hb_itemNew( NULL );
  641. SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem );
  642. pKey = hb_cdxKeyPutItem( pKey, pItem, pArea->ulRecNo, pTag, FALSE, TRUE );
  643. hb_itemRelease( pItem );
  644. }
  645. else if ( HB_IS_BLOCK( pTag->pKeyItem ) )
  646. {
  647. pKey = hb_cdxKeyPutItem( pKey, hb_vmEvalBlock( pTag->pKeyItem ), pArea->ulRecNo, pTag, FALSE, TRUE );
  648. }
  649. else
  650. {
  651. pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
  652. hb_macroRun( pMacro );
  653. pKey = hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( -1 ), pArea->ulRecNo, pTag, FALSE, TRUE );
  654. hb_stackPop();
  655. }
  656. if ( iCurrArea )
  657. hb_rddSelectWorkAreaNumber( iCurrArea );
  658. #ifndef HB_CDP_SUPPORT_OFF
  659. hb_cdp_page = cdpTmp;
  660. #endif
  661. return pKey;
  662. }
  663. /*
  664. * evaluate macro expression
  665. * the result is on the stack hb_stackItemFromTop(-1)
  666. * TODO: eliminate it by implementing macro evaluation
  667. * in SELF_EVALBLOCK( AREAP pArea, PHB_ITEM pExpr)
  668. */
  669. static void hb_cdxMacroRun( CDXAREAP pArea, HB_MACRO_PTR pMacro )
  670. {
  671. int iCurrArea;
  672. iCurrArea = hb_rddGetCurrentWorkAreaNumber();
  673. if ( iCurrArea != pArea->uiArea )
  674. hb_rddSelectWorkAreaNumber( pArea->uiArea );
  675. else
  676. iCurrArea = 0;
  677. hb_macroRun( pMacro );
  678. if ( iCurrArea )
  679. hb_rddSelectWorkAreaNumber( iCurrArea );
  680. }
  681. /*
  682. * evaluate conditional expression and return the result
  683. */
  684. static BOOL hb_cdxEvalCond( CDXAREAP pArea, PHB_ITEM pCondItem, BOOL fSetWA )
  685. {
  686. HB_MACRO_PTR pMacro;
  687. int iCurrArea = 0;
  688. BOOL fRet;
  689. if ( !pCondItem )
  690. return TRUE;
  691. if ( fSetWA ) {
  692. iCurrArea = hb_rddGetCurrentWorkAreaNumber();
  693. if ( iCurrArea != pArea->uiArea )
  694. hb_rddSelectWorkAreaNumber( pArea->uiArea );
  695. else
  696. iCurrArea = 0;
  697. }
  698. if ( HB_IS_BLOCK( pCondItem ) )
  699. {
  700. fRet = hb_itemGetL( hb_vmEvalBlock( pCondItem ) );
  701. }
  702. else
  703. {
  704. pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pCondItem );
  705. hb_macroRun( pMacro );
  706. fRet = hb_itemGetL( hb_stackItemFromTop( -1 ) );
  707. hb_stackPop();
  708. }
  709. if ( iCurrArea )
  710. hb_rddSelectWorkAreaNumber( iCurrArea );
  711. return fRet;
  712. }
  713. /*
  714. * evaluate seek/skip block: {|key, rec| ... }
  715. */
  716. static BOOL hb_cdxEvalSeekCond( LPCDXTAG pTag, PHB_ITEM pCondItem )
  717. {
  718. BOOL fRet;
  719. HB_ITEM ItemKey;
  720. if ( ! HB_IS_BLOCK( pCondItem ) )
  721. return TRUE;
  722. ItemKey.type = HB_IT_NIL;
  723. hb_cdxKeyGetItem( pTag->CurKey, &ItemKey, pTag->uiType );
  724. hb_vmPushSymbol( &hb_symEval );
  725. hb_vmPush( pCondItem );
  726. hb_vmPush( &ItemKey );
  727. hb_vmPushLong( ( LONG ) pTag->CurKey->rec );
  728. hb_vmDo( 2 );
  729. fRet = hb_itemGetL( hb_stackReturnItem() );
  730. hb_itemClear( &ItemKey );
  731. return fRet;
  732. }
  733. /*
  734. * find field index for single field expressions
  735. */
  736. static USHORT hb_cdxFieldIndex( CDXAREAP pArea, char * cExpr )
  737. {
  738. char szKeyExpr[ CDX_MAXKEY + 1 ],
  739. szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ];
  740. int i, j, l, n = 0;
  741. if ( SELF_ALIAS( ( AREAP ) pArea, ( BYTE * ) szAlias ) == SUCCESS )
  742. l = strlen( szAlias );
  743. else
  744. l = 0;
  745. hb_strncpyUpperTrim( szKeyExpr, cExpr, CDX_MAXKEY );
  746. /*
  747. * strip the _FIELD-> and FIELD-> prefix, it could be nested so repeat
  748. * this process until all prefixes will be removed
  749. */
  750. do
  751. {
  752. j = n;
  753. if ( strncmp( &szKeyExpr[ n ], "FIELD", 5 ) == 0 )
  754. i = 5;
  755. else if ( strncmp( &szKeyExpr[ n ], "_FIELD", 6 ) == 0 )
  756. i = 6;
  757. else if ( l > 0 && strncmp( &szKeyExpr[ n ], szAlias, l ) == 0 )
  758. i = l;
  759. else
  760. i = 0;
  761. if ( i > 0 )
  762. {
  763. i = n + 5;
  764. while ( szKeyExpr[ i ] == ' ' )
  765. i++;
  766. if ( szKeyExpr[ i ] == '-' && szKeyExpr[ i + 1 ] == '>' )
  767. {
  768. n = i + 2;
  769. while ( szKeyExpr[ n ] == ' ' )
  770. n++;
  771. }
  772. }
  773. }
  774. while ( n != j );
  775. return hb_rddFieldIndex( ( AREAP ) pArea, &szKeyExpr[ n ] );
  776. }
  777. /*
  778. * check if Key is in top scope
  779. */
  780. static BOOL hb_cdxTopScope( LPCDXTAG pTag )
  781. {
  782. LPCDXKEY pKey;
  783. if ( pTag->UsrAscend )
  784. {
  785. pKey = pTag->topScopeKey;
  786. return !pKey || !pKey->len ||
  787. hb_cdxValCompare( pTag, pKey->val, pKey->len,
  788. pTag->CurKey->val, pTag->CurKey->len, FALSE ) <= 0;
  789. }
  790. else
  791. {
  792. pKey = pTag->bottomScopeKey;
  793. return !pKey || !pKey->len ||
  794. hb_cdxValCompare( pTag, pKey->val, pKey->len,
  795. pTag->CurKey->val, pTag->CurKey->len, FALSE ) >= 0;
  796. }
  797. }
  798. /*
  799. * check if Key is in bottom scope
  800. */
  801. static BOOL hb_cdxBottomScope( LPCDXTAG pTag )
  802. {
  803. LPCDXKEY pKey;
  804. if ( pTag->UsrAscend )
  805. {
  806. pKey = pTag->bottomScopeKey;
  807. return !pKey || !pKey->len ||
  808. hb_cdxValCompare( pTag, pKey->val, pKey->len,
  809. pTag->CurKey->val, pTag->CurKey->len, FALSE ) >= 0;
  810. }
  811. else
  812. {
  813. pKey = pTag->topScopeKey;
  814. return !pKey || !pKey->len ||
  815. hb_cdxValCompare( pTag, pKey->val, pKey->len,
  816. pTag->CurKey->val, pTag->CurKey->len, FALSE ) <= 0;
  817. }
  818. }
  819. /*
  820. * clear scopes
  821. */
  822. static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope )
  823. {
  824. PHB_ITEM *pScope;
  825. LPCDXKEY *pScopeKey;
  826. HB_TRACE(HB_TR_DEBUG, ("hb_cdxTagClearScope(%p, %hu)", pTag, nScope));
  827. if ( pTag->UsrAscend ? nScope == 0 : nScope != 0 )
  828. {
  829. pScope = &pTag->topScope;
  830. pScopeKey = &pTag->topScopeKey;
  831. }
  832. else
  833. {
  834. pScope = &pTag->bottomScope;
  835. pScopeKey = &pTag->bottomScopeKey;
  836. }
  837. if ( *pScope )
  838. {
  839. hb_itemRelease( *pScope );
  840. *pScope = NULL;
  841. }
  842. if ( *pScopeKey )
  843. {
  844. hb_cdxKeyFree( *pScopeKey );
  845. *pScopeKey = NULL;
  846. pTag->curKeyState &= ~( CDX_CURKEY_RAWCNT | CDX_CURKEY_LOGCNT );
  847. if ( nScope == 0 )
  848. pTag->curKeyState &= ~( CDX_CURKEY_RAWPOS | CDX_CURKEY_LOGPOS );
  849. }
  850. }
  851. #ifdef HB_CDX_DBGCODE_EXT
  852. /*
  853. * check internal integrity of page pool
  854. */
  855. static void hb_cdxTagPoolCheck( LPCDXTAG pTag )
  856. {
  857. LPCDXPAGE pPage, pPrevPage;
  858. pPage = pTag->pagePool;
  859. pPrevPage = NULL;
  860. while ( pPage )
  861. {
  862. if ( pPage->pPoolPrev != pPrevPage || pPage->TagParent != pTag )
  863. hb_cdxErrInternal( "hb_cdxTagPoolCheck: data integrity error." );
  864. pPrevPage = pPage;
  865. pPage = pPage->pPoolNext;
  866. }
  867. }
  868. /*
  869. * check if the Tag buffers was not changed without write lock
  870. */
  871. static void hb_cdxTagCheckBuffers( LPCDXTAG pTag )
  872. {
  873. BOOL fChanged = FALSE;
  874. hb_cdxTagPoolCheck( pTag );
  875. if ( pTag->TagChanged )
  876. fChanged = TRUE;
  877. else
  878. {
  879. LPCDXPAGE pPage = pTag->pagePool;
  880. while ( pPage && !fChanged )
  881. {
  882. fChanged = pPage->fChanged;
  883. pPage = pPage->pPoolNext;
  884. }
  885. }
  886. if ( fChanged )
  887. hb_cdxErrInternal( "hb_cdxTagCheckBuffers: modification without write lock." );
  888. }
  889. /*
  890. * check if the Index buffers was not changed without write lock
  891. */
  892. static void hb_cdxIndexCheckBuffers( LPCDXINDEX pIndex )
  893. {
  894. LPCDXTAG pTag;
  895. if ( pIndex->fChanged || ( pIndex->freeLst && pIndex->freeLst->fStat ) )
  896. hb_cdxErrInternal( "hb_cdxIndexCheckBuffers: modification without write lock." );
  897. if ( pIndex->pCompound )
  898. hb_cdxTagCheckBuffers( pIndex->pCompound );
  899. pTag = pIndex->TagList;
  900. while ( pTag )
  901. {
  902. hb_cdxTagCheckBuffers( pTag );
  903. pTag = pTag->pNext;
  904. }
  905. }
  906. #endif
  907. /*
  908. * get free index page
  909. */
  910. static ULONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex, BOOL bHeader )
  911. {
  912. FHANDLE hFile = pIndex->hFile;
  913. BYTE byBuf[4];
  914. ULONG ulPos;
  915. if ( pIndex->fReadonly )
  916. {
  917. hb_errInternal( 9101, "hb_cdxIndexGetAvailPage on readonly database.", "", "" );
  918. }
  919. if ( pIndex->fShared && !pIndex->lockWrite )
  920. {
  921. hb_errInternal( 9102, "hb_cdxIndexGetAvailPage on not locked index file.", "", "" );
  922. }
  923. if ( pIndex->freePage != 0 && pIndex->freePage != CDX_DUMMYNODE && !bHeader )
  924. {
  925. ulPos = pIndex->freePage;
  926. if ( pIndex->freeLst != NULL )
  927. {
  928. LPCDXLIST pLst = pIndex->freeLst;
  929. pIndex->freePage = pLst->ulAddr;
  930. pIndex->freeLst = pLst->pNext;
  931. hb_xfree( pLst );
  932. }
  933. else
  934. {
  935. if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos ||
  936. hb_fsRead( hFile, (BYTE *) byBuf, 4 ) != 4 )
  937. hb_errInternal( EDBF_READ, "hb_cdxIndexGetAvailPage: Read index page failed.", "", "" );
  938. pIndex->freePage = HB_GET_LE_UINT32( byBuf );
  939. #ifdef HB_CDX_DBGUPDT
  940. cdxReadNO++;
  941. #endif
  942. }
  943. }
  944. else
  945. {
  946. int iCnt = ( bHeader ? CDX_HEADERPAGES : 1 );
  947. if ( pIndex->nextAvail != CDX_DUMMYNODE )
  948. ulPos = pIndex->nextAvail;
  949. else
  950. ulPos = hb_fsSeek( hFile, 0, FS_END );
  951. pIndex->nextAvail = ulPos + iCnt * CDX_PAGELEN;
  952. /* TODO: ### */
  953. if ( bHeader )
  954. {
  955. BYTE byBuf[CDX_PAGELEN];
  956. memset( byBuf, 0, CDX_PAGELEN );
  957. if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos )
  958. hb_errInternal( EDBF_WRITE, "Write in index page failed.(1)", "", "" );
  959. while ( iCnt-- )
  960. {
  961. if ( hb_fsWrite( hFile, byBuf, CDX_PAGELEN ) != CDX_PAGELEN )
  962. hb_errInternal( EDBF_WRITE, "Write in index page failed.(2)", "", "" );
  963. }
  964. pIndex->fChanged = TRUE;
  965. }
  966. }
  967. return ulPos;
  968. }
  969. /*
  970. * free index page
  971. */
  972. static void hb_cdxIndexPutAvailPage( LPCDXINDEX pIndex, ULONG ulPos, BOOL bHeader )
  973. {
  974. if ( ulPos != 0 && ulPos != CDX_DUMMYNODE )
  975. {
  976. int iCnt = ( bHeader ? CDX_HEADERPAGES : 1 );
  977. LPCDXLIST pLst;
  978. if ( pIndex->fReadonly )
  979. hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" );
  980. if ( pIndex->fShared && !pIndex->lockWrite )
  981. hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" );
  982. while ( iCnt-- )
  983. {
  984. pLst = (LPCDXLIST) hb_xgrab( sizeof( CDXLIST ) );
  985. pLst->ulAddr = pIndex->freePage;
  986. pIndex->freePage = ulPos;
  987. pLst->fStat = TRUE;
  988. pLst->pNext = pIndex->freeLst;
  989. pIndex->freeLst = pLst;
  990. ulPos += CDX_PAGELEN;
  991. }
  992. }
  993. }
  994. /*
  995. * flush list of free pages into index file
  996. */
  997. static void hb_cdxIndexFlushAvailPage( LPCDXINDEX pIndex )
  998. {
  999. LPCDXLIST pLst = pIndex->freeLst;
  1000. BYTE byPageBuf[CDX_PAGELEN];
  1001. ULONG ulPos;
  1002. if ( pIndex->fReadonly )
  1003. hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" );
  1004. if ( pIndex->fShared && !pIndex->lockWrite )
  1005. hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" );
  1006. memset( byPageBuf, 0, CDX_PAGELEN );
  1007. ulPos = pIndex->freePage;
  1008. while ( pLst && pLst->fStat )
  1009. {
  1010. HB_PUT_LE_UINT32( byPageBuf, pLst->ulAddr );
  1011. if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
  1012. hb_fsWrite( pIndex->hFile, byPageBuf, CDX_PAGELEN ) != CDX_PAGELEN )
  1013. {
  1014. hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" );
  1015. }
  1016. pIndex->fChanged = TRUE;
  1017. ulPos = pLst->ulAddr;
  1018. pLst->fStat = FALSE;
  1019. pLst = pLst->pNext;
  1020. #ifdef HB_CDX_DBGUPDT
  1021. cdxWriteNO++;
  1022. #endif
  1023. }
  1024. }
  1025. /*
  1026. * drop list of free pages in index file
  1027. */
  1028. static void hb_cdxIndexDropAvailPage( LPCDXINDEX pIndex )
  1029. {
  1030. LPCDXLIST pLst;
  1031. while ( pIndex->freeLst )
  1032. {
  1033. pLst = pIndex->freeLst->pNext;
  1034. hb_xfree( pIndex->freeLst );
  1035. pIndex->freeLst = pLst;
  1036. }
  1037. }
  1038. /*
  1039. * write index page
  1040. */
  1041. static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer,
  1042. USHORT uiSize )
  1043. {
  1044. if ( pIndex->fReadonly )
  1045. hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", "", "" );
  1046. if ( pIndex->fShared && !pIndex->lockWrite )
  1047. hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", "", "" );
  1048. if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
  1049. hb_fsWrite( pIndex->hFile, pBuffer, uiSize ) != uiSize )
  1050. hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" );
  1051. pIndex->fChanged = TRUE;
  1052. #ifdef HB_CDX_DBGUPDT
  1053. cdxWriteNO++;
  1054. #endif
  1055. }
  1056. /*
  1057. * read index page
  1058. */
  1059. static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer,
  1060. USHORT uiSize )
  1061. {
  1062. if ( pIndex->fShared && !( pIndex->lockRead || pIndex->lockWrite ) )
  1063. hb_errInternal( 9103, "hb_cdxIndexPageRead on not locked index file.", "", "" );
  1064. if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos ||
  1065. hb_fsRead( pIndex->hFile, pBuffer, uiSize ) != uiSize )
  1066. hb_errInternal( EDBF_READ, "hb_cdxIndexPageRead: Read index page failed.", "", "" );
  1067. #ifdef HB_CDX_DBGUPDT
  1068. cdxReadNO++;
  1069. #endif
  1070. }
  1071. /*
  1072. * check if index was updated by other process and if it was discard buffers
  1073. */
  1074. static void hb_cdxIndexCheckVersion( LPCDXINDEX pIndex )
  1075. {
  1076. BYTE byBuf[8];
  1077. ULONG ulVer, ulFree;
  1078. if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
  1079. hb_fsRead( pIndex->hFile, byBuf, 8 ) != 8 )
  1080. {
  1081. if ( pIndex->lockWrite > 0 && hb_fsSeek( pIndex->hFile, 0, FS_END ) == 0 )
  1082. memset( byBuf, 0, 8 );
  1083. else
  1084. hb_errInternal( 2155, "hb_cdxIndexCheckVersion: Read error on index heading page.", "", "" );
  1085. }
  1086. #ifdef HB_CDX_DBGUPDT
  1087. cdxReadNO++;
  1088. #endif
  1089. ulFree = HB_GET_LE_UINT32( &byBuf[0] );
  1090. ulVer = HB_GET_BE_UINT32( &byBuf[4] );
  1091. if ( !pIndex->fShared )
  1092. pIndex->ulVersion = pIndex->freePage;
  1093. else if ( ulVer != pIndex->ulVersion || ulFree != pIndex->freePage )
  1094. {
  1095. pIndex->nextAvail = CDX_DUMMYNODE;
  1096. pIndex->ulVersion = ulVer;
  1097. pIndex->freePage = ulFree;
  1098. hb_cdxIndexDiscardBuffers( pIndex );
  1099. }
  1100. /* TODO: !!! ## remove it it's for test only */
  1101. /* hb_cdxIndexDiscardBuffers( pIndex ); */
  1102. }
  1103. /*
  1104. * lock index for reading (shared lock)
  1105. */
  1106. static BOOL hb_cdxIndexLockRead( LPCDXINDEX pIndex )
  1107. {
  1108. BOOL ret;
  1109. if ( pIndex->lockRead > 0 || pIndex->lockWrite > 0 ||
  1110. !pIndex->pArea->fShared || !pIndex->fShared )
  1111. {
  1112. pIndex->lockRead++;
  1113. return TRUE;
  1114. }
  1115. #ifdef HB_CDX_DBGCODE
  1116. if ( pIndex->lockRead != 0 )
  1117. hb_errInternal( 9105, "hb_cdxIndexLockRead: bad count of locks.", "", "" );
  1118. if ( pIndex->WrLck || pIndex->RdLck )
  1119. hb_errInternal( 9107, "hb_cdxIndexLockRead: lock failure (*)", "", "" );
  1120. pIndex->RdLck = TRUE;
  1121. #endif
  1122. ret = hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType,
  1123. FL_LOCK | FLX_SHARED | FLX_WAIT, &pIndex->ulLockPos );
  1124. if ( !ret )
  1125. hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0 );
  1126. if ( ret )
  1127. {
  1128. pIndex->lockRead++;
  1129. hb_cdxIndexCheckVersion( pIndex );
  1130. }
  1131. return ret;
  1132. }
  1133. /*
  1134. * lock index for writing (exclusive lock)
  1135. */
  1136. static BOOL hb_cdxIndexLockWrite( LPCDXINDEX pIndex )
  1137. {
  1138. BOOL ret;
  1139. if ( pIndex->lockRead )
  1140. hb_errInternal( 9105, "hb_cdxIndexLockRead: writeLock after readLock.", "", "" );
  1141. if ( pIndex->lockWrite > 0 )
  1142. {
  1143. pIndex->lockWrite++;
  1144. return TRUE;
  1145. }
  1146. if ( pIndex->lockWrite != 0 )
  1147. hb_errInternal( 9105, "hb_cdxIndexLockWrite: bad count of locks.", "", "" );
  1148. if ( !pIndex->pArea->fShared || !pIndex->fShared )
  1149. ret = TRUE;
  1150. else
  1151. {
  1152. #ifdef HB_CDX_DBGCODE
  1153. if ( pIndex->WrLck || pIndex->RdLck )
  1154. hb_errInternal( 9107, "hb_cdxIndexLockWrite: lock failure (*)", "", "" );
  1155. pIndex->WrLck = TRUE;
  1156. #endif
  1157. ret = hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType,
  1158. FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT, &pIndex->ulLockPos );
  1159. }
  1160. if ( !ret )
  1161. hb_cdxErrorRT( pIndex->pArea, EG_LOCK, EDBF_LOCK, pIndex->szFileName, hb_fsError(), 0 );
  1162. if ( ret )
  1163. {
  1164. pIndex->lockWrite++;
  1165. if ( pIndex->fShared || pIndex->nextAvail == CDX_DUMMYNODE )
  1166. hb_cdxIndexCheckVersion( pIndex );
  1167. }
  1168. return ret;
  1169. }
  1170. /*
  1171. * remove index read lock (shared lock)
  1172. */
  1173. static BOOL hb_cdxIndexUnLockRead( LPCDXINDEX pIndex )
  1174. {
  1175. pIndex->lockRead--;
  1176. if ( pIndex->lockRead < 0 )
  1177. {
  1178. hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" );
  1179. }
  1180. if ( pIndex->lockRead || pIndex->lockWrite )
  1181. {
  1182. return TRUE;
  1183. }
  1184. #ifdef HB_CDX_DBGCODE_EXT
  1185. hb_cdxIndexCheckBuffers( pIndex );
  1186. #endif
  1187. hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE );
  1188. if ( pIndex->pArea->fShared && pIndex->fShared )
  1189. {
  1190. #ifdef HB_CDX_DBGCODE
  1191. if ( pIndex->WrLck || ! pIndex->RdLck )
  1192. hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error (*)", "", "" );
  1193. pIndex->RdLck = FALSE;
  1194. #endif
  1195. if ( !hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType, FL_UNLOCK, &pIndex->ulLockPos ) )
  1196. {
  1197. hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error.", "", "" );
  1198. }
  1199. }
  1200. return TRUE;
  1201. }
  1202. /*
  1203. * remove index write lock (exclusive lock)
  1204. */
  1205. static BOOL hb_cdxIndexUnLockWrite( LPCDXINDEX pIndex )
  1206. {
  1207. if ( pIndex->lockWrite > 1 )
  1208. {
  1209. pIndex->lockWrite--;
  1210. return TRUE;
  1211. }
  1212. if ( pIndex->lockWrite < 1 )
  1213. {
  1214. hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" );
  1215. }
  1216. if ( pIndex->lockRead )
  1217. {
  1218. hb_errInternal( 9105, "hb_cdxIndexUnLockWrite: writeUnLock before readUnLock.", "", "" );
  1219. }
  1220. hb_cdxIndexFlushBuffers( pIndex );
  1221. hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE );
  1222. pIndex->lockWrite--;
  1223. if ( pIndex->pArea->fShared && pIndex->fShared )
  1224. {
  1225. if ( pIndex->fChanged )
  1226. {
  1227. BYTE byBuf[8];
  1228. (pIndex->ulVersion)++;
  1229. HB_PUT_LE_UINT32( &byBuf[0], pIndex->freePage );
  1230. HB_PUT_BE_UINT32( &byBuf[4], pIndex->ulVersion );
  1231. if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
  1232. hb_fsWrite( pIndex->hFile, byBuf, 8) != 8 )
  1233. {
  1234. hb_errInternal( EDBF_WRITE, "Write in index page failed (ver)", "", "" );
  1235. }
  1236. pIndex->fFlush = TRUE;
  1237. pIndex->fChanged = FALSE;
  1238. }
  1239. #ifdef HB_CDX_DBGCODE
  1240. if ( ! pIndex->WrLck || pIndex->RdLck )
  1241. hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error (*)", "", "" );
  1242. pIndex->WrLck = FALSE;
  1243. #endif
  1244. if ( !hb_dbfLockIdxFile( pIndex->hFile, pIndex->pArea->bLockType, FL_UNLOCK, &pIndex->ulLockPos ) )
  1245. {
  1246. hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error.", "", "" );
  1247. }
  1248. }
  1249. else
  1250. {
  1251. if ( pIndex->ulVersion != pIndex->freePage )
  1252. {
  1253. BYTE byBuf[4];
  1254. HB_PUT_LE_UINT32( &byBuf[0], pIndex->freePage );
  1255. if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 ||
  1256. hb_fsWrite( pIndex->hFile, byBuf, 4) != 4 )
  1257. {
  1258. hb_errInternal( EDBF_WRITE, "Write in index page failed (ver.ex)", "", "" );
  1259. }
  1260. pIndex->ulVersion = pIndex->freePage;
  1261. pIndex->fFlush = TRUE;
  1262. #ifdef HB_CDX_DBGUPDT
  1263. cdxWriteNO++;
  1264. #endif
  1265. }
  1266. else if ( pIndex->fChanged )
  1267. {
  1268. pIndex->fFlush = TRUE;
  1269. }
  1270. pIndex->fChanged = FALSE;
  1271. }
  1272. return TRUE;
  1273. }
  1274. /*
  1275. * discard all pages in cache (TagClose and TagPoolFree for all Tags)
  1276. */
  1277. static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex )
  1278. {
  1279. LPCDXTAG pTag;
  1280. #ifdef HB_CDX_DBGCODE_EXT
  1281. hb_cdxIndexCheckBuffers( pIndex );
  1282. #endif
  1283. hb_cdxIndexDropAvailPage( pIndex );
  1284. if ( pIndex->pCompound )
  1285. {
  1286. hb_cdxTagClose( pIndex->pCompound );
  1287. hb_cdxTagPoolFree( pIndex->pCompound, 0 );
  1288. pIndex->pCompound->fRePos = TRUE;
  1289. pIndex->pCompound->curKeyState = 0;
  1290. if ( pIndex->pCompound->CurKey )
  1291. pIndex->pCompound->CurKey->rec = 0;
  1292. }
  1293. pTag = pIndex->TagList;
  1294. while ( pTag )
  1295. {
  1296. hb_cdxTagClose( pTag );
  1297. hb_cdxTagPoolFree( pTag, 0 );
  1298. pTag->fRePos = TRUE;
  1299. pTag->curKeyState = 0;
  1300. if ( pTag->CurKey && !pTag->Custom )
  1301. pTag->CurKey->rec = 0;
  1302. pTag = pTag->pNext;
  1303. }
  1304. }
  1305. /*
  1306. * write all changed pages in cache (pagePool, pages in Tags and Tag Header)
  1307. */
  1308. static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex )
  1309. {
  1310. LPCDXTAG pTag;
  1311. if ( pIndex->pCompound )
  1312. {
  1313. hb_cdxTagPoolFlush( pIndex->pCompound );
  1314. if ( pIndex->pCompound->TagChanged )
  1315. hb_cdxTagHeaderStore( pIndex->pCompound );
  1316. }
  1317. pTag = pIndex->TagList;
  1318. while ( pTag )
  1319. {
  1320. hb_cdxTagPoolFlush( pTag );
  1321. if ( pTag->TagChanged )
  1322. hb_cdxTagHeaderStore( pTag );
  1323. pTag = pTag->pNext;
  1324. }
  1325. hb_cdxIndexFlushAvailPage( pIndex );
  1326. }
  1327. /*
  1328. * free cached pages of index file
  1329. */
  1330. static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft )
  1331. {
  1332. LPCDXTAG pTag;
  1333. if ( pIndex->pCompound )
  1334. {
  1335. hb_cdxTagPoolFree( pIndex->pCompound, nPagesLeft );
  1336. }
  1337. pTag = pIndex->TagList;
  1338. while ( pTag )
  1339. {
  1340. hb_cdxTagPoolFree( pTag, nPagesLeft );
  1341. pTag = pTag->pNext;
  1342. }
  1343. }
  1344. /*
  1345. * get key value ptr from index page
  1346. */
  1347. static BYTE * hb_cdxPageGetKeyVal( LPCDXPAGE pPage, SHORT iKey )
  1348. {
  1349. #ifdef HB_CDX_DBGCODE
  1350. if ( iKey < 0 || iKey >= pPage->iKeys )
  1351. hb_cdxErrInternal( "hb_cdxPageGetKeyVal: wrong iKey index." );
  1352. #endif
  1353. if ( pPage->pKeyBuf )
  1354. return &pPage->pKeyBuf[ iKey * ( pPage->TagParent->uiLen + 6 ) ];
  1355. else if ( pPage->PageType & CDX_NODE_LEAF )
  1356. {
  1357. SHORT iPos, iLen, iTmp, iTrl, iDup;
  1358. BYTE bTrail;
  1359. iLen = pPage->TagParent->uiLen;
  1360. bTrail = ( BYTE ) ( pPage->TagParent->uiType == 'C' ? ' ' : '\0' );
  1361. if ( iKey < pPage->bufKeyNum - 1 )
  1362. pPage->bufKeyNum = 0;
  1363. if ( pPage->bufKeyNum == 0 )
  1364. {
  1365. pPage->bufKeyPos = CDX_EXT_FREESPACE;
  1366. pPage->bufKeyLen = iLen;
  1367. }
  1368. while ( pPage->bufKeyNum <= iKey )
  1369. {
  1370. iPos = pPage->bufKeyNum * pPage->ReqByte;
  1371. iTmp = HB_GET_LE_UINT16( &pPage->node.extNode.keyPool[ iPos + pPage->ReqByte - 2 ] ) >>
  1372. ( 16 - pPage->TCBits - pPage->DCBits );
  1373. iDup = ( pPage->bufKeyNum == 0 ) ? 0 : ( iTmp & pPage->DCMask );
  1374. iTrl = ( iTmp >> pPage->DCBits ) & pPage->TCMask;
  1375. if ( ( iTmp = iLen - iDup - iTrl ) > 0 )
  1376. {
  1377. pPage->bufKeyPos -= iTmp;
  1378. memcpy( &pPage->bufKeyVal[ iDup ],
  1379. &pPage->node.extNode.keyPool[ pPage->bufKeyPos ], iTmp );
  1380. }
  1381. #ifdef HB_CDX_DBGCODE
  1382. else if ( iTmp < 0 )
  1383. {
  1384. printf("\r\npPage->Page=%lx, iLen=%d, iDup=%d, iTrl=%d", pPage->Page, iLen, iDup, iTrl); fflush(stdout);
  1385. hb_cdxErrInternal( "hb_cdxPageGetKeyVal: index corrupted." );
  1386. }
  1387. #endif
  1388. if ( iTrl > 0 && ( iTmp = pPage->bufKeyLen - iLen + iTrl ) > 0 )
  1389. memset( &pPage->bufKeyVal[ iLen - iTrl ], bTrail, iTmp );
  1390. pPage->bufKeyLen = iLen - iTrl;
  1391. pPage->bufKeyNum++;
  1392. }
  1393. return pPage->bufKeyVal;
  1394. }
  1395. else
  1396. return &pPage->node.intNode.keyPool[ iKey * ( pPage->TagParent->uiLen + 8 ) ];
  1397. }
  1398. /*
  1399. * get record number from index page
  1400. */
  1401. static ULONG hb_cdxPageGetKeyRec( LPCDXPAGE pPage, SHORT iKey )
  1402. {
  1403. #ifdef HB_CDX_DBGCODE
  1404. if ( iKey < 0 || iKey >= pPage->iKeys )
  1405. hb_cdxErrInternal( "hb_cdxPageGetKeyRec: wrong iKey index." );
  1406. #endif
  1407. if ( pPage->pKeyBuf )
  1408. return HB_GET_LE_UINT32( &pPage->pKeyBuf[ ( iKey + 1 ) * ( pPage->TagParent->uiLen + 6 ) - 6 ] );
  1409. else if ( pPage->PageType & CDX_NODE_LEAF )
  1410. return HB_GET_LE_UINT32( &pPage->node.extNode.keyPool[ iKey * pPage->ReqByte ] ) & pPage->RNMask;
  1411. else
  1412. return HB_GET_BE_UINT32( &pPage->node.intNode.keyPool[
  1413. ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 8 ] );
  1414. }
  1415. /*
  1416. * get child page number from interrior index page
  1417. */
  1418. static ULONG hb_cdxPageGetKeyPage( LPCDXPAGE pPage, SHORT iKey )
  1419. {
  1420. #ifdef HB_CDX_DBGCODE
  1421. if ( iKey < 0 || iKey >= pPage->iKeys )
  1422. hb_cdxErrInternal( "hb_cdxPageGetKeyPage: wrong iKey index." );
  1423. if ( pPage->PageType & CDX_NODE_LEAF )
  1424. hb_cdxErrInternal( "hb_cdxPageGetKeyPage: page is a leaf." );
  1425. #endif
  1426. return HB_GET_BE_UINT32( &pPage->node.intNode.keyPool[
  1427. ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 4 ] );
  1428. }
  1429. #if 0
  1430. /*
  1431. * get key from uncompressed page
  1432. */
  1433. static LPCDXKEY hb_cdxPageGetKey( LPCDXPAGE pPage, SHORT iKey, LPCDXKEY pKey )
  1434. {
  1435. return hb_cdxKeyPut( pKey,
  1436. hb_cdxPageGetKeyVal( pPage, iKey ),
  1437. pPage->TagParent->uiLen,
  1438. hb_cdxPageGetKeyRec( pPage, iKey ) );
  1439. }
  1440. #endif
  1441. #ifdef HB_CDX_DBGCODE_EXT
  1442. /*
  1443. * check if keys are sorted in proper order
  1444. */
  1445. static void hb_cdxPageCheckKeys( LPCDXPAGE pPage )
  1446. {
  1447. SHORT i, K, iLen = pPage->TagParent->uiLen;
  1448. ULONG ulRec, ulRecPrev;
  1449. BYTE * pbVal, pbValPrev[CDX_MAXKEY];
  1450. if ( pPage->iKeys > 1 )
  1451. {
  1452. pPage->bufKeyNum = 0;
  1453. pbVal = hb_cdxPageGetKeyVal( pPage, 0 );
  1454. ulRec = hb_cdxPageGetKeyRec( pPage, 0 );
  1455. for ( i = 1; i < pPage->iKeys; i++ )
  1456. {
  1457. memcpy( pbValPrev, pbVal, iLen );
  1458. ulRecPrev = ulRec;
  1459. pbVal = hb_cdxPageGetKeyVal( pPage, i );
  1460. ulRec = hb_cdxPageGetKeyRec( pPage, i );
  1461. K = hb_cdxValCompare( pPage->TagParent,
  1462. pbValPrev, iLen,
  1463. pbVal, iLen, TRUE );
  1464. if ( K > 0 || ( K == 0 && ulRecPrev >= ulRec ) )
  1465. {
  1466. printf( "\r\nikey=%d, pPage->iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld",
  1467. i, pPage->iKeys, K, ulRecPrev, ulRec );fflush(stdout);
  1468. printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pPage->pKeyBuf=%p, pPage->iCurKey=%d",
  1469. pbValPrev, pbVal, memcmp( pbValPrev, pbVal, iLen ),
  1470. pPage->pKeyBuf, pPage->iCurKey );fflush(stdout);
  1471. hb_cdxErrInternal( "hb_cdxPageCheckKeys: index corrupted." );
  1472. }
  1473. }
  1474. }
  1475. }
  1476. /*
  1477. * Check decoded leaf page if all trailing and duplicate characters are set
  1478. */
  1479. static void hb_cdxPageCheckDupTrl( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys, BOOL fSpc )
  1480. {
  1481. SHORT iNum = pPage->TagParent->uiLen, iKey, iPos, iFree = CDX_EXT_FREESPACE;
  1482. SHORT iLen = iNum + 6;
  1483. BYTE bDup, bTrl;
  1484. BYTE bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0';
  1485. BOOL bErr = FALSE;
  1486. for ( iKey = 0; iKey < iKeys; iKey++ )
  1487. {
  1488. iPos = iKey * iLen;
  1489. bTrl = bDup = 0;
  1490. while ( bTrl < iNum && pKeyBuf[ iPos + iNum - bTrl - 1 ] == bTrail )
  1491. ++bTrl;
  1492. if ( iKey > 0 )
  1493. {
  1494. #ifdef HB_CDX_PACKTRAIL
  1495. SHORT iMax = iNum - bTrl;
  1496. #else
  1497. SHORT iMax = iNum - HB_MAX( pKeyBuf[ iPos - 1 ], bTrl );
  1498. #endif
  1499. while ( bDup < iMax && pKeyBuf[ iPos + bDup ] ==
  1500. pKeyBuf[ iPos - iLen + bDup ] )
  1501. ++bDup;
  1502. }
  1503. if ( bTrl != pKeyBuf[ iPos + iNum + 5 ] )
  1504. {
  1505. printf("\r\nbTrl=%d, keybuf->bTrl=%d, iKey=%d/%d\r\n", bTrl, pKeyBuf[ iPos + iNum + 5 ], iKey, iKeys );
  1506. fflush(stdout);
  1507. bErr = TRUE;
  1508. }
  1509. if ( bDup != ( iKey == 0 ? 0 : pKeyBuf[ iPos + iNum + 4 ] ) )
  1510. {
  1511. printf("\r\nbDup=%d, keybuf->bDup=%d (bTrl=%d), iKey=%d/%d\r\n", bDup, pKeyBuf[ iPos + iNum + 4 ], bTrl, iKey, iKeys );
  1512. fflush(stdout);
  1513. bErr = TRUE;
  1514. }
  1515. if ( iKey > 0 )
  1516. {
  1517. SHORT K;
  1518. K = hb_cdxValCompare( pPage->TagParent,
  1519. &pKeyBuf[ iPos - iLen ], iNum,
  1520. &pKeyBuf[ iPos ], iNum, TRUE );
  1521. if ( K > 0 || ( K == 0 &&
  1522. HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum - iLen ] ) >=
  1523. HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum ] ) ) )
  1524. {
  1525. printf( "\r\nikey=%d, iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld",
  1526. iKey, iKeys, K,
  1527. (ULONG) HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum - iLen ] ),
  1528. (ULONG) HB_GET_LE_UINT32( &pKeyBuf[ iPos + iNum ] ) );
  1529. printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pKeyBuf=%p",
  1530. &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ],
  1531. memcmp( &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ], iNum ),
  1532. pKeyBuf );
  1533. fflush(stdout);
  1534. bErr = TRUE;
  1535. }
  1536. }
  1537. iFree -= iNum + pPage->ReqByte - bDup - bTrl;
  1538. }
  1539. if ( fSpc && ( iFree != pPage->iFree /* || iFree < 0 */ ) )
  1540. {
  1541. printf( "\r\nFreeSpace calculated wrong! iFree=%d, pPage->iFree=%d",
  1542. iFree, pPage->iFree );
  1543. fflush(stdout);
  1544. bErr = TRUE;
  1545. }
  1546. if ( bErr )
  1547. {
  1548. printf("\r\nPage=%lx, Page->iFree=%d, iLen=%d\r\n", pPage->Page, pPage->iFree, iNum );
  1549. fflush(stdout);
  1550. hb_cdxErrInternal( "hb_cdxPageCheckDupTrl: index corrupted." );
  1551. }
  1552. }
  1553. static void hb_cdxPageLeafDecode( LPCDXPAGE pPage, BYTE * pKeyBuf );
  1554. static void hb_cdxPageCheckDupTrlRaw( LPCDXPAGE pPage )
  1555. {
  1556. BYTE *pKeyBuf = (BYTE *) hb_xgrab( pPage->iKeys * ( pPage->TagParent->uiLen + 6 ) );
  1557. hb_cdxPageLeafDecode( pPage, pKeyBuf );
  1558. hb_cdxPageCheckDupTrl( pPage, pKeyBuf, pPage->iKeys, TRUE );
  1559. hb_xfree( pKeyBuf );
  1560. }
  1561. #endif
  1562. /*
  1563. * put record and duplicate + trailing counters into leaf page
  1564. */
  1565. static void hb_cdxSetLeafRecord( BYTE *pDst, ULONG ulRec, int iDup, int iTrl,
  1566. int iReq, int iDCbits, int iTCbits )
  1567. {
  1568. int i;
  1569. USHORT usBit;
  1570. usBit = ( ( iTrl << iDCbits ) | iDup ) << ( 16 - iTCbits - iDCbits );
  1571. for ( i = 0; i < iReq; i++, ulRec >>= 8 )
  1572. {
  1573. if ( i < iReq - 2 )
  1574. pDst[ i ] = ( BYTE ) ( ulRec & 0xff );
  1575. else if ( i == iReq - 2 )
  1576. pDst[ i ] = ( BYTE ) ( ulRec & 0xff ) | ( usBit & 0xff );
  1577. else
  1578. pDst[ i ] = ( BYTE ) ( ulRec & 0xff ) | ( ( usBit >> 8 ) & 0xff );
  1579. }
  1580. }
  1581. /*
  1582. * encode keys in buffer into cdx leaf node
  1583. */
  1584. static void hb_cdxPageLeafEncode( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys )
  1585. {
  1586. int iKey, iTrl, iDup, iReq, iTmp, iNum, iLen;
  1587. BYTE *pKeyPos, *pRecPos, *pSrc;
  1588. #ifdef HB_CDX_DBGCODE
  1589. if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 )
  1590. {
  1591. printf("\r\npPage->Page=%lx. left=%lx, right=%lx",
  1592. pPage->Page, pPage->Left, pPage->

Large files files are truncated, but you can click here to view the full file