af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
2370 lines
65 KiB
C
Executable File
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 */
|