PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/harbour-1.0.0/contrib/hbbmcdx/bmdbfcdx.c

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

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