* *
* partial sync with the 3.4 fork codebase. These are the things
synces for the most part:
- copyright headers
- grammar/typos in comments and some readmes
- comment/whitespace/decorations
- variable scoping in C files
- DO CASE/SWITCH and some other alternate syntax usage
- minimal amount of human readable text in strings
- minor code updates
- HB_TRACE() void * casts for pointers and few other changes to
avoid C compiler warnings
- various other, minor code cleanups
- only Harbour/C code/headers were touched in src, utils, contrib,
include. No 3rd party code, no make files, and with just a few
exceptions, no 'tests' code was touched.
- certain components were not touched were 3.4 diverged too much
already, like f.e. hbmk2, hbssl, hbcurl, hbexpat
- the goal was that no actual program logic should be altered by
these changes. Except some possible minor exceptions, any such
change is probably a bug in this patch.
It's a massive patch, if you find anything broken after it, please
open an Issue with the details. Build test was done on macOS.
The goal is make it easier to see what actual code/logic was changed
in 3.4 compared to 3.2 and to make patches easier to apply in both
ways.
592 lines
23 KiB
C
592 lines
23 KiB
C
/*
|
|
* DBFNSX RDD
|
|
*
|
|
* Copyright 2008 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; see the file LICENSE.txt. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
NSX description:
|
|
1. Keys are stored in interior (branch) and exterior (leaf) nodes
|
|
like in NTX not a CDX where all keys are in leaf nodes and keys
|
|
in interior nodes are duplicated higher key value in subnodes.
|
|
2. The hidden part of index key is record number what causes that
|
|
keys are always unique (like in CDX not in NTX)
|
|
3. Because the leaf and branch nodes have different internal structure
|
|
it's necessary to keep the index tree well balanced (all leaf
|
|
nodes have to be located at the same level). The number of keys
|
|
in leaf pages is variable and the keys in interior node records
|
|
are not duplicated in leafs so when index is created it's impossible
|
|
to calculate the optimal tree in one pass. To resolve this problem
|
|
at the end empty pages (without keys) must be added to the tree.
|
|
Then the keys in the two last pages at each level can be balanced
|
|
if we want to keep strict minimum keys in page factor or want to
|
|
eliminate empty pages though it's not necessary in interior nodes.
|
|
Only last leaf page cannot be empty because it breaks classic index
|
|
navigation code. To resolve this problem SIX3 NSX RDD moves the
|
|
last key added to index from branch node to the last empty leaf
|
|
node and then moves the last key from the leaf node before last
|
|
to the branch page from which the last index key was taken. It
|
|
does not balance the right most pages. This may not work correctly
|
|
for unique indexes if the last key is not added to the index because
|
|
it's replicated. In such case SIX3 creates buggy indexes - Harbour
|
|
will report them as corrupted after dbGoBottom(). Harbour creates
|
|
correct indexes.
|
|
4. All numbers are in little endian byte order
|
|
5. The numeric and date key values are modified IEEE754 double value
|
|
8 bytes length (the same format as in CDX), the logical values are
|
|
1-byte length "T" or "F"
|
|
6. Minimum RecNoLen used by SIX3 driver seems to be 2 and maximum 3!!!
|
|
It means that tables with more then 167772165 are not supported.
|
|
SIX3 RDD creates indexes for them but they are buggy and the most
|
|
important byte in record number is lost. It cannot be easy detected
|
|
in normal navigation so Harbour will report corruption error only
|
|
during update operation if previous key value with valid record
|
|
number cannot be located. Harbour RDD does not have such limit
|
|
and can support 2^32-2 records = 4294967294.
|
|
7. Branch nodes have also field to mark record length (RecNoLen) but
|
|
it seems to be unused (filled with 0 or 4) and record number is
|
|
always stored in 4 bytes.
|
|
8. Maximum key length is set to 250 but in fact with 4 bytes record
|
|
length such keys cannot be supported without adding some hack because
|
|
RecNoLen[4] + Size[1] + DupCount[1] + 250 gives 256 and it cannot
|
|
be stored in 1 byte (Size). We can add support for such long
|
|
indexes but we have to define that Size=0 means Size=256. It can
|
|
be done because Size=0 cannot appear in other way. I implemented
|
|
it and Harbour works well with such indexes.
|
|
9. In root header is address of 1st available free page in index file,
|
|
addresses of next pages are stored in the free pages at the same
|
|
position as in root header (offset = 6)
|
|
10.Leaf nodes use for duplicate compression keys' values from upper
|
|
interior nodes so it's necessary to keep them on the index tree
|
|
stack. The first key in index is not compressed at all.
|
|
11.Non duplicated part of key in leaf page is compressed by RLE
|
|
algorithm and special RLE char is 0xFF.
|
|
12.During indexing SIX3 NSX RDD adds key to leaf node only if it can be
|
|
added in raw form without any compression. It checks if free space
|
|
in leaf node is at least KEY_LEN + RECNO_LEN + 2 and if it is
|
|
then it always adds key. It should be safe but seems that it uses
|
|
hard coded RECNO_LEN=2 value so when RECNO_LEN is 3 (DBF has more
|
|
then 64645 records) the last byte from key can be lost!!! and corrupted
|
|
index is created. Harbour NSX RDD checks if there is enough space for
|
|
fully compressed key. It also means that it can hold more records in
|
|
leaf nodes and total index size is usually smaller then in SIX3.
|
|
SIX3 can use Harbour indexes though I cannot be sure if they will not
|
|
cause some other memory buffer overflows like the one described above
|
|
in SIX3 code. I only hope that not or at least they will not be critical.
|
|
13.During index update SIX3 NSX do not execute any code to balance key in
|
|
index nodes to keep some minimum number of keys in page. It may cause
|
|
that in systems with a lot of updates indexes will be much bigger then
|
|
they should. It means that it's good to make some temporary reindexing.
|
|
The base Harbour implementation replicate this behavior but it may
|
|
change in the future and I'll add some code to keep keys in index
|
|
pages well balanced. In well balanced indexes exist some conditions
|
|
which can make whole code much simpler but unfortunately if we want
|
|
to be SIX3 compatible we cannot use them because after updating index
|
|
by SIX3 we will lost them.
|
|
14.Harbour do not use any tricks with byte oriented sorting and pass
|
|
whole index keys for comparison to CP compare function which respects
|
|
all national settings. Such tricks may speed up some operations but
|
|
they break sorting in languages which uses multibyte characters or
|
|
accented characters with the same weight as normal ones.
|
|
15.The default memo type in DBFNSX is set to SMT. It will affect only
|
|
newly created files (dbCreate()). When DBF table is open memo type
|
|
is detected automatically in all DBF* Harbour's RDDs. If you want
|
|
to change default memo type for new DBF files then use:
|
|
rddInfo( RDDI_MEMOTYPE, DB_MEMO_FPT, "DBFNSX" )
|
|
or:
|
|
rddInfo( RDDI_MEMOTYPE, DB_MEMO_DBT, "DBFNSX" )
|
|
16.Harbour NSX implementation in default format supports NSX files
|
|
up to 4 GiB. This is maximum keeping binary compatibility with SIX3
|
|
NSX RDD. But Harbour can support files up to 4 TiB - it's a little
|
|
bit modified format with 'I' instead of 'i' in index header signature.
|
|
Such indexes are created when locking mode is set to 64-bit. On open
|
|
Harbour RDDs automatically recognize type of index files so it
|
|
can use new format also with different locking schemes. SIX3 NSX
|
|
cannot use new index.
|
|
17.This version do not have yet any speed optimization in navigation
|
|
and index update code for easier detecting any problems with SIX3
|
|
compatibility. I'll add it later.
|
|
|
|
LEAF KEY COMPRESSION:
|
|
a. store record number (RecNo)
|
|
b. count duplicated characters
|
|
c. if full key is duplicated then key size = n + 1 and goto @g
|
|
d. count trailing characters to the duplicate limit
|
|
e. if rest of key value (without dup and trail chars) is not empty
|
|
then store it using RLE compression:
|
|
- replace each repeated 3 or more characters with with FF xx yy
|
|
- replace each FF character with FF 01
|
|
- if compressed key size is greater or equal then KEY_SIZE - DupCount
|
|
break compression and store the key as raw data coping source,
|
|
key size = KEY_SIZE - DupCount + n + 2
|
|
f. store number of duplicated characters (DupCount)
|
|
g. store key size (Size)
|
|
Harbour NSX RDD has small extension here and also compressed two
|
|
repeated 0xFF character so instead of FF 01 FF 01 it stores FF 02 FF
|
|
It saves one byte and can be still decoded by SIX3 NSX RDD
|
|
*/
|
|
|
|
|
|
#ifndef HB_RDDNSX_H_
|
|
#define HB_RDDNSX_H_
|
|
|
|
#include "hbrdddbf.h"
|
|
|
|
HB_EXTERN_BEGIN
|
|
|
|
#define NSX_INDEXEXT ".nsx"
|
|
|
|
#define NSX_PAGELEN_BITS 10 /* Size of NSX page in bits */
|
|
#define NSX_PAGELEN (1<<NSX_PAGELEN_BITS) /* Size of page in NSX file */
|
|
#define NSX_MAXEXPLEN 256
|
|
#define NSX_MAXKEYLEN 250
|
|
#define NSX_MAXTAGS 50
|
|
#define NSX_TAGNAME 11
|
|
#define NSX_BRANCHPAGE 0
|
|
#define NSX_ROOTPAGE 1
|
|
#define NSX_LEAFPAGE 2
|
|
#define NSX_LEAFKEYOFFSET 6
|
|
#define NSX_LEAFSPLITOFFSET 592 /* minimum value to avoid anomalies in some worst cases */
|
|
#define NSX_PAGE_BUFFER 8
|
|
#define NSX_STACKSIZE 32 /* Maximum page stack size */
|
|
#define NSX_SIGNATURE 'i'
|
|
#define NSX_SIGNATURE_LARGE 'I'
|
|
#define NSX_RLE_CHAR 0xFF
|
|
#define NSX_DUMMYNODE 0xFFFFFFFFUL
|
|
#define NSX_IGNORE_REC_NUM 0x0UL
|
|
#define NSX_MAX_REC_NUM 0xFFFFFFFFUL
|
|
|
|
#define NSX_ROOTHEAD_HEADSIZE 14
|
|
#define NSX_TAGHEAD_HEADSIZE 6
|
|
|
|
|
|
/*
|
|
* type of key expression
|
|
* these are the same values as in CL5.3 extend.api
|
|
* #define S_LNUM 2
|
|
* #define S_DNUM 8
|
|
* #define S_LDATE 32
|
|
* #define S_LOG 128
|
|
* #define S_CHAR 1024
|
|
* #define S_ANYNUM (S_LNUM | S_DNUM)
|
|
* #define S_ANYEXP (S_ANYNUM | S_CHAR | S_LDATE | S_LOG)
|
|
*/
|
|
#define NSX_TYPE_LNUM 0x0002
|
|
#define NSX_TYPE_DNUM 0x0008
|
|
#define NSX_TYPE_LDATE 0x0020
|
|
#define NSX_TYPE_TIMESTAMP 0x0040 /* Harbour extension */
|
|
#define NSX_TYPE_LOG 0x0080
|
|
#define NSX_TYPE_CHAR 0x0400
|
|
#define NSX_TYPE_ANYNUM ( NSX_TYPE_LNUM | NSX_TYPE_DNUM )
|
|
#define NSX_TYPE_ANYEXP ( NSX_TYPE_ANYNUM | NSX_TYPE_CHAR | NSX_TYPE_LDATE | NSX_TYPE_TIMESTAMP | NSX_TYPE_LOG )
|
|
|
|
#define NSX_CMP_EXACT 0x00 /* exact comparison */
|
|
#define NSX_CMP_PREFIX 0x01 /* prefix comparison */
|
|
#define NSX_CMP_DATE 0x02 /* date comparison */
|
|
|
|
#define NSX_TAG_FULLUPDT 0x00
|
|
#define NSX_TAG_PARTIAL 0x01
|
|
#define NSX_TAG_TEMPLATE 0x02
|
|
#define NSX_TAG_CHGONLY 0x04
|
|
#define NSX_TAG_NOUPDATE 0x08
|
|
#define NSX_TAG_SHADOW 0x10
|
|
#define NSX_TAG_MULTIKEY 0x20
|
|
|
|
/*
|
|
sx_Chill() => if ( indexFlag & ( NSX_TAG_NOUPDATE | NSX_TAG_TEMPLATE ) == 0 )
|
|
indexFlag |= NSX_TAG_CHGONLY | NSX_TAG_PARTIAL;
|
|
sx_Warm() => if ( indexFlag & ( NSX_TAG_NOUPDATE | NSX_TAG_TEMPLATE ) == 0 )
|
|
indexFlag &= ~NSX_TAG_CHGONLY
|
|
indexFlag |= NSX_TAG_PARTIAL // I do not like this
|
|
sx_Freeze() => indexFlag |= NSX_TAG_NOUPDATE | NSX_TAG_PARTIAL
|
|
indexFlag &= ~NSX_TAG_CHGONLY
|
|
|
|
sx_Thermometer() => if ( NSX_TAG_NOUPDATE | NSX_TAG_TEMPLATE ) -> 4
|
|
if ( NSX_TAG_CHGONLY ) -> 3
|
|
if ( NSX_TAG_PARTIAL ) -> 2
|
|
else -> 1
|
|
1 - NSX_TAG_FULLUPDT
|
|
2 - NSX_TAG_PARTIAL
|
|
3 - NSX_TAG_CHGONLY
|
|
4 - NSX_TAG_NOUPDATE | NSX_TAG_TEMPLATE
|
|
*/
|
|
|
|
/* index file structures - defined in HB_BYTEs to avoid alignment problems */
|
|
|
|
typedef struct _NSXTAGITEM
|
|
{
|
|
HB_UCHAR TagName[ NSX_TAGNAME + 1 ]; /* name of tag in ASCIIZ */
|
|
HB_UCHAR TagOffset[ 4 ]; /* Tag header offset */
|
|
} NSXTAGITEM;
|
|
typedef NSXTAGITEM * LPNSXTAGITEM;
|
|
|
|
typedef struct _NSXROOTHEADER
|
|
{
|
|
HB_UCHAR Signature[ 1 ]; /* "i" = 0x69 */
|
|
HB_UCHAR IndexFlags[ 1 ]; /* 0x00 */
|
|
HB_UCHAR TagCount[ 2 ]; /* number of tags in index file */
|
|
HB_UCHAR Version[ 2 ]; /* cyclic counter for concurrent access */
|
|
HB_UCHAR FreePage[ 4 ]; /* offset of first free page in index file */
|
|
HB_UCHAR FileSize[ 4 ]; /* the index file length */
|
|
NSXTAGITEM TagList[ NSX_MAXTAGS ];
|
|
HB_UCHAR Unused[ NSX_PAGELEN - 14 - NSX_MAXTAGS * sizeof( NSXTAGITEM ) ];
|
|
} NSXROOTHEADER;
|
|
typedef NSXROOTHEADER * LPNSXROOTHEADER;
|
|
|
|
typedef struct _NSXTAGHEADER
|
|
{
|
|
HB_UCHAR Signature[ 1 ]; /* "i" = 0x69 */
|
|
HB_UCHAR TagFlags[ 1 ]; /* update flags: NSX_TAG_* */
|
|
HB_UCHAR RootPage[ 4 ]; /* offset of tag root page */
|
|
HB_UCHAR KeyType[ 2 ]; /* index key type: NSX_TYPE_* */
|
|
HB_UCHAR KeySize[ 2 ]; /* index key size */
|
|
HB_UCHAR Unique[ 2 ]; /* 0x0001 for UNIQUE indexes */
|
|
HB_UCHAR Descend[ 2 ]; /* 0x0001 for descend indexes */
|
|
HB_UCHAR KeyExpr[ NSX_MAXEXPLEN ]; /* index KEY expression ASCIIZ */
|
|
HB_UCHAR ForExpr[ NSX_MAXEXPLEN ]; /* index FOR expression ASCIIZ */
|
|
HB_UCHAR Unused[ NSX_PAGELEN - 14 - NSX_MAXEXPLEN - NSX_MAXEXPLEN ];
|
|
} NSXTAGHEADER;
|
|
typedef NSXTAGHEADER * LPNSXTAGHEADER;
|
|
|
|
typedef struct
|
|
{
|
|
HB_UCHAR Signature[ 1 ]; /* "i" = 0x69 */
|
|
HB_UCHAR TagFlags[ 1 ]; /* update flags: NSX_TAG_* */
|
|
HB_UCHAR RootPage[ 4 ]; /* offset of tag root page */
|
|
} NSXTAGHEADERUPDT;
|
|
|
|
typedef struct _NSXBRANCHPAGE
|
|
{
|
|
HB_UCHAR NodeID[ 1 ]; /* NSX_BRANCHPAGE | ( lRoot ? NSX_ROOTPAGE : 0 ) */
|
|
HB_UCHAR RecNoLen[ 1 ]; /* number of bytes for recno in branch keys - seems to be unused */
|
|
HB_UCHAR KeyCount[ 2 ]; /* number of key in page */
|
|
HB_UCHAR LowerPage[ 4 ]; /* offset to the page with lower keys */
|
|
HB_UCHAR KeyData[ NSX_PAGELEN - 8 ]; /* with branch keys */
|
|
} NSXBRANCHPAGE;
|
|
typedef NSXBRANCHPAGE * LPNSXBRANCHPAGE;
|
|
|
|
typedef struct _NSXLEAFPAGE
|
|
{
|
|
HB_UCHAR NodeID[ 1 ]; /* NSX_LEAFPAGE | ( lRoot ? NSX_ROOTPAGE : 0 ) */
|
|
HB_UCHAR RecNoLen[ 1 ]; /* number of bytes for recno in leaf keys */
|
|
HB_UCHAR KeyCount[ 2 ]; /* number of key in page */
|
|
HB_UCHAR UsedArea[ 2 ]; /* area used in page -> offset to free area */
|
|
HB_UCHAR KeyData[ NSX_PAGELEN - NSX_LEAFKEYOFFSET ]; /* with branch keys */
|
|
} NSXLEAFPAGE;
|
|
typedef NSXLEAFPAGE * LPNSXLEAFPAGE;
|
|
|
|
#if 0
|
|
/* meta structures for description only, cannot be compiled due to
|
|
variable member sizes */
|
|
typedef struct _NSXBRANCHKEY
|
|
{
|
|
HB_UCHAR Page[ 4 ]; /* page offset with higher keys values */
|
|
HB_UCHAR RecNo[ n ]; /* where n is RecNoLen */
|
|
HB_UCHAR KeyData[ l ]; /* key value where l is KeySize */
|
|
} NSXBRANCHKEY;
|
|
typedef NSXBRANCHKEY * LPNSXBRANCHKEY;
|
|
|
|
typedef struct _NSXLEAFKEY
|
|
{
|
|
HB_UCHAR RecNo[ n ]; /* where n is RecNoLen */
|
|
HB_UCHAR Size[ 1 ]; /* key data size with this byte and n RecNo HB_BYTEs
|
|
* if Size == n + 1 then key is fully duplicated
|
|
*/
|
|
HB_UCHAR DupCount[ 1 ]; /* number of bytes from previous key */
|
|
HB_UCHAR KeyData[ m ]; /* rest of key value with RLE compression:
|
|
* FF xx yy => Replicate(yy, xx)
|
|
* FF 01 => FF
|
|
* m = Size - n - 2
|
|
* if m == KEY_SIZE - DupCount then key value
|
|
* is stored as raw data and can be copied as is
|
|
* if after decompression size of key value is
|
|
* smaller then KEY_SIZE then rest if filled with
|
|
* trailing character (\0 for numeric and date
|
|
* indexes and SPACE for others (character
|
|
* and logical))
|
|
*/
|
|
} NSXLEAFKEY;
|
|
typedef NSXLEAFKEY * LPNSXLEAFKEY;
|
|
#endif
|
|
|
|
|
|
/* forward declarations
|
|
*/
|
|
struct _RDDFUNCS;
|
|
struct _NSXAREA;
|
|
struct _TAGINFO;
|
|
struct _NSXINDEX;
|
|
|
|
typedef struct _KEYINFO
|
|
{
|
|
HB_ULONG page; /* page number */
|
|
HB_ULONG rec; /* record number */
|
|
int mode; /* comparison mode NSX_CMP_* */
|
|
HB_UCHAR val[ 1 ]; /* key value */
|
|
} KEYINFO;
|
|
typedef KEYINFO * LPKEYINFO;
|
|
|
|
typedef struct _TREE_STACK
|
|
{
|
|
HB_ULONG page;
|
|
HB_SHORT ikey;
|
|
HB_UCHAR * value;
|
|
} TREE_STACK;
|
|
typedef TREE_STACK * LPTREESTACK;
|
|
|
|
typedef struct _HB_PAGEINFO
|
|
{
|
|
HB_ULONG Page;
|
|
HB_BOOL Changed;
|
|
int iUsed;
|
|
HB_USHORT uiKeys;
|
|
HB_USHORT uiOffset;
|
|
struct _HB_PAGEINFO * pNext;
|
|
struct _HB_PAGEINFO * pPrev;
|
|
#ifdef HB_NSX_EXTERNAL_PAGEBUFFER
|
|
union
|
|
{
|
|
HB_UCHAR * buffer;
|
|
LPNSXROOTHEADER rootHeader;
|
|
LPNSXTAGHEADER tagHeader;
|
|
} data;
|
|
#else
|
|
union
|
|
{
|
|
HB_UCHAR buffer[ NSX_PAGELEN ];
|
|
NSXROOTHEADER rootHeader;
|
|
NSXTAGHEADER tagHeader;
|
|
} data;
|
|
#endif
|
|
} HB_PAGEINFO;
|
|
typedef HB_PAGEINFO * LPPAGEINFO;
|
|
|
|
typedef union
|
|
{
|
|
HB_UCHAR * buffer;
|
|
LPNSXROOTHEADER header;
|
|
} HB_NSXPAGEHEAD;
|
|
|
|
typedef struct _HB_NSXSCOPE
|
|
{
|
|
PHB_ITEM scopeItem;
|
|
LPKEYINFO scopeKey;
|
|
HB_USHORT scopeKeyLen;
|
|
} HB_NSXSCOPE;
|
|
typedef HB_NSXSCOPE * PHB_NSXSCOPE;
|
|
|
|
typedef struct _TAGINFO
|
|
{
|
|
char * TagName;
|
|
char * KeyExpr;
|
|
char * ForExpr;
|
|
PHB_ITEM pKeyItem;
|
|
PHB_ITEM pForItem;
|
|
HB_NSXSCOPE top;
|
|
HB_NSXSCOPE bottom;
|
|
|
|
|
|
HB_BOOL fUsrDescend;
|
|
HB_BOOL AscendKey;
|
|
HB_BOOL UniqueKey;
|
|
|
|
HB_BOOL Custom;
|
|
HB_BOOL ChgOnly;
|
|
HB_BOOL Partial;
|
|
HB_BOOL Template;
|
|
HB_BOOL MultiKey;
|
|
|
|
HB_BOOL HdrChanged;
|
|
HB_BOOL TagBOF;
|
|
HB_BOOL TagEOF;
|
|
HB_BOOL HotFor;
|
|
|
|
HB_ULONG HeadBlock;
|
|
HB_ULONG RootBlock;
|
|
|
|
HB_UCHAR TagFlags;
|
|
HB_UCHAR KeyType;
|
|
HB_UCHAR TrailChar;
|
|
HB_USHORT KeyLength;
|
|
HB_USHORT nField;
|
|
HB_USHORT uiNumber;
|
|
HB_USHORT MaxKeys;
|
|
|
|
HB_USHORT CurKeyOffset;
|
|
HB_USHORT CurKeyNo;
|
|
|
|
HB_USHORT stackSize;
|
|
HB_USHORT stackLevel;
|
|
LPTREESTACK stack;
|
|
|
|
HB_ULONG keyCount;
|
|
LPKEYINFO CurKeyInfo;
|
|
LPKEYINFO HotKeyInfo;
|
|
|
|
struct _NSXINDEX * pIndex;
|
|
} TAGINFO;
|
|
typedef TAGINFO * LPTAGINFO;
|
|
|
|
typedef struct _NSXINDEX
|
|
{
|
|
char * IndexName;
|
|
char * RealName;
|
|
HB_ULONG Version; /* index VERSION filed to signal index updates for other stations */
|
|
HB_ULONG NextAvail; /* next free page in index file */
|
|
HB_ULONG FileSize; /* index file size */
|
|
struct _NSXAREA * pArea;
|
|
PHB_FILE pFile;
|
|
HB_BOOL fDelete; /* delete on close flag */
|
|
HB_BOOL fReadonly;
|
|
HB_BOOL fShared;
|
|
HB_BOOL fFlush;
|
|
HB_BOOL LargeFile;
|
|
HB_BOOL Changed;
|
|
HB_BOOL Update;
|
|
HB_BOOL Production; /* Production index */
|
|
HB_DBFLOCKDATA lockData; /* index lock data */
|
|
int lockWrite; /* number of write lock set */
|
|
int lockRead; /* number of read lock set */
|
|
|
|
NSXROOTHEADER HeaderBuff;
|
|
HB_BOOL fValidHeader;
|
|
int iTags;
|
|
LPTAGINFO * lpTags;
|
|
|
|
HB_ULONG ulPages;
|
|
HB_ULONG ulPageLast;
|
|
HB_ULONG ulPagesDepth;
|
|
LPPAGEINFO *pages;
|
|
LPPAGEINFO pChanged;
|
|
LPPAGEINFO pFirst;
|
|
LPPAGEINFO pLast;
|
|
|
|
struct _NSXINDEX * pNext; /* The next index in the list */
|
|
} NSXINDEX;
|
|
typedef NSXINDEX * LPNSXINDEX;
|
|
|
|
/* for index creation */
|
|
typedef struct
|
|
{
|
|
HB_FOFFSET nOffset; /* offset in temporary file */
|
|
HB_ULONG ulKeys; /* number of keys in page */
|
|
HB_ULONG ulKeyBuf; /* number of keys in memory buffer */
|
|
HB_ULONG ulCurKey; /* current key in memory buffer */
|
|
HB_UCHAR * pKeyPool; /* memory buffer */
|
|
} NSXSWAPPAGE;
|
|
typedef NSXSWAPPAGE * LPNSXSWAPPAGE;
|
|
|
|
typedef struct
|
|
{
|
|
LPTAGINFO pTag; /* current Tag */
|
|
PHB_FILE pTempFile; /* handle to temporary file */
|
|
char * szTempFileName; /* temporary file name */
|
|
int keyLen; /* key length */
|
|
HB_UCHAR trailChar; /* index key trail character */
|
|
HB_UCHAR recSize; /* record size in leaf keys */
|
|
HB_BOOL fUnique; /* HB_TRUE if index is unique */
|
|
HB_BOOL fReindex; /* HB_TRUE if reindexing is in process */
|
|
HB_ULONG ulMaxRec; /* the highest record number */
|
|
HB_ULONG ulTotKeys; /* total number of keys indexed */
|
|
HB_ULONG ulKeys; /* keys in currently created page */
|
|
HB_ULONG ulPages; /* number of pages */
|
|
HB_ULONG ulCurPage; /* current page */
|
|
HB_ULONG ulPgKeys; /* maximum number of key in page memory buffer */
|
|
HB_ULONG ulMaxKey; /* maximum number of keys in single page */
|
|
HB_UCHAR * pKeyPool; /* memory buffer for current page then for pages */
|
|
HB_UCHAR * pStartKey; /* beginning of key pool after sorting */
|
|
LPNSXSWAPPAGE pSwapPage; /* list of pages */
|
|
LPPAGEINFO NodeList[ NSX_STACKSIZE ]; /* Stack of pages */
|
|
HB_ULONG ulFirst;
|
|
HB_ULONG * pSortedPages;
|
|
HB_UCHAR pLastKey[ NSX_MAXKEYLEN ]; /* last key val */
|
|
HB_ULONG ulLastRec;
|
|
HB_ULONG ulLastLeaf; /* last non empty leaf page written to tag */
|
|
|
|
HB_UCHAR * pBuffIO; /* index IO buffer */
|
|
HB_ULONG ulSizeIO; /* size of IO buffer in index pages */
|
|
HB_ULONG ulPagesIO; /* number of index pages in buffer */
|
|
HB_ULONG ulFirstIO; /* first page in buffer */
|
|
HB_ULONG ulLastIO; /* last page in buffer */
|
|
} NSXSORTINFO;
|
|
typedef NSXSORTINFO * LPNSXSORTINFO;
|
|
|
|
/*
|
|
* DBF WORKAREA
|
|
* ------------
|
|
* The Workarea Structure of DBFNSX RDD
|
|
*
|
|
*/
|
|
|
|
typedef struct _NSXAREA
|
|
{
|
|
DBFAREA dbfarea;
|
|
|
|
/*
|
|
* NSX's additions to the workarea structure
|
|
*
|
|
* Warning: The above section MUST match DBFAREA exactly! Any
|
|
* additions to the structure MUST be added below, as in this
|
|
* example.
|
|
*/
|
|
|
|
HB_BOOL fIdxAppend; /* HB_TRUE if new record is added */
|
|
HB_BOOL fSetTagNumbers; /* Tag number should be recreated */
|
|
LPNSXINDEX lpIndexes; /* Pointer to list of indexes */
|
|
LPTAGINFO lpCurTag; /* Pointer to current order */
|
|
LPNSXSORTINFO pSort; /* Index build structure */
|
|
|
|
} NSXAREA;
|
|
typedef NSXAREA * LPNSXAREA;
|
|
|
|
#ifndef NSXAREAP
|
|
#define NSXAREAP LPNSXAREA
|
|
#endif
|
|
|
|
#undef SUPERTABLE
|
|
#define SUPERTABLE ( &nsxSuper )
|
|
|
|
HB_EXTERN_END
|
|
|
|
#endif /* HB_RDDNSX_H_ */
|