campo-sirio/cb/source/r4reinde.c

2062 lines
65 KiB
C
Raw Normal View History

/* r4reinde.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif /* __TURBOC__ */
#ifndef S4OFF_WRITE
#ifndef S4INDEX_OFF
#ifndef S4CLIENT
#ifndef S4OFF_TRAN
void i4deleteRemoveKeys( INDEX4 *index )
{
TAG4 *tagOn ;
TAG4KEY_REMOVED *removed ;
for( tagOn = 0 ;; )
{
tagOn = (TAG4 *)l4next( &index->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
for ( ;; )
{
removed =(TAG4KEY_REMOVED *)l4first( &tagOn->removedKeys ) ;
if ( removed == 0 )
break ;
l4remove( &tagOn->removedKeys, removed ) ;
u4free( removed ) ;
}
}
}
#endif /* S4OFF_TRAN */
#endif /* S4CLIENT */
#ifndef N4OTHER
#ifdef S4CLIENT
int S4FUNCTION i4reindex( INDEX4 *index )
{
int rc ;
CONNECTION4 *connection ;
CONNECTION4REINDEX_INFO_OUT *out ;
CODE4 *c4 ;
DATA4 *d4 ;
#ifdef S4VBASIC
if ( c4parm_check( index, 0, E92101 ) )
return -1 ;
#endif /* S4VBASIC */
#ifdef E4PARM_HIGH
if ( index == 0 )
return error4( 0, e4parm_null, E92101 ) ;
#endif
d4 = index->data ;
if ( error4code( d4->codeBase ) < 0 )
return e4codeBase ;
rc = 0 ;
connection = d4->dataFile->connection ;
if ( connection == 0 )
return e4connection ;
c4 = d4->codeBase ;
rc = connection4assign( connection, CON4INDEX_REINDEX, data4clientId( d4 ), data4serverId( d4 ) ) ;
if ( rc < 0 )
return rc ;
connection4addData( connection, index->indexFile->accessName, sizeof( index->indexFile->accessName ), 0 ) ;
rc = connection4repeat( connection, -2, -1, -1, d4 ) ;
if ( rc == r4locked )
return r4locked ;
if ( rc != 0 )
return connection4error( connection, c4, rc, E92101 ) ;
if ( connection4len( connection ) != sizeof( CONNECTION4REINDEX_INFO_OUT ) )
return error4( c4, e4packetLen, E92101 ) ;
out = (CONNECTION4REINDEX_INFO_OUT *)connection4data( connection ) ;
if ( out->lockedDatafile == 1 )
d4->dataFile->fileLock = d4 ;
d4->recNum = -1 ;
d4->recNumOld = -1 ;
memset( d4->record, ' ', dfile4recWidth( d4->dataFile ) ) ;
return 0 ;
}
#else
#include "r4reinde.h"
int S4FUNCTION i4reindex( INDEX4 *i4 )
{
R4REINDEX reindex ;
INDEX4FILE *indexFile ;
CODE4 *c4 ;
TAG4 *tagOn ;
int rc ;
DATA4 *data ;
#ifndef S4OPTIMIZE_OFF
#ifdef S4LOW_MEMORY
int hasOpt ;
#endif
#endif
#ifdef S4FOX
B4BLOCK *block ;
long rNode, goTo ;
char tagName[LEN4TAG_ALIAS + 1] ;
long i ;
int len ;
#ifdef S4BYTE_SWAP
char *swapPtr ;
S4LONG longVal ;
short shortVal ;
#endif
#endif /* S4FOX */
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E92101 ) )
return -1 ;
#endif /* S4VBASIC */
#ifdef E4PARM_HIGH
if ( i4 == 0 )
return error4( 0, e4parm_null, E92101 ) ;
#endif
c4 = i4->codeBase ;
#ifdef E4ANALYZE
if ( c4 == 0 )
return error4( 0, e4struct, E92101 ) ;
#endif
if ( error4code( c4 ) < 0 )
return e4codeBase ;
indexFile = i4->indexFile ;
data = i4->data ;
#ifndef S4OPTIMIZE_OFF
#ifdef S4LOW_MEMORY
hasOpt = c4->hasOpt ;
code4optSuspend( c4 ) ;
#endif
#endif
#ifndef S4SINGLE
rc = d4lockAll( data ) ;
if ( rc )
return rc ;
#endif /* S4SINGLE */
#ifndef S4OFF_TRAN
/* reindex is allowed, but need to fix-up any unique settings */
i4deleteRemoveKeys( i4 ) ;
#endif
for( ;; )
{
rc = r4reindexInit( &reindex, i4, i4->indexFile ) ;
if ( rc < 0 )
break ;
rc = r4reindexTagHeadersCalc( &reindex ) ;
if ( rc < 0 )
break ;
rc = r4reindexBlocksAlloc(&reindex ) ;
if ( rc < 0 )
break ;
#ifndef S4SINGLE
#ifdef S4FOX
if ( indexFile->file.lowAccessMode != OPEN4DENY_RW )
indexFile->tagIndex->header.version = indexFile->versionOld + 1 ;
#endif
#endif
#ifdef E4ANALYZE
if ( i4->tags.nLink != indexFile->tags.nLink )
{
rc = e4struct ;
break ;
}
#endif
#ifdef S4FOX
reindex.nBlocksUsed = 0 ;
tagName[LEN4TAG_ALIAS] = '\0' ;
if ( indexFile->tagIndex->header.typeCode >= 64 ) /* if .cdx */
{
reindex.tag = indexFile->tagIndex ;
rc = sort4init( &reindex.sort, c4, indexFile->tagIndex->header.keyLen, 0 ) ;
if ( rc < 0 )
break ;
reindex.sort.cmp = (S4CMP_FUNCTION *)u4memcmp ;
for( tagOn = 0, i = 1 ; ; i++ )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
len = strlen( tfile4alias( tagOn->tagFile ) ) ;
memset( tagName, ' ', LEN4TAG_ALIAS ) ;
memcpy( tagName, tfile4alias( tagOn->tagFile ), (unsigned int)len ) ;
rc = sort4put( &reindex.sort, 2 * B4BLOCK_SIZE * i, tagName, "" ) ;
if ( rc < 0 )
break ;
#ifdef E4MISC
reindex.keyCount++ ;
#endif /* E4MISC */
}
if ( rc < 0 )
break ;
rc = r4reindexWriteKeys( &reindex, e4unique ) ; /* tag index should have no uniques */
if ( rc != 0 )
{
r4reindexFree( &reindex ) ;
break ;
}
}
else
if ( reindex.nTags > 1 ) /* should only be 1 tag in an .idx */
{
rc = e4index ;
break ;
}
#endif /* S4FOX */
for( tagOn = 0 ; ; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
reindex.tag = tagOn->tagFile ;
#ifdef S4FOX
reindex.nBlocksUsed = 0 ;
#else /* S4MDX */
reindex.tag->header.version++ ;
#endif /* S4FOX */
rc = expr4context( tagOn->tagFile->expr, data ) ;
if ( rc < 0 )
break ;
if ( tagOn->tagFile->filter != 0 )
{
rc = expr4context( tagOn->tagFile->filter, data ) ;
if ( rc < 0 )
break ;
}
rc = r4reindexSupplyKeys( &reindex ) ;
if ( rc )
{
r4reindexFree( &reindex ) ;
break ;
}
rc = r4reindexWriteKeys( &reindex, t4unique( tagOn ) ) ;
if ( rc )
{
r4reindexFree( &reindex ) ;
break ;
}
}
if ( rc != 0 ) /* r4unique or error */
break ;
rc = r4reindexTagHeadersWrite( &reindex ) ;
if ( rc < 0 )
break ;
#ifdef S4FOX
/* now must fix the right node branches for all blocks by moving leftwards */
for( tagOn = 0 ; ; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
for( tfile4rlBottom( tagOn->tagFile ) ; tagOn->tagFile->blocks.lastNode ; tfile4up( tagOn->tagFile ) )
{
block = tfile4block( tagOn->tagFile ) ;
goTo = block->header.leftNode ;
while ( goTo != -1 )
{
#ifdef E4DEBUG
if ( goTo <= 0 ) /* invalid value, esp. zero */
return error4( c4, e4struct, E92101 ) ;
#endif
rNode = block->fileBlock ;
if ( block->changed )
{
rc = b4flush( block ) ;
if ( rc < 0 )
break ;
}
rc = file4readAll( &indexFile->file, I4MULTIPLY*goTo, &block->header, B4BLOCK_SIZE ) ;
if ( rc < 0 )
break ;
#ifdef S4BYTE_SWAP
block->header.nodeAttribute = x4reverseShort( (void *)&block->header.nodeAttribute ) ;
block->header.nKeys = x4reverseShort( (void *)&block->header.nKeys ) ;
block->header.leftNode = x4reverseLong( (void *)&block->header.leftNode ) ;
block->header.rightNode = x4reverseLong( (void *)&block->header.rightNode ) ;
if (block->header.nodeAttribute >= 2 ) /* if block is a leaf */
{
block->nodeHdr.freeSpace = x4reverseShort( (void *)&block->nodeHdr.freeSpace ) ;
longVal = x4reverseLong( (void *)&block->nodeHdr.recNumMask[0] ) ;
memcpy( (void *)&block->nodeHdr.recNumMask[0], (void *)&longVal, sizeof(S4LONG) ) ;
}
else /* if block is a branch */
{
shortVal = block->tag->header.keyLen + sizeof(S4LONG) ;
/* position swapPtr to end of first key expression */
swapPtr = (char *) &block->nodeHdr.freeSpace + block->tag->header.keyLen ;
/* move through all B4KEY's to swap 'long's */
for ( i = 0 ; i < (int) block->header.nKeys ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += shortVal ;
}
}
#endif
block->fileBlock = goTo ;
if ( block->header.rightNode != rNode ) /* if a bad value */
{
block->header.rightNode = rNode ;
block->changed = 1 ;
}
goTo = block->header.leftNode ;
}
if ( rc < 0 )
break ;
block->builtOn = -1 ;
rc = b4top( block ) ;
if ( rc < 0 )
break ;
}
if ( rc < 0 )
break ;
}
if ( rc < 0 )
break ;
#endif /* S4FOX */
r4reindexFree( &reindex ) ;
#ifndef S4OPTIMIZE_OFF
#ifdef S4LOW_MEMORY
if ( hasOpt )
code4optRestart( c4 ) ;
#endif
#endif
break ;
}
if ( rc < 0 )
return error4stack( c4, (short)rc, E92101 ) ;
data->recNum = -1 ;
data->recNumOld = -1 ;
memset( data->record, ' ', dfile4recWidth( data->dataFile ) ) ;
return rc ;
}
int r4reindexInit( R4REINDEX *r4, INDEX4 *i4, INDEX4FILE *indexFile )
{
#ifdef E4PARM_LOW
if ( r4 == 0 || i4 == 0 || indexFile == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
memset( (void *)r4, 0, sizeof( R4REINDEX ) ) ;
r4->indexFile = indexFile ;
r4->data = i4->data ;
r4->dataFile = indexFile->dataFile ;
r4->codeBase = i4->codeBase ;
r4->minKeysmax = INT_MAX ;
r4->startBlock = 0 ;
r4->sort.file.hand = -1 ;
#ifndef S4FOX
r4->blocklen = indexFile->header.blockRw ;
#endif /* S4FOX */
r4->bufferLen = i4->codeBase->memSizeSortBuffer ;
if ( r4->bufferLen < 1024 )
r4->bufferLen = 1024 ;
r4->buffer = (char *)u4allocEr( i4->codeBase, (long)r4->bufferLen ) ;
if ( r4->buffer == 0 )
return e4memory ;
#ifdef S4FOX
r4->lastblock = 1024 ; /* leave space for the index header block */
#endif /* S4FOX */
return 0 ;
}
void r4reindexFree( R4REINDEX *r4 )
{
u4free( r4->buffer ) ;
u4free( r4->startBlock ) ;
sort4free( &r4->sort ) ;
}
int r4reindexBlocksAlloc( R4REINDEX *r4 )
{
long onCount ;
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
#ifdef E4MISC
if ( (unsigned)r4->minKeysmax > INT_MAX )
return error4( r4->codeBase, e4info, E92102 ) ;
#endif
/* Calculate the block stack height */
onCount = dfile4recCount( r4->dataFile, -2 ) ;
if ( onCount < 0 )
return error4stack( r4->codeBase, (short)onCount, E92102 ) ;
for ( r4->nBlocks = 2; onCount != 0L; r4->nBlocks++ )
onCount /= r4->minKeysmax ;
if ( r4->startBlock == 0 )
{
#ifdef S4FOX
r4->startBlock = (R4BLOCK_DATA *)u4allocEr( r4->codeBase, (long)B4BLOCK_SIZE * r4->nBlocks ) ;
#endif /* S4FOX */
#ifdef S4MDX
r4->startBlock = (R4BLOCK_DATA *)u4allocEr( r4->codeBase, (long)r4->blocklen * r4->nBlocks ) ;
#endif /* S4MDX */
}
if ( r4->startBlock == 0 )
return e4memory ;
return 0 ;
}
int r4reindexSupplyKeys( R4REINDEX *r4 )
{
FILE4SEQ_READ seqRead ;
EXPR4 *filter ;
unsigned char *keyResult ;
int rc, *filterResult ;
long count, iRec ;
DATA4FILE *dataFile ;
TAG4FILE *t4 ;
#ifndef S4MEMO_OFF
int i ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
dataFile = r4->dataFile ;
t4 = r4->tag ;
#ifdef E4MISC
r4->keyCount = 0L ;
#endif /* E4MISC */
rc =sort4init( &r4->sort, r4->codeBase, t4->header.keyLen, 0 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
#ifdef S4FOX
r4->sort.cmp = (S4CMP_FUNCTION *)u4memcmp ;
#endif /* S4FOX */
#ifdef S4MDX
r4->sort.cmp = (S4CMP_FUNCTION *)t4->cmp ;
#endif /* S4MDX */
filter = t4->filter ;
count = dfile4recCount( dataFile, -2L ) ;
if ( count < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = expr4context( r4->tag->expr, r4->data ) ;
if ( rc < 0 )
return rc ;
if ( r4->tag->filter != 0 )
{
rc = expr4context( r4->tag->filter, r4->data ) ;
if ( rc < 0 )
return rc ;
}
#ifdef S4ADVANCE_READ
file4seqReadInitDo( &seqRead, &dataFile->file, dfile4recordPosition( dataFile, 1L ), r4->buffer, r4->bufferLen, 1 ) ;
#else
file4seqReadInit( &seqRead, &dataFile->file, dfile4recordPosition( dataFile, 1L ), r4->buffer, r4->bufferLen ) ;
#endif
for ( iRec = 1L; iRec <= count; iRec++ )
{
rc = file4seqReadAll( &seqRead, dataFile->record, dfile4recWidth( dataFile ) ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
r4->data->recNum = iRec ;
#ifndef S4MEMO_OFF
for ( i = 0; i < dataFile->nFieldsMemo; i++ )
f4memoReset( r4->data->fieldsMemo[i].field ) ;
#endif /* S4MEMO_OFF */
if ( filter )
{
rc = expr4vary( filter, (char **)&filterResult ) ;
if ( rc < 0 )
{
#ifdef S4ADVANCE_READ
file4seqReadInitUndo( &seqRead ) ;
#endif
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
}
#ifdef E4MISC
if ( expr4type( filter ) != r4log )
{
#ifdef S4ADVANCE_READ
file4seqReadInitUndo( &seqRead ) ;
#endif
return error4( r4->codeBase, e4result, E92102 ) ;
}
#endif /* E4MISC */
if ( ! *filterResult )
continue ;
t4->hasKeys = 1 ;
#ifdef S4MDX
t4->hadKeys = 0 ;
#endif
}
tfile4exprKey( t4, &keyResult ) ;
rc = sort4put( &r4->sort, iRec, keyResult, "" ) ;
if ( rc < 0 )
{
#ifdef S4ADVANCE_READ
file4seqReadInitUndo( &seqRead ) ;
#endif
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
}
#ifdef E4MISC
r4->keyCount++ ;
#endif /* E4MISC */
}
#ifdef S4ADVANCE_READ
file4seqReadInitUndo( &seqRead ) ;
#endif
return 0 ;
}
int r4reindexTagHeadersCalc( R4REINDEX *r4 )
{
TAG4FILE *tag ;
int rc ;
CODE4 *c4 ;
#ifdef S4FOX
#ifdef S4DATA_ALIGN
unsigned int size, delta ;
#endif
int keysmax, exprType ;
#endif /* S4FOX */
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
c4 = r4->codeBase ;
r4->nTags = 0 ;
for( tag = 0 ;; )
{
tag = (TAG4FILE *)l4next( &r4->indexFile->tags, tag ) ;
if ( tag == 0 )
break ;
rc = tfile4freeAll( tag ) ;
if ( rc < 0 )
return error4stack( c4, (short)rc, E92102 ) ;
expr4context( tag->expr, r4->data ) ;
tag->header.keyLen = (short)expr4keyLen( tag->expr ) ;
#ifdef S4FOX
#ifdef S4DATA_ALIGN
size = (unsigned int)sizeof(long) + tag->header.keyLen ;
delta = 4 - size % 4 ;
tag->builtKeyMemory = mem4create( c4, 3, size + delta, 2, 0 ) ;
#else
tag->builtKeyMemory = mem4create( c4, 3, (unsigned int)sizeof(long) + tag->header.keyLen + 1, 2, 0 ) ;
#endif
exprType = expr4type( tag->expr ) ;
if ( exprType < 0 )
return error4stack( c4, (short)rc, E92102 ) ;
tfile4initSeekConv( tag, exprType ) ;
if ( tag->header.keyLen < 0 )
return error4( c4, e4index, E92102 ) ;
keysmax = ( B4BLOCK_SIZE - sizeof(B4STD_HEADER) ) / ( tag->header.keyLen + 2*sizeof(long) ) ;
if ( keysmax < r4->minKeysmax )
r4->minKeysmax = keysmax ;
#endif /* S4FOX */
#ifdef S4MDX
if ( tag->header.keyLen < 0 )
return error4( c4, e4index, E92102 ) ;
rc = expr4type( tag->expr ) ;
if ( rc < 0 )
return error4( c4, rc, E92102 ) ;
tag->header.type = (char)rc ;
if ( tag->header.type == r4dateDoub )
tag->header.type = r4date ;
if ( tag->header.type == r4numDoub )
tag->header.type = r4num ;
tfile4initSeekConv( tag, tag->header.type ) ;
tag->header.groupLen = (short)(tag->header.keyLen+ 2*sizeof(S4LONG)-1) ;
tag->header.groupLen-= (short)(tag->header.groupLen % sizeof(S4LONG)) ;
tag->header.keysMax = (short)((r4->indexFile->header.blockRw - sizeof(short)
- 6 - sizeof(S4LONG)) / tag->header.groupLen) ;
if ( tag->header.keysMax < r4->minKeysmax )
r4->minKeysmax = tag->header.keysMax ;
tag->hasKeys = 0 ;
tag->hadKeys = 1 ;
#endif /* S4MDX */
r4->nTags++ ;
}
#ifdef S4FOX
if ( r4->indexFile->tagIndex->header.typeCode >= 64 )
{
r4->lastblock += ((long)r4->nTags-1)*2*B4BLOCK_SIZE + B4BLOCK_SIZE ;
tfile4initSeekConv( r4->indexFile->tagIndex, r4str ) ;
}
else
r4->lastblock -= B4BLOCK_SIZE ;
#endif /* S4FOX */
#ifdef S4MDX
r4->lastblockInc = r4->indexFile->header.blockRw/ 512 ;
r4->lastblock = 4 + (r4->nTags-1)*r4->lastblockInc ;
#endif /* S4MDX */
return 0 ;
}
TAG4FILE *r4reindexFindITag( R4REINDEX *r4, const int tagNum )
{
/* First 'iTag' starts at '1' for this specific routine */
TAG4FILE *tagOn ;
int iTag ;
#ifdef E4PARM_LOW
if ( r4 == 0 || tagNum <= 0 )
{
error4( 0, e4parm, E92102 ) ;
return 0 ;
}
#endif
iTag = tagNum ;
tagOn = (TAG4FILE *)l4first( &r4->indexFile->tags ) ;
while ( --iTag >= 1 )
{
tagOn = (TAG4FILE *) l4next( &r4->indexFile->tags, tagOn ) ;
if ( tagOn == 0 )
return 0 ;
}
return tagOn ;
}
#ifdef S4MDX
#define GARBAGE_LEN 518
int r4reindexTagHeadersWrite( R4REINDEX *r4 )
{
/* First, calculate the T4DESC.leftChld, T4DESC.rightChld values, T4DESC.parent values */
int rc, higher[49], lower[49], parent[49] ;
TAG4FILE *tagOn, *tagPtr ;
INDEX4FILE *i4 ;
DATA4 *d4 ;
CODE4 *c4 ;
int nTag, iTag, jField, len, saveCode ;
T4DESC tagInfo ;
const char *ptr ;
#ifdef S4BYTE_SWAP
I4HEADER swapHeader ;
T4HEADER swapTagHeader ;
#endif /* S4BYTE_SWAP */
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
memset( (void *)higher, 0, sizeof( higher ) ) ;
memset( (void *)lower, 0, sizeof( lower ) ) ;
memset( (void *)parent, 0, sizeof( parent ) ) ;
i4 = r4->indexFile ;
d4 = r4->data ;
c4 = r4->codeBase ;
#ifdef E4ANALYZE
if ( i4 == 0 || d4 == 0 )
return error4( c4, e4struct, E92102 ) ;
#endif
tagOn = (TAG4FILE *) l4first( &i4->tags ) ;
if ( tagOn != 0 )
{
nTag = 1 ;
for ( ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn) ;
if ( tagOn == 0 )
break ;
nTag++ ;
iTag = 1 ;
for (;;)
{
tagPtr = r4reindexFindITag( r4, iTag ) ;
#ifdef E4MISC
if ( tagPtr == 0 || iTag < 0 || iTag >= 48 || nTag > 48 )
return error4( c4, e4result, E92102 ) ;
#endif /* E4MISC */
if ( u4memcmp( tagOn->alias, tagPtr->alias, sizeof(tagOn->alias)) < 0)
{
if ( lower[iTag] == 0 )
{
lower[iTag] = nTag ;
parent[nTag] = iTag ;
break ;
}
else
iTag = lower[iTag] ;
}
else
{
if ( higher[iTag] == 0 )
{
higher[iTag] = nTag ;
parent[nTag] = iTag ;
break ;
}
else
iTag = higher[iTag] ;
}
}
}
}
/* Now write the headers */
file4seqWriteInit( &r4->seqwrite, &i4->file, 0L, r4->buffer, r4->bufferLen ) ;
i4->header.eof = r4->lastblock + r4->lastblockInc ;
i4->header.freeList = 0L ;
u4yymmdd( i4->header.yymmdd ) ;
#ifdef S4BYTE_SWAP
memcpy( (void *)&swapHeader, (void *)&i4->header, sizeof(I4HEADER) ) ;
swapHeader.blockChunks = x4reverseShort( (void *)&swapHeader.blockChunks ) ;
swapHeader.blockRw = x4reverseShort( (void *)&swapHeader.blockRw ) ;
swapHeader.slotSize = x4reverseShort( (void *)&swapHeader.slotSize ) ;
swapHeader.numTags = x4reverseShort( (void *)&swapHeader.numTags ) ;
swapHeader.eof = x4reverseLong( (void *)&swapHeader.eof ) ;
swapHeader.freeList = x4reverseLong( (void *)&swapHeader.freeList ) ;
rc = file4seqWrite( &r4->seqwrite, &swapHeader, sizeof(I4HEADER) ) ;
#else
rc = file4seqWrite( &r4->seqwrite, &i4->header, sizeof(I4HEADER) ) ;
#endif /* S4BYTE_SWAP */
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 512-sizeof(I4HEADER)+17, 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
/* There is a 0x01 on byte 17 of the first 32 bytes. */
rc = file4seqWrite( &r4->seqwrite, "\001", 1 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 14, 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
tagOn = (TAG4FILE *) l4first( &i4->tags ) ;
for ( iTag = 0; iTag < 47; iTag++ )
{
memset( (void *)&tagInfo, 0, sizeof(tagInfo) ) ;
if ( iTag < r4->nTags )
{
tagInfo.headerPos = 4 + (long) iTag * r4->lastblockInc ;
tagOn->headerOffset = tagInfo.headerPos * 512 ;
memcpy( (void *)tagInfo.tag, tagOn->alias, sizeof(tagInfo.tag) ) ;
tagInfo.indexType = tagOn->header.type ;
#ifdef S4BYTE_SWAP
tagInfo.headerPos = x4reverseLong( (void *)&tagInfo.headerPos ) ;
tagInfo.x1000 = 0x0010 ;
#else
tagInfo.x1000 = 0x1000 ;
#endif /* S4BYTE_SWAP */
tagInfo.x2 = 2 ;
tagInfo.leftChld = (char) lower[iTag+1] ;
tagInfo.rightChld = (char) higher[iTag+1] ;
tagInfo.parent = (char) parent[iTag+1] ;
if ( i4->header.isProduction )
{
saveCode = c4->errFieldName ;
c4->errFieldName = 0 ;
jField = d4fieldNumber( d4, tagOn->expr->source ) ;
c4->errFieldName = saveCode ;
if ( jField > 0 )
{
rc = file4write( &r4->dataFile->file, ( jField + 1 ) * sizeof( FIELD4IMAGE ) - 1, "\001", 1 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
}
}
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
}
rc = file4seqWrite( &r4->seqwrite, &tagInfo, sizeof( T4DESC ) ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
}
for (tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
#ifdef S4BYTE_SWAP
memcpy( (void *)&swapTagHeader, (void *)&tagOn->header, sizeof(T4HEADER) ) ;
swapTagHeader.root = x4reverseLong( (void *)&swapTagHeader.root ) ;
swapTagHeader.keyLen = x4reverseShort( (void *)&swapTagHeader.keyLen ) ;
swapTagHeader.keysMax = x4reverseShort( (void *)&swapTagHeader.keysMax ) ;
swapTagHeader.groupLen = x4reverseShort( (void *)&swapTagHeader.groupLen ) ;
swapTagHeader.unique = x4reverseShort( (void *)&swapTagHeader.unique ) ;
rc = file4seqWrite( &r4->seqwrite, &swapTagHeader, sizeof( T4HEADER ) ) ;
#else
rc = file4seqWrite( &r4->seqwrite, &tagOn->header, sizeof( T4HEADER ) ) ;
#endif /* S4BYTE_SWAP */
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
ptr = tagOn->expr->source ;
len = strlen( ptr ) ;
rc = file4seqWrite( &r4->seqwrite, ptr, len) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 221-len, 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
if( tagOn->filter != 0 )
{
rc = file4seqWriteRepeat( &r4->seqwrite, 1, 1 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
if ( tagOn->hasKeys )
rc = file4seqWriteRepeat( &r4->seqwrite, 1, 1 ) ;
else
rc = file4seqWriteRepeat( &r4->seqwrite, 1, 0 ) ;
}
else
rc = file4seqWriteRepeat( &r4->seqwrite, 2, 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
/* write extra space up to filter write point */
rc = file4seqWriteRepeat( &r4->seqwrite, GARBAGE_LEN-3 , 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
if ( tagOn->filter == 0 )
len = 0 ;
else
{
ptr = tagOn->filter->source ;
len = strlen(ptr) ;
rc = file4seqWrite( &r4->seqwrite, ptr, len ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
}
rc = file4seqWriteRepeat( &r4->seqwrite, r4->blocklen - GARBAGE_LEN - len - 220 - sizeof(tagOn->header), 0 ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
}
rc = file4lenSet( &i4->file, i4->header.eof * 512) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
rc = file4seqWriteFlush( &r4->seqwrite ) ;
if ( rc < 0 )
return error4stack( c4, rc, E92102 ) ;
return 0 ;
}
int r4reindexWriteKeys( R4REINDEX *r4, short int errUnique )
{
TAG4FILE *t4 ;
char lastKey[I4MAX_KEY_SIZE], *keyData ;
int isUnique, rc, isFirst ;
void *dummyPtr ;
long keyRec ;
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
t4 = r4->tag ;
r4->grouplen = t4->header.groupLen ;
r4->valuelen = t4->header.keyLen ;
r4->keysmax = t4->header.keysMax ;
memset( (void *)r4->startBlock, 0, r4->nBlocks*r4->blocklen ) ;
rc = sort4getInit( &r4->sort ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
file4seqWriteInit( &r4->seqwrite, &r4->indexFile->file, (r4->lastblock+r4->lastblockInc)*512, r4->buffer,r4->bufferLen) ;
#ifdef E4MISC
if ( I4MAX_KEY_SIZE < r4->sort.sortLen )
return error4( r4->codeBase, e4index, E82102 ) ;
#endif
isFirst = 1 ;
isUnique = t4->header.unique ;
for(;;) /* For each key to write */
{
rc = sort4get( &r4->sort, &keyRec, (void **) &keyData, &dummyPtr) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
#ifdef E4MISC
if ( r4->keyCount < 0L || r4->keyCount == 0L && rc != 1 || r4->keyCount > 0L && rc == 1 )
return error4( r4->codeBase, e4info, E92102 ) ;
r4->keyCount-- ;
#endif
if ( rc == 1 ) /* No more keys */
{
rc = r4reindexFinish( r4 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
rc = file4seqWriteFlush( &r4->seqwrite ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
break ;
}
if ( isUnique )
{
if( isFirst )
isFirst = 0 ;
else
if ( (*t4->cmp)( keyData, lastKey, r4->sort.sortLen) == 0 )
{
switch( errUnique )
{
case e4unique:
return error4describe( r4->codeBase, e4unique, E82103, t4->alias, (char *)0, (char *)0 ) ;
case r4unique:
return r4unique ;
default:
continue ;
}
}
memcpy( lastKey, keyData, r4->sort.sortLen ) ;
}
/* Add the key */
rc = r4reindexAdd( r4, keyRec, (unsigned char *)keyData ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
}
/* Now complete the tag header info. */
t4->header.root = r4->lastblock ;
return 0 ;
}
int r4reindexAdd( R4REINDEX *r4, const long rec, const unsigned char *keyValue )
{
B4KEY_DATA *keyTo ;
R4BLOCK_DATA *startBlock ;
int rc ;
#ifdef E4ANALYZE
long dif ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 || rec < 0 || keyValue == 0 )
return error4( 0, e4parm, E92102 ) ;
#endif
startBlock = r4->startBlock ;
if ( startBlock->nKeys >= r4->keysmax )
{
rc = r4reindexTodisk( r4 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
memset( (void *)startBlock, 0, r4->blocklen ) ;
}
keyTo = (B4KEY_DATA *)( startBlock->info + (startBlock->nKeys++) * r4->grouplen ) ;
#ifdef E4ANALYZE
dif = (char *) keyTo - (char *) startBlock ;
if ( ((unsigned)dif + r4->grouplen) > r4->blocklen || dif < 0 )
return error4( r4->codeBase, e4index, E92102 ) ;
#endif
keyTo->num = rec ;
memcpy( (void *)keyTo->value, keyValue, r4->valuelen ) ;
return 0 ;
}
int r4reindexFinish( R4REINDEX *r4 )
{
R4BLOCK_DATA *block ;
int iBlock, rc ;
B4KEY_DATA *keyTo ;
#ifdef E4ANALYZE
long dif ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
#ifdef S4BYTE_SWAP
char *swap, *swapPtr ;
int i ;
S4LONG longVal ;
short shortVal ;
swap = (char *)u4allocEr( r4->codeBase, r4->blocklen ) ;
if ( swap == 0 )
return error4stack( r4->codeBase, e4memory, E92102 ) ;
memcpy( (void *)swap, (void *)r4->startBlock, r4->blocklen ) ;
/* position swapPtr at beginning of B4KEY's */
swapPtr = swap ;
swapPtr += 6 + sizeof(short) ;
/* move through all B4KEY's to swap 'long' */
for ( i = 0 ; i < (* (short *)swap) ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += r4->grouplen ;
}
/* swap the numKeys value */
shortVal = x4reverseShort( (void *)swap ) ;
memcpy( swap, (void *)&shortVal, sizeof(short) ) ;
rc = file4seqWrite( &r4->seqwrite, swap ,r4->blocklen ) ;
if ( rc < 0 )
{
u4free( swap ) ;
return error4stack( r4->codeBase, rc, E92102 ) ;
}
#else
rc = file4seqWrite( &r4->seqwrite, r4->startBlock, r4->blocklen ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
#endif /* S4BYTE_SWAP */
r4->lastblock += r4->lastblockInc ;
block = r4->startBlock ;
for( iBlock=1; iBlock < r4->nBlocks; iBlock++ )
{
block = (R4BLOCK_DATA *)( (char *)block + r4->blocklen ) ;
if ( block->nKeys >= 1 )
{
keyTo = (B4KEY_DATA *) (block->info + block->nKeys*r4->grouplen) ;
#ifdef E4ANALYZE
dif = (char *) keyTo - (char *) block ;
if ( ( (unsigned)dif + sizeof( long ) ) > r4->blocklen || dif < 0 )
return error4( r4->codeBase, e4index, E92102 ) ;
#endif
keyTo->num = r4->lastblock ;
#ifdef S4BYTE_SWAP
memcpy( (void *)swap, (void *)block, r4->blocklen ) ;
/* position swapPtr at beginning of B4KEY's */
swapPtr = swap ;
swapPtr += 6 + sizeof(short) ;
/* move through all B4KEY's to swap 'long' */
for ( i = 0 ; i < (*(short *)swap) ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += r4->grouplen ;
}
/* this is a branch */
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
/* swap the numKeys value */
shortVal = x4reverseShort( (void *)swap ) ;
memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
rc = file4seqWrite( &r4->seqwrite, swap, r4->blocklen ) ;
if ( rc < 0 )
{
u4free( swap ) ;
return error4stack( r4->codeBase, rc, E92102 ) ;
}
#else
rc = file4seqWrite( &r4->seqwrite, block, r4->blocklen ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
#endif /* S4BYTE_SWAP */
r4->lastblock += r4->lastblockInc ;
}
}
#ifdef S4BYTE_SWAP
u4free( swap ) ;
#endif /* S4BYTE_SWAP */
return 0 ;
}
int r4reindexTodisk( R4REINDEX *r4 )
{
R4BLOCK_DATA *block ;
int iBlock, rc ;
B4KEY_DATA *keyOn, *keyTo ;
#ifdef E4ANALYZE
long dif ;
#endif
#ifdef S4BYTE_SWAP
char *swap, *swapPtr ;
int i ;
S4LONG longVal ;
short shortVal ;
#endif /* S4BYTE_SWAP */
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
/* Writes out the current block and adds references to higher blocks */
block = r4->startBlock ;
iBlock= 0 ;
keyOn = (B4KEY_DATA *) (block->info + (block->nKeys-1) * r4->grouplen) ;
#ifdef E4ANALYZE
dif = (char *) keyOn - (char *) block ;
if ( ( (unsigned)dif + r4->grouplen ) > r4->blocklen || dif < 0 )
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4ANALYZE */
for(;;)
{
#ifdef S4BYTE_SWAP
swap = (char *) u4allocEr( r4->codeBase, r4->blocklen + sizeof(S4LONG) ) ;
if ( swap == 0 )
return error4stack( r4->codeBase, e4memory, E92102 ) ;
memcpy( (void *)swap, (void *)block, r4->blocklen ) ;
/* position swapPtr at beginning of B4KEY's */
swapPtr = swap ;
swapPtr += 6 + sizeof(short) ;
/* move through all B4KEY's to swap 'long' */
for ( i = 0 ; i < (*(short *)swap) ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += r4->grouplen ;
}
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
/* swap the numKeys value */
shortVal = x4reverseShort( (void *)swap ) ;
memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
rc = file4seqWrite( &r4->seqwrite, swap, r4->blocklen) ;
u4free( swap ) ;
#else
rc = file4seqWrite( &r4->seqwrite, block, r4->blocklen ) ;
#endif /* S4BYTE_SWAP */
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
if ( iBlock )
memset( (void *)block, 0, r4->blocklen ) ;
r4->lastblock += r4->lastblockInc ;
block = (R4BLOCK_DATA *) ((char *)block + r4->blocklen) ;
iBlock++ ;
#ifdef E4ANALYZE
if ( iBlock >= r4->nBlocks )
return error4( r4->codeBase, e4info, E92102 ) ;
#endif /* E4ANALYZE */
keyTo = (B4KEY_DATA *) (block->info + block->nKeys * r4->grouplen) ;
#ifdef E4ANALYZE
dif = (char *) keyTo - (char *) block ;
if ( ( (unsigned)dif + sizeof( long ) ) > r4->blocklen || dif < 0 )
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4ANALYZE */
keyTo->num = r4->lastblock ;
if ( block->nKeys < r4->keysmax )
{
block->nKeys++ ;
#ifdef E4ANALYZE
if ( ((unsigned)dif+r4->grouplen) > r4->blocklen )
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4ANALYZE */
memcpy( keyTo->value, keyOn->value, r4->valuelen ) ;
return 0 ;
}
}
}
#endif /* ifdef S4MDX */
#ifdef S4FOX
int r4reindexTagHeadersWrite( R4REINDEX *r4 )
{
TAG4FILE *tagOn ;
INDEX4FILE *i4file ;
int rc, totLen, iTag ;
unsigned int exprHdrLen ;
const char *ptr ;
#ifdef S4BYTE_SWAP
T4HEADER swapTagHeader ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
iTag = 2 ;
i4file = r4->indexFile ;
/* Now write the headers */
file4seqWriteInit( &r4->seqwrite, &i4file->file, 0L, r4->buffer, r4->bufferLen ) ;
i4file->tagIndex->header.freeList = 0L ;
exprHdrLen = 5 * sizeof(short) ;
i4file->eof = r4->lastblock + B4BLOCK_SIZE ;
if ( i4file->tagIndex->header.typeCode >= 64 )
{
#ifdef S4BYTE_SWAP
memcpy( (void *)&swapTagHeader, (void *)&i4file->tagIndex->header, sizeof(T4HEADER) ) ;
swapTagHeader.root = x4reverseLong( (void *)&swapTagHeader.root ) ;
swapTagHeader.freeList = x4reverseLong( (void *)&swapTagHeader.freeList ) ;
swapTagHeader.version = x4reverseLong( (void *)&swapTagHeader.version ) ;
swapTagHeader.keyLen = x4reverseShort( (void *)&swapTagHeader.keyLen ) ;
swapTagHeader.descending = x4reverseShort( (void *)&swapTagHeader.descending ) ;
swapTagHeader.filterPos = x4reverseShort( (void *)&swapTagHeader.filterPos ) ;
swapTagHeader.filterLen = x4reverseShort( (void *)&swapTagHeader.filterLen ) ;
swapTagHeader.exprPos = x4reverseShort( (void *)&swapTagHeader.exprPos ) ;
swapTagHeader.exprLen = x4reverseShort( (void *)&swapTagHeader.exprLen ) ;
rc = file4seqWrite( &r4->seqwrite, &swapTagHeader, LEN4HEADER_WR ) ; /* write first header part */
#else
rc = file4seqWrite( &r4->seqwrite, &i4file->tagIndex->header, LEN4HEADER_WR ) ; /* write first header part */
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 478L, 0 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWrite( &r4->seqwrite, &i4file->tagIndex->header.sortSeq, 8 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
#ifdef S4BYTE_SWAP
rc = file4seqWrite( &r4->seqwrite, &swapTagHeader.descending, exprHdrLen ) ;
#else
rc = file4seqWrite( &r4->seqwrite, &i4file->tagIndex->header.descending, exprHdrLen ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 512L, 0 ) ; /* no expression */
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
}
for ( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4file->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
if ( i4file->tagIndex->header.typeCode >= 64 )
tagOn->headerOffset = ((long)iTag) * B4BLOCK_SIZE ;
else
tagOn->headerOffset = 0L ;
#ifdef S4BYTE_SWAP
memcpy( (void *)&swapTagHeader, (void *)&tagOn->header, sizeof(T4HEADER) ) ;
swapTagHeader.root = x4reverseLong( (void *)&swapTagHeader.root ) ;
swapTagHeader.freeList = x4reverseLong( (void *)&swapTagHeader.freeList ) ;
swapTagHeader.version = x4reverseLong( (void *)&swapTagHeader.version ) ;
swapTagHeader.keyLen = x4reverseShort( (void *)&swapTagHeader.keyLen ) ;
swapTagHeader.descending = x4reverseShort( (void *)&swapTagHeader.descending ) ;
swapTagHeader.filterPos = x4reverseShort( (void *)&swapTagHeader.filterPos ) ;
swapTagHeader.filterLen = x4reverseShort( (void *)&swapTagHeader.filterLen ) ;
swapTagHeader.exprPos = x4reverseShort( (void *)&swapTagHeader.exprPos ) ;
swapTagHeader.exprLen = x4reverseShort( (void *)&swapTagHeader.exprLen ) ;
rc = file4seqWrite( &r4->seqwrite, &swapTagHeader, LEN4HEADER_WR ) ;
#else
rc = file4seqWrite( &r4->seqwrite, &tagOn->header, LEN4HEADER_WR ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWriteRepeat( &r4->seqwrite, 478L, 0 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWrite( &r4->seqwrite, &tagOn->header.sortSeq, 8 ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
#ifdef S4BYTE_SWAP
rc = file4seqWrite( &r4->seqwrite, &swapTagHeader.descending, exprHdrLen ) ;
#else
rc = file4seqWrite( &r4->seqwrite, &tagOn->header.descending, exprHdrLen ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
ptr = tagOn->expr->source ;
totLen = tagOn->header.exprLen ;
rc = file4seqWrite( &r4->seqwrite, ptr, (unsigned int)tagOn->header.exprLen ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
if ( tagOn->filter != 0 )
{
ptr = tagOn->filter->source ;
file4seqWrite( &r4->seqwrite, ptr, (unsigned int)tagOn->header.filterLen ) ;
totLen += tagOn->header.filterLen ;
}
rc = file4seqWriteRepeat( &r4->seqwrite, (long)B4BLOCK_SIZE - totLen, 0 );
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
iTag += 2 ;
}
rc = file4lenSet( &i4file->file, i4file->eof ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWriteFlush( &r4->seqwrite ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, rc, E92102 ) ;
return 0 ;
}
int r4reindexWriteKeys( R4REINDEX *r4, short int errUnique )
{
char lastKey[I4MAX_KEY_SIZE] ;
unsigned char *keyData ;
int isUnique, rc, cLen, tLen, lastTrail ;
int onCount, isFirst ;
unsigned short int kLen ;
void *dummyPtr ;
long keyRec, recCount ;
TAG4FILE *t4 ;
unsigned long ff ;
unsigned long rLen ;
R4BLOCK_DATA *r4block ;
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
t4 = r4->tag ;
kLen = (unsigned short int)t4->header.keyLen ;
ff = 0xFFFFFFFFL ;
isFirst = 1 ;
memset( lastKey, r4->tag->pChar, kLen ) ;
for ( cLen = 0 ; kLen ; kLen >>= 1, cLen++ ) ;
kLen = (unsigned short int)t4->header.keyLen ; /* reset the key length */
r4->nodeHdr.trailCntLen = r4->nodeHdr.dupCntLen = (unsigned char)cLen ;
r4->nodeHdr.trailByteCnt = (unsigned char)(0xFF >> ( 8 - ((cLen / 8) * 8 + cLen % 8))) ;
r4->nodeHdr.dupByteCnt = r4->nodeHdr.trailByteCnt ;
recCount = dfile4recCount( r4->dataFile, -2L ) ;
if ( recCount < 0 )
return error4stack( r4->codeBase, (short)recCount, E92102 ) ;
rLen = (unsigned long)recCount ;
for ( cLen = 0 ; rLen ; rLen>>=1, cLen++ ) ;
r4->nodeHdr.recNumLen = (unsigned char) cLen ;
if ( r4->nodeHdr.recNumLen < 12 )
r4->nodeHdr.recNumLen = 12 ;
for( tLen = r4->nodeHdr.recNumLen + r4->nodeHdr.trailCntLen + r4->nodeHdr.dupCntLen ;
(tLen / 8)*8 != tLen ; tLen++, r4->nodeHdr.recNumLen++ ) ; /* make at an 8-bit offset */
rLen = ff >> ( sizeof(long)*8 - r4->nodeHdr.recNumLen ) ;
memcpy( (void *)&r4->nodeHdr.recNumMask[0], (void *)&rLen, sizeof(long) ) ;
r4->nodeHdr.infoLen = (unsigned char)((unsigned int)(r4->nodeHdr.recNumLen + r4->nodeHdr.trailCntLen + r4->nodeHdr.dupCntLen) / 8) ;
r4->valuelen = t4->header.keyLen ;
r4->grouplen = t4->header.keyLen + 2*sizeof(long) ;
memset( (void *)r4->startBlock, 0, (unsigned int)r4->nBlocks * B4BLOCK_SIZE ) ;
#ifdef S4FOX
for ( r4block = r4->startBlock, onCount = 0 ; onCount < r4->nBlocks;
r4block = (R4BLOCK_DATA *) ( (char *)r4block + B4BLOCK_SIZE), onCount++ )
{
memset( (void *)r4block, 0, B4BLOCK_SIZE ) ;
r4block->header.leftNode = -1 ;
r4block->header.rightNode = -1 ;
}
#endif /* S4FOX */
r4->nodeHdr.freeSpace = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - sizeof( B4NODE_HEADER ) ;
r4->keysmax = (B4BLOCK_SIZE - sizeof( B4STD_HEADER ) ) / (unsigned)r4->grouplen ;
#ifdef E4ANALYZE
if ( r4->nodeHdr.freeSpace <= 0 || r4->keysmax <= 0 )
return error4( r4->codeBase, e4index, E92102 ) ;
#endif
rc = sort4getInit( &r4->sort ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
file4seqWriteInit( &r4->seqwrite, &r4->indexFile->file, r4->lastblock+B4BLOCK_SIZE, r4->buffer, r4->bufferLen ) ;
#ifdef E4MISC
if ( I4MAX_KEY_SIZE < r4->sort.sortLen )
return error4( r4->codeBase, e4index, E92102 ) ;
#endif /* E4MISC */
lastTrail = kLen ; /* default is no available duplicates */
isUnique = t4->header.typeCode & 0x01 ;
for( ;; ) /* For each key to write */
{
rc = sort4get( &r4->sort, &keyRec, (void **) &keyData, &dummyPtr ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
#ifdef E4MISC
if ( r4->keyCount < 0L || r4->keyCount == 0L && rc != 1 || r4->keyCount > 0L && rc == 1 )
return error4( r4->codeBase, e4info, E92102 ) ;
r4->keyCount-- ;
#endif /* E4MISC */
if ( rc == 1 ) /* No more keys */
{
rc = r4reindexFinish( r4, lastKey ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
rc = file4seqWriteFlush( &r4->seqwrite ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
break ;
}
if ( isUnique )
{
if( isFirst )
isFirst = 0 ;
else
if ( u4memcmp( keyData, lastKey, r4->sort.sortLen) == 0 )
{
switch( errUnique )
{
case e4unique:
case e4candidate:
return error4describe( r4->codeBase, e4unique, E82103, t4->alias, (char *)0, (char *)0 ) ;
case r4unique:
case r4candidate:
return r4unique ;
default:
continue ;
}
}
}
/* Add the key */
rc = r4reindexAdd( r4, keyRec, keyData, lastKey, &lastTrail ) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
memcpy( lastKey, keyData, r4->sort.sortLen ) ;
}
/* Now complete the tag header info. */
t4->header.root = r4->lastblock ;
return 0 ;
}
/* for compact leaf nodes only */
int r4reindexAdd( R4REINDEX *r4, const long rec, const unsigned char *keyValue, const char *lastKey, int *lastTrail )
{
R4BLOCK_DATA *startBlock ;
int rc, dupCnt, trail, kLen, iLen, len ;
unsigned char buffer[6] ;
char *infoPos ;
#ifdef E4PARM_LOW
if ( r4 == 0 || rec < 0 || keyValue == 0 )
return error4( 0, e4parm, E92102 ) ;
#endif
startBlock = r4->startBlock ;
kLen = r4->valuelen ;
iLen = r4->nodeHdr.infoLen ;
if ( startBlock->header.nKeys == 0 ) /* reset */
{
dupCnt = 0 ;
r4->curPos = ((char *)startBlock) + B4BLOCK_SIZE ;
memcpy( ((char *)startBlock) + sizeof( B4STD_HEADER ), (void *)&r4->nodeHdr, sizeof( B4NODE_HEADER ) ) ;
startBlock->header.nodeAttribute |= 2 ; /* leaf block */
*lastTrail = kLen ;
}
else
dupCnt = b4calcDups( keyValue,(const unsigned char*)lastKey, kLen ) ;
if ( dupCnt > kLen - *lastTrail ) /* don't allow duplicating trail bytes */
dupCnt = kLen - *lastTrail ;
if ( dupCnt == kLen ) /* duplicate key */
trail = 0 ;
else
{
if ( d4version( r4->data ) != 0x30 && r4->codeBase->compatibility == 26 && r4->tag->filter != 0 )
trail = 0 ;
else
trail = b4calcBlanks( keyValue, kLen, r4->tag->pChar ) ;
}
*lastTrail = trail ;
if ( dupCnt > kLen - *lastTrail ) /* watch for case where < ' ' exissts */
dupCnt = kLen - *lastTrail ;
len = kLen - dupCnt - trail ;
if ( r4->nodeHdr.freeSpace < iLen + len )
{
rc = r4reindexTodisk(r4, lastKey) ;
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
r4->nodeHdr.freeSpace = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - sizeof( B4NODE_HEADER ) ;
dupCnt = 0 ;
r4->curPos = ((char *)startBlock) + B4BLOCK_SIZE ;
memcpy( ((char *)&startBlock->header) + sizeof( B4STD_HEADER ), (void *)&r4->nodeHdr, sizeof( B4NODE_HEADER ) ) ;
startBlock->header.nodeAttribute |= 2 ; /* leaf block */
if ( d4version( r4->data ) != 0x30 && r4->codeBase->compatibility == 26 && r4->tag->filter != 0 )
trail = 0 ;
else
trail = b4calcBlanks( keyValue, kLen, r4->tag->pChar ) ;
len = kLen - trail ;
}
r4->curPos -= len ;
memcpy( r4->curPos, keyValue + dupCnt, (unsigned int)len ) ;
infoPos = ((char *)&startBlock->header) + sizeof(B4STD_HEADER) + sizeof(B4NODE_HEADER) + startBlock->header.nKeys * iLen ;
x4putInfo( &r4->nodeHdr, buffer, rec, trail, dupCnt ) ;
memcpy( infoPos, (void *)buffer, (unsigned int)iLen ) ;
r4->nodeHdr.freeSpace -= (unsigned char) ( len + iLen ) ;
startBlock->header.nKeys++ ;
return 0 ;
}
int r4reindexFinish( R4REINDEX *r4, char *keyValue )
{
R4BLOCK_DATA *block ;
int rc, iBlock ;
long revLb, lRecno ;
char *keyTo ;
#ifdef S4DATA_ALIGN
long longTemp ;
#endif
#ifdef S4BYTE_SWAP
char swap[B4BLOCK_SIZE] ;
char *swapPtr ;
int i ;
S4LONG longVal ;
short shortVal ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
block = r4->startBlock ;
if ( r4->nBlocksUsed <= 1 ) /* just output first block */
{
memcpy( ((char *)block) + sizeof( B4STD_HEADER ), (void *)&r4->nodeHdr, sizeof( B4NODE_HEADER ) ) ;
block->header.nodeAttribute |= (short)3 ; /* leaf and root block */
#ifdef S4BYTE_SWAP
memcpy( (void *)swap, (void *)block, B4BLOCK_SIZE ) ;
/* position at either B4NODE_HEADER (leaf) or data (branch) */
swapPtr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
if (block->header.nodeAttribute >= 2 ) /* if block is a leaf */
{
/* swap B4NODE_HEADER members */
shortVal = x4reverseShort( (void *)swapPtr ) ; /* freeSpace */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* recNumMask */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
}
else /* if block is a branch */
{
shortVal = r4->tag->header.keyLen + sizeof(S4LONG) ;
/* position swapPtr to end of first key expression */
swapPtr += r4->tag->header.keyLen ;
/* move through all B4KEY's to swap 'long's */
for ( i = 0 ; i < (int)block->header.nKeys ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += shortVal ;
}
}
/* reposition to B4STD_HEADER and swap members */
swapPtr = swap ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nodeAttribute */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nKeys */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* leftNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* rightNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
rc = file4seqWrite( &r4->seqwrite, swap,B4BLOCK_SIZE ) ;
#else
rc = file4seqWrite( &r4->seqwrite, block,B4BLOCK_SIZE ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
r4->lastblock += B4BLOCK_SIZE ;
}
else
{
memcpy( (void *)&lRecno, (void *) (((char *)(&block->header)) + sizeof(B4STD_HEADER)
+ sizeof(B4NODE_HEADER) + (block->header.nKeys - 1) * r4->nodeHdr.infoLen), sizeof( long ) ) ;
#ifdef S4DO_BYTEORDER
lRecno = x4reverseLong( (void *)&lRecno ) ;
#endif
#ifdef S4DATA_ALIGN
memcpy( (void *)&longTemp, (void *)&r4->nodeHdr.recNumMask[0], sizeof(S4LONG) ) ;
lRecno &= longTemp ;
#else
lRecno &= *(long *)&r4->nodeHdr.recNumMask[0] ;
#endif
if ( block->header.nodeAttribute >= 2 ) /* if leaf, record freeSpace */
memcpy( ((char *)block) + sizeof( B4STD_HEADER ), (void *)&r4->nodeHdr, sizeof( B4NODE_HEADER ) ) ;
#ifdef S4BYTE_SWAP
memcpy( (void *)swap, (void *)r4->startBlock, B4BLOCK_SIZE ) ;
/* position at either B4NODE_HEADER (leaf) or data (branch) */
swapPtr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
if (block->header.nodeAttribute >= 2 ) /* if block is a leaf */
{
/* swap B4NODE_HEADER members */
shortVal = x4reverseShort( (void *)swapPtr ) ; /* freeSpace */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* recNumMask */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
}
else /* if block is a branch */
{
shortVal = r4->tag->header.keyLen + sizeof(S4LONG) ;
/* position swapPtr to end of first key expression */
swapPtr += r4->tag->header.keyLen ;
/* move through all B4KEY's to swap 'long's */
for ( i = 0 ; i < (int) block->header.nKeys ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += shortVal ;
}
}
/* reposition to B4STD_HEADER and swap members */
swapPtr = swap ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nodeAttribute */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nKeys */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* leftNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* rightNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
rc = file4seqWrite( &r4->seqwrite, swap,B4BLOCK_SIZE ) ;
#else
rc = file4seqWrite(&r4->seqwrite, r4->startBlock,B4BLOCK_SIZE ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
r4->lastblock += B4BLOCK_SIZE ;
lRecno = x4reverseLong( (void *)&lRecno ) ;
for( iBlock=1; iBlock < r4->nBlocksUsed ; iBlock++ )
{
block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE) ;
keyTo = ((char *) (&block->header)) + sizeof(B4STD_HEADER) + block->header.nKeys * r4->grouplen ;
block->header.nKeys++ ;
#ifdef E4MISC
if ( (char *) keyTo - (char *) block + r4->grouplen > B4BLOCK_SIZE ||
(char *) keyTo - (char *) block < 0 )
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4MISC */
memcpy( keyTo, (void *)keyValue, (unsigned int)r4->valuelen ) ;
keyTo += r4->valuelen ;
memcpy( keyTo, (void *)&lRecno, sizeof( long ) ) ;
revLb = x4reverseLong( (void *)&r4->lastblock ) ;
memcpy( keyTo + sizeof( long ), (void *)&revLb, sizeof( long ) ) ;
if ( iBlock == r4->nBlocksUsed - 1 )
block->header.nodeAttribute = 1 ; /* root block */
#ifdef S4BYTE_SWAP
memcpy( (void *)swap, (void *)block, B4BLOCK_SIZE ) ;
/* position at either B4NODE_HEADER (leaf) or data (branch) */
swapPtr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
if (block->header.nodeAttribute >= 2 ) /* if block is a leaf */
{
/* swap B4NODE_HEADER members */
shortVal = x4reverseShort( (void *)swapPtr ) ; /* freeSpace */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* recNumMask */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
}
else /* if block is a branch */
{
shortVal = r4->tag->header.keyLen + sizeof(S4LONG) ;
/* position swapPtr to end of first key expression */
swapPtr += r4->tag->header.keyLen ;
/* move through all B4KEY's to swap 'long's */
for ( i = 0 ; i < (int) block->header.nKeys ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += shortVal ;
}
}
/* reposition to B4STD_HEADER and swap members */
swapPtr = swap ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nodeAttribute */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nKeys */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* leftNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* rightNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
rc = file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE ) ;
#else
rc = file4seqWrite( &r4->seqwrite, block, B4BLOCK_SIZE ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
r4->lastblock += B4BLOCK_SIZE ;
}
}
return 0 ;
}
/* Writes out the current block and adds references to higher blocks */
int r4reindexTodisk( R4REINDEX *r4, const char *keyValue )
{
R4BLOCK_DATA *block ;
long lRecno, revLb ;
int tnUsed, rc ;
char *keyTo ;
#ifdef S4DATA_ALIGN
long longTemp ;
#endif
#ifdef S4BYTE_SWAP
char swap[B4BLOCK_SIZE] ;
char *swapPtr ;
int i ;
S4LONG longVal ;
short shortVal ;
#endif
#ifdef E4ANALYZE
int iBlock ;
iBlock = 0 ;
#endif
#ifdef E4PARM_LOW
if ( r4 == 0 )
return error4( 0, e4parm_null, E92102 ) ;
#endif
block = r4->startBlock ;
tnUsed = 1 ;
memcpy( (void *)&lRecno, ((unsigned char *) (&block->header)) + sizeof(B4STD_HEADER)
+ sizeof(B4NODE_HEADER) + (block->header.nKeys - 1) * r4->nodeHdr.infoLen, sizeof( long ) ) ;
#ifdef S4DO_BYTEORDER
lRecno = x4reverseLong( (void *)&lRecno ) ;
#endif
#ifdef S4DATA_ALIGN
memcpy( (void *)&longTemp, (void *)&r4->nodeHdr.recNumMask[0], sizeof(S4LONG) ) ;
lRecno &= longTemp ;
#else
lRecno &= *(long *)&r4->nodeHdr.recNumMask[0] ;
#endif
lRecno = x4reverseLong( (void *)&lRecno ) ;
for(;;)
{
tnUsed++ ;
r4->lastblock += B4BLOCK_SIZE ;
/* next line only works when on leaf branches... */
block->header.rightNode = r4->lastblock + B4BLOCK_SIZE ;
if ( block->header.nodeAttribute >= 2 ) /* if leaf, record freeSpace */
memcpy( ((char *)block) + sizeof( B4STD_HEADER ), (void *)&r4->nodeHdr.freeSpace, sizeof( r4->nodeHdr.freeSpace ) ) ;
#ifdef S4BYTE_SWAP
memcpy( (void *)swap, (void *)block, B4BLOCK_SIZE ) ;
/* position at either B4NODE_HEADER (leaf) or data (branch) */
swapPtr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
/* if block is a leaf */
if (r4->startBlock->header.nodeAttribute >= 2 )
{
/* swap B4NODE_HEADER members */
shortVal = x4reverseShort( (void *)swapPtr ) ; /* freeSpace */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* recNumMask */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
}
else /* if block is a branch */
{
shortVal = r4->tag->header.keyLen + sizeof(S4LONG) ;
/* position swapPtr to end of first key expression */
swapPtr += r4->tag->header.keyLen ;
/* move through all B4KEY's to swap 'long's */
for ( i = 0 ; i < (int) block->header.nKeys ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += shortVal ;
}
}
/* reposition to B4STD_HEADER and swap members */
swapPtr = swap ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nodeAttribute */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
shortVal = x4reverseShort( (void *)swapPtr ) ; /* nKeys */
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* leftNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
longVal = x4reverseLong( (void *)swapPtr ) ; /* rightNode */
memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
swapPtr += sizeof(S4LONG) ;
rc = file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE ) ;
#else
rc = file4seqWrite( &r4->seqwrite, block, B4BLOCK_SIZE ) ;
#endif
if ( rc < 0 )
return error4stack( r4->codeBase, (short)rc, E92102 ) ;
memset( (void *)block, 0, B4BLOCK_SIZE ) ;
block->header.leftNode = r4->lastblock ;
block->header.rightNode = -1 ;
block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE) ;
#ifdef E4ANALYZE
iBlock++ ;
if ( iBlock >= r4->nBlocks )
return error4( r4->codeBase, e4info, E92102 ) ;
#endif /* E4ANALYZE */
if ( block->header.nKeys < r4->keysmax )
{
keyTo = ((char *) (&block->header)) + sizeof(B4STD_HEADER) + block->header.nKeys * r4->grouplen ;
block->header.nKeys++ ;
#ifdef E4ANALYZE
if ( (char *) keyTo - (char *) block + r4->grouplen > B4BLOCK_SIZE || (char *) keyTo - (char *) block < 0 )
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4ANALYZE */
memcpy( keyTo, (void *)keyValue, (unsigned int)r4->valuelen ) ;
keyTo += r4->valuelen ;
memcpy( keyTo, (void *)&lRecno, sizeof( long ) ) ;
revLb = x4reverseLong( (void *)&r4->lastblock ) ;
memcpy( keyTo + sizeof( long ), (void *)&revLb, sizeof( long ) ) ;
if ( block->header.nKeys < r4->keysmax ) /* then done, else do next one up */
{
if ( tnUsed > r4->nBlocksUsed )
r4->nBlocksUsed = tnUsed ;
return 0 ;
}
}
#ifdef E4ANALYZE
else /* should never occur */
return error4( r4->codeBase, e4result, E92102 ) ;
#endif /* E4ANALYZE */
}
}
#endif /* S4FOX */
#endif /* S4CLIENT */
#endif /* N4OTHER */
#endif /* S4INDEX_OFF */
#endif /* S4WRITE_OFF */