campo-sirio/cb/source/i4ntag.c
alex af15e0698b Codebase
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-06-16 13:01:08 +00:00

1974 lines
54 KiB
C
Executable File

/* i4ntag.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
#ifdef S4CLIENT
TAG4 *S4FUNCTION t4openLow( DATA4 *d4, INDEX4 *i4ndx, const char *fileName, const char *indexName )
{
CODE4 *c4 ;
CONNECTION4OPEN_TAG_INFO_IN dataIn ;
CONNECTION4OPEN_TAG_INFO_OUT *out ;
CONNECTION4 *connection ;
int rc ;
TAG4 *returnTag ;
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E94903 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( d4 == 0 || fileName == 0 )
{
error4( 0, e4parm_null, E94903 ) ;
return 0 ; ;
}
#endif
c4 = d4->codeBase ;
if ( error4code( c4 ) < 0 )
return 0 ;
switch( code4indexFormat( c4 ) )
{
case r4ndx:
case r4ntx:
break ;
default:
{
error4( c4, e4notSupported, E81719 ) ;
return 0 ;
}
}
if ( strlen( fileName ) > LEN4PATH )
{
error4( c4, e4name, E94903 ) ;
return 0 ;
}
memset( &dataIn, 0, sizeof( CONNECTION4OPEN_TAG_INFO_IN ) ) ;
connection = d4->dataFile->connection ;
if ( connection == 0 )
{
error4( c4, e4connection, E81704 ) ;
return 0 ;
}
connection4assign( connection, CON4TAG_OPEN, data4clientId( d4 ), data4serverId( d4 ) ) ;
dataIn.openForCreate = c4->openForCreate ;
#ifdef S4SINGLE
dataIn.exclusiveClient = 1 ;
#else
if ( c4->singleOpen == OPEN4DENY_RW )
dataIn.accessMode = OPEN4DENY_RW ;
else
dataIn.accessMode = c4->accessMode ;
#endif
dataIn.readOnly = c4->readOnly ;
dataIn.safety = c4->safety ; /* for catalog */
dataIn.errDefaultUnique = c4->errDefaultUnique ;
u4ncpy( dataIn.tagName, fileName, sizeof( dataIn.tagName ) ) ;
if ( i4ndx != 0 )
dataIn.hasIndex = 1 ;
if ( indexName != 0 )
u4ncpy( dataIn.indexName, indexName, sizeof( dataIn.indexName ) ) ;
if ( i4ndx != 0 )
dataIn.nameLen = strlen( i4ndx->indexFile->accessName ) + 1 ;
connection4addData( connection, &dataIn, sizeof( CONNECTION4OPEN_TAG_INFO_IN ), 0 ) ;
if ( i4ndx != 0 )
connection4addData( connection, i4ndx->indexFile->accessName, dataIn.nameLen, 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
{
error4( c4, rc, E81701 ) ;
return 0 ;
}
rc = connection4status( connection ) ;
if ( rc != 0 )
{
if ( rc < 0 )
{
if ( c4->errOpen == 0 )
{
if ( error4code( c4 ) >= 0 )
error4set( c4, r4noOpen ) ;
}
else
connection4error( connection, c4, rc, E94903 ) ;
}
return 0 ;
}
out = (CONNECTION4OPEN_TAG_INFO_OUT *)connection4data( connection ) ;
if ( client4indexSetup( c4, d4, d4->dataFile, 1, connection4data( connection ) + sizeof(CONNECTION4OPEN_TAG_INFO_OUT),
(unsigned int)connection4len( connection ), (char*)fileName, i4ndx ) < 0 )
{
error4( c4, e4connection, E94903 ) ;
return 0 ;
}
i4setup( c4, d4, (char *)fileName, out->autoOpened, i4ndx ) ;
returnTag = d4tag( d4, fileName ) ;
#ifndef S4OFF_TRAN
returnTag->isValid = 1 ;
#endif
return returnTag ;
}
int S4FUNCTION t4close( TAG4 *t4 )
{
INDEX4 *i4 ;
CODE4 *c4 ;
#ifdef S4VBASIC
if ( c4parm_check( t4, 4, E91637 ) )
return -1 ;
#endif
i4 = t4->index ;
c4 = i4->codeBase ;
if ( code4indexFormat( c4 ) != r4ntx ) /* function not supported */
return error4( c4, e4notSupported, E81719 ) ;
if ( l4numNodes( &i4->tags ) == 1 ) /* only the one tag, so remove index */
return i4close( i4 ) ;
else /* just free up the one tag so it is no longer available */
{
l4remove( &i4->tags, t4 ) ;
mem4free( c4->tagMemory, t4 ) ;
}
return 0 ;
}
#else
#ifndef S4INDEX_OFF
int tfile4type( TAG4FILE *t4 )
{
#ifdef S4FOX
return t4->expr->type ;
#endif
#ifdef S4CLIPPER
return t4->expr->type ;
#endif
#ifdef S4NDX
return t4->header.type ;
#endif
#ifdef S4MDX
return t4->header.type ;
#endif
}
#ifdef N4OTHER
B4BLOCK *tfile4block( TAG4FILE *t4 )
{
#ifdef E4PARM_LOW
if ( t4 == 0 )
{
error4( 0, e4parm_null, E91642 ) ;
return 0 ;
}
#endif
#ifdef E4ANALYZE
if ( t4->blocks.lastNode == 0 )
{
error4( 0, e4struct, E91642 ) ;
return 0 ;
}
#endif
return (B4BLOCK *)t4->blocks.lastNode ;
}
#ifdef S4CLIPPER
int tfile4rlBottom( TAG4FILE *t4 )
#else
int tfile4bottom( TAG4FILE *t4 )
#endif
{
int rc ;
B4BLOCK *blockOn ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return -1 ;
do
{
rc = tfile4upToRoot( t4 ) ;
if ( rc < 0 )
return -1 ;
if ( rc != 2 )
{
b4goEof( tfile4block( t4 ) ) ;
do
{
rc = tfile4down( t4 ) ;
if ( rc < 0 )
return -1 ;
b4goEof( tfile4block( t4 ) ) ;
} while ( rc == 0 ) ;
}
if ( rc == 2 ) /* failed due to read while locked */
tfile4outOfDate( t4 ) ;
} while ( rc == 2 ) ;
blockOn = tfile4block(t4) ;
if ( blockOn->keyOn > 0 )
blockOn->keyOn = blockOn->nKeys-1 ;
#ifdef E4ANALYZE
if ( blockOn->keyOn < 0 )
return error4( t4->codeBase, e4info, E91642 ) ;
#endif
return 0 ;
}
#ifdef S4CLIPPER
int tfile4bottom( TAG4FILE *t4 )
{
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
if ( t4->header.descending ) /* if descending, go bottom means go top */
return tfile4rlTop( t4 ) ;
else
return tfile4rlBottom( t4 ) ;
}
#endif
#ifdef S4CLIPPER
#ifdef S4HAS_DESCENDING
void tfile4descending( TAG4FILE *tag, const unsigned short int setting )
{
tag->header.descending = setting ;
}
#endif
#endif
/* Returns 1 - Cannot move down; 0 - Success; -1 Error */
int tfile4down( TAG4FILE *t4 )
{
long blockDown ;
B4BLOCK *blockOn, *popBlock, *newBlock, *parent ;
int rc ;
#ifdef S4BYTE_SWAP
char *swapPtr ;
int i ;
short shortVal ;
long longVal ;
#endif
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
if ( blockOn == 0 ) /* Read the root block */
{
if ( t4->header.root <= 0L )
{
#ifdef S4NDX
if ( file4readAll( &t4->file, t4->header.headerOffset, &t4->header.root, 2*sizeof(long)) < 0 )
return -1 ;
#else
#ifdef S4CLIPPER
if ( file4readAll( &t4->file, t4->header.headerOffset + 2*sizeof(short), &t4->header.root, 2*sizeof(long)) < 0 )
return -1 ;
#endif
#endif
#ifdef S4BYTE_SWAP
t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
#endif
}
blockDown = t4->header.root ;
}
else
{
if ( b4leaf( blockOn ) )
return 1 ;
blockDown = b4key( blockOn, blockOn->keyOn )->pointer ;
#ifdef E4ANALYZE
if ( blockDown <= 0L )
error4( t4->codeBase, e4info, E81602 ) ;
#endif
}
/* Get memory for the new block */
popBlock = (B4BLOCK *)l4pop( &t4->saved ) ;
newBlock = popBlock ;
if ( newBlock == 0 )
newBlock = b4alloc( t4, blockDown ) ;
if ( newBlock == 0 )
return -1 ;
parent = (B4BLOCK *)l4last( &t4->blocks ) ;
l4add( &t4->blocks, newBlock ) ;
#ifdef S4NDX
if ( popBlock == 0 || newBlock->fileBlock != blockDown )
#else
if ( popBlock == 0 || newBlock->fileBlock*I4MULTIPLY != blockDown )
#endif
{
#ifndef S4OFF_WRITE
if ( newBlock->changed == 1 )
if ( b4flush(newBlock) < 0 )
return -1 ;
#endif
rc = i4readBlock( &t4->file, blockDown, parent, newBlock ) ;
if ( rc < 0 )
return -1 ;
if ( rc == 1 )
{
l4remove( &t4->blocks, newBlock ) ;
l4add( &t4->saved, newBlock ) ;
return 2 ;
}
#ifdef S4BYTE_SWAP
#ifdef S4NDX
swapPtr = (void *)&newBlock->nKeys ;
shortVal = x4reverseShort( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += 2 + sizeof(short) ;
for ( i = 0 ; i < (*(short *)swap) ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
swapPtr += r4->groupLen ;
}
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
#endif
#ifdef S4CLIPPER
swapPtr = (void *)&newBlock->nKeys ;
shortVal = x4reverseShort( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += 2 ;
/* swap the short pointers to B4KEY_DATA */
for ( i = 0 ; i <= t4->header.keysMax ; i++ )
{
shortVal = x4reverseShort( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
swapPtr += sizeof(short) ;
}
/* swap the B4KEY_DATA's */
for ( i = 0 ; i < t4->header.keysMax ; i++ )
{
longVal = x4reverseLong( (void *)swapPtr ) ;
memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
swapPtr += t4->header.groupLen ;
}
#endif
#endif
for ( ;; )
{
blockOn = (B4BLOCK *)l4pop( &t4->saved ) ;
if ( blockOn == 0 )
break ;
#ifndef S4OFF_WRITE
if ( b4flush(blockOn) < 0 )
return -1 ;
#endif
b4free( blockOn ) ;
}
}
newBlock->keyOn = 0 ;
return 0 ;
}
int tfile4eof( TAG4FILE *t4 )
{
B4BLOCK *b4 ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
b4 = tfile4block( t4 ) ;
return ( b4->keyOn >= b4->nKeys ) ;
}
#ifndef S4OFF_WRITE
int tfile4flush( TAG4FILE *t4 )
{
int rc ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E94901 ) ;
#endif
rc = tfile4update( t4 ) ;
#ifndef S4OPTIMIZE_OFF
if ( rc )
rc = file4flush( &t4->file ) ;
#endif
return rc ;
}
#endif
int tfile4freeAll( TAG4FILE *t4 )
{
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
while ( tfile4up( t4 ) == 0 ) ;
return tfile4freeSaved( t4 ) ;
}
int tfile4freeSaved( TAG4FILE *t4 )
{
B4BLOCK *blockOn ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
#ifndef S4OFF_WRITE
if ( tfile4update( t4 ) < 0 )
return -1 ;
#endif
for ( ;; )
{
blockOn = (B4BLOCK *)l4pop( &t4->saved ) ;
if ( blockOn == 0 )
return 0 ;
#ifndef S4OFF_WRITE
if ( b4flush( blockOn ) < 0 )
return -1 ;
#endif
b4free( blockOn ) ;
}
}
B4KEY_DATA *tfile4keyData( TAG4FILE *t4 )
{
B4BLOCK *b4 ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
{
error4( 0, e4parm_null, E91642 ) ;
return 0 ;
}
#endif
b4 = (B4BLOCK *)t4->blocks.lastNode ;
return b4key( b4, b4->keyOn ) ;
}
long tfile4recNo( TAG4FILE *t4 )
{
B4BLOCK *blockOn ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return (long)error4( 0, e4parm_null, E91642 ) ;
#endif
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
if ( blockOn == 0 )
return -2L ;
#ifdef S4NDX
if ( !b4leaf( blockOn ) )
return -2L ;
#else
if ( blockOn->keyOn >= blockOn->nKeys )
return -1 ;
#endif
return b4recNo( blockOn, blockOn->keyOn ) ;
}
int tfile4seek( TAG4FILE *t4, const void *ptr, const int lenPtrIn )
{
int rc, lenPtr ;
B4BLOCK *blockOn ;
#ifdef S4CLIPPER
int upperFnd, upperAft, incPos, dSet ;
unsigned char *cPtr ;
dSet = 0 ;
cPtr = (unsigned char *)ptr ;
#endif
#ifdef E4PARM_LOW
if ( t4 == 0 || ptr == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
#ifdef E4ANALYZE
#ifndef S4CLIPPER
/* clipper stores all keys as strings, so length-mismatches are
ok */
if ( lenPtrIn != t4->header.keyLen && tfile4type( t4 ) != r4str )
return error4( t4->codeBase, e4struct, E91642 ) ;
#endif
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
lenPtr = lenPtrIn ;
if ( lenPtr > t4->header.keyLen )
lenPtr = t4->header.keyLen ;
#ifdef S4CLIPPER
if ( t4->header.descending ) /* look for current item less one: */
{
for( incPos = lenPtr-1 ; dSet == 0 && incPos >=0 ; incPos-- )
if ( cPtr[incPos] != 0xFF )
{
cPtr[incPos]++ ;
dSet = 1 ;
}
}
#endif
rc = 3 ;
for(;;) /* Repeat until found */
{
while ( rc >= 2 )
{
if ( rc == 2 )
tfile4outOfDate( t4 ) ;
rc = tfile4upToRoot( t4 ) ;
#ifdef S4CLIPPER
upperFnd = 0 ;
upperAft = 0 ;
#endif
if ( rc < 0 )
return -1 ;
}
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
#ifdef E4ANALYZE
if ( blockOn == 0 )
return error4( t4->codeBase, e4info, E91642 ) ;
#endif
rc = b4seek( blockOn, (char *)ptr, lenPtr ) ;
#ifdef S4NDX
if ( b4leaf( blockOn ) )
break ;
#else
#ifdef S4CLIPPER
if ( b4leaf( blockOn ) )
{
if ( rc == r4after && upperAft && blockOn->keyOn >= blockOn->nKeys )
while( upperAft-- > 1 )
tfile4up( t4 ) ;
if ( rc == 0 || !upperFnd )
break ;
while( upperFnd-- > 1 )
tfile4up( t4 ) ;
rc = 0 ;
break ;
}
if ( rc == 0 )
{
upperFnd = 1 ;
upperAft = 0 ;
}
else
if ( rc == r4after && !upperFnd && !( blockOn->keyOn >= blockOn->nKeys ) )
upperAft = 1 ;
#endif
#endif
rc = tfile4down( t4 ) ;
if ( rc < 0 )
return -1 ;
#ifdef S4CLIPPER
if ( upperFnd )
upperFnd++ ;
if ( upperAft )
upperAft++ ;
#endif
}
#ifdef S4CLIPPER
if ( t4->header.descending ) /* must go back one! */
{
cPtr[incPos+1]-- ; /* reset the search_ptr ; */
if ( dSet )
{
rc = (int)tfile4skip( t4, -1L ) ;
if ( rc == 0L ) /* bof = eof condition */
{
b4goEof( blockOn ) ;
rc = r4eof ;
}
else
{
if ( (u4memcmp)( b4keyKey( tfile4block( t4 ), tfile4block( t4 )->keyOn ), ptr, lenPtr ) )
rc = r4after ;
else
rc = 0 ; /* successful find */
}
}
else
{
if ( rc == 0 ) /* the item was found, so go top, */
tfile4top( t4 ) ;
else /* otherwise want an eof type condition */
{
b4goEof( blockOn ) ;
rc = r4eof ;
}
}
}
#endif
return rc ;
}
long tfile4skip( TAG4FILE *t4, long numSkip )
{
int rc, sign, seekSpecial ;
B4BLOCK *blockOn ;
#ifdef S4NDX
long numLeft = numSkip ;
#endif
#ifdef S4CLIPPER
long j ;
#endif
#ifdef E4PARM_LOW
if ( t4 == 0 )
return (long)error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
if ( numSkip < 0)
sign = -1 ;
else
sign = 1 ;
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
if ( blockOn == 0 )
{
rc = tfile4top( t4 ) ;
if ( rc < 0 )
return -numSkip ;
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
}
#ifdef S4NDX
#ifdef E4ANALYZE
if ( !b4leaf( blockOn ) )
return (long)error4( t4->codeBase, e4info, E91642 ) ;
#endif
for(;;)
{
/* save the current key in case skip fails */
memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn ), t4->header.keyLen ) ;
while ( (rc = tfile4down(t4)) == 0 )
if ( sign < 0 )
{
blockOn = tfile4block(t4) ;
b4goEof( blockOn ) ;
if ( b4leaf(blockOn) )
{
blockOn->keyOn-- ;
#ifdef E4ANALYZE
if ( blockOn->keyOn < 0 )
return (long)error4( t4->codeBase, e4info, E91642 ) ;
#endif
}
}
if ( rc < 0 )
return -numSkip ;
if ( rc == 2 ) /* failed on i/o, seek current spot to make valid */
{
tfile4outOfDate( t4 ) ;
rc = tfile4seek( t4, t4->codeBase->savedKey, t4->header.keyLen ) ;
if ( rc < 0 )
return -numSkip ;
if ( rc == r4after ) /* means skipped 1 ahead */
numLeft-- ;
continue ;
}
blockOn = tfile4block( t4 ) ;
if ( rc < 0 ) /* Error */
return( -numSkip ) ;
numLeft -= b4skip( blockOn, numLeft ) ;
if ( numLeft == 0 ) /* Success */
return( numSkip ) ;
do /* Skip 1 to the next leaf block */
{
#ifdef E4ANALYZE
if ( t4->blocks.lastNode == 0 )
return (long)error4( t4->codeBase, e4result, E91642 ) ;
#endif
if ( l4prev( &t4->blocks, t4->blocks.lastNode ) == 0 ) /* root block */
{
if ( numSkip > 0 )
{
if ( tfile4bottom( t4 ) < 0 )
return -numSkip ;
}
else
if ( tfile4top( t4 ) < 0 )
return -numSkip ;
return( numSkip - numLeft ) ;
}
tfile4up( t4 ) ;
blockOn = (B4BLOCK *)t4->blocks.lastNode ;
} while ( b4skip( blockOn, (long) sign) != sign) ;
numLeft -= sign ;
}
#else
#ifdef S4CLIPPER
for( j = numSkip; j != 0; j -= sign ) /* skip 1 * numSkip */
{
if ( b4leaf(blockOn) )
{
if ( b4skip( blockOn, (long) sign) != sign ) /* go up */
{
int go_on = 1 ;
while ( go_on )
{
if ( l4prev( &t4->blocks, t4->blocks.lastNode ) == 0 ) /* root block */
{
if ( numSkip > 0 && t4->header.descending == 0 ||
numSkip <= 0 && t4->header.descending == 1 )
/* if ( numSkip > 0 )*/
{
if ( tfile4bottom( t4 ) < 0 )
return -numSkip ;
}
else
if ( tfile4top( t4 ) < 0 )
return -numSkip ;
return ( numSkip - j ) ;
}
rc = tfile4up( t4 ) ;
blockOn = tfile4block( t4 ) ;
if ( rc != 0 ) return -1 ;
if ( sign > 0 ) /* forward skipping */
{
if ( !( blockOn->keyOn >= blockOn->nKeys ) )
go_on = 0 ;
}
else /* backward skipping */
{
if ( ! (blockOn->keyOn == 0) )
{
b4skip( blockOn, -1L ) ;
go_on = 0 ;
}
}
}
}
}
else
{
if ( sign > 0 )
b4skip( blockOn, 1L ) ;
/* save the current key in case skip fails */
if ( blockOn->keyOn >= blockOn->nKeys ) /* case where no proper key to copy exists */
{
if ( blockOn->nKeys == 0 ) /* invalid, so must discard this block */
{
/* codeBase can't recover from this gracefully, so just go back up saying
that couldn't skip */
return 0 ;
}
/* not on a true key, so instead just go to the old position, and then try the skip again (unless r4after)*/
memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn - 1 ), t4->header.keyLen ) ;
seekSpecial = 1 ;
}
else
{
memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn ), t4->header.keyLen ) ;
seekSpecial = 0 ;
}
while ( (rc = tfile4down( t4 ) ) == 0 )
{
if ( sign < 0 )
{
blockOn = tfile4block( t4 ) ;
b4goEof( blockOn ) ;
if ( b4leaf( blockOn ) )
blockOn->keyOn-- ;
}
}
if ( rc < 0 )
return -numSkip ;
if ( rc == 2 ) /* failed on i/o, seek current spot to make valid */
{
#ifndef S4OPTIMIZE_OFF
#ifndef S4SINGLE
file4refresh( &t4->file ) ;
#endif
#endif
rc = tfile4seek( t4, t4->codeBase->savedKey, t4->header.keyLen ) ;
if ( rc < 0 )
return -numSkip ;
if ( rc == r4after ) /* means skipped 1 ahead */
if ( j != 1 )
j-- ;
if ( seekSpecial == 1 ) /* means we are actually on wrong pos, need to skip one */
j += sign ; /* pre-increment # of skip times */
}
blockOn = tfile4block( t4 ) ;
}
}
return numSkip ;
#endif
#endif
}
#ifndef S4OFF_WRITE
#ifdef S4NDX
B4BLOCK *tfile4split( TAG4FILE *t4, B4BLOCK *oldBlock )
{
long newFileBlock ;
B4BLOCK *newBlock ;
int newLen ;
if ( error4code( t4->codeBase ) < 0 )
return 0 ;
#ifdef E4INDEX_VERIFY
if ( b4verify( oldBlock ) == -1 )
error4describe( oldBlock->tag->codeBase, e4index, E91622, oldBlock->tag->alias, 0, 0 ) ;
#endif
newFileBlock = tfile4extend( t4 ) ;
newBlock = b4alloc( t4, newFileBlock ) ;
if ( newBlock == 0 )
return 0 ;
newBlock->changed = 1 ;
oldBlock->changed = 1 ;
/* NNNNOOOO N - New, O - Old */
newBlock->nKeys = ( oldBlock->nKeys )/2 ;
oldBlock->nKeys -= newBlock->nKeys ;
newLen = newBlock->nKeys * t4->header.groupLen ;
c4memmove( b4key(newBlock,0), b4key(oldBlock, oldBlock->nKeys ), newLen+ (sizeof(long)*(!(b4leaf( oldBlock )) ) ) ) ;
newBlock->keyOn = oldBlock->keyOn - oldBlock->nKeys ;
oldBlock->nKeys -= !( b4leaf( oldBlock ) ) ;
return newBlock ;
}
#else
#ifdef S4CLIPPER
/* NTX only needs to do a copy and adjust the index pointers */
/* if extraOld is true then the extra key is placed in old, otherwise in new */
B4BLOCK *tfile4split( TAG4FILE *t4, B4BLOCK *oldBlock, const int extraOld )
{
long newFileBlock ;
B4BLOCK *newBlock ;
int isBranch ;
if ( error4code( t4->codeBase ) < 0 )
return 0 ;
#ifdef E4INDEX_VERIFY
if ( b4verify( oldBlock ) == -1 )
error4describe( oldBlock->tag->codeBase, e4index, E91642, oldBlock->tag->alias, 0, 0 ) ;
#endif
newFileBlock = tfile4extend( t4 ) ;
newBlock = b4alloc( t4, newFileBlock ) ;
if ( newBlock == 0 )
return 0 ;
newBlock->changed = 1 ;
oldBlock->changed = 1 ;
memcpy( newBlock->data, oldBlock->data, B4BLOCK_SIZE - ( t4->header.keysMax + 2 ) * sizeof(short) ) ;
if ( extraOld )
{
newBlock->nKeys = oldBlock->nKeys / 2 ;
oldBlock->nKeys -= newBlock->nKeys ;
}
else
{
newBlock->nKeys = oldBlock->nKeys ;
oldBlock->nKeys = oldBlock->nKeys / 2 ;
newBlock->nKeys -= oldBlock->nKeys ;
if ( oldBlock->nKeys == newBlock->nKeys )
{
newBlock->nKeys++ ;
oldBlock->nKeys-- ;
}
}
isBranch = !b4leaf( oldBlock ) ;
memcpy( newBlock->pointers, &oldBlock->pointers[oldBlock->nKeys + isBranch], newBlock->nKeys * sizeof(short) ) ;
memcpy( &newBlock->pointers[newBlock->nKeys], oldBlock->pointers, (oldBlock->nKeys + isBranch) * sizeof(short) ) ;
if ( isBranch == 0 ) /* leaf blocks need one more copy */
newBlock->pointers[t4->header.keysMax] = oldBlock->pointers[t4->header.keysMax] ;
newBlock->keyOn = oldBlock->keyOn - oldBlock->nKeys - isBranch ;
newBlock->nKeys -= isBranch ;
return newBlock ;
}
#endif
#endif
#endif /* S4OFF_WRITE */
#ifdef S4CLIPPER
int tfile4rlTop( TAG4FILE *t4 )
#else
int tfile4top( TAG4FILE *t4 )
#endif
{
int rc ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
do
{
rc = tfile4upToRoot( t4 ) ;
if ( rc < 0 )
return -1 ;
if ( rc != 2 )
{
((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
do
{
if ( (rc = tfile4down(t4)) < 0 )
return -1 ;
((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
} while ( rc == 0 ) ;
}
if ( rc == 2 ) /* failed due to read while locked */
tfile4outOfDate( t4 ) ;
} while ( rc == 2 ) ;
return 0 ;
}
#ifdef S4CLIPPER
int tfile4top( TAG4FILE *t4 )
{
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
if ( t4->header.descending ) /* if descending, go top means go bottom */
return tfile4rlBottom( t4 ) ;
else
return tfile4rlTop( t4 ) ;
}
#endif
int tfile4up( TAG4FILE *t4 )
{
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( t4->blocks.lastNode == 0 )
return 1 ;
l4add( &t4->saved, l4pop(&t4->blocks) ) ;
return 0 ;
}
#ifndef S4OFF_WRITE
int tfile4update( TAG4FILE *t4 )
{
B4BLOCK *blockOn ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
if ( tfile4updateHeader( t4 ) < 0 )
return -1 ;
for( blockOn = 0 ;; )
{
blockOn = (B4BLOCK *)l4next( &t4->saved ,blockOn ) ;
if ( blockOn == 0 )
break ;
if ( b4flush(blockOn) < 0 )
return -1 ;
}
for( blockOn = 0 ;; )
{
blockOn = (B4BLOCK *)l4next( &t4->blocks, blockOn ) ;
if ( blockOn == 0 )
break ;
if ( b4flush( blockOn ) < 0 )
return -1 ;
}
if ( t4->rootWrite )
{
#ifdef S4BYTE_SWAP
t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
#endif
#ifdef S4NDX
if ( file4write( &t4->file, t4->headerOffset, &t4->header.root, 2 * sizeof(long) ) < 0 )
return -1 ;
#else
#ifdef S4CLIPPER
if ( file4write( &t4->file, t4->headerOffset + 2*sizeof( short ),
&t4->header.root, 2*sizeof(long) ) < 0 ) return -1 ;
#endif
#endif
#ifdef S4BYTE_SWAP
t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
#endif
t4->rootWrite = 0 ;
}
return 0 ;
}
#endif /* S4OFF_WRITE */
int tfile4upToRoot( TAG4FILE *t4 )
{
LINK4 *linkOn ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
for ( ;; )
{
linkOn = (LINK4 *)l4pop( &t4->blocks ) ;
if ( linkOn == 0 )
return tfile4down(t4) ;
l4add( &t4->saved, linkOn ) ;
}
}
int tfile4close( TAG4FILE *t4, DATA4FILE *d4 )
{
CODE4 *c4 ;
int finalRc ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91638 ) ;
#endif
c4 = t4->codeBase ;
finalRc = 0 ;
#ifdef E4ANALYZE
if ( t4->userCount <= 0 )
return error4( c4, e4struct, E91638 ) ;
#endif
t4->userCount-- ;
#ifdef S4SERVER
if ( c4->server->keepOpen != 2 || t4->file.isTemp != 1 )
#endif
if ( t4->userCount == 0 )
{
if ( tfile4freeAll( t4 ) < 0 )
finalRc = error4set( c4, 0) ;
expr4free( t4->expr ) ;
expr4free( t4->filter ) ;
mem4release( t4->blockMemory ) ;
t4->blockMemory = 0 ;
if ( file4openTest( &t4->file ) )
{
if ( c4->doRemove == 1 )
t4->file.isTemp = 1 ;
if ( file4close( &t4->file ) < 0 )
finalRc = error4set( c4, 0 ) ;
}
if ( t4->link.n != (LINK4 *)0 )
l4remove( &d4->tagfiles, t4 ) ;
mem4free( c4->tagFileMemory, t4 ) ;
error4set( c4, finalRc ) ;
}
return finalRc ;
}
int S4FUNCTION t4close( TAG4 *t4 )
{
int finalRc ;
DATA4 *d4 ;
CODE4 *c4 ;
#ifdef S4VBASIC
if ( c4parm_check( t4, 4, E91637 ) )
return -1 ;
#endif
#ifdef E4PARM_HIGH
if ( t4 == 0 )
return error4( 0, e4parm_null, E91637 ) ;
#endif
if ( l4seek( &t4->index->tags, t4 ) == 1 ) /* i4close removes the tag, so if still there, was not called from i4close() */
{
if ( l4numNodes( &t4->index->tags ) == 1 ) /* only the one tag, so remove index */
return i4close( t4->index ) ;
else /* must remove from the list manually */
l4remove( &t4->index->tags, t4 ) ;
}
c4 = t4->tagFile->codeBase ;
d4 = t4->index->data ;
#ifndef S4OFF_TRAN
if ( t4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
if ( code4transEnabled( c4 ) )
if ( code4trans( c4 )->currentTranStatus == r4active ) /* disallow on current active only */
return error4( c4, e4transViolation, E81522 ) ;
#endif
finalRc = error4set( c4, 0 ) ;
#ifndef S4OFF_WRITE
#ifndef S4OFF_TRAN
if ( t4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
#endif
if ( d4 )
if ( d4update( d4 ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
#ifndef S4SINGLE
if ( tfile4unlock( t4->tagFile, data4serverId( t4->index->data ) ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
if ( tfile4close( t4->tagFile, d4->dataFile ) < 0 )
finalRc = error4set( c4, 0 ) ;
mem4free( c4->tagMemory, t4 ) ;
error4set( c4, finalRc ) ;
return finalRc ;
}
#ifndef S4OFF_WRITE
long tfile4extend( TAG4FILE *t4 )
{
long oldEof ;
CODE4 *c4 = t4->codeBase ;
if ( error4code( c4 ) < 0 )
return e4codeBase ;
#ifdef E4ANALYZE
if ( t4->header.version == t4->header.oldVersion )
return (long)error4( c4, e4info, E91636 ) ;
#endif
oldEof = t4->header.eof ;
#ifdef S4NDX
#ifdef E4ANALYZE
if ( oldEof <= 0L )
return (long)error4( c4, e4info, E91636 ) ;
#endif
t4->header.eof += B4BLOCK_SIZE / I4MULTIPLY ;
t4->rootWrite = 1 ;
return oldEof ;
#else
#ifdef S4CLIPPER
#ifdef S4SINGLE
if ( oldEof != 0 ) /* case where free-list exists */
t4->header.eof = 0L ;
else
{
#endif
oldEof = file4len( &t4->file ) ;
#ifdef E4ANALYZE
if ( oldEof <= t4->checkEof )
return (long)error4( c4, e4info, E91636 ) ;
t4->checkEof = oldEof ;
#endif
file4lenSet( &t4->file, file4len( &t4->file ) + 1024 ) ; /* and extend the file */
#ifdef S4SINGLE
}
#endif
return oldEof/512 ;
#endif
#endif
}
#endif /* S4OFF_WRITE */
#ifdef P4ARGS_USED
#pragma argsused
#endif
int tfile4go2( TAG4FILE *t4, const unsigned char *ptr, const long recNum, const int goAdd )
{
int rc ;
long rec ;
#ifdef E4PARM_LOW
if ( t4 == 0 || ptr == 0 || recNum < 1 )
return error4( 0, e4parm, E91642 ) ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
rc = tfile4seek( t4, ptr, t4->header.keyLen ) ;
if ( rc )
return rc ;
for(;;)
{
rec = tfile4recNo( t4 ) ;
if (rec == recNum )
return 0 ;
rc = (int)tfile4skip( t4, 1L ) ;
if ( rc == -1 )
return -1 ;
if ( rc == 0 )
{
b4goEof( tfile4block( t4 ) ) ;
return r4found ;
}
if ( (*t4->cmp)( tfile4keyData( t4 )->value, ptr, t4->header.keyLen ) )
return r4found ;
}
}
static TAG4FILE *tfile4open( DATA4 *d4, const char *fileName )
{
TAG4FILE *tfile ;
CODE4 *c4 ;
char buf[258], buffer[1024] ;
char exprBuf[I4MAX_EXPR_SIZE + 1] ;
#ifdef S4CLIPPER
char *ptr, garbage ;
#endif
FILE4SEQ_READ seqRead ;
int rc, len, oldTagNameError ;
c4 = d4->codeBase ;
u4ncpy( buf, fileName, sizeof( buf ) ) ;
c4upper(buf) ;
#ifdef S4NDX
#ifdef S4CASE_SEN
u4nameExt( buf, sizeof(buf), "ndx", 0 ) ;
#else
u4nameExt( buf, sizeof(buf), "NDX", 0 ) ;
#endif
#else
#ifdef S4CLIPPER
#ifdef S4CASE_SEN
u4nameExt( buf, sizeof(buf), "ntx", 0 ) ;
#else
u4nameExt( buf, sizeof(buf), "NTX", 0 ) ;
#endif
#endif
#endif
oldTagNameError = c4->errTagName ;
c4->errTagName = 0 ;
tfile = dfile4tag( d4->dataFile, buf ) ;
c4->errTagName = oldTagNameError ;
if ( tfile != 0 ) /* because t4open() verifies no duplicates, this must be a duplicate data4 instance */
{
/* changed 09/19/95 - test program t4skip.c */
tfile->userCount++ ;
return tfile ;
/* only one instance ever allowed */
/* error4( c4, e4instance, E94906 ) ;*/
/* return 0 ; */
/*
#ifndef S4SERVER
if ( c4->singleOpen != OPEN4SPECIAL ) only one instance allowed...
{
error4( c4, e4instance, E94906 ) ;
return 0 ;
}
#endif
tfile->userCount++ ;
return tfile ;
*/
}
if ( c4->tagFileMemory == 0 )
{
c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof(TAG4FILE), c4->memExpandTagFile, 0 ) ;
if ( c4->tagFileMemory == 0 )
return 0 ;
}
tfile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
if ( tfile == 0 )
return 0 ;
tfile->file.hand = -1 ;
tfile->codeBase = c4 ;
tfile->userCount = 1 ;
if ( tfile->blockMemory == 0 )
tfile->blockMemory = mem4create( c4, c4->memStartBlock, (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
(sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])),
c4->memExpandBlock, 0 ) ;
if ( tfile->blockMemory == 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
rc = file4open( &tfile->file, c4, buf, 1 ) ;
if ( rc != 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#ifndef S4OPTIMIZE_OFF
file4optimizeLow( &tfile->file, c4->optimize, OPT4INDEX, 0, tfile ) ;
#endif
file4seqReadInit( &seqRead, &tfile->file, 0, buffer, 1024 ) ;
#ifdef S4NDX
if ( file4seqReadAll( &seqRead, &tfile->header.root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#ifdef S4BYTE_SWAP
tfile->header.root = x4reverseLong( (void *)&tfile->header.root ) ;
tfile->header.eof = x4reverseLong( (void *)&tfile->header.eof ) ;
tfile->header.keyLen = x4reverseShort( (void *)&tfile->header.keyLen ) ;
tfile->header.keysMax = x4reverseShort( (void *)&tfile->header.keysMax ) ;
tfile->header.int_or_date = x4reverseShort( (void *)&tfile->header.int_or_date ) ;
tfile->header.groupLen = x4reverseShort( (void *)&tfile->header.groupLen ) ;
tfile->header.dummy = x4reverseShort( (void *)&tfile->header.dummy ) ;
tfile->header.unique = x4reverseShort( (void *)&tfile->header.unique ) ;
#endif
t4->header.type = 0 ;
#else
#ifdef S4CLIPPER
if ( file4seqReadAll( &seqRead, &tfile->header.sign, sizeof(I4IND_HEAD_WRITE) ) < 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#endif
#ifdef S4BYTE_SWAP
tfile->header.sign = x4reverseShort( (void *)&tfile->header.sign ) ;
tfile->header.version = x4reverseShort( (void *)&tfile->header.version ) ;
tfile->header.root = x4reverseLong( (void *)&tfile->header.root ) ;
tfile->header.eof = x4reverseLong( (void *)&tfile->header.eof ) ;
tfile->header.groupLen = x4reverseShort( (void *)&tfile->header.groupLen ) ;
tfile->header.keyLen = x4reverseShort( (void *)&tfile->header.keyLen ) ;
tfile->header.keyDec = x4reverseShort( (void *)&tfile->header.keyDec ) ;
tfile->header.keysMax = x4reverseShort( (void *)&tfile->header.keysMax ) ;
tfile->header.keysHalf = x4reverseShort( (void *)&tfile->header.keysHalf ) ;
#endif
#endif
tfile->header.headerOffset = 0 ;
/* Perform some checks */
if ( tfile->header.keyLen > I4MAX_KEY_SIZE || tfile->header.keyLen <= 0 ||
#ifdef S4CLIPPER
tfile->header.keysMax != 2* tfile->header.keysHalf || tfile->header.keysHalf <= 0 ||
tfile->header.groupLen != tfile->header.keyLen+ 8 ||
(tfile->header.sign != 0x6 && tfile->header.sign != 0x106 ) )
#else
tfile->header.keyLen+8 > tfile->header.groupLen ||
tfile->header.keysMax < 4 || tfile->header.keysMax > 50 ||
tfile->header.eof <= 0L )
#endif
{
error4describe( c4, e4index, E84904, buf, 0, 0 ) ;
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
tfile->cmp = (S4CMP_FUNCTION *)u4memcmp ;
tfile->header.root = -1 ;
tfile->header.oldVersion = tfile->header.version ;
u4namePiece( tfile->alias, sizeof( tfile->alias ), fileName, 0, 0 ) ;
#ifndef S4CASE_SEN
c4upper( tfile->alias ) ;
#endif
file4seqReadAll( &seqRead, exprBuf, sizeof( exprBuf ) - 1 ) ;
c4trimN( exprBuf, sizeof( exprBuf ) ) ;
tfile->expr = expr4parseLow( d4, exprBuf, tfile ) ;
if ( tfile->expr == 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#ifdef S4CLIPPER
tfile->expr->keyLen = tfile->header.keyLen ;
tfile->expr->keyDec = tfile->header.keyDec ;
#endif
if ( expr4context( tfile->expr, d4 ) < 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
len = expr4keyLen( tfile->expr ) ;
if ( len < 0 )
{
error4describe( c4, e4info, 84906, exprBuf, 0, 0 ) ;
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#ifdef S4NDX
tfile->header.type = (char) expr4type(tfile->expr) ;
if ( t4->header.keyLen != (short) len )
{
error4describe( c4, e4index, E84905, i4->file.name, 0 ) ;
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
#else
#ifdef S4CLIPPER
file4seqReadAll( &seqRead, &tfile->header.unique, sizeof( tfile->header.unique ) ) ;
file4seqReadAll( &seqRead, &garbage, sizeof( garbage ) ) ;
file4seqReadAll( &seqRead, &tfile->header.descending, sizeof( tfile->header.descending ) ) ;
#ifdef S4BYTE_SWAP
t4->header.unique = x4reverseShort( (void *)&tfile->header.unique ) ;
t4->header.descending = x4reverseShort( (void *)&tfile->header.descending ) ;
#endif
file4seqReadAll( &seqRead, exprBuf, sizeof( exprBuf ) - 1 ) ;
c4trimN( exprBuf, sizeof( exprBuf ) ) ;
if ( exprBuf[0] != 0 )
{
tfile->filter = expr4parseLow( d4, exprBuf, tfile ) ;
if ( tfile->filter != 0 )
{
if ( expr4context( tfile->filter, d4 ) < 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
len = expr4key( tfile->filter, &ptr ) ;
if ( len < 0 )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
if ( expr4type( tfile->filter ) != 'L' )
{
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
}
}
#endif
#endif
/* if( tfile->header.unique )
tfile->uniqueError = c4->errDefaultUnique ;
*/
l4add( &d4->dataFile->tagfiles, tfile ) ; /* add the tag to its index list */
#ifdef S4NDX
tfile4initSeekConv( tfile, tfile->header.type) ;
#else
#ifdef S4CLIPPER
tfile4initSeekConv( tfile, (char)expr4type( tfile->expr ) ) ;
#endif
#endif
if ( tfile->blockMemory == 0 )
tfile->blockMemory = mem4create( c4, c4->memStartBlock, (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
(sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])), c4->memExpandBlock, 0 ) ;
if ( tfile->blockMemory == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94906 ) ;
#endif
tfile4close( tfile, d4->dataFile ) ;
return 0 ;
}
if ( d4->dataFile->indexLocked == 1 ) /* index locked, so lock this tag as well */
tfile4lock( tfile, data4serverId( d4 ) ) ;
return tfile ;
}
#ifdef P4ARGS_USED
#pragma argsused
#endif
TAG4 *S4FUNCTION t4openLow( DATA4 *d4, INDEX4 *i4ndx, const char *fileName, const char *dummy )
{
CODE4 *c4 ;
INDEX4 *i4 ;
TAG4 *t4 ;
int oldTagErr ;
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E94903 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( d4 == 0 || fileName == 0 )
{
error4( 0, e4parm_null, E94903 ) ;
return 0 ; ;
}
#endif
c4 = d4->codeBase ;
if ( error4code( c4 ) < 0 )
return 0 ;
oldTagErr = c4->errTagName ;
c4->errTagName = 0 ;
if ( d4tag( d4, fileName ) )
{
error4describe( c4, e4instance, E85308, fileName, 0, 0 ) ;
c4->errTagName = oldTagErr ;
return 0 ;
}
c4->errTagName = oldTagErr ;
error4set( c4, 0 ) ;
if ( i4ndx == 0 ) /* must create an index for the tag */
{
if ( c4->indexMemory == 0 )
{
c4->indexMemory = mem4create( c4, c4->memStartIndex, sizeof( INDEX4 ), c4->memExpandIndex, 0 ) ;
if ( c4->indexMemory == 0 )
return 0 ;
}
i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
if ( i4 == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94903 ) ;
#endif
return 0 ;
}
i4->codeBase = c4 = d4->codeBase ;
/* 09/22/95 AS - changed last parm to 0 for t4group (c/s access name needs extension if provided) */
u4namePiece( i4->accessName, sizeof( i4->accessName ), fileName, 0, 1 ) ;
}
else
i4 = i4ndx ;
if ( c4->tagMemory == 0 )
{
c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
if ( c4->tagMemory == 0 )
{
if ( i4ndx == 0 )
mem4free( c4->indexMemory, i4 ) ;
return 0 ;
}
}
t4 = (TAG4 *)mem4alloc( c4->tagMemory ) ;
if ( t4 == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94903 ) ;
#endif
if ( i4ndx == 0 )
mem4free( c4->indexMemory, i4 ) ;
return 0 ;
}
t4->tagFile = tfile4open( d4, fileName ) ;
if ( t4->tagFile == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94903 ) ;
#endif
mem4free( c4->tagMemory, t4 ) ;
if ( i4ndx == 0 )
mem4free( c4->indexMemory, i4 ) ;
return 0 ;
}
if ( t4->tagFile->header.unique )
t4->errUnique = c4->errDefaultUnique ;
t4->index = i4 ;
if ( i4ndx == 0 )
{
i4->data = d4 ;
l4add( &d4->indexes, i4 ) ;
}
l4add( &t4->index->tags, t4 ) ;
#ifndef S4OFF_TRAN
t4->isValid = 1 ;
#endif
return t4 ;
}
#ifndef S4OFF_WRITE
#ifdef S4CLIPPER
#ifdef P4ARGS_USED
#pragma argsused
#endif
int tfile4shrink( TAG4FILE *t4, long blockNo )
{
#ifdef S4SINGLE
t4->header.eof = blockNo * 512 ;
#endif
return 0 ;
}
#endif /* S4CLIPPER */
int tfile4updateHeader( TAG4FILE *t4 )
{
T4HEADER *header ;
FILE4 *file ;
#ifdef S4BYTE_SWAP
I4IND_HEAD_WRITE swap ;
#endif
if ( error4code( t4->codeBase ) < 0 )
return e4codeBase ;
header = &t4->header ;
file = &t4->file ;
/* header->version = header->oldVersion + 2 ; */
if ( header->oldVersion != header->version )
{
#ifdef S4NDX
#ifdef S4BYTE_SWAP
swap.root = x4reverseLong( (void *)&header->root ) ;
swap.eof = x4reverseLong( (void *)&header->eof ) ;
swap.keyLen = x4reverseShort( (void *)&header->keyLen ) ;
swap.keysMax = x4reverseShort( (void *)&header->keysMax ) ;
swap.int_or_date = x4reverseShort( (void *)&header->int_or_date ) ;
swap.groupLen = x4reverseShort( (void *)&header->groupLen ) ;
swap.dummy = x4reverseShort( (void *)&header->dummy ) ;
swap.unique = x4reverseShort( (void *)&header->unique ) ;
if ( file4write( file, 0L, &swap, sizeof(I4IND_HEAD_WRITE)) < 0 )
return -1 ;
header->version = x4reverseLong( (void *)&header->version ) ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->version, sizeof(header->version)) < 0 )
return -1 ;
header->version = x4reverseLong( (void *)&header->version ) ;
#else
if ( file4write( file, 0L, &header->root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
return -1 ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->version, sizeof(header->version)) < 0 )
return -1 ;
#endif
#else
#ifdef S4CLIPPER
#ifdef S4BYTE_SWAP
swap.sign = x4reverseShort( (void *)&header->sign ) ;
swap.version = x4reverseShort( (void *)&header->version ) ;
swap.root = x4reverseLong( (void *)&header->root ) ;
swap.eof = x4reverseLong( (void *)&header->eof ) ;
swap.groupLen = x4reverseShort( (void *)&header->groupLen ) ;
swap.keyLen = x4reverseShort( (void *)&header->keyLen ) ;
swap.keyDec = x4reverseShort( (void *)&header->keyDec ) ;
swap.keysMax = x4reverseShort( (void *)&header->keysMax ) ;
swap.keysHalf = x4reverseShort( (void *)&header->keysHalf ) ;
if ( file4write( file, 0L, &swap, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0)
return -1 ;
header->unique = x4reverseShort( (void *)&header->unique ) ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->unique, sizeof(header->unique)) < 0 )
return -1 ;
header->unique = x4reverseShort( (void *)&header->unique ) ;
header->descending = x4reverseShort( (void *)&header->descending ) ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(header->unique) + 1, &header->descending, sizeof(header->descending)) < 0 )
return -1 ;
header->descending = x4reverseShort( (void *)&header->descending ) ;
#else
if ( file4write( file, 0L, &header->sign, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0 )
return -1 ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->unique, sizeof(header->unique)) < 0 )
return -1 ;
if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(header->unique) + 1, &header->descending, sizeof(header->descending)) < 0 )
return -1 ;
#endif
#endif
#endif
header->oldVersion = header->version ;
}
return 0;
}
#endif /* S4OFF_WRITE */
int tfile4goEof( TAG4FILE *t4 )
{
int rc ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91642 ) ;
#endif
rc = tfile4bottom( t4 ) ;
if ( rc != 0 )
return rc ;
#ifdef E4ANALYZE
if ( tfile4block( t4 ) == 0 )
return error4( 0, e4info, E91642 ) ;
#endif
tfile4block(t4)->keyOn++ ;
return 0 ;
}
int tfile4doVersionCheck( TAG4FILE *t4, int doSeek, int updateVersion )
{
#ifndef S4SINGLE
int rc, needSeek ;
B4BLOCK *b4 ;
CODE4 *c4 ;
#ifdef E4PARM_LOW
if ( t4 == 0 )
return error4( 0, e4parm_null, E91635 ) ;
#endif
c4 = t4->codeBase ;
if ( error4code( c4 ) < 0 )
return e4codeBase ;
if ( tfile4lockTest( t4 ) )
return 0 ;
#ifndef S4OPTIMIZE_OFF
/* make sure read from disk */
if ( t4->file.doBuffer )
c4->opt.forceCurrent = 1 ;
#endif
#ifdef S4NDX
rc = file4readAll( &t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE,
&t4->header.version, sizeof(t4->header.version ) ) ;
#ifndef S4OPTIMIZE_OFF
if ( t4->file.doBuffer )
c4->opt.forceCurrent = 0 ;
#endif
if ( rc < 0 )
return rc ;
#ifdef S4BYTE_SWAP
t4->header.version = x4reverseLong( (void *)&t4->header.version ) ;
#endif
#else
rc = file4readAll( &t4->file, 0L, &t4->header.sign , 2 * sizeof( short ) + 2 * sizeof( long ) ) ;
#ifndef S4OPTIMIZE_OFF
if ( t4->file.doBuffer )
c4->opt.forceCurrent = 0 ;
#endif
if ( rc < 0 )
return rc ;
#ifdef S4BYTE_SWAP
t4->header.sign = x4reverseShort( (void *)&t4->header.sign ) ;
t4->header.version = x4reverseShort( (void *)&t4->header.version ) ;
t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
t4->header.groupLen = x4reverseShort( (void *)&t4->header.groupLen ) ;
t4->header.keyLen = x4reverseShort( (void *)&t4->header.keyLen ) ;
t4->header.keyDec = x4reverseShort( (void *)&t4->header.keyDec ) ;
t4->header.keysMax = x4reverseShort( (void *)&t4->header.keysMax ) ;
t4->header.keysHalf = x4reverseShort( (void *)&t4->header.keysHalf ) ;
#endif
#endif
if ( t4->header.version == t4->header.oldVersion )
return 0 ;
if ( updateVersion == 1 )
t4->header.oldVersion = t4->header.version ;
else
t4->header.version = t4->header.oldVersion ;
/* remember the old position */
needSeek = 0 ;
if ( doSeek )
{
b4 = (B4BLOCK *)t4->blocks.lastNode ; /* can't use tfile4block( t4 ) since might be null */
if ( b4 != 0 )
{
if ( tfile4eof( t4 ) )
needSeek = 2 ;
else
/* if ( b4leaf( b4 ) && b4->nKeys != 0 )
changed line 04/09/96 AS --> if on a branch, and no seek is performed, a gpf or general
error can later occur (in d4seek) --> this should be ok for S4CLIPPER */
if ( b4->nKeys != 0 )
{
memcpy( c4->savedKey, b4key( b4, b4->keyOn ), t4->header.keyLen + 2 * sizeof( long ) ) ;
needSeek = 1 ;
}
}
}
if ( tfile4freeAll( t4 ) < 0 ) /* Should be a memory operation only */
#ifdef E4ANALYZE
return error4( c4, e4result, E91635 ) ;
#else
return e4result ;
#endif
switch( needSeek )
{
case 1:
#ifdef E4ANALYZE_ALL
if ( tfile4go( t4, ((B4KEY_DATA *)c4->savedKey)->value, ((B4KEY_DATA *)c4->savedKey)->num, 0 ) != 0 )
return error4( c4, e4index, E91635 ) ;
#else
tfile4go( t4, ((B4KEY_DATA *)c4->savedKey)->value, ((B4KEY_DATA *)c4->savedKey)->num, 0 ) ;
#endif
break ;
case 2:
tfile4goEof( t4 ) ;
break ;
}
#endif
return 0;
}
int tfile4versionCheck( TAG4FILE *t4, const int doSeek, const int updateVersion )
{
#ifndef S4OPTIMIZE_OFF
if ( t4->file.doBuffer == 0 )
#endif
#ifndef S4SINGLE
if ( tfile4lockTest( t4 ) == 0 )
#endif
return tfile4doVersionCheck( t4, doSeek, updateVersion ) ;
return 0 ;
}
#endif /* N4OTHER */
#endif /* S4INDEX_OFF */
#ifdef S4VB_DOS
#ifdef N4OTHER
TAG4 *S4FUNCTION tfile4open_v(DATA4 *d4, char *name)
{
return tfile4open( d4, 0, c4str(name) ) ;
}
#endif /* N4OTHER */
#endif /* S4VB_DOS */
#endif /* S4CLIENT */