campo-sirio/cb/source/i4index.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

2370 lines
65 KiB
C
Executable File

/* i4index.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
#ifndef S4INDEX_OFF
#ifdef S4CLIENT
/* if i4old is set to a value, then it is used instead of creating a new i4 */
/* if doFull is set to false and i4old is valid, a tag update between i4file
and i4 are done only */
static INDEX4 *i4setup2( CODE4 *c4, INDEX4FILE *i4file, DATA4 *d4, const char *name, INDEX4 *i4old, int doFull )
{
INDEX4 *i4 ;
TAG4FILE *tagOn ;
TAG4 *tag, *tag2 ;
int doUpdate ;
if ( i4old == 0 )
{
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 ) ;
i4->codeBase = c4 ;
i4->data = d4 ;
i4->indexFile = i4file ;
l4add( &d4->indexes, i4 ) ;
u4ncpy( i4->alias, name, sizeof( i4->alias ) - 1 ) ;
}
else
i4 = i4old ;
for ( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4file->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
if ( doFull == 0 ) /* check that tag doesn't already exit */
{
doUpdate = 1 ;
for ( tag2 = 0 ;; )
{
tag2 = (TAG4 *)l4next( &i4->tags, tag2 ) ;
if ( tag2 == 0 )
break ;
if ( tag2->tagFile == tagOn )
{
doUpdate = 0 ;
break ;
}
}
if ( doUpdate == 0 )
continue ;
}
tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
if ( tag == 0 )
return 0 ;
tag->tagFile = tagOn ;
tag->index = i4 ;
tag->errUnique = tagOn->errUniqueHold ;
l4add( &i4->tags, tag ) ;
}
return i4 ;
}
/* if i4old is set to a value, then it is used instead of creating a new i4 */
int i4setup( CODE4 *c4, DATA4 *d4, const char *name, int autoOpened, INDEX4 *i4old )
{
INDEX4FILE *i4file ;
INDEX4 *i4 ;
int addIndex, addTags ;
/* now set up the tags */
if ( c4->tagMemory == 0 )
{
c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
if ( c4->tagMemory == 0 )
{
d4close( d4 ) ;
return 0 ;
}
}
for ( i4file = 0 ;; )
{
i4file = (INDEX4FILE *)l4next( &d4->dataFile->indexes, i4file ) ;
if ( i4file == 0 )
break ;
addIndex = 1 ;
addTags = 0 ;
for ( i4 = 0 ;; ) /* only set up for i4file's not in i4's of d4 */
{
i4 = (INDEX4 *)l4next( &d4->indexes, i4 ) ;
if ( i4 == 0 )
break ;
if ( i4->indexFile == i4file )
{
if ( l4numNodes( &i4->tags ) < l4numNodes( &i4file->tags ) )
addTags = 1 ;
addIndex = 0 ;
break ;
}
}
if ( addIndex == 0 )
{
if ( addTags == 0 )
continue ;
}
else
i4file->userCount++ ;
i4 = i4setup2( c4, i4file, d4, name, i4old, addIndex ) ;
if ( i4 == 0 )
{
d4close( d4 ) ;
return 0 ;
}
i4file->autoOpened = autoOpened ; /* if in i4open, must be a manual open */
}
return 0 ;
}
#else
#ifdef S4CLIPPER
#ifdef P4ARGS_USED
#pragma argsused
#endif
int i4setup( CODE4 *c4, DATA4 *d4, const char *name, int autoOpened )
{
TAG4FILE *tagFile ;
TAG4 *tag ;
DATA4FILE *dfile ;
INDEX4 *i4 = 0 ;
dfile = d4->dataFile ;
for ( tagFile = 0 ;; )
{
tagFile = (TAG4FILE *)l4next( &dfile->tagfiles, tagFile ) ;
if ( tagFile == 0 )
break ;
if ( i4 == 0 )
{
i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
i4->codeBase = c4 ;
i4->data = d4 ;
l4add( &d4->indexes, i4 ) ;
u4ncpy( i4->accessName, name, sizeof( i4->accessName ) - 1 ) ;
}
tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
if ( tag == 0 )
return 0 ;
tag->tagFile = tagFile ;
tag->tagFile->userCount++ ;
tag->index = i4 ;
#ifdef S4SERVER
tag->errUnique = tfile4unique( tag->tagFile, (short int)d4->codeBase->errDefaultUnique ) ;
#endif
l4add( &i4->tags, tag ) ;
}
return 0 ;
}
#endif
#endif /* S4CLIENT */
#ifdef S4CLIENT
int index4close( INDEX4FILE *i4 )
{
CONNECTION4 *connection ;
CODE4 *c4 ;
TAG4FILE *tagOn ;
int finalRc, rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91702 ) ;
#endif
#ifdef E4ANALYZE
if ( i4->userCount <= 0 )
return error4( i4->codeBase, e4struct, E81702 ) ;
if ( i4->codeBase == 0 )
return error4( i4->codeBase, e4struct, E91702 ) ;
#endif
i4->userCount-- ;
finalRc = 0 ;
if ( i4->userCount == 0 )
{
c4 = i4->codeBase ;
if ( i4->autoOpened == 0 ) /* must manually close ... */
{
#ifndef S4OFF_TRAN
if ( code4transEnabled( c4 ) )
if ( code4trans( c4 )->currentTranStatus == r4active ) /* disallow on current active only */
return error4( c4, e4transViolation, E81522 ) ;
#endif
connection = i4->dataFile->connection ;
#ifdef E4ANALYZE
if ( connection == 0 )
finalRc = error4( c4, e4struct, E91702 ) ;
else
{
#endif
connection4assign( connection, CON4INDEX_CLOSE, i4->clientId, i4->serverId ) ;
connection4addData( connection, i4->accessName, strlen( i4->accessName ) + 1, 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc != 0 )
finalRc = error4( c4, rc, E81701 ) ;
else
{
rc = connection4status( connection ) ;
if ( rc != 0 )
finalRc = connection4error( connection, c4, rc, E91702 ) ;
}
#ifdef E4ANALYZE
}
#endif
}
for( ;; )
{
tagOn = (TAG4FILE *)l4pop( &i4->tags ) ;
if ( tagOn == 0 )
break ;
if ( tagOn->exprPtr != 0 )
{
u4free( tagOn->exprPtr ) ;
tagOn->exprPtr = 0 ;
}
if ( tagOn->filterPtr != 0 )
{
u4free( tagOn->filterPtr ) ;
tagOn->filterPtr = 0 ;
}
mem4free( c4->tagFileMemory, tagOn ) ;
tagOn = 0 ;
}
l4remove( &i4->dataFile->indexes, i4 ) ;
mem4free( c4->index4fileMemory, i4 ) ;
i4 = 0 ;
return finalRc ;
}
return 0 ;
}
int S4FUNCTION i4close( INDEX4 *i4 )
{
int rc, finalRc ;
TAG4 *tagOn ;
CODE4 *c4 ;
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E91701 ) )
return -1 ;
#endif
#ifdef E4PARM_HIGH
if ( i4 == 0 )
return error4( 0, e4parm_null, E91701 ) ;
if ( i4->codeBase == 0 )
return error4( 0, e4parm, E91701 ) ;
#endif
c4 = i4->codeBase ;
finalRc = 0 ;
#ifndef S4OFF_WRITE
if ( i4->data )
if ( d4update( i4->data ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
#ifdef E4ANALYZE
if ( i4->data == 0 )
return error4( 0, e4struct, E91701 ) ;
if ( i4->data->dataFile == 0 )
return error4( 0, e4struct, E91701 ) ;
#endif
if ( i4->data->tagSelected != 0 )
if ( i4->data->tagSelected->index == i4 )
i4->data->tagSelected = 0 ;
for( ;; )
{
tagOn = (TAG4 *)l4pop( &i4->tags ) ;
if ( tagOn == 0 )
break ;
mem4free( c4->tagMemory, tagOn ) ;
tagOn = 0 ;
}
l4remove( &i4->data->indexes, i4 ) ;
rc = index4close( i4->indexFile ) ;
mem4free( c4->indexMemory, i4 ) ;
i4 = 0 ;
if ( rc < 0 )
return rc ;
return finalRc ;
}
#endif /* S4CLIENT */
const char *S4FUNCTION i4fileName( INDEX4 *i4 )
{
#ifdef S4CLIENT
CONNECTION4 *connection ;
int rc ;
#else
#ifdef S4CLIPPER
TAG4FILE *tag ;
#endif
#endif
#ifdef E4PARM_HIGH
if ( i4 == 0 )
{
error4( 0, e4parm_null, E91720 ) ;
return 0 ;
}
#endif
#ifdef S4CLIENT
if ( error4code( i4->codeBase ) < 0 )
return 0 ;
connection = i4->data->dataFile->connection ;
connection4assign( connection, CON4INDEX_FNAME, data4clientId( i4->data ), data4serverId( i4->data ) ) ;
connection4addData( connection, i4->indexFile->accessName, strlen( i4->indexFile->accessName ) + 1, 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
{
#ifdef E4STACK
error4stack( i4->codeBase, rc, E95501 ) ;
#endif
return 0 ;
}
rc = connection4status( connection ) ;
if ( rc < 0 )
{
connection4error( connection, i4->codeBase, rc, E95501 ) ;
return 0 ;
}
return connection4data( connection ) ;
#else
#ifdef S4CLIPPER
if ( i4->path != 0 )
return i4->path ;
if ( l4numNodes( &i4->tags ) == 1 )
{
tag = (TAG4FILE *)(((TAG4 *)(i4->tags.lastNode))->tagFile) ;
return tag->alias ;
}
else
return d4fileName( i4->data ) ;
#else
return i4->indexFile->file.name ;
#endif /* S4CLIPPER */
#endif /* S4CLIENT */
}
#ifndef S4CLIPPER
#ifndef S4CLIENT
int S4FUNCTION i4close( INDEX4 *i4 )
{
int rc, finalRc ;
TAG4 *tagOn ;
CODE4 *c4 ;
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E91701 ) )
return -1 ;
#endif
#ifdef E4PARM_HIGH
if ( i4 == 0 )
return error4( 0, e4parm_null, E91701 ) ;
if ( i4->codeBase == 0 )
return error4( 0, e4parm, E91701 ) ;
#endif
c4 = i4->codeBase ;
#ifndef S4OFF_TRAN
if ( i4->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 = 0 ;
#ifndef S4OFF_WRITE
#ifndef S4OFF_TRAN
if ( i4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
#endif
if ( i4->data )
if ( d4update( i4->data ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
for( ;; )
{
tagOn = (TAG4 *)l4pop( &i4->tags ) ;
if ( tagOn == 0 )
break ;
#ifndef S4OFF_TRAN
#ifdef E4ANALYZE
if ( tagOn->removedKeys.nLink != 0 )
return error4( c4, e4info, E91701 ) ;
#endif
#endif
if ( i4->data->tagSelected == tagOn ) /* can't have a tag selected from a closed index */
i4->data->tagSelected = 0 ;
mem4free( c4->tagMemory, tagOn ) ;
tagOn = 0 ;
}
if ( i4->indexFile != 0 )
{
rc = index4close( i4->indexFile ) ;
if ( rc != 0 )
finalRc = rc ;
}
if ( i4->link.n != 0 )
l4remove( &i4->data->indexes, i4 ) ;
mem4free( c4->indexMemory, i4 ) ;
i4 = 0 ;
if ( finalRc != 0 )
{
error4set( c4, finalRc ) ;
return finalRc ;
}
return 0 ;
}
int index4close( INDEX4FILE *i4 )
{
int finalRc, isProduction ;
CODE4 *c4 ;
TAG4FILE *tagOn ;
#ifndef S4SINGLE
int saveAttempts ;
#endif
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91702 ) ;
#endif
#ifdef E4ANALYZE
if ( i4->userCount < 0 )
return error4( i4->codeBase, e4struct, E81702 ) ;
#endif
isProduction = index4isProduction( i4 ) ;
if ( ( i4->userCount <= 1 && isProduction == 0 ) || ( i4->userCount == 0 && i4->dataFile->userCount == 0 ) )
{
c4 = i4->codeBase ;
finalRc = error4code( c4 ) ;
#ifndef S4SINGLE
saveAttempts = c4->lockAttempts ;
c4->lockAttempts = WAIT4EVER ;
#endif
#ifndef S4OFF_WRITE
if ( index4update( i4 ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
#ifndef S4SINGLE
if ( index4unlock( i4, 0UL ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
#ifdef S4FOX
if ( i4->tagIndex )
if ( i4->tagIndex->header.typeCode >= 64 ) /* compound index */
#endif
for( ;; )
{
tagOn = (TAG4FILE *)l4pop( &i4->tags ) ;
if ( tagOn == 0 )
break ;
if ( tfile4freeAll( tagOn ) < 0 )
{
finalRc = error4set( c4, 0 ) ;
break ;
}
expr4free( tagOn->expr ) ;
expr4free( tagOn->filter ) ;
#ifdef S4FOX
mem4release( tagOn->builtKeyMemory ) ;
#endif
mem4free( c4->tagFileMemory, tagOn ) ;
tagOn = 0 ;
}
#ifdef S4FOX
if ( i4->tagIndex != 0 )
{
if ( tfile4freeAll( i4->tagIndex ) < 0 )
finalRc = error4set( c4, 0 ) ;
else
{
expr4free( i4->tagIndex->expr ) ;
expr4free( i4->tagIndex->filter ) ;
#ifdef S4FOX
mem4release( i4->tagIndex->builtKeyMemory ) ;
#endif
mem4free( c4->tagFileMemory, i4->tagIndex ) ;
i4->tagIndex = 0 ;
}
}
#endif
mem4release( i4->blockMemory ) ;
if ( file4openTest( &i4->file ) )
{
if ( i4->dataFile )
l4remove( &i4->dataFile->indexes, i4 ) ;
#ifndef S4CLIPPER
#ifndef S4SERVER
if ( c4->doRemove == 1 )
i4->file.isTemp = 1 ;
#endif
#endif
if ( file4close( &i4->file ) < 0 )
finalRc = error4set( c4, 0 ) ;
}
mem4free( c4->index4fileMemory, i4 ) ;
i4 = 0 ;
#ifndef S4SINGLE
c4->lockAttempts = saveAttempts ;
#endif
error4set( c4, (short)finalRc ) ;
return finalRc ;
}
else
{
i4->userCount-- ;
return 0 ;
}
}
#ifndef S4OFF_WRITE
long index4extend( INDEX4FILE *i4 )
{
long oldEof ;
unsigned len ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91703 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
#ifndef S4FOX
oldEof = i4->header.freeList ;
if( i4->header.freeList == 0L ) /* case where no free list */
{
oldEof = i4->header.eof ;
i4->header.eof = i4->header.eof + i4->header.blockRw/I4MULTIPLY ;
}
else
{
len = file4read( &i4->file, i4->header.freeList*I4MULTIPLY + sizeof(S4LONG),
(char *)&i4->header.freeList, sizeof(i4->header.freeList)) ;
#ifdef S4BYTE_SWAP
i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
#endif
if ( error4code( i4->codeBase ) < 0 ) return -1 ;
switch( len )
{
case 0:
#ifdef E4ANALYZE
return error4( i4->codeBase, e4index, E91703 ) ;
#else /* try to fix up */
i4->header.freeList = 0L ;
oldEof = i4->header.eof ;
i4->header.eof = i4->header.eof + i4->header.blockRw/I4MULTIPLY ;
break ;
#endif
case sizeof(i4->header.freeList):
break ;
default:
return file4readError( &i4->file, i4->header.freeList*I4MULTIPLY + sizeof(S4LONG), sizeof(i4->header.freeList), "index4extend" ) ;
}
}
#endif
#ifdef S4FOX
#ifdef E4ANALYZE
if ( i4->tagIndex->header.version == i4->versionOld )
return error4( i4->codeBase, e4index, E91703 ) ;
#endif
oldEof = i4->tagIndex->header.freeList ;
if( oldEof == 0L ) /* case where no free list */
{
oldEof = i4->eof ;
i4->eof += B4BLOCK_SIZE ;
}
else
{
len = file4read( &i4->file, i4->tagIndex->header.freeList*I4MULTIPLY,
(char *)&i4->tagIndex->header.freeList, sizeof(i4->tagIndex->header.freeList)) ;
#ifdef S4BYTE_SWAP
i4->tagIndex->header.freeList = x4reverseLong( &i4->tagIndex->header.freeList ) ;
#endif
if ( error4code( i4->codeBase ) < 0 ) return -1 ;
switch( len )
{
case 0:
#ifdef E4ANALYZE
return error4( i4->codeBase, e4index, E91703 ) ;
#else /* else fix up */
i4->tagIndex->header.freeList = 0L ;
oldEof = i4->eof ;
i4->eof += B4BLOCK_SIZE ;
break ;
#endif
case sizeof(i4->tagIndex->header.freeList):
break ;
default:
return file4readError( &i4->file, i4->tagIndex->header.freeList*I4MULTIPLY, sizeof(i4->tagIndex->header.freeList), "index4extend" ) ;
}
}
#endif
return oldEof ;
}
int index4flush( INDEX4FILE *i4 )
{
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91704 ) ;
#endif
rc = index4update( i4 ) ;
if ( file4flush( &i4->file ) < 0 )
rc = -1 ;
return rc ;
}
int index4update( INDEX4FILE *i4 )
{
TAG4FILE *tagOn ;
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91705 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
#ifndef S4SINGLE
if ( i4->fileLocked != 0 )
{
#endif
rc = index4updateHeader( i4 ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, (short)rc, E91705 ) ;
#ifdef S4FOX
rc = tfile4update(i4->tagIndex) ;
if ( rc < 0 )
return error4stack( i4->codeBase, (short)rc, E91705 ) ;
if ( i4->tagIndex->header.typeCode >= 64 ) /* compound index */
#endif
for ( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
rc = tfile4update( tagOn ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, (short)rc, E91705 ) ;
tagOn->header.root = -1L ;
}
#ifndef S4SINGLE
}
#endif
return 0 ;
}
#endif /* S4OFF_WRITE */
#endif /* S4CLIENT */
INDEX4 *S4FUNCTION i4open( DATA4 *d4, const char *fileName )
{
CODE4 *c4 ;
INDEX4 *i4 ;
#ifdef S4CLIENT
INDEX4FILE *i4file ;
unsigned char buf[258] ;
#else
TAG4 *tag ;
TAG4FILE *tagFile ;
#endif
#ifdef E4PARM_HIGH
if ( d4 == 0 )
{
error4( 0, e4parm_null, E91706 ) ;
return 0 ;
}
#endif
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E91706 ) )
return 0 ;
#endif
c4 = d4->codeBase ;
if ( error4code( c4 ) < 0 )
return 0 ;
#ifdef S4CLIENT
if ( fileName == 0 )
u4ncpy( (char *)buf, d4->dataFile->accessName, sizeof( buf ) - 1 ) ;
else
{
if ( strlen( fileName ) > sizeof( buf ) - 1 )
{
error4( c4, e4name, E91706 ) ;
return 0 ;
}
strcpy( (char*)buf, fileName ) ;
}
c4upper( (char*)buf ) ;
i4 = d4index( d4, (char S4PTR*)buf ) ;
if ( i4 != 0 ) /* duplicates not allowed */
error4( c4, e4instance, E91706 ) ;
i4file = index4open( d4, (char S4PTR*)buf, 0 ) ;
if ( error4code( c4 ) < 0 )
return 0 ;
i4 = d4index( d4, (char S4PTR*)buf ) ;
if ( i4file == 0 )
{
if ( i4 == 0 )
return 0 ;
#ifdef E4ANALZE
if ( i4->indexFile == 0 )
{
error4( c4, e4info, E91706 ) ;
return 0 ;
}
#endif
i4file = i4->indexFile ;
i4file->clientId = data4clientId( d4 ) ;
i4file->serverId = data4serverId( d4 ) ;
}
else /* indexfile already exists so set up another index4 structure */
{
i4 = i4setup2( c4, i4file, d4, (char S4PTR*)buf, 0, 1 ) ;
if ( i4 == 0 )
{
index4close( i4file ) ;
return 0 ;
}
}
#ifdef E4ANALZE
else
{
if ( i4->indexFile != i4file )
{
error4( c4, e4info, E91706 ) ;
return 0 ;
}
}
#endif
i4->codeBase = c4 ;
#ifndef S4OFF_TRAN
i4->isValid = 1 ;
#endif
return i4 ;
#else
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 ERROR4STACK
error4stack( c4, e4memory, E91706 ) ;
#endif
return 0 ;
}
i4->data = d4 ;
i4->codeBase = c4 ;
if ( fileName != 0 )
{
#ifdef E4MISC
if ( strlen( fileName ) > sizeof( i4->accessName ) )
{
error4describe( c4, e4name, E91706, fileName, 0, 0 ) ;
i4close( i4 ) ;
return 0 ;
}
#endif
u4ncpy( i4->accessName, fileName, sizeof( i4->accessName ) - 1 ) ;
}
#ifdef S4STAND_ALONE
else
{
u4namePiece( i4->accessName, sizeof( i4->accessName ), d4->alias, 0, 0 ) ;
}
#ifndef S4CASE_SEN
c4upper( i4->accessName ) ;
#endif
#endif
i4->indexFile = index4open( d4, fileName, i4 ) ;
if ( i4->indexFile == 0 )
{
i4close( i4 ) ;
return 0 ;
}
l4add( &d4->indexes, i4 ) ;
for ( tagFile = 0 ;; )
{
tagFile = (TAG4FILE *)l4next( &i4->indexFile->tags, tagFile ) ;
if ( tagFile == 0 )
break ;
tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
if ( tag == 0 )
{
i4close( i4 ) ;
error4( c4, e4memory, E91706 ) ;
return 0 ;
}
tag->index = i4 ;
tag->tagFile = tagFile ;
#ifdef S4FOX
if ( tag->tagFile->header.typeCode & 0x04 ) /* r4/e4 candidate */
{
if ( c4->errDefaultUnique == e4unique )
tag->errUnique = e4candidate ;
else
tag->errUnique = r4candidate ;
}
else
if ( tag->tagFile->header.typeCode & 0x01 )
#else
if ( tag->tagFile->header.unique )
#endif
tag->errUnique = c4->errDefaultUnique ;
l4add( &i4->tags, tag ) ;
}
#ifndef S4OFF_TRAN
i4->isValid = 1 ;
#endif
return i4 ;
#endif
}
/* for the client, if index is not null, then the function only verifies the
existance of the index file and does not actually open it */
INDEX4FILE *index4open( DATA4 *d4, const char *fileName, INDEX4 *index )
{
CODE4 *c4 ;
int rc ;
INDEX4FILE *i4 ;
#ifdef S4CLIENT
CONNECTION4OPEN_INDEX_INFO_OUT *info ;
CONNECTION4OPEN_INDEX_INFO_IN dataIn ;
CONNECTION4 *connection ;
#else
char buf[258] ;
TAG4FILE *tagFile ;
DATA4FILE *dfile ;
#ifdef E4MISC
INDEX4FILE *i4ptr ;
#endif
#ifdef S4FOX
B4BLOCK *b4 ;
#ifndef S4SINGLE
long oldFileLock ;
#endif
#else
T4DESC tagInfo[47] ;
int iTag ;
#endif
#endif
#ifndef S4SERVER
INDEX4 *indexLoop ;
#endif
#ifdef E4PARM_LOW
if ( d4 == 0 )
{
error4( 0, e4parm_null, E91707 ) ;
return 0 ;
}
#ifndef S4CLIENT
if ( index == 0 )
{
error4( 0, e4parm_null, E91707 ) ;
return 0 ;
}
#endif
#endif
c4 = d4->codeBase ;
#ifdef S4CLIENT
i4 = dfile4index( d4->dataFile, fileName ) ;
#else
dfile = d4->dataFile ;
#ifdef E4ANALYZE
if ( code4indexExtension( c4 ) == 0 )
{
error4( c4, e4struct, E91707 ) ;
return 0 ;
}
#endif
if ( fileName == 0 )
u4ncpy( (char *)buf, dfile->file.name, sizeof( buf ) - 1 ) ;
else
{
rc = u4nameCurrent( (char *)buf, sizeof( buf ), fileName ) ;
if ( rc < 0 )
{
error4( c4, rc, E94509 ) ; /* from u4nameCurrent */
return 0 ;
}
}
u4nameExt( (char *)buf, sizeof( buf ), code4indexExtension( c4 ), ( fileName == 0 ? 1 : 0 ) ) ;
#ifndef S4CASE_SEN
c4upper( (char *)buf ) ;
#endif
i4 = dfile4index( dfile, (char *)buf ) ;
#endif
if ( i4 != 0 )
{
#ifndef S4SERVER
/* allowed if current data4 does not have a pointer to index */
for ( indexLoop = 0 ;; )
{
indexLoop = (INDEX4 *)l4next( &d4->indexes, indexLoop ) ;
if ( indexLoop == 0 )
break ;
if ( indexLoop->indexFile == i4 )
{
error4( c4, e4instance, E91707 ) ;
return 0 ;
}
}
#ifdef S4OFF_FOR_NOW
if ( i4->userCount > 0 && c4->singleOpen != OPEN4SPECIAL ) /* only one instance allowed unless performing additional d4open */
{
#ifdef S4STAND_ALONE
#ifndef S4OFF_TRAN
/* verify that index4 not on the closed data list if within a
transaction (which is allowed) */
if ( code4tranStatus( c4 ) == r4active )
{
list = tran4dataList( (&(c4->c4trans.trans)) ) ;
for ( data4 = 0 ;; )
{
data4 = (DATA4 *)l4next( list, data4 ) ;
if ( data4 == 0 )
break ;
for ( indexLoop = 0 ;; )
{
indexLoop = (INDEX4 *)l4next( &data4->indexes, indexLoop ) ;
if ( indexLoop == 0 )
break ;
if ( indexLoop->indexFile == i4 )
{
error4( c4, e4instance, E91707 ) ;
return 0 ;
}
}
}
}
else
#endif /* S4OFF_TRAN */
#endif /* S4STAND_ALONE */
{
error4( c4, e4instance, E91707 ) ;
return 0 ;
}
}
#endif /* OFF_FOR_NOW */
#endif
i4->userCount++ ;
return i4 ;
}
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E91707 ) )
return 0 ;
#endif
#ifdef S4CLIENT
if ( index != 0 ) /* just wanted to verify existance of... */
return 0 ;
c4 = d4->dataFile->c4 ;
#else
c4 = dfile->c4 ;
#endif
if ( error4code( c4 ) < 0 )
return 0 ;
if ( c4->index4fileMemory == 0 )
c4->index4fileMemory = mem4create( c4, c4->memStartIndexFile, sizeof(INDEX4FILE), c4->memExpandIndexFile, 0 ) ;
if ( c4->index4fileMemory == 0 )
return 0 ;
if ( c4->tagMemory == 0 )
{
c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
if ( c4->tagMemory == 0 )
return 0 ;
}
if ( c4->tagFileMemory == 0 )
{
c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof(TAG4FILE), c4->memExpandTagFile, 0 ) ;
if ( c4->tagFileMemory == 0 )
return 0 ;
}
#ifdef S4CLIENT
memset( &dataIn, 0, sizeof( CONNECTION4OPEN_INDEX_INFO_IN ) ) ;
connection = d4->dataFile->connection ;
if ( connection == 0 )
{
error4( c4, e4connection, E81704 ) ;
return 0 ;
}
connection4assign( connection, CON4INDEX_OPEN, data4clientId( d4 ), data4serverId( d4 ) ) ;
dataIn.nameLen = strlen( (char*)fileName ) + 1 ;
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 ;
connection4addData( connection, &dataIn, sizeof( CONNECTION4OPEN_INDEX_INFO_IN ), 0 ) ;
connection4addData( connection, fileName, 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, E91707 ) ;
}
return 0 ;
}
#ifdef E4MISC
if ( connection4len( connection ) < sizeof( info ) )
{
error4( c4, e4packetLen, E91707 ) ;
return 0 ;
}
#endif
info = (CONNECTION4OPEN_INDEX_INFO_OUT *)connection4data( connection ) ;
if ( client4indexSetup( c4, d4, d4->dataFile, info->numTags, connection4data( connection ) + sizeof(CONNECTION4OPEN_INDEX_INFO_OUT),
(unsigned int)connection4len( connection ) - sizeof(CONNECTION4OPEN_INDEX_INFO_OUT), (char*)fileName, 0 ) < 0 )
{
error4( c4, e4connection, E91707 ) ;
return 0 ;
}
/* in the client case, a null is a valid return code as the index is
later extracted */
i4setup( c4, d4, (char*)fileName, 0, 0 ) ;
return 0 ;
#else
i4 = (INDEX4FILE *)mem4alloc( c4->index4fileMemory ) ;
if ( i4 == 0 )
{
#ifdef ERROR4STACK
error4stack( c4, e4memory, E91707 ) ;
#endif
return 0 ;
}
/* next line for this function duration only since the return of this
function is assigned into index->indexFile but upper level.
Therefore, we still must clean up ourselves if failure */
index->indexFile = i4 ;
i4->dataFile = dfile ;
i4->codeBase = c4 ;
#ifdef S4FOX
#ifdef E4MISC
for ( i4ptr = 0 ;; )
{
i4ptr = (INDEX4FILE *)l4next( &dfile->indexes, i4ptr ) ;
if ( i4ptr == 0 )
break ;
if ( !c4memcmp( i4ptr->file.name, buf, (size_t)strlen( (char *)buf ) ) )
{
mem4free( c4->index4fileMemory, i4 ) ;
index->indexFile = 0 ;
error4( c4, e4parm, E81703 ) ;
return 0 ;
}
}
#endif
rc = file4open( &i4->file, c4, (char *)buf, 1 ) ;
if ( rc )
{
index->indexFile = 0 ;
mem4free( c4->index4fileMemory, i4 ) ;
return 0 ;
}
i4->eof = file4len( &i4->file ) ;
i4->tagIndex = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
if ( i4->tagIndex == 0 )
{
file4close( &i4->file ) ;
index->indexFile = 0 ;
mem4free( c4->index4fileMemory, i4 ) ;
error4( c4, e4memory, E91707 ) ;
return 0 ;
}
l4add( &dfile->indexes, i4 ) ;
if ( fileName == 0 )
{
if ( tfile4init( i4->tagIndex, index, 0L, (unsigned char *)"" ) < 0 )
{
index4close( i4 ) ;
return 0 ;
}
}
else
{
u4namePiece( (char *)buf, 258, fileName, 0, 0 ) ; /* get the tagName based on the fileName */
if ( tfile4init( i4->tagIndex, index, 0L, (unsigned char *)buf) < 0 )
{
index4close( i4 ) ;
return 0 ;
}
}
if ( tfile4setCodePage( i4->tagIndex, d4->codePage ) < 0 )
{
error4( c4, e4index, E91642 ) ;
index4close( i4 ) ;
return 0 ;
}
/* Perform some checks */
if ( i4->tagIndex->header.root <= 0L || i4->tagIndex->header.typeCode < 32 )
{
#ifdef E4ANALYZE_ALL
error4describe( c4, e4index, E81714, buf, 0, 0 ) ;
#endif
index4close( i4 ) ;
#ifndef E4ANALYZE_ALL
error4describe( c4, e4index, E81714, (char *)buf, 0, 0 ) ;
#endif
return 0 ;
}
i4->versionOld = i4->tagIndex->header.version ;
i4->blockMemory = mem4create( c4, c4->memStartBlock, sizeof(B4BLOCK) + B4BLOCK_SIZE
- sizeof(B4STD_HEADER) - sizeof(B4NODE_HEADER), c4->memExpandBlock, 0 ) ;
if ( i4->blockMemory == 0 )
{
index4close( i4 ) ;
return 0 ;
}
/* do an initial block allocation to make sure minimal is allocated while optimization is suspended */
b4 = (B4BLOCK *)mem4alloc2( i4->blockMemory, c4 ) ;
if ( b4 == 0 )
{
index4close( i4 ) ;
error4( c4, e4memory, E91707 ) ;
return 0 ;
}
else
{
mem4free( i4->blockMemory, b4 ) ;
b4 = 0 ;
}
#ifndef S4SINGLE
/* disable locking */
oldFileLock = i4->fileLocked ;
i4->fileLocked = data4serverId( d4 ) ;
#endif
rc = tfile4top( i4->tagIndex ) ;
if ( rc < 0 )
{
#ifndef S4SINGLE
i4->fileLocked = oldFileLock ;
#endif
index4close( i4 ) ;
return 0 ;
}
/* if we have a compound index, then load the tags, otherwise this is the only tag */
if ( i4->tagIndex->header.typeCode >= 64 )
{
if ( b4numKeys( tfile4block( i4->tagIndex ) ) )
do
{
tagFile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
if ( tagFile == 0 )
{
index4close( i4 ) ;
error4( c4, e4memory, E91707 ) ;
#ifndef S4SINGLE
i4->fileLocked = oldFileLock ;
#endif
return 0 ;
}
if ( tfile4init( tagFile, index, b4recNo( tfile4block(i4->tagIndex), tfile4block(i4->tagIndex)->keyOn ), tfile4keyData( i4->tagIndex )->value ) < 0 )
{
#ifndef S4SINGLE
i4->fileLocked = oldFileLock ;
#endif
index4close( i4 ) ;
return 0 ;
}
if ( tfile4setCodePage( tagFile, d4->codePage ) < 0 )
{
error4( c4, e4index, E91642 ) ;
index4close( i4 ) ;
return 0 ;
}
l4add( &i4->tags, tagFile ) ;
} while ( tfile4skip( i4->tagIndex, 1L ) == 1L ) ;
}
else
{
#ifdef E4MISC
if ( fileName == 0 )
{
index4close( i4 ) ;
error4( c4, e4index, E81715 ) ;
}
#endif
tagFile = i4->tagIndex ;
l4add( &i4->tags, i4->tagIndex ) ; /* if an .idx, add single tag */
}
#ifndef S4SINGLE
i4->fileLocked = oldFileLock ;
#endif
#endif
#ifndef S4FOX
#ifdef E4MISC
for ( i4ptr = 0 ;; )
{
i4ptr = (INDEX4FILE *)l4next(&dfile->indexes, i4ptr) ;
if ( i4ptr == 0 )
break ;
if ( !c4memcmp( i4ptr->file.name, buf, (size_t) strlen(buf) ) )
{
error4( c4, e4parm, E81703 ) ;
return 0 ;
}
}
#endif
rc = file4open( &i4->file, c4, buf, 1 ) ;
if ( rc )
{
index->indexFile = 0 ;
mem4free( c4->index4fileMemory, i4 ) ;
return 0 ;
}
if ( file4readAll( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) < 0 )
{
file4close( &i4->file ) ;
index->indexFile = 0 ;
mem4free( c4->index4fileMemory, i4 ) ;
return 0 ;
}
#ifdef S4BYTE_SWAP
i4->header.blockChunks = x4reverseShort( (void *)&i4->header.blockChunks ) ;
i4->header.blockRw = x4reverseShort( (void *)&i4->header.blockRw ) ;
i4->header.slotSize = x4reverseShort( (void *)&i4->header.slotSize ) ;
i4->header.numTags = x4reverseShort( (void *)&i4->header.numTags ) ;
i4->header.eof = x4reverseLong( (void *)&i4->header.eof ) ;
i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
#endif
l4add( &dfile->indexes, i4 ) ;
/* Perform some checks */
if ( i4->header.blockRw != i4->header.blockChunks*512 ||
i4->header.blockChunks <= 0 ||
i4->header.blockChunks > 63 ||
i4->header.numTags < 0 || i4->header.numTags > 47 ||
i4->header.eof <= 0L )
{
index4close( i4 ) ;
error4describe( c4, e4index, E81716, buf, 0, 0 ) ;
return 0 ;
}
if ( file4readAll( &i4->file, 544L, tagInfo, sizeof(tagInfo)) < 0 )
{
index4close( i4 ) ;
return 0 ;
}
for ( iTag = 0; iTag < (int) i4->header.numTags; iTag++ )
{
tagFile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
if ( tagFile == 0 )
{
index4close( i4 ) ;
#ifdef E4STACK
error4stack( c4, e4memory, E91707 ) ;
#endif
return 0 ;
}
#ifdef S4BYTE_SWAP
tagInfo[iTag].headerPos = x4reverseLong( (void *)&tagInfo[iTag].headerPos ) ;
tagInfo[iTag].x1000 = 0x1000 ;
#endif
if ( tfile4init( tagFile, index, tagInfo + iTag ) < 0 )
{
index4close( i4 ) ;
return 0 ;
}
l4add( &i4->tags, tagFile ) ;
}
i4->blockMemory = mem4create( c4, c4->memStartBlock, sizeof(B4BLOCK) + i4->header.blockRw -
sizeof(B4KEY_DATA) - sizeof(short) - sizeof(char[6]), c4->memExpandBlock, 0 ) ;
if ( i4->blockMemory == 0 )
{
index4close( i4 ) ;
return 0 ;
}
#endif
#ifndef S4OPTIMIZE_OFF
file4optimize( &i4->file, c4->optimize, OPT4INDEX ) ;
#endif
i4->userCount++ ;
return i4 ;
#endif
}
TAG4 *S4FUNCTION i4tag( INDEX4 *i4, const char *tagName )
{
char tagLookup[LEN4TAG_ALIAS+1] ;
TAG4 *tagOn ;
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E91709 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( i4 == 0 )
{
error4( 0, e4parm_null, E91709 ) ;
return 0 ;
}
if ( tagName == 0 )
{
error4( i4->codeBase, e4parm_null, E91709 ) ;
return 0 ;
}
#endif
u4ncpy( tagLookup, tagName, sizeof( tagLookup ) - 1 ) ;
c4upper( tagLookup ) ;
for( tagOn = 0 ;; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
if ( strcmp( tagOn->tagFile->alias, tagLookup ) == 0 )
return tagOn ;
}
if ( i4->codeBase->errTagName )
error4describe( i4->codeBase, e4tagName, E91709, tagName, 0, 0 ) ;
return 0 ;
}
#ifndef S4CLIENT
#ifndef S4OFF_WRITE
int index4shrink( INDEX4FILE *i4, long blockNo )
{
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91708 ) ;
if ( blockNo < 0 )
return error4( i4->codeBase, e4parm, E91708 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
#ifdef S4FOX
#ifdef S4BYTE_SWAP
i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
#endif
rc = file4write( &i4->file, blockNo, (char *)&i4->tagIndex->header.freeList,
sizeof(i4->tagIndex->header.freeList) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, (short)rc, E91708 ) ;
i4->tagIndex->header.freeList = blockNo ;
#else
#ifdef S4BYTE_SWAP
i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
#endif
rc = file4write( &i4->file, blockNo*I4MULTIPLY + sizeof(S4LONG),
(char *)&i4->header.freeList, sizeof(i4->header.freeList) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91708 ) ;
i4->header.freeList = blockNo ;
#endif
return 0 ;
}
#endif /* S4OFF_WRITE */
#ifndef S4OFF_WRITE
/* Updates the header if the version has changed */
int i4updateHeader( INDEX4 *i4 )
{
return index4updateHeader( i4->indexFile ) ;
}
int index4updateHeader( INDEX4FILE *i4 )
{
#ifdef S4MDX
int rc ;
TAG4FILE *tagOn ;
#ifdef S4BYTE_SWAP
I4HEADER swap ;
#endif
#endif
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91710 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
#ifdef S4FOX
if ( i4->tagIndex == 0 ) /* index file not complete */
return 0 ;
if ( i4->versionOld != i4->tagIndex->header.version )
{
#ifdef S4BYTE_SWAP
i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
#else
i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
#endif
if ( file4write( &i4->file,0L, (char *)&i4->tagIndex->header, LEN4HEADER_WR ) < 0 )
return -1;
#ifdef S4BYTE_SWAP
i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
#else
i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
#endif
i4->versionOld = i4->tagIndex->header.version ;
}
#else
if ( i4->changed )
{
#ifdef S4BYTE_SWAP
memcpy( (void *)&swap, (void *)&i4->header, sizeof(I4HEADER) ) ;
swap.blockChunks = x4reverseShort( (void *)&swap.blockChunks ) ;
swap.blockRw = x4reverseShort( (void *)&swap.blockRw ) ;
swap.slotSize = x4reverseShort( (void *)&swap.slotSize ) ;
swap.numTags = x4reverseShort( (void *)&swap.numTags ) ;
swap.eof = x4reverseLong( (void *)&swap.eof ) ;
swap.freeList = x4reverseLong( (void *)&swap.freeList ) ;
rc = file4write( &i4->file, 0L, (char *)&swap, sizeof( I4HEADER ) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91710 ) ;
#else
rc = file4write( &i4->file, 0L, (char *)&i4->header, sizeof( I4HEADER ) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91710 ) ;
#endif
i4->changed = 0 ;
for( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
if ( tagOn->changed == 1 )
{
tagOn->header.version++ ;
tagOn->changed = 0 ;
rc = file4write( &i4->file, tagOn->headerOffset + 20L, &tagOn->header.version, sizeof(char) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91710 ) ;
if ( tagOn->hadKeys != tagOn->hasKeys )
{
/* just update the tag to record that it has keys (no other update yet) */
rc = file4write( &i4->file, tagOn->headerOffset + 222 + sizeof( T4HEADER ), &tagOn->hasKeys, sizeof(char) ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91710 ) ;
tagOn->hadKeys = tagOn->hasKeys ;
}
}
}
}
#endif
return 0 ;
}
#endif /* S4OFF_WRITE */
int t4versionCheck( TAG4 *t4, const int doSeek, const int updateVersion )
{
#ifndef S4OPTIMIZE_OFF
if ( t4->index->indexFile->file.doBuffer == 0 )
return i4versionCheck( t4->index, doSeek, updateVersion ) ;
else
return 0 ;
#else
return i4versionCheck( t4->index, doSeek, updateVersion ) ;
#endif
}
#ifdef P4ARGS_USED
#pragma argsused
#endif
int i4versionCheck( INDEX4 *i4, const int doSeek, const int updateVersion )
{
#ifndef S4SINGLE
TAG4 *saveTag ;
TAG4FILE *tagOn ;
int needSeek ;
B4BLOCK *b4 ;
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91711 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
rc = index4versionCheck( i4->indexFile, updateVersion ) ;
if ( rc < 0 )
return error4stack( 0, (short)rc, E91711 ) ;
if ( rc == 0 ) /* version did not change */
return 0 ;
needSeek = 0 ;
saveTag = d4tagSelected( i4->data ) ;
if ( saveTag != 0 )
{
/* remember the old position */
if ( doSeek )
{
b4 = (B4BLOCK *)saveTag->tagFile->blocks.lastNode ;
if ( b4 != 0 )
{
if ( tfile4eof( saveTag->tagFile ) )
needSeek = 2 ;
else
#ifdef S4FOX
if ( b4leaf( b4 ) && b4numKeys( b4 ) != 0 )
#else
if ( b4leaf( b4 ) && b4numKeys( b4 ) != 0 && b4->keyOn < b4numKeys( b4 ) )
#endif
{
#ifdef S4FOX
memcpy( i4->codeBase->savedKey, (void *)(b4key( b4, b4->keyOn )), saveTag->tagFile->header.keyLen + sizeof(long) ) ;
#else
memcpy( i4->codeBase->savedKey, (void *)(b4key( b4, b4->keyOn )), saveTag->tagFile->header.keyLen + 2 * sizeof(S4LONG) ) ;
#endif
needSeek = 1 ;
}
}
}
}
for ( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->indexFile->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
if ( tfile4freeAll( tagOn ) < 0 ) /* Should be a memory operation only */
return error4( i4->codeBase, e4result, E91711 ) ;
}
switch ( needSeek )
{
case 1:
tfile4go( saveTag->tagFile, ((B4KEY_DATA *)i4->codeBase->savedKey)->value, ((B4KEY_DATA *)i4->codeBase->savedKey)->num, 0 ) ;
break ;
case 2:
tfile4goEof( saveTag->tagFile ) ;
break ;
default:
break ;
}
#endif
return 0 ;
}
/* Reads the header, checks the version to see if the blocks need to be freed. */
/* returns 1 if version needs to be updated, else 0 */
#ifdef P4ARGS_USED
#pragma argsused
#endif
int index4versionCheck( INDEX4FILE *i4, const int updateVersion )
{
#ifdef S4SINGLE
return 0 ;
#else
#ifndef S4FOX
TAG4FILE *tagOn ;
#endif
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91712 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
if ( index4lockTest( i4 ) )
return 0 ;
#ifndef S4OPTIMIZE_OFF
/* make sure read from disk unless file locked, etc. */
if ( i4->file.doBuffer ) /* also makes sure 'opt' should exist */
i4->codeBase->opt.forceCurrent = 1 ;
#endif
#ifdef S4FOX
rc = file4readAll( &i4->file, 0L, &i4->tagIndex->header, LEN4HEADER_WR ) ;
#ifdef S4BYTE_SWAP
i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
i4->tagIndex->header.version = x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
#endif
#ifndef S4OPTIMIZE_OFF
if ( i4->file.doBuffer )
i4->codeBase->opt.forceCurrent = 0 ;
#endif
if ( rc < 0 )
return error4stack( i4->codeBase, (short)rc, E91712 ) ;
i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
if ( i4->tagIndex->header.version == i4->versionOld )
return 0 ;
if ( updateVersion == 1 )
i4->versionOld = i4->tagIndex->header.version ;
else
i4->tagIndex->header.version = i4->versionOld ;
return 1 ;
#else
rc = file4readAll( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) ;
#ifndef S4OPTIMIZE_OFF
if ( i4->file.doBuffer )
i4->codeBase->opt.forceCurrent = 0 ;
#endif
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91712 ) ;
#ifdef S4BYTE_SWAP
i4->header.blockChunks = x4reverseShort( (void *)&i4->header.blockChunks ) ;
i4->header.blockRw = x4reverseShort( (void *)&i4->header.blockRw ) ;
i4->header.slotSize = x4reverseShort( (void *)&i4->header.slotSize ) ;
i4->header.numTags = x4reverseShort( (void *)&i4->header.numTags ) ;
i4->header.eof = x4reverseLong( (void *)&i4->header.eof ) ;
i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
#endif
#ifndef S4OPTIMIZE_OFF
/* make sure read from disk unless file locked, etc. */
if ( i4->file.doBuffer ) /* also makes sure 'opt' should exist */
i4->codeBase->opt.forceCurrent = 1 ;
#endif
for( tagOn = 0 ;; )
{
tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
rc = file4readAll( &i4->file, tagOn->headerOffset + 20L, &tagOn->header.version, sizeof(char) ) ;
if ( rc < 0 )
{
#ifndef S4OPTIMIZE_OFF
if ( i4->file.doBuffer )
i4->codeBase->opt.forceCurrent = 0 ;
#endif
return error4stack( i4->codeBase, rc, E91712 ) ;
}
rc = file4readAll( &i4->file, tagOn->headerOffset + 222 + sizeof( T4HEADER ), &tagOn->hasKeys, sizeof(char) ) ;
if ( rc < 0 )
{
#ifndef S4OPTIMIZE_OFF
if ( i4->file.doBuffer )
i4->codeBase->opt.forceCurrent = 0 ;
#endif
return error4stack( i4->codeBase, rc, E91712 ) ;
}
tagOn->hadKeys = tagOn->hasKeys ;
}
#ifndef S4OPTIMIZE_OFF
if ( i4->file.doBuffer )
i4->codeBase->opt.forceCurrent = 0 ;
#endif
return 1 ;
#endif
#endif
}
#endif /* S4CLIENT */
#endif /* S4CLIPPER */
#ifdef S4CLIPPER
/* This function closes all the tags corresponding with the index */
int S4FUNCTION i4close( INDEX4 *i4 )
{
int finalRc ;
CODE4 *c4 ;
TAG4 *tagOn ;
int oldOpenErr, rc ;
char buf[258] ;
#ifndef S4SINGLE
int saveAttempts ;
#endif
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E91701 ) )
return -1 ;
#endif
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91701 ) ;
#endif
c4 = i4->codeBase ;
finalRc = error4code( c4 ) ;
#ifndef S4OFF_WRITE
if ( i4->data )
if ( d4update( i4->data ) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
#ifndef S4SINGLE
saveAttempts = c4->lockAttempts ;
c4->lockAttempts = WAIT4EVER ;
if ( i4unlock(i4) < 0 )
finalRc = error4set( c4, 0 ) ;
#endif
for( ;; )
{
tagOn = (TAG4 *)l4pop( &i4->tags ) ;
if ( tagOn == 0 )
break ;
if ( i4->data->tagSelected == tagOn ) /* can't have a non-existant tag selected */
i4->data->tagSelected = 0 ;
t4close( tagOn ) ;
tagOn = 0 ;
}
if ( c4->doRemove == 1 )
{
oldOpenErr = c4->errOpen ;
c4->errOpen = 0 ;
u4ncpy( buf, i4->accessName, sizeof( buf ) - 1 ) ;
u4nameExt( buf, sizeof( buf ), "CGP", 1 ) ;
rc = file4open( &i4->file, c4, buf, 0 ) ;
if ( rc == 0 )
{
i4->file.isTemp = 1 ;
file4close( &i4->file ) ;
}
c4->errOpen = oldOpenErr ;
}
if ( i4->data )
l4remove( &i4->data->indexes, i4 ) ;
mem4free( c4->indexMemory, i4 ) ;
i4 = 0 ;
#ifndef S4SINGLE
c4->lockAttempts = saveAttempts ;
#endif
error4set( c4, finalRc ) ;
return finalRc ;
}
#ifndef S4OFF_WRITE
/* This function flushes all the tags corresponding with the index */
int i4flush( INDEX4 *i4 )
{
TAG4 *tagOn ;
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91713 ) ;
#endif
#ifndef S4SINGLE
if ( i4->data->dataFile->indexLocked == 1 )
#endif
for ( tagOn = 0 ;; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
rc = tfile4flush( tagOn->tagFile ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91713 ) ;
tagOn->tagFile->header.root = -1L ;
}
return 0 ;
}
int i4update( INDEX4 *i4 )
{
TAG4 *tagOn ;
int rc ;
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91705 ) ;
#endif
if ( error4code( i4->codeBase ) < 0 )
return e4codeBase ;
#ifndef S4SINGLE
if ( i4->data->dataFile->indexLocked == 1 )
#endif
for ( tagOn = 0 ;; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
if ( tagOn == 0 )
break ;
rc = tfile4update( tagOn->tagFile ) ;
if ( rc < 0 )
return error4stack( i4->codeBase, rc, E91705 ) ;
tagOn->tagFile->header.root = -1L ;
}
return 0 ;
}
#endif
INDEX4 *S4FUNCTION i4open( DATA4 *d4, const char *fileName )
{
INDEX4 *i4 ;
CODE4 *c4 ;
TAG4 *tag ;
int len, rc, i ;
char buf[258], tagBuf[258], ext[3] ;
int numFiles ;
FILE4SEQ_READ seqread ;
char buffer[1024], tNames[258], firstByte ;
int pos, iPos, saveLen, tempLen ;
#ifdef S4VBASIC
if ( c4parm_check( d4, 2, E91706 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( d4 == 0 )
{
error4( 0, e4parm_null, E91706 ) ;
return 0 ;
}
#endif
c4 = d4->codeBase ;
if ( error4code( c4 ) < 0 )
return 0 ;
#ifdef S4CLIENT
if ( fileName == 0 )
u4ncpy( (char *)buf, d4->dataFile->accessName, sizeof( buf ) - 1 ) ;
else
{
if ( strlen( fileName ) > sizeof( buf ) - 1 )
{
error4( c4, e4name, E91707 ) ;
return 0 ;
}
strcpy( (char*)buf, fileName ) ;
}
c4upper( (char*)buf ) ;
i4file = index4open( d4, (char S4PTR*)buf, 0 ) ;
if ( error4code( c4 ) < 0 )
return 0 ;
i4 = d4index( d4, (char S4PTR*)buf ) ;
if ( i4file == 0 )
{
if ( i4 == 0 )
return 0 ;
#ifdef E4ANALZE
if ( i4->indexFile == 0 )
{
error4( c4, e4info, E91706 ) ;
return 0 ;
}
#endif
i4file = i4->indexFile ;
i4file->clientId = data4clientId( d4 ) ;
i4file->serverId = data4serverId( d4 ) ;
}
else /* indexfile already exists so set up another index4 structure */
{
i4 = i4setup2( c4, i4file, d4, (char S4PTR*)buf ) ;
if ( i4 == 0 )
{
index4close( i4file ) ;
return 0 ;
}
}
#ifdef E4ANALZE
else
{
if ( i4->indexFile != i4file )
{
error4( c4, e4info, E91706 ) ;
return 0 ;
}
}
#endif
i4->codeBase = c4 ;
#else
if ( fileName == 0 )
{
u4ncpy( buf, d4->dataFile->file.name, sizeof( buf ) - 1 ) ;
u4nameExt( buf, sizeof( buf ), "CGP", 1 ) ;
}
else
{
u4ncpy( buf, fileName, sizeof( buf ) - 1 ) ;
c4upper( buf ) ;
rc = u4nameRetExt( ext, 3, buf ) ;
if ( rc ) /* extension provided */
{
if ( rc == 3 )
if ( c4memcmp( ext, "NTX", 3 ) == 0 )
{
tag = t4open( d4, (INDEX4 *)0, fileName ) ;
if ( tag == 0 )
return 0 ;
#ifndef S4OFF_TRAN
tag->index->isValid = 1 ;
#endif
return tag->index ;
}
}
else
u4nameExt( buf, sizeof(buf), "CGP", 0 ) ;
}
if ( c4->indexMemory == 0 )
{
c4->indexMemory = mem4create( c4, c4->memStartIndex, sizeof( INDEX4 ), c4->memExpandIndex, 0 ) ;
if ( c4->indexMemory == 0 )
return 0 ;
}
if ( c4->tagMemory == 0 )
{
c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof( TAG4 ), c4->memExpandTag, 0 ) ;
if ( c4->tagMemory == 0 )
return 0 ;
}
if ( c4->tagFileMemory == 0 )
{
c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof( TAG4FILE ), c4->memExpandTagFile, 0 ) ;
if ( c4->tagFileMemory == 0 )
return 0 ;
}
i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
if ( i4 == 0 )
return 0 ;
i4->codeBase = c4 ;
i4->data = d4 ;
l4add( &d4->indexes, i4 ) ;
if ( fileName == 0 )
u4namePiece( i4->accessName, sizeof( i4->accessName ), buf, 0, 0 ) ;
else
strcpy( i4->accessName, fileName ) ;
c4upper( i4->accessName ) ;
if ( file4open( &i4->file, c4, buf, 1 ) )
{
i4close( i4 ) ;
if ( c4->errOpen )
error4( c4, e4open, E81708 ) ;
return 0 ;
}
file4seqReadInit( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
pos = 0L ;
rc = file4seqReadAll( &seqread, &firstByte, sizeof( firstByte ) ) ;
if ( rc )
{
i4close( i4 ) ;
if ( c4->errOpen )
error4( c4, e4info, E81709 ) ;
return 0 ;
}
if ( firstByte < 65 ) /* old format - potential problem if >= 65 files in an old format file. */
{
numFiles = firstByte ;
if ( file4seqReadAll( &seqread, &firstByte, sizeof( firstByte ) ) )
{
i4close( i4 ) ;
if ( c4->errOpen )
error4( c4, e4info, E81709 ) ;
return 0 ;
}
for ( i = 0 ; i < numFiles ; i++ )
{
if ( file4seqReadAll( &seqread, &len, sizeof( len ) ) )
{
file4close( &i4->file ) ;
i4close( i4 ) ;
if ( c4->errOpen )
error4( c4, e4info, E81709 ) ;
return 0 ;
}
pos += sizeof( len ) ;
rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
tagBuf[rc+len] = '\0' ;
if ( sizeof( tagBuf ) > rc + len ) /* make sure room to read */
rc = file4seqReadAll( &seqread, tagBuf+rc, len ) ;
else
rc = -1 ;
if ( rc )
{
if ( c4->errOpen )
error4( c4, e4info, E81709 ) ;
file4close( &i4->file ) ;
i4close( i4 ) ;
return 0 ;
}
pos += len ;
if ( t4open( d4, i4, tagBuf ) == 0 )
{
file4close( &i4->file ) ;
i4close( i4 ) ;
return 0 ;
}
}
file4close( &i4->file ) ;
}
else
{
file4seqReadInit( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
saveLen = 0 ;
for( len = sizeof( tNames ) ; len == sizeof( tNames ) ; )
{
len = file4seqRead( &seqread, tNames, sizeof( tNames )) ;
if ( len < sizeof( tNames ) ) /* case where all read in now - free up this file handle for use */
{
if ( file4close ( &i4->file ) )
{
i4close( i4 ) ;
if ( c4->errOpen )
error4( c4, e4info, E81710 ) ;
return 0 ;
}
if ( len == 0 )
break ;
}
for( iPos = 0, pos = 0 ; pos < len ; )
{
switch( tNames[pos] )
{
/* cases where the values are ignored, or found name */
case ' ':
case '\r':
case '\n':
case '\t':
case '\x1A':
if ( iPos < pos ) /* try to open the file */
{
tempLen = pos - iPos ;
if ( saveLen == 0 )
{
rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
tagBuf[rc + tempLen] = '\0' ;
}
else
rc = saveLen ;
memcpy( tagBuf + rc, &tNames[iPos], tempLen ) ;
if ( t4open( d4, i4, tagBuf ) == 0 )
{
file4close( &i4->file ) ;
i4close( i4 ) ;
return 0 ;
}
}
iPos = ++pos ;
break ;
/* case where a name is attempted to be read in */
default:
pos++ ;
}
}
tempLen = pos - iPos ;
rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
tagBuf[rc+tempLen] = '\0' ;
memcpy( tagBuf + rc, &tNames[iPos], tempLen ) ;
saveLen = rc + tempLen ;
}
if ( ( saveLen - rc ) > 0 ) /* try to open the file */
{
if ( t4open( d4, i4, tagBuf ) == 0 )
{
file4close( &i4->file ) ;
i4close( i4 ) ;
return 0 ;
}
}
}
#endif
#ifndef S4OFF_TRAN
i4->isValid = 1 ;
#endif
return i4 ;
}
TAG4 *S4FUNCTION i4tag( INDEX4 *i4, const char *tagName )
{
char tagLookup[LEN4TAG_ALIAS+1] ;
TAG4 *tagOn ;
#ifdef S4VBASIC
if ( c4parm_check( i4, 0, E91709 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( i4 == 0 || tagName == 0 )
{
error4( 0, e4parm_null, E91709 ) ;
return 0 ;
}
#endif
u4ncpy( tagLookup, tagName, sizeof( tagLookup ) - 1 ) ;
c4upper( tagLookup ) ;
for( tagOn = 0 ;; )
{
tagOn = (TAG4 *)l4next( &i4->tags, tagOn) ;
if ( tagOn == 0 )
break ;
if ( strcmp( tagOn->tagFile->alias, tagLookup) == 0 )
return tagOn ;
}
if ( i4->codeBase->errTagName )
error4describe( i4->codeBase, e4tagName, E91709, tagName, 0, 0 ) ;
return 0 ;
}
#endif /* ifdef S4CLIPPER */
#ifndef S4CLIPPER
#ifndef S4CLIENT
int index4isProduction( INDEX4FILE *i4 )
{
#ifdef S4FOX
int l1, l2, count ;
#endif
#ifdef E4PARM_LOW
if ( i4 == 0 )
return error4( 0, e4parm_null, E91714 ) ;
#endif
#ifdef S4MDX
#ifdef S4SERVER
return i4->header.isProduction ;
#else
return i4->dataFile->openMdx ;
#endif
#endif
#ifdef S4FOX
#ifdef S4SERVER
if ( i4->dataFile->hasMdxMemo )
#else
if ( i4->dataFile->openMdx )
#endif
{
if ( i4->file.name == 0 ) /* most likely a failure during open/create now closing */
return 0 ;
l1 = strlen( i4->file.name ) ;
if ( l1 == 0 )
return 0 ;
for ( count = l1 - 1 ;; count-- )
{
if ( count <= 0 )
break ;
if ( i4->file.name[count] == '.' )
{
l1 = count ;
break ;
}
}
l2 = strlen( i4->dataFile->file.name ) ;
if ( l2 == 0 )
return 0 ;
for ( count = l2 - 1 ;; count-- )
{
if ( count <= 0 )
break ;
if ( i4->dataFile->file.name[count] == '.' )
{
l2 = count ;
break ;
}
}
if ( l1 == l2 )
return( c4memcmp( i4->file.name, i4->dataFile->file.name, (unsigned)l1 ) ? 0 : 1 ) ;
}
return 0 ;
#endif
}
#endif /* S4CLIENT */
#endif /* S4CLIPPER */
#endif /* S4INDEX_OFF */
#ifdef S4VB_DOS
INDEX4 * i4open_v( DATA4 *d4, char *name )
{
char *namePtr ;
namePtr = c4str(name) ;
if (namePtr[0] == '\0' )
return i4open( d4, 0 ) ;
return i4open( d4, namePtr ) ;
}
TAG4 *i4tag_v( INDEX4 *ind, char *tagName )
{
return i4tag( ind, c4str(tagName) ) ;
}
#endif /* S4VB_DOS */