908 lines
25 KiB
C
Executable File
908 lines
25 KiB
C
Executable File
/* i4check.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
int S4FUNCTION d4check( DATA4 *d4 )
|
|
{
|
|
#ifdef S4INDEX_OFF
|
|
return 0 ;
|
|
#else
|
|
CONNECTION4 *connection ;
|
|
int rc ;
|
|
CONNECTION4CHECK_INFO_OUT *out ;
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( d4 == 0 )
|
|
return error4( 0, e4parm_null, E95702 ) ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_MULTI
|
|
#ifdef S4SERVER
|
|
rc = dfile4lockFile( d4->dataFile, d4->currentClientId, d4->serverId ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#else
|
|
rc = d4lockFile( d4 ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#endif
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
connection = d4->dataFile->connection ;
|
|
if ( connection == 0 )
|
|
return e4connection ;
|
|
connection4assign( connection, CON4CHECK, data4clientId( d4 ), data4serverId( d4 ) ) ;
|
|
connection4send( connection ) ;
|
|
rc = connection4receive( connection ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
rc = connection4status( connection ) ;
|
|
if ( rc != 0 )
|
|
return connection4error( connection, d4->codeBase, rc, E95702 ) ;
|
|
|
|
if ( connection4len( connection ) != sizeof( CONNECTION4CHECK_INFO_OUT ) )
|
|
return error4( d4->codeBase, e4packetLen, E95702 ) ;
|
|
out = (CONNECTION4CHECK_INFO_OUT *)connection4data( connection ) ;
|
|
if ( out->lockedDatafile == 1 )
|
|
d4->dataFile->fileLock = d4 ;
|
|
return 0 ;
|
|
#endif /* S4INDEX_OFF */
|
|
}
|
|
#else
|
|
|
|
#ifndef S4INDEX_OFF
|
|
|
|
typedef struct
|
|
{
|
|
F4FLAG flag ;
|
|
|
|
TAG4FILE *tag ;
|
|
char *oldKey ;
|
|
long oldRec ;
|
|
long numRecs ;
|
|
int doCompare ; /* Do not compare the first time */
|
|
CODE4 *codeBase ;
|
|
DATA4 *data ;
|
|
} C4CHECK ;
|
|
|
|
static int c4checkInit( C4CHECK *check, CODE4 *cb, TAG4FILE *t4, long nRecs, DATA4 *d4 )
|
|
{
|
|
int rc ;
|
|
|
|
memset( (void *)check, 0, sizeof(C4CHECK) ) ;
|
|
|
|
rc = f4flagInit( &check->flag, cb, (unsigned long)nRecs ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
check->codeBase = cb ;
|
|
check->tag = t4 ;
|
|
check->numRecs = nRecs ;
|
|
check->data = d4 ;
|
|
|
|
check->oldKey = (char *)u4allocFree( t4->codeBase, (long)t4->header.keyLen ) ;
|
|
if (check->oldKey == 0)
|
|
return e4memory ;
|
|
return 0 ;
|
|
}
|
|
|
|
static void c4checkFree( C4CHECK *c4 )
|
|
{
|
|
u4free( c4->flag.flags ) ;
|
|
u4free( c4->oldKey ) ;
|
|
}
|
|
|
|
static int c4checkRecord( C4CHECK *check )
|
|
{
|
|
B4KEY_DATA *keyData ;
|
|
TAG4FILE *t4 ;
|
|
unsigned char *newPtr ;
|
|
int len, rc ;
|
|
|
|
t4 = check->tag ;
|
|
|
|
keyData = tfile4keyData( check->tag ) ;
|
|
if ( keyData == 0 )
|
|
return error4( check->codeBase, e4index, E95701 ) ;
|
|
|
|
if ( keyData->num < 1 || keyData->num > check->numRecs )
|
|
return error4describe( check->codeBase, e4index, E85703, check->tag->alias, (char *)0, (char *)0 ) ;
|
|
|
|
if ( f4flagIsSet( &check->flag, (unsigned long)keyData->num) )
|
|
return error4describe( check->codeBase, e4index, E85703, check->tag->alias, (char *)0, (char *)0 ) ;
|
|
else
|
|
f4flagSet( &check->flag, (unsigned long)keyData->num ) ;
|
|
|
|
rc = d4go( check->data, keyData->num ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
rc = expr4context( t4->expr, check->data ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
len = tfile4exprKey( t4, &newPtr ) ;
|
|
|
|
if ( len != t4->header.keyLen )
|
|
return error4describe( check->codeBase, e4index, E85704, t4->alias, (char *)0, (char *)0 ) ;
|
|
|
|
#ifdef S4MDX
|
|
if ( expr4type( t4->expr ) == r4num )
|
|
{
|
|
if ( c4bcdCmp( newPtr, keyData->value, 0 ) != 0 )
|
|
return error4describe( check->codeBase, e4index, E85705, t4->alias, (char *)0, (char *)0 ) ;
|
|
}
|
|
else
|
|
#endif
|
|
if ( c4memcmp( newPtr, keyData->value, (unsigned int)t4->header.keyLen ) != 0 )
|
|
return error4describe( check->codeBase, e4index, E85705, t4->alias, (char *)0, (char *)0 ) ;
|
|
|
|
if ( check->doCompare )
|
|
{
|
|
#ifdef S4FOX
|
|
#ifdef S4VFP_KEY
|
|
if ( tfile4type( t4 ) != r4str )
|
|
rc = c4memcmp( check->oldKey, newPtr, (unsigned int)t4->header.keyLen ) ;
|
|
else
|
|
#endif
|
|
rc = u4keycmp( check->oldKey, newPtr, (unsigned int)t4->header.keyLen, (unsigned int)t4->header.keyLen, 0, &t4->vfpInfo ) ;
|
|
#else
|
|
rc = (*t4->cmp)( check->oldKey, newPtr, (unsigned int)t4->header.keyLen ) ;
|
|
#endif
|
|
|
|
if ( rc > 0)
|
|
error4describe( check->codeBase, e4index, E85706, t4->alias, (char *)0, (char *)0 ) ;
|
|
#ifdef S4FOX
|
|
if ( rc == 0 && keyData->num <= check->oldRec )
|
|
error4describe( check->codeBase, e4index, E85707, t4->alias, (char *)0, (char *)0 ) ;
|
|
#endif /* S4FOX */
|
|
|
|
#ifdef S4FOX
|
|
if ( t4->header.typeCode & 0x01 )
|
|
#else
|
|
if ( t4->header.unique )
|
|
#endif /* S4FOX */
|
|
if ( rc == 0 )
|
|
error4describe( check->codeBase, e4index, E85708, t4->alias, (char *)0, (char *)0 ) ;
|
|
}
|
|
else
|
|
check->doCompare = 1 ;
|
|
|
|
memcpy( check->oldKey, newPtr, (unsigned int)t4->header.keyLen ) ;
|
|
|
|
check->oldRec = keyData->num ;
|
|
|
|
if ( error4code( check->codeBase ) < 0 )
|
|
return error4code( check->codeBase ) ;
|
|
return 0 ;
|
|
}
|
|
|
|
#ifdef S4CLIPPER
|
|
static int tfile4blockCheck( TAG4FILE *t4, int firstTime )
|
|
{
|
|
B4BLOCK *b4 ;
|
|
int i, bType, rc ;
|
|
CODE4 *c4 ;
|
|
|
|
if ( firstTime )
|
|
tfile4upToRoot( t4 ) ;
|
|
|
|
c4 = t4->codeBase ;
|
|
b4 = (B4BLOCK *)t4->blocks.lastNode ;
|
|
if ( b4 == 0 )
|
|
return 0 ;
|
|
if ( b4->nKeys < t4->header.keysHalf && t4->header.root / 512 != b4->fileBlock )
|
|
return error4describe( c4, e4index, E85709, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
if ( !b4leaf( b4 ) )
|
|
{
|
|
for ( i = 0 ; i <= b4->nKeys ; i++ )
|
|
{
|
|
b4->keyOn = i ;
|
|
rc = tfile4down( t4 ) ;
|
|
if ( rc != 0 )
|
|
return error4describe( c4, e4index, E81601, tfile4alias( t4 ), 0, 0 ) ;
|
|
if ( i == 0 )
|
|
bType = b4leaf( (B4BLOCK *)t4->blocks.lastNode ) ;
|
|
else
|
|
if ( bType != b4leaf( (B4BLOCK *)t4->blocks.lastNode ) )
|
|
return error4describe( c4, e4index, E85709, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
rc = tfile4blockCheck( t4, 0 ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
rc = tfile4up( t4 ) ;
|
|
if ( rc != 0 )
|
|
return error4describe( c4, e4index, E81601, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
}
|
|
}
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4NDX
|
|
static int tfile4blockCheck( TAG4FILE *t4, int firstTime )
|
|
{
|
|
B4BLOCK *b4 ;
|
|
int i, bType, rc ;
|
|
CODE4 *c4 ;
|
|
|
|
if ( firstTime )
|
|
tfile4upToRoot( t4 ) ;
|
|
|
|
c4 = t4->codeBase ;
|
|
b4 = (B4BLOCK *)t4->blocks.lastNode ;
|
|
if ( b4 == 0 )
|
|
return 0 ;
|
|
if ( !b4leaf( b4 ) )
|
|
{
|
|
for ( i = 0 ; i <= b4->nKeys ; i++ )
|
|
{
|
|
if ( b4key( b4, b4->keyOn )->pointer >= t4->header.eof )
|
|
return error4describe( c4, e4index, E81601, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
b4->keyOn = i ;
|
|
rc = tfile4down( t4 ) ;
|
|
if ( rc != 0 )
|
|
return error4describe( c4, e4index, E81601, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
rc = tfile4blockCheck( t4, 0 ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
rc = tfile4up( t4 ) ;
|
|
if ( rc != 0 )
|
|
return error4describe( c4, e4index, E81601, tfile4alias( t4 ), (char *)0, (char *)0 ) ;
|
|
}
|
|
}
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
int t4check( TAG4 *t4 )
|
|
{
|
|
C4CHECK check ;
|
|
int rc, isRecord, keysSkip, rc2 ;
|
|
CODE4 *c4 ;
|
|
TAG4 *oldSelectedTag ;
|
|
B4BLOCK *blockOn ;
|
|
long baseSize, onRec ;
|
|
unsigned char *ptr ;
|
|
DATA4 *d4 ;
|
|
#ifdef S4FOX
|
|
unsigned char *tempVal ;
|
|
long tempLong ;
|
|
#endif
|
|
#ifndef S4CLIPPER
|
|
B4KEY_DATA *keyBranch, *keyLeaf ;
|
|
#endif
|
|
#ifdef S4PRINTF_OUT
|
|
unsigned long loop ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( t4 == 0 )
|
|
return error4( 0, e4parm_null, E95703 ) ;
|
|
#endif
|
|
|
|
d4 = t4->index->data ;
|
|
c4 = d4->codeBase ;
|
|
|
|
rc = expr4context( t4->tagFile->expr, d4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( t4->tagFile->filter != 0 )
|
|
{
|
|
rc = expr4context( t4->tagFile->filter, d4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
|
|
#ifndef S4OFF_MULTI
|
|
#ifdef S4SERVER
|
|
rc = dfile4lockFile( d4->dataFile, data4clientId( d4 ), data4serverId( d4 ) ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#else
|
|
rc = d4lockFile( d4 ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#endif
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
#ifdef N4OTHER
|
|
rc = i4lock( t4->index ) ;
|
|
#else
|
|
rc = index4lock( t4->tagFile->indexFile, data4serverId( d4 ) ) ;
|
|
#endif
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
rc = d4refresh( d4 ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( d4, 1 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( rc )
|
|
return error4( c4, rc, E95703 ) ;
|
|
#endif
|
|
|
|
oldSelectedTag = d4tagSelected( d4 ) ;
|
|
d4tagSelect( d4, t4 ) ;
|
|
|
|
#ifdef N4OTHER
|
|
rc = tfile4blockCheck( t4->tagFile, 1 ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
#endif
|
|
|
|
baseSize = d4recCount( d4 ) ;
|
|
if ( baseSize < 0L )
|
|
return (int)baseSize ;
|
|
|
|
rc = d4top( d4 ) ;
|
|
if (rc < 0 )
|
|
return rc ;
|
|
if ( rc == 0 )
|
|
rc = 1 ;
|
|
|
|
if ( baseSize == 0L )
|
|
{
|
|
if ( tfile4skip( t4->tagFile, 1L ) == 0 )
|
|
{
|
|
d4tagSelect( d4, oldSelectedTag ) ;
|
|
return( 0 ) ;
|
|
}
|
|
else
|
|
return error4describe( c4, e4index, E85710, d4alias( d4 ), tfile4alias( t4->tagFile ), (char *)0 ) ;
|
|
}
|
|
|
|
rc2 = c4checkInit( &check, c4, t4->tagFile, baseSize, d4 ) ;
|
|
if ( rc2 < 0 )
|
|
return rc2 ;
|
|
|
|
#ifdef S4PRINTF_OUT
|
|
loop = 0 ;
|
|
printf( "On Rec %10ld\n", loop ) ;
|
|
#endif
|
|
while ( rc == 1 )
|
|
{
|
|
rc = c4checkRecord( &check ) ;
|
|
if ( rc )
|
|
break ;
|
|
rc = (int)tfile4skip( t4->tagFile, 1L ) ;
|
|
if ( rc < 0 )
|
|
break ;
|
|
#ifdef S4PRINTF_OUT
|
|
if ( (loop++ % 100) == 0 )
|
|
printf( "\b\b\b\b\b\b\b\b\b\b%10ld", loop ) ;
|
|
#endif
|
|
}
|
|
|
|
if ( rc < 0 )
|
|
{
|
|
c4checkFree( &check ) ;
|
|
return rc ;
|
|
}
|
|
|
|
isRecord = 1 ;
|
|
|
|
/* Now Test for Duplication */
|
|
for ( onRec = 1; onRec <= baseSize; onRec++)
|
|
{
|
|
#ifndef S4NDX
|
|
if ( t4->tagFile->filter != 0 )
|
|
{
|
|
if ( d4go( d4, onRec ) < 0 )
|
|
break ;
|
|
rc2 = expr4context( t4->tagFile->filter, check.data ) ;
|
|
if ( rc2 < 0 )
|
|
return rc2 ;
|
|
|
|
isRecord = expr4true( t4->tagFile->filter ) ;
|
|
}
|
|
#endif
|
|
|
|
if ( f4flagIsSet( &check.flag, (unsigned long)onRec ) )
|
|
{
|
|
if ( !isRecord )
|
|
{
|
|
error4describe( c4, e4index, E95703, t4->tagFile->alias, (char *)0, (char *)0 ) ;
|
|
break ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! isRecord )
|
|
continue ;
|
|
|
|
#ifdef S4FOX
|
|
if ( t4->tagFile->header.typeCode & 0x01 )
|
|
#else
|
|
if ( t4->tagFile->header.unique )
|
|
#endif
|
|
{
|
|
if ( d4go(d4,onRec) < 0 )
|
|
break ;
|
|
if ( expr4context( t4->tagFile->expr, check.data ) < 0 )
|
|
break ;
|
|
if ( tfile4exprKey( t4->tagFile, &ptr) < 0 )
|
|
break ;
|
|
if ( tfile4seek( t4->tagFile, ptr, expr4keyLen( t4->tagFile->expr ) ) == 0 )
|
|
continue ;
|
|
}
|
|
|
|
error4describe( c4, e4index, E85711, t4->tagFile->alias, 0, 0 ) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
c4checkFree( &check ) ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return error4code( c4 ) ;
|
|
|
|
/* Now make sure the block key pointers match the blocks they point to. */
|
|
/* This needs to be true for d4seek to function perfectly. */
|
|
|
|
rc = d4bottom( d4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
if ( rc == 3 )
|
|
{
|
|
d4tagSelect( d4, oldSelectedTag ) ;
|
|
return 0 ;
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
#ifdef S4FOX
|
|
keysSkip = -tfile4block(t4->tagFile)->header.nKeys ;
|
|
#else
|
|
keysSkip = -tfile4block(t4->tagFile)->nKeys ;
|
|
#endif
|
|
|
|
rc = (int)tfile4skip( t4->tagFile, (long) keysSkip ) ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return error4code( c4 ) ;
|
|
if ( rc != keysSkip )
|
|
{
|
|
d4tagSelect( d4, oldSelectedTag ) ;
|
|
return 0 ;
|
|
}
|
|
|
|
blockOn = (B4BLOCK *)t4->tagFile->blocks.lastNode ;
|
|
if ( blockOn == 0 )
|
|
return error4describe( c4, e4index, E85712, tfile4alias( t4->tagFile ), (char *)0, (char *)0 ) ;
|
|
|
|
#ifdef S4FOX
|
|
tempVal = (unsigned char *)u4allocFree( c4, (long)t4->tagFile->header.keyLen ) ;
|
|
if ( tempVal == 0 )
|
|
return error4stack( c4, e4memory, E95703 ) ;
|
|
memcpy( tempVal, (void *)b4keyKey( blockOn, blockOn->keyOn ), (unsigned int)t4->tagFile->header.keyLen ) ;
|
|
tempLong = b4recNo( blockOn, blockOn->keyOn ) ;
|
|
|
|
if ( tfile4go( t4->tagFile, tempVal, tempLong, 0 ) )
|
|
{
|
|
u4free( tempVal ) ;
|
|
return error4describe( c4, e4index, E85712, tfile4alias( t4->tagFile ), (char *)0, (char *)0 ) ;
|
|
}
|
|
u4free( tempVal ) ;
|
|
#endif
|
|
|
|
#ifndef S4CLIPPER
|
|
for ( ;; )
|
|
{
|
|
blockOn = (B4BLOCK *)blockOn->link.p ;
|
|
if ( blockOn == 0 )
|
|
break ;
|
|
if ( blockOn == (B4BLOCK *)t4->tagFile->blocks.lastNode )
|
|
break ;
|
|
|
|
#ifdef S4FOX
|
|
if ( blockOn->keyOn < blockOn->header.nKeys )
|
|
#else
|
|
if ( blockOn->keyOn < blockOn->nKeys )
|
|
#endif
|
|
{
|
|
keyBranch = b4key( blockOn, blockOn->keyOn ) ;
|
|
keyLeaf = b4key( tfile4block( t4->tagFile ), tfile4block( t4->tagFile )->keyOn ) ;
|
|
|
|
if ( c4memcmp( keyBranch->value, keyLeaf->value, (unsigned int)t4->tagFile->header.keyLen) != 0 )
|
|
return error4describe( c4, e4index, E85712, tfile4alias( t4->tagFile ), (char *)0, (char *)0 ) ;
|
|
|
|
break ;
|
|
}
|
|
}
|
|
if ( blockOn == 0 )
|
|
return error4describe( c4, e4index, E85712, tfile4alias( t4->tagFile ), (char *)0, (char *)0 ) ;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef S4FOX
|
|
static int flag4blocks( TAG4FILE *t4, F4FLAG *f4, long *node1, long *node2, long *node3 )
|
|
{
|
|
int i, rc ;
|
|
B4BLOCK *blockOn ;
|
|
long flagNo ;
|
|
|
|
rc = tfile4down( t4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( rc == 2 )
|
|
return e4index ;
|
|
if ( rc == 1 )
|
|
return error4( t4->codeBase, e4index, E95704 ) ;
|
|
|
|
blockOn = tfile4block(t4) ;
|
|
|
|
flagNo = blockOn->fileBlock / B4BLOCK_SIZE ;
|
|
if ( *node2 != -2 )
|
|
if ( *node2 != blockOn->fileBlock )
|
|
return error4( t4->codeBase, e4index, E81601 ) ;
|
|
if ( *node1 != -2 )
|
|
if ( *node1 != blockOn->header.leftNode )
|
|
return error4( t4->codeBase, e4index, E81601 ) ;
|
|
if ( *node3 != -2 )
|
|
if ( *node3 != blockOn->header.rightNode )
|
|
return error4( t4->codeBase, e4index, E81601 ) ;
|
|
|
|
if ( f4flagIsSet( f4, (unsigned long)flagNo ) )
|
|
return error4( t4->codeBase, e4index, E81601 ) ;
|
|
|
|
rc = f4flagSet( f4, (unsigned long)flagNo ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( ! b4leaf(blockOn) )
|
|
{
|
|
if ( blockOn->header.leftNode == -1 )
|
|
*node1 = -1L ;
|
|
else
|
|
*node1 = -2L ;
|
|
*node2 = b4key( blockOn, 0 )->num ;
|
|
|
|
for( i = 0; i < blockOn->header.nKeys; i++ )
|
|
{
|
|
b4go( blockOn, (long)i ) ;
|
|
if ( i == blockOn->header.nKeys - 1 && blockOn->header.rightNode == -1 )
|
|
*node3 = -1 ;
|
|
else
|
|
*node3 = -2 ;
|
|
rc = flag4blocks( t4, f4, node1, node2, node3 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
}
|
|
|
|
*node1 = blockOn->fileBlock ;
|
|
*node2 = blockOn->header.rightNode ;
|
|
tfile4up(t4) ;
|
|
return 0 ;
|
|
}
|
|
#else
|
|
#ifndef S4NDX
|
|
static int flag4blocks( TAG4FILE *t4, F4FLAG *f4 )
|
|
{
|
|
int i, rc ;
|
|
B4BLOCK *blockOn ;
|
|
long flagNo ;
|
|
|
|
rc = tfile4down( t4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( rc == 2 )
|
|
return -1 ;
|
|
if ( rc == 1 )
|
|
return error4( t4->codeBase, e4index, E95704 ) ;
|
|
|
|
blockOn = tfile4block(t4) ;
|
|
|
|
#ifdef S4CLIPPER
|
|
flagNo = (blockOn->fileBlock) * I4MULTIPLY / B4BLOCK_SIZE ;
|
|
#else
|
|
flagNo = (blockOn->fileBlock-4) * I4MULTIPLY / t4->indexFile->header.blockRw ;
|
|
#endif
|
|
|
|
if ( f4flagIsSet( f4, flagNo ) )
|
|
return error4( t4->codeBase, e4index, E81601 ) ;
|
|
|
|
rc = f4flagSet( f4, flagNo ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
if ( ! b4leaf(blockOn) )
|
|
{
|
|
#ifdef S4MDX
|
|
for( i = 0; i <= blockOn->nKeys; i++ )
|
|
{
|
|
blockOn->keyOn = i ;
|
|
rc = flag4blocks( t4, f4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
#else
|
|
#ifdef S4CLIPPER
|
|
for( i = 0; i <= blockOn->nKeys; i++ )
|
|
{
|
|
blockOn->keyOn = i ;
|
|
rc = flag4blocks( t4, f4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
tfile4up(t4) ;
|
|
return 0 ;
|
|
}
|
|
#endif /* ifndef S4NDX */
|
|
#endif /* ifdef S4FOX */
|
|
|
|
/* checks that all blocks in the file are on free list or are being used */
|
|
#ifdef P4ARGS_USED
|
|
#pragma argsused
|
|
#endif
|
|
static int i4checkBlocks( INDEX4 *i4 )
|
|
{
|
|
#ifndef N4OTHER
|
|
TAG4FILE *tagOn ;
|
|
F4FLAG flags ;
|
|
#ifndef S4OFF_MULTI
|
|
int rc ;
|
|
#endif
|
|
long flagNo ;
|
|
S4LONG totBlocks, freeBlock, eofBlockNo, len ;
|
|
CODE4 *c4 ;
|
|
#ifdef S4FOX
|
|
long node1, node2, node3 ;
|
|
#else
|
|
T4DESC desc[48] ;
|
|
int i ;
|
|
#endif
|
|
|
|
c4 = i4->codeBase ;
|
|
|
|
#ifndef S4OFF_MULTI
|
|
rc = d4lockIndex( i4->data ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
#endif
|
|
|
|
len = file4len(&i4->indexFile->file) ;
|
|
|
|
#ifdef S4MDX
|
|
totBlocks = (len-2048) / i4->indexFile->header.blockRw ;
|
|
#else
|
|
totBlocks = len / B4BLOCK_SIZE ;
|
|
#endif
|
|
|
|
/* First Flag for the Free Chain */
|
|
f4flagInit( &flags, i4->codeBase, (unsigned long)totBlocks ) ;
|
|
|
|
eofBlockNo = len/I4MULTIPLY ;
|
|
#ifdef S4FOX
|
|
for ( freeBlock = i4->indexFile->tagIndex->header.freeList ; freeBlock ; )
|
|
#else
|
|
for ( freeBlock = i4->indexFile->header.freeList ; freeBlock ; )
|
|
#endif
|
|
{
|
|
if ( freeBlock == eofBlockNo || error4code( c4 ) < 0 )
|
|
break ;
|
|
|
|
#ifdef S4MDX
|
|
flagNo = (int)((freeBlock-4)*I4MULTIPLY/i4->indexFile->header.blockRw) ;
|
|
#else
|
|
flagNo = (int) (freeBlock / B4BLOCK_SIZE) ;
|
|
#endif
|
|
|
|
if ( freeBlock >= eofBlockNo || f4flagIsSet(&flags, (unsigned long)flagNo ) )
|
|
{
|
|
error4( c4, e4index, E85701 ) ;
|
|
break ;
|
|
}
|
|
f4flagSet( &flags, (unsigned long)flagNo ) ;
|
|
|
|
#ifdef S4MDX
|
|
file4readAll( &i4->indexFile->file, freeBlock * I4MULTIPLY + sizeof(long), &freeBlock, sizeof(freeBlock) ) ;
|
|
#else
|
|
file4readAll( &i4->indexFile->file, freeBlock * I4MULTIPLY, &freeBlock, sizeof(freeBlock) ) ;
|
|
#endif
|
|
|
|
#ifdef S4BYTE_SWAP
|
|
freeBlock = x4reverseLong( (void *)&freeBlock ) ;
|
|
#endif
|
|
}
|
|
|
|
#ifdef S4FOX
|
|
/* do the header tag */
|
|
tagOn = i4->indexFile->tagIndex ;
|
|
flagNo = (int)((tagOn->headerOffset) / (long)B4BLOCK_SIZE) ;
|
|
if ( f4flagIsSet( &flags, (unsigned long)flagNo ) )
|
|
return error4( i4->codeBase, e4index, E81601 ) ;
|
|
f4flagSet( &flags, (unsigned long)flagNo ) ;
|
|
f4flagSet( &flags, (unsigned long)flagNo + 1L ) ; /* tag header is 2 blocks long */
|
|
|
|
if ( tfile4freeAll( tagOn ) >= 0 )
|
|
{
|
|
#ifdef S4FOX
|
|
node1 = -1L ;
|
|
node2 = tagOn->header.root ;
|
|
node3 = -1L ;
|
|
flag4blocks( tagOn, &flags, &node1, &node2, &node3 ) ;
|
|
#else
|
|
flag4blocks( tagOn, &flags ) ;
|
|
#endif
|
|
|
|
/* Now Flag for each block in each tag */
|
|
for ( tagOn = 0 ;; )
|
|
{
|
|
tagOn = (TAG4FILE *)l4next( &i4->indexFile->tags,tagOn ) ;
|
|
if ( tagOn == 0 )
|
|
break ;
|
|
flagNo = (int)( tagOn->headerOffset / (long)B4BLOCK_SIZE) ;
|
|
if ( f4flagIsSet( &flags, (unsigned long)flagNo ) )
|
|
return error4( i4->codeBase, e4index, E81601 ) ;
|
|
f4flagSet( &flags, (unsigned long)flagNo ) ;
|
|
f4flagSet( &flags, (unsigned long)flagNo + 1L ) ; /* tag header is 2 blocks long */
|
|
|
|
if ( tfile4freeAll( tagOn ) < 0 )
|
|
break ;
|
|
#ifdef S4FOX
|
|
node1 = -1L ;
|
|
node2 = tagOn->header.root ;
|
|
node3 = -1L ;
|
|
if ( node2 == -1 )
|
|
{
|
|
if ( file4readAll( &i4->indexFile->file, tagOn->headerOffset, &node2, sizeof(node2)) < 0 )
|
|
return error4( i4->codeBase, e4index, E81601 ) ;
|
|
#ifdef S4BYTE_SWAP
|
|
node2 = x4reverseLong( (void *)&node2 ) ;
|
|
#endif
|
|
}
|
|
flag4blocks( tagOn, &flags, &node1, &node2, &node3 ) ;
|
|
#else
|
|
flag4blocks( tagOn, &flags ) ;
|
|
#endif
|
|
}
|
|
}
|
|
#else
|
|
/* Read header information to flag the tag header blocks */
|
|
file4readAll( &i4->indexFile->file, 512, desc, sizeof(desc) ) ;
|
|
|
|
/* Now Flag for each block in each tag */
|
|
i = 1 ;
|
|
|
|
for ( tagOn = 0 ;; i++ )
|
|
{
|
|
tagOn = (TAG4FILE *)l4next( &i4->indexFile->tags, tagOn ) ;
|
|
if ( tagOn == 0 )
|
|
break ;
|
|
#ifdef S4BYTE_SWAP
|
|
desc[i].headerPos = x4reverseLong( (void *)&desc[i].headerPos ) ;
|
|
desc[i].x1000 = 0x1000 ;
|
|
#endif
|
|
|
|
flagNo = (int) ((desc[i].headerPos * I4MULTIPLY - 2048) / (long) i4->indexFile->header.blockRw) ;
|
|
if ( f4flagIsSet( &flags, flagNo ) )
|
|
return error4( i4->codeBase, e4index, E81601 ) ;
|
|
f4flagSet( &flags, flagNo ) ;
|
|
|
|
if ( tfile4freeAll(tagOn) < 0 )
|
|
break ;
|
|
flag4blocks( tagOn, &flags ) ;
|
|
}
|
|
#endif
|
|
|
|
if ( f4flagIsAllSet( &flags, 0UL, (unsigned long)totBlocks - 1L ) == 0 )
|
|
error4( i4->codeBase, e4index, E85702 ) ;
|
|
|
|
u4free( flags.flags ) ;
|
|
if ( error4code( i4->codeBase ) < 0 )
|
|
return error4code( i4->codeBase ) ;
|
|
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
int i4check( INDEX4 *i4 )
|
|
{
|
|
int rc ;
|
|
TAG4 *tagOn ;
|
|
#ifdef S4HAS_DESCENDING
|
|
int oldDesc ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( i4 == 0 )
|
|
return error4( 0, e4parm_null, E95705 ) ;
|
|
#endif
|
|
|
|
if ( error4code( i4->codeBase ) < 0 )
|
|
return e4codeBase ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
#ifdef N4OTHER
|
|
rc = i4update( i4 ) ;
|
|
#else
|
|
rc = index4update( i4->indexFile ) ;
|
|
#endif
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
#endif
|
|
|
|
rc = i4checkBlocks( i4 ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
for( tagOn = 0 ;; )
|
|
{
|
|
tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
|
|
if ( tagOn == 0 )
|
|
return 0 ;
|
|
#ifdef S4HAS_DESCENDING
|
|
oldDesc = tagOn->tagFile->header.descending ;
|
|
tagOn->tagFile->header.descending = 0 ; /* force ascending */
|
|
rc = t4check( tagOn ) ;
|
|
tagOn->tagFile->header.descending = (short)oldDesc ; /* return to previous */
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
#else
|
|
rc = t4check( tagOn ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#endif /* S4INDEX_OFF */
|
|
|
|
#ifdef P4ARGS_USED
|
|
#pragma argsused
|
|
#endif
|
|
int S4FUNCTION d4check( DATA4 *d4 )
|
|
{
|
|
#ifdef S4INDEX_OFF
|
|
return 0 ;
|
|
#else
|
|
INDEX4 *indexOn ;
|
|
int rc ;
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( d4 == 0 )
|
|
return error4( 0, e4parm_null, E95702 ) ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( d4, 1 ) ;
|
|
if ( rc != 0 ) /* either an error or r4unique */
|
|
return rc ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_MULTI
|
|
#ifdef S4SERVER
|
|
rc = dfile4lockFile( d4->dataFile, data4clientId( d4 ), data4serverId( d4 ) ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#else
|
|
rc = d4lockFile( d4 ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
#endif
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_TRAN
|
|
rc = tran4active( d4->codeBase, d4 ) ;
|
|
if ( rc != 0 )
|
|
return error4( d4->codeBase, rc, E81517 ) ;
|
|
#endif
|
|
|
|
for( indexOn = 0 ;; )
|
|
{
|
|
indexOn = (INDEX4 *)l4next( &d4->indexes, indexOn ) ;
|
|
if ( indexOn == 0 )
|
|
return 0 ;
|
|
rc = i4check( indexOn ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
}
|
|
#endif /* S4INDEX_OFF */
|
|
}
|
|
|
|
#endif /* S4CLIENT */
|