1408 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1408 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* r4reindx.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| #ifndef S4INDEX_OFF
 | |
| #ifdef N4OTHER
 | |
| 
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif  /* __TURBOC__ */
 | |
| #endif  /* S4UNIX */
 | |
| 
 | |
| #include "r4reinde.h"
 | |
| 
 | |
| #ifdef S4NDX
 | |
|    B4KEY_DATA *r4key( R4BLOCK_DATA *r4, int i, int keylen)
 | |
|    {
 | |
|       return (B4KEY_DATA *)( &r4->info + i * keylen ) ;
 | |
|    }
 | |
| #endif  /* S4NDX */
 | |
| 
 | |
| #ifdef S4CLIPPER
 | |
|    /* CLIPPER */
 | |
| 
 | |
|    #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
|    B4KEY_DATA   *r4key( R4BLOCK_DATA *r4, int i, int keylen)
 | |
|    {
 | |
|       return (B4KEY_DATA *)( (char *)&r4->nKeys + r4->blockIndex[i] ) ;
 | |
|    }
 | |
| #endif  /* S4CLIPPER */
 | |
| 
 | |
| int S4FUNCTION i4reindex( INDEX4 *i4 )
 | |
| {
 | |
|    int rc ;
 | |
|    TAG4 *tagOn ;
 | |
|    DATA4 *data ;
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          int hasOpt ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E92101 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0  )
 | |
|          return error4( 0, e4parm_null, E92101 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    data = i4->data ;
 | |
| 
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          hasOpt = i4->codeBase->hasOpt && i4->codeBase->opt.numBuffers ;
 | |
|          if ( hasOpt )
 | |
|             code4optSuspend( i4->codeBase ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       rc = d4lockAll( data ) ;
 | |
|       if ( rc )
 | |
|          return rc ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       /* reindex is allowed, but need to fix-up any unique settings */
 | |
|       i4deleteRemoveKeys( i4 ) ;
 | |
| /*      if ( code4transEnabled( c4 ) )
 | |
|          if ( tran4active( c4, data ) != 0 )
 | |
|             return error4( c4, e4transViolation, E81520 ) ;
 | |
| */
 | |
|    #endif
 | |
| 
 | |
|    for( tagOn = 0 ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
| 
 | |
|       rc = expr4context( tagOn->tagFile->expr, data ) ;
 | |
|       if ( rc < 0 )
 | |
|          return rc ;
 | |
|       if ( tagOn->tagFile->filter != 0 )
 | |
|       {
 | |
|          rc = expr4context( tagOn->tagFile->filter, data ) ;
 | |
|          if ( rc < 0 )
 | |
|             return rc ;
 | |
|       }
 | |
| 
 | |
|       rc = t4reindex( tagOn ) ;
 | |
|       if ( rc )
 | |
|          return rc ;
 | |
|    }
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          if ( hasOpt )
 | |
|             code4optRestart( i4->codeBase ) ;
 | |
|       #endif
 | |
|    #endif
 | |
|    data->recNum = -1 ;
 | |
|    data->recNumOld = -1 ;
 | |
|    memset( data->record, ' ', dfile4recWidth( data->dataFile ) ) ;
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int t4reindex( TAG4 *t4 )
 | |
| {
 | |
|    R4REINDEX reindex ;
 | |
|    INDEX4 *i4 ;
 | |
|    int rc ;
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          int hasOpt ;
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifdef S4CLIPPER
 | |
|       B4KEY_DATA *bdata ;
 | |
|       int i ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( t4->tagFile->codeBase ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    i4 = t4->index ;
 | |
| 
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          hasOpt = i4->codeBase->hasOpt && i4->codeBase->opt.numBuffers ;
 | |
|          if ( hasOpt )
 | |
|             code4optSuspend( i4->codeBase ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       {
 | |
|          rc = d4lockIndex( i4->data ) ;
 | |
|          if ( rc )
 | |
|             return rc  ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( r4reindexInit( &reindex, t4 ) < 0 )
 | |
|       return -1 ;
 | |
|    if ( r4reindexTagHeadersCalc( &reindex, t4->tagFile ) < 0 )
 | |
|       return -1 ;
 | |
|    if ( r4reindexBlocksAlloc( &reindex ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       reindex.nBlocksUsed = 0 ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    rc = r4reindexSupplyKeys( &reindex, t4->tagFile ) ;
 | |
|    if ( rc < 0 )
 | |
|    {
 | |
|       r4reindexFree( &reindex ) ;
 | |
|       return rc ;
 | |
|    }
 | |
| 
 | |
|    rc = r4reindexWriteKeys( &reindex, t4->tagFile, t4unique( t4 ) ) ;
 | |
|    if ( rc )
 | |
|    {
 | |
|       r4reindexFree( &reindex ) ;
 | |
|       return rc ;
 | |
|    }
 | |
| 
 | |
|    rc = r4reindexTagHeadersWrite( &reindex, t4->tagFile ) ;
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       if ( rc )
 | |
|          return rc ;
 | |
| 
 | |
|       #ifdef E4MISC
 | |
|          t4->tagFile->checkEof = file4len( &t4->tagFile->file ) - B4BLOCK_SIZE ;  /* reset verify eof variable */
 | |
|       #endif
 | |
| 
 | |
|       t4->index->codeBase->doIndexVerify = 0 ;  /* avoid verify errors due to our partial removal */
 | |
|       tfile4bottom( t4->tagFile ) ;
 | |
|       tfile4balance( t4->tagFile, tfile4block( t4->tagFile ), 1 ) ;
 | |
|       t4->index->codeBase->doIndexVerify = 1 ;
 | |
| 
 | |
|       if ( reindex.stranded )   /* add stranded entry */
 | |
|          tfile4add( t4->tagFile, (unsigned char *)reindex.stranded->value, reindex.stranded->num, t4unique( t4 ) ) ;
 | |
| 
 | |
|       /* and also add any extra block members */
 | |
|       if ( reindex.startBlock->nKeys < t4->tagFile->header.keysHalf && reindex.nBlocksUsed > 1 )
 | |
|       {
 | |
|          for ( i = 0 ; i < reindex.startBlock->nKeys ; i++ )
 | |
|          {
 | |
|             bdata = r4key( reindex.startBlock, i, t4->tagFile->header.keyLen ) ;
 | |
|             tfile4add( t4->tagFile, (unsigned char *)bdata->value, bdata->num, t4unique( t4 ) ) ;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       tfile4update( t4->tagFile ) ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    r4reindexFree( &reindex ) ;
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       #ifdef S4LOW_MEMORY
 | |
|          if ( hasOpt )
 | |
|             code4optRestart( i4->codeBase ) ;
 | |
|       #endif
 | |
|    #endif
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| int r4reindexInit( R4REINDEX *r4, TAG4 *t4 )
 | |
| {
 | |
|    INDEX4 *i4 ;
 | |
| 
 | |
|    i4 = t4->index ;
 | |
| 
 | |
|    memset( r4, 0, sizeof( R4REINDEX ) ) ;
 | |
| 
 | |
|    r4->data = t4->index->data ;
 | |
|    r4->codeBase = t4->tagFile->codeBase ;
 | |
| 
 | |
|    r4->minKeysmax = INT_MAX ;
 | |
|    r4->startBlock = 0 ;
 | |
|    r4->sort.file.hand = -1 ;
 | |
| 
 | |
|    r4->bufferLen = i4->codeBase->memSizeSortBuffer ;
 | |
|    if ( r4->bufferLen < 1024 )
 | |
|       r4->bufferLen = 1024 ;
 | |
| 
 | |
|    r4->buffer = (char *)u4allocEr( r4->codeBase, r4->bufferLen ) ;
 | |
|    if ( r4->buffer == 0 )
 | |
|       return e4memory ;
 | |
| 
 | |
|    r4->tag = t4->tagFile ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| void r4reindexFree( R4REINDEX *r4 )
 | |
| {
 | |
|    u4free( r4->buffer ) ;
 | |
|    u4free( r4->startBlock ) ;
 | |
|    sort4free( &r4->sort ) ;
 | |
| }
 | |
| 
 | |
| int r4reindexBlocksAlloc( R4REINDEX *r4 )
 | |
| {
 | |
|    long onCount ;
 | |
|    #ifdef S4CLIPPER
 | |
|       long numSub ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( (unsigned) r4->minKeysmax > INT_MAX )
 | |
|          return error4( 0, e4struct, E92102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    /* Calculate the block stack height */
 | |
|    onCount = d4recCount( r4->data ) ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       if ( onCount < 0 )
 | |
|          return error4( r4->codeBase, (short int)onCount, E92102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4NDX
 | |
|       for ( r4->nBlocks = 2; onCount; r4->nBlocks++ )
 | |
|          onCount /= r4->minKeysmax ;
 | |
|       r4->startBlock = (R4BLOCK_DATA *)u4alloc( (long) B4BLOCK_SIZE * r4->nBlocks ) ;
 | |
|    #endif  /* S4NDX */
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       numSub = r4->minKeysmax ;
 | |
|       for ( r4->nBlocks = 0 ; onCount > 0L ; r4->nBlocks++ )
 | |
|       {
 | |
|          onCount -= numSub ;
 | |
|          numSub *= r4->minKeysmax ;
 | |
|       }
 | |
|       r4->nBlocks ++ ;
 | |
|       if( r4->nBlocks < 2 )
 | |
|          r4->nBlocks = 2 ;
 | |
|       r4->startBlock = (R4BLOCK_DATA *) u4alloc( (long) ( B4BLOCK_SIZE + 2 * sizeof( void *) ) * r4->nBlocks ) ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    if ( r4->startBlock == 0 )
 | |
|       return error4( r4->codeBase, e4memory, E82105 ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int r4reindexSupplyKeys( R4REINDEX *r4, TAG4FILE *t4 )
 | |
| {
 | |
|    FILE4SEQ_READ seqRead ;
 | |
|    EXPR4 *filter ;
 | |
|    char *keyResult ;
 | |
|    int rc, *filterResult ;
 | |
|    long count, iRec ;
 | |
|    DATA4 *d4 ;
 | |
|    DATA4FILE *d4file ;
 | |
|    #ifndef S4MEMO_OFF
 | |
|       int i ;
 | |
|    #endif
 | |
| 
 | |
|    d4 = r4->data ;
 | |
|    d4file = d4->dataFile ;
 | |
|    #ifdef E4MISC
 | |
|       r4->keyCount = 0L ;
 | |
|    #endif
 | |
| 
 | |
|    if ( sort4init( &r4->sort, r4->codeBase, t4->header.keyLen, 0 ) < 0 )
 | |
|       return -1 ;
 | |
|    r4->sort.cmp = t4->cmp ;
 | |
| 
 | |
|    rc = expr4context( r4->tag->expr, d4 ) ;
 | |
|    if ( rc < 0 )
 | |
|       return rc ;
 | |
|    if ( r4->tag->filter != 0 )
 | |
|    {
 | |
|       rc = expr4context( r4->tag->filter, d4 ) ;
 | |
|       if ( rc < 0 )
 | |
|          return rc ;
 | |
|    }
 | |
| 
 | |
|    filter = t4->filter ;
 | |
|    count = dfile4recCount( d4file, -2L ) ;
 | |
|    if ( count < 0 )
 | |
|       return error4stack( r4->codeBase, (short)rc, E92102 ) ;
 | |
| 
 | |
|    #ifdef S4ADVANCE_READ
 | |
|       file4seqReadInitDo( &seqRead, &d4file->file, dfile4recordPosition( d4file, 1L ), r4->buffer, r4->bufferLen, 1 ) ;
 | |
|    #else
 | |
|       file4seqReadInit( &seqRead, &d4file->file, dfile4recordPosition( d4file, 1L ), r4->buffer, r4->bufferLen ) ;
 | |
|    #endif
 | |
| 
 | |
|    for ( iRec = 1L; iRec <= count; iRec++ )
 | |
|    {
 | |
|       if ( file4seqReadAll( &seqRead, d4->record, dfile4recWidth( d4file ) ) < 0 )
 | |
|          return -1 ;
 | |
|       d4->recNum = iRec ;
 | |
| 
 | |
|       #ifndef S4MEMO_OFF
 | |
|          for ( i = 0; i < d4file->nFieldsMemo; i++ )
 | |
|             f4memoReset( d4->fieldsMemo[i].field ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( filter )
 | |
|       {
 | |
|          rc = expr4vary( filter, (char **)&filterResult ) ;
 | |
|          if ( rc < 0 )
 | |
|          {
 | |
|             #ifdef S4ADVANCE_READ
 | |
|                file4seqReadInitUndo( &seqRead ) ;
 | |
|             #endif
 | |
|             return error4stack( r4->codeBase, (short)rc, E92102 ) ;
 | |
|          }
 | |
|          #ifdef E4MISC
 | |
|             if ( expr4type( filter ) != r4log )
 | |
|             {
 | |
|                #ifdef S4ADVANCE_READ
 | |
|                   file4seqReadInitUndo( &seqRead ) ;
 | |
|                #endif
 | |
|                return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|             }
 | |
|          #endif  /* E4MISC */
 | |
|          if ( ! *filterResult )
 | |
|             continue ;
 | |
|          t4->hasKeys = 1 ;
 | |
|          #ifdef S4MDX
 | |
|             t4->hadKeys = 0 ;
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       tfile4exprKey( t4, (unsigned char **)&keyResult ) ;
 | |
| 
 | |
|       if ( sort4put( &r4->sort, iRec, keyResult, "" ) < 0)
 | |
|       {
 | |
|          #ifdef S4ADVANCE_READ
 | |
|             file4seqReadInitUndo( &seqRead ) ;
 | |
|          #endif
 | |
|          return -1 ;
 | |
|       }
 | |
|       #ifdef E4MISC
 | |
|          r4->keyCount++ ;
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    #ifdef S4ADVANCE_READ
 | |
|       file4seqReadInitUndo( &seqRead ) ;
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifdef S4NDX
 | |
| /* NDX */
 | |
| int  r4reindexTagHeadersCalc( R4REINDEX *r4, TAG4FILE *t4 )
 | |
| {
 | |
|    if ( tfile4freeAll( t4 ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    t4->header.keyLen = expr4keyLen( t4->expr ) ;
 | |
|    if ( t4->header.keyLen < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    t4->header.type = (char)expr4type( t4->expr ) ;
 | |
|    if ( t4->header.type == r4date_doub )
 | |
|       t4->header.type = r4date ;
 | |
|    if ( t4->header.type == r4num_doub )
 | |
|       t4->header.type = r4num ;
 | |
|    if ( t4->header.type < 0 )
 | |
|       return -1 ;
 | |
|    t4initSeekConv( t4, t4->header.type ) ;
 | |
|    t4->header.groupLen = t4->header.keyLen + 3*sizeof(long) - t4->header.keyLen % sizeof(long) ;
 | |
|    if ( t4->header.keyLen%sizeof(long) == 0 )
 | |
|       t4->header.groupLen -= sizeof(long) ;
 | |
|    t4->header.int_or_date = ( t4->header.type == r4num || t4->header.type == r4date );
 | |
|    t4->header.keysMax = ( B4BLOCK_SIZE - 2*sizeof(long)) / t4->header.groupLen ;
 | |
| 
 | |
|    if ( t4->header.keysMax < r4->minKeysmax )
 | |
|       r4->minKeysmax = t4->header.keysMax ;
 | |
| 
 | |
|    r4->lastblockInc = B4BLOCK_SIZE / 512 ;
 | |
|    r4->lastblock = 0 ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* NDX */
 | |
| int r4reindexTagHeadersWrite( R4REINDEX *r4, TAG4FILE *t4 )
 | |
| {
 | |
|    int len ;
 | |
|    char *ptr ;
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       I4IND_HEAD_WRITE *swap ;
 | |
|    #endif
 | |
| 
 | |
|    /* Now write the headers */
 | |
|    file4seqWriteInit( &r4->seqwrite, &t4->file, 0L, r4->buffer, r4->bufferLen ) ;
 | |
| 
 | |
|    if ( t4->header.type == r4num )
 | |
|       t4->header.type = r4float ;
 | |
| 
 | |
|    t4->header.eof = r4->lastblock + r4->lastblockInc ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       swap = (I4IND_HEAD_WRITE *)u4allocEr( t4->codeBase, sizeof( I4IND_HEAD_WRITE ) ) ;
 | |
|       if ( swap == 0 )
 | |
|          return -1 ;
 | |
|       swap->root = x4reverseLong( (void *)&t4->header.root ) ;
 | |
|       swap->eof = x4reverseLong( (void *)&t4->header.eof ) ;
 | |
|       swap->keyLen = x4reverseShort( (void *)&t4->header.keyLen ) ;
 | |
|       swap->keysMax = x4reverseShort( (void *)&t4->header.keysMax ) ;
 | |
|       swap->int_or_date = x4reverseShort( (void *)&t4->header.int_or_date ) ;
 | |
|       swap->groupLen = x4reverseShort( (void *)&t4->header.groupLen ) ;
 | |
|       swap->dummy = x4reverseShort( (void *)&t4->header.dummy ) ;
 | |
|       swap->unique = x4reverseShort( (void *)&t4->header.unique ) ;
 | |
| 
 | |
|       file4seqWrite( &r4->seqwrite, swap, sizeof(I4IND_HEAD_WRITE) ) ;
 | |
|       u4free( swap ) ;
 | |
|    #else
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.root, sizeof(I4IND_HEAD_WRITE) ) ;
 | |
|    #endif
 | |
| 
 | |
|    ptr = t4->expr->source ;
 | |
|    len = strlen(ptr) ;
 | |
|    if ( len > I4MAX_EXPR_SIZE )
 | |
|       return error4( r4->codeBase, e4index, E82106 ) ;
 | |
|    file4seqWrite( &r4->seqwrite, ptr, len) ;
 | |
| 
 | |
|    file4seqWriteRepeat( &r4->seqwrite, 1, ' ' ) ;
 | |
|    file4seqWriteRepeat( &r4->seqwrite, I4MAX_EXPR_SIZE - len, 0 ) ;
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       t4->header.version = x4reverseLong( (void *)&t4->header.version ) ;
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.version, sizeof( t4->header.version ) ) ;
 | |
|       t4->header.version = x4reverseLong( (void *)&t4->header.version ) ;
 | |
|    #else
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.version, sizeof( t4->header.version ) ) ;
 | |
|    #endif
 | |
| 
 | |
|    file4seqWriteRepeat( &r4->seqwrite, B4BLOCK_SIZE - (r4->seqwrite.working - r4->seqwrite.avail) , 0 ) ;
 | |
| 
 | |
|    if ( file4seqWriteFlush(&r4->seqwrite) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    file4lenSet( &t4->file, t4->header.eof * 512) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4NDX */
 | |
| 
 | |
| #ifdef S4CLIPPER
 | |
| /* CLIPPER */
 | |
| int  r4reindexTagHeadersCalc( R4REINDEX *r4, TAG4FILE *t4 )
 | |
| {
 | |
|    int exprType ;
 | |
| 
 | |
|    if ( tfile4freeAll( t4 ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
| /*   if ( t4->header.keyLen != 0 )*/
 | |
| /*      t4->expr->keyLen = t4->header.keyLen ;*/
 | |
| /*   else*/
 | |
|       t4->header.keyLen = t4->expr->keyLen = expr4keyLen( t4->expr ) ;
 | |
|    t4->expr->keyDec = t4->header.keyDec ;
 | |
|    if( t4->header.keyLen < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
| 
 | |
|    exprType = expr4type( t4->expr ) ;
 | |
|    if ( exprType < 0 )
 | |
|       return exprType ;
 | |
|    tfile4initSeekConv( t4, exprType ) ;
 | |
|    t4->header.groupLen = t4->header.keyLen+8 ;
 | |
|    r4->keysHalf = t4->header.keysHalf = (1020/ (t4->header.groupLen+2) - 1)/ 2;
 | |
|    t4->header.sign   = 6 ;
 | |
|    t4->header.keysMax  = t4->header.keysHalf * 2 ;
 | |
|    if ( t4->header.keysMax < 2 )
 | |
|       return error4( t4->codeBase, e4info, E81601 ) ;
 | |
| 
 | |
|    if ( t4->header.keysMax < r4->minKeysmax )
 | |
|       r4->minKeysmax = t4->header.keysMax ;
 | |
| 
 | |
|    r4->lastblockInc = B4BLOCK_SIZE / 512 ;
 | |
|    r4->lastblock = 0 ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* CLIPPER */
 | |
| int r4reindexTagHeadersWrite( R4REINDEX *r4, TAG4FILE *t4 )
 | |
| {
 | |
|    int len ;
 | |
|    const char *ptr ;
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       I4IND_HEAD_WRITE *swap ;
 | |
|    #endif
 | |
| 
 | |
|    /* Now write the headers */
 | |
|    file4seqWriteInit( &r4->seqwrite, &t4->file, 0L, r4->buffer, r4->bufferLen ) ;
 | |
| 
 | |
|    t4->header.eof = 0 ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       swap = (I4IND_HEAD_WRITE *) t4->codeBase, u4allocEr( sizeof(I4IND_HEAD_WRITE ) ) ;
 | |
|       if ( swap == 0 )
 | |
|          return -1 ;
 | |
|       swap->sign = x4reverseShort( (void *)&t4->header.sign ) ;
 | |
|       swap->version = x4reverseShort( (void *)&t4->header.version ) ;
 | |
|       swap->root = x4reverseLong( (void *)&t4->header.root ) ;
 | |
|       swap->eof = x4reverseLong( (void *)&t4->header.eof ) ;
 | |
|       swap->groupLen = x4reverseShort( (void *)&t4->header.groupLen ) ;
 | |
|       swap->keyLen = x4reverseShort( (void *)&t4->header.keyLen ) ;
 | |
|       swap->keyDec = x4reverseShort( (void *)&t4->header.keyDec ) ;
 | |
|       swap->keysMax = x4reverseShort( (void *)&t4->header.keysMax ) ;
 | |
|       swap->keysHalf = x4reverseShort( (void *)&t4->header.keysHalf ) ;
 | |
| 
 | |
|       #ifdef S4UNIX
 | |
|          file4seqWrite( &r4->seqwrite, swap, sizeof(I4IND_HEAD_WRITE) - sizeof(short) ) ;
 | |
|       #else
 | |
|          file4seqWrite( &r4->seqwrite, swap, sizeof(I4IND_HEAD_WRITE) ) ;
 | |
|       #endif
 | |
|       u4free( swap ) ;
 | |
|    #else
 | |
|       #ifdef S4UNIX
 | |
|          file4seqWrite( &r4->seqwrite, &t4->header.sign, sizeof(I4IND_HEAD_WRITE) - sizeof(short) ) ;
 | |
|       #else
 | |
|          file4seqWrite( &r4->seqwrite, &t4->header.sign, sizeof(I4IND_HEAD_WRITE) ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    ptr = t4->expr->source ;
 | |
|    len = strlen(ptr) ;
 | |
|    if ( len > I4MAX_EXPR_SIZE )
 | |
|       return error4( r4->codeBase, e4index, E82106 ) ;
 | |
| 
 | |
|    file4seqWrite( &r4->seqwrite, ptr, len) ;
 | |
|    file4seqWriteRepeat( &r4->seqwrite, I4MAX_EXPR_SIZE - len, 0 ) ;
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       t4->header.unique = x4reverseLong( (void *)&t4->header.unique ) ;
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.unique, sizeof( t4->header.unique ) ) ;
 | |
|       t4->header.unique = x4reverseLong( (void *)&t4->header.unique ) ;
 | |
|    #else
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.unique, sizeof( t4->header.unique ) ) ;
 | |
|    #endif
 | |
| 
 | |
|    file4seqWriteRepeat( &r4->seqwrite, 1, (char)0 ) ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       t4->header.descending = x4reverseLong( (void *)&t4->header.descending ) ;
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.descending, sizeof( t4->header.descending ) ) ;
 | |
|       t4->header.descending = x4reverseLong( (void *)&t4->header.descending ) ;
 | |
|    #else
 | |
|       file4seqWrite( &r4->seqwrite, &t4->header.descending, sizeof( t4->header.descending ) ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( t4->filter != 0 )
 | |
|    {
 | |
|       ptr = t4->filter->source ;
 | |
|       len = strlen(ptr) ;
 | |
| 
 | |
|       file4seqWrite( &r4->seqwrite, ptr, len) ;
 | |
|       file4seqWriteRepeat( &r4->seqwrite, I4MAX_EXPR_SIZE - len, 0 ) ;
 | |
|    }
 | |
|    else
 | |
|       file4seqWriteRepeat( &r4->seqwrite, I4MAX_EXPR_SIZE, 0 ) ;
 | |
| 
 | |
|    file4seqWriteRepeat( &r4->seqwrite, B4BLOCK_SIZE - (r4->seqwrite.working - r4->seqwrite.avail) , 0 ) ;
 | |
| 
 | |
|    if ( file4seqWriteFlush(&r4->seqwrite) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    file4lenSet( &t4->file, (r4->lastblock + r4->lastblockInc) * 512) ;
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4CLIPPER */
 | |
| 
 | |
| int r4reindexWriteKeys( R4REINDEX *r4, TAG4FILE *t4, short int errUnique )
 | |
| {
 | |
|    char  lastKey[I4MAX_KEY_SIZE] ;
 | |
|    unsigned char *keyData ;
 | |
|    int   isUnique, rc, isFirst ;
 | |
|    void *dummyPtr ;
 | |
|    long  keyRec ;
 | |
| 
 | |
|    r4->grouplen = t4->header.groupLen ;
 | |
|    r4->valuelen = t4->header.keyLen ;
 | |
|    r4->keysmax  = t4->header.keysMax ;
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       memset( r4->startBlock, 0, (int)(( (long)B4BLOCK_SIZE + 2 * sizeof( void *) ) * r4->nBlocks) ) ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    #ifdef S4NDX
 | |
|       memset( r4->startBlock, 0, r4->nBlocks*B4BLOCK_SIZE ) ;
 | |
|    #endif  /* S4NDX */
 | |
| 
 | |
|    if ( sort4getInit( &r4->sort ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    file4seqWriteInit( &r4->seqwrite, &t4->file, (r4->lastblock+r4->lastblockInc)*512, r4->buffer,r4->bufferLen) ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       if ( I4MAX_KEY_SIZE < r4->sort.sortLen )
 | |
|          return error4( r4->codeBase, e4info, E82102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    memset( lastKey, 0, sizeof(lastKey) ) ;
 | |
|    isUnique = t4->header.unique ;
 | |
| 
 | |
|    isFirst = 1 ;
 | |
| 
 | |
|    for(;;)  /* For each key to write */
 | |
|    {
 | |
|       if ( (rc = sort4get( &r4->sort, &keyRec, (void **) &keyData, &dummyPtr)) < 0)  return -1 ;
 | |
| 
 | |
|       #ifdef E4MISC
 | |
|          if ( r4->keyCount < 0L  ||  r4->keyCount == 0L && rc != 1 ||  r4->keyCount > 0L && rc == 1 )
 | |
|             return error4( r4->codeBase, e4info, E92102 ) ;
 | |
|          r4->keyCount-- ;
 | |
|       #endif
 | |
| 
 | |
|       if ( rc == 1 )  /* No more keys */
 | |
|       {
 | |
|          if ( r4reindexFinish( r4 ) < 0 )
 | |
|             return -1 ;
 | |
|          if ( file4seqWriteFlush( &r4->seqwrite ) < 0 )
 | |
|             return -1 ;
 | |
|          break ;
 | |
|       }
 | |
| 
 | |
|       if ( isUnique )
 | |
|       {
 | |
|          if( isFirst )
 | |
|             isFirst = 0 ;
 | |
|          else
 | |
|             if ( (*t4->cmp)( keyData, lastKey, r4->sort.sortLen) == 0 )
 | |
|             {
 | |
|                switch( errUnique )
 | |
|                {
 | |
|                   case e4unique:
 | |
|                      return error4describe( r4->codeBase, e4unique, E82103, t4->alias, (char *)0, 0 ) ;
 | |
| 
 | |
|                   case r4unique:
 | |
|                      return r4unique ;
 | |
| 
 | |
|                   default:
 | |
|                      continue ;
 | |
|                }
 | |
|             }
 | |
| 
 | |
|          memcpy( lastKey, keyData, r4->sort.sortLen ) ;
 | |
|       }
 | |
| 
 | |
|       /* Add the key */
 | |
|       if ( r4reindexAdd( r4, keyRec, keyData) < 0 )
 | |
|          return -1 ;
 | |
|    }
 | |
| 
 | |
|    /* Now complete the tag header info. */
 | |
|    #ifdef S4NDX
 | |
|       t4->header.root = r4->lastblock ;
 | |
|    #endif  /* S4NDX */
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       t4->header.root = r4->lastblock * 512 ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int r4reindexAdd( R4REINDEX *r4, const long rec, const unsigned char *keyValue )
 | |
| {
 | |
|    B4KEY_DATA *keyTo ;
 | |
|    R4BLOCK_DATA *startBlock ;
 | |
|    #ifdef E4MISC
 | |
|       long  dif ;
 | |
|    #endif
 | |
|    #ifdef S4CLIPPER
 | |
|       short offset ;
 | |
|       int i ;
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    startBlock = r4->startBlock ;
 | |
| 
 | |
|    /* for NTX, if keysmax, then todisk() with the latest value... */
 | |
| 
 | |
|    #ifdef S4NDX
 | |
|       if ( startBlock->nKeys >= r4->keysmax )
 | |
|       {
 | |
|          if ( r4reindexTodisk(r4) < 0 )
 | |
|             return -1 ;
 | |
|          memset( startBlock, 0, B4BLOCK_SIZE ) ;
 | |
|       }
 | |
|    #endif  /* S4NDX */
 | |
| 
 | |
|    #ifdef S4CLIPPER
 | |
|       if ( startBlock->nKeys == 0 )   /* first, so add references */
 | |
|       {
 | |
|          offset = ( r4->keysmax + 2 + ( ( r4->keysmax / 2 ) * 2 != r4->keysmax ) ) * sizeof(short) ;
 | |
|          startBlock->blockIndex = &startBlock->nKeys + 1 ;  /* 1 short off of nKeys */
 | |
|          for ( i = 0 ; i <= r4->keysmax ; i++ )
 | |
|              startBlock->blockIndex[i] = r4->grouplen * i + offset ;
 | |
|          startBlock->data = (char *)&startBlock->nKeys + startBlock->blockIndex[0] ;  /* first entry */
 | |
|       }
 | |
|       if ( startBlock->nKeys >= r4->keysmax )
 | |
|       {
 | |
|          if ( r4reindexTodisk( r4, rec, (const char*)keyValue ) < 0 )
 | |
|             return -1 ;
 | |
|          memset( startBlock, 0, B4BLOCK_SIZE + 2 * sizeof( void *) ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif  /* S4CLIPPER */
 | |
| 
 | |
|    keyTo = r4key( startBlock, startBlock->nKeys++, r4->grouplen ) ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       dif = (char *)keyTo -  (char *)startBlock ;
 | |
|       if ( dif + r4->grouplen > B4BLOCK_SIZE || dif < 0 )
 | |
|          return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|    #endif
 | |
|    keyTo->num = rec ;
 | |
|    memcpy( keyTo->value, keyValue, r4->valuelen ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifdef S4NDX
 | |
| /* NDX */
 | |
| int r4reindexFinish( R4REINDEX *r4 )
 | |
| {
 | |
|    B4KEY_DATA *keyTo ;
 | |
|    #ifdef E4MISC
 | |
|       long dif ;
 | |
|    #endif
 | |
|    int iBlock = 1 ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       char *swap, *swap_ptr ;
 | |
|       int j ;
 | |
|       long long_val ;
 | |
|       short short_val ;
 | |
|    #endif
 | |
| 
 | |
|    R4BLOCK_DATA *block = r4->startBlock ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       swap = (char *)u4allocEr( r4->tag->codeBase, B4BLOCK_SIZE ) ;
 | |
|       if ( swap == 0 )
 | |
|          return -1 ;
 | |
| 
 | |
|       memcpy( (void *)swap, (void *)&r4->startBlock->nKeys, B4BLOCK_SIZE ) ;
 | |
| 
 | |
|       /* position swap_ptr at beginning of pointers */
 | |
|       swap_ptr += swap + 2 + sizeof(short) ;
 | |
| 
 | |
|       for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | |
|       {
 | |
|          long_val = x4reverseLong( (void *)swap_ptr ) ;
 | |
|          memcpy( swap_ptr, (void *) &long_val, sizeof(long) ) ;
 | |
|          long_val = x4reverseLong( (void *)(swap_ptr+sizeof(long)) ) ;
 | |
|          memcpy( swap_ptr+sizeof(long), (void *) &long_val, sizeof(long) ) ;
 | |
|          swap_ptr += r4->groupLen ;
 | |
|       }
 | |
| 
 | |
|       long_val = x4reverseLong( (void *)swap_ptr ) ;
 | |
|       memcpy( swap_ptr, (void *) &long_val, sizeof(long) ) ;
 | |
| 
 | |
|       short_val = x4reverseShort( (void *)swap ) ;
 | |
|       memcpy( swap, (void *) &short_val, sizeof(short) ) ;
 | |
| 
 | |
|       if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|          return -1 ;
 | |
|       u4free( swap ) ;
 | |
|    #else
 | |
|       if ( file4seqWrite(&r4->seqwrite, &r4->startBlock->nKeys, B4BLOCK_SIZE) < 0 ) return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    r4->lastblock += r4->lastblockInc ;
 | |
|    block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE ) ;
 | |
|    for(; iBlock < r4->nBlocks; iBlock++ )
 | |
|    {
 | |
|       if ( block->nKeys >= 1 )
 | |
|       {
 | |
|          keyTo = r4key( block, block->nKeys, r4->grouplen ) ;
 | |
|          #ifdef E4MISC
 | |
|             dif = (char *)keyTo - (char *)block ;
 | |
|             if ( dif + sizeof(long) > B4BLOCK_SIZE || dif < 0 )
 | |
|                return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|          #endif
 | |
|          keyTo->pointer = r4->lastblock ;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             swap = (char *)u4allocEr( r4->tag->codeBase, B4BLOCK_SIZE ) ;
 | |
|             if ( swap == 0 )
 | |
|                return -1 ;
 | |
| 
 | |
|             memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
| 
 | |
|             /* position swap_ptr at beginning of pointers */
 | |
|             swap_ptr += swap + 2 + sizeof(short) ;
 | |
| 
 | |
|             for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | |
|             {
 | |
|                long_val = x4reverseLong( (void *)swap_ptr ) ;
 | |
|                memcpy( swap_ptr, (void *) &longVal, sizeof(long) ) ;
 | |
|                longVal = x4reverseLong( (void *)(swap_ptr+sizeof(long)) ) ;
 | |
|                memcpy( swap_ptr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|                swap_ptr += r4->groupLen ;
 | |
|             }
 | |
| 
 | |
|             longVal = x4reverseLong( (void *)swap_ptr ) ;
 | |
|             memcpy( swap_ptr, (void *) &longVal, sizeof(long) ) ;
 | |
| 
 | |
|             shortVal = x4reverseShort( (void *)swap ) ;
 | |
|             memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|             if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|                return -1 ;
 | |
|             u4free( swap ) ;
 | |
|          #else
 | |
|             if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0 )
 | |
|                return -1;
 | |
|          #endif
 | |
| 
 | |
|          r4->lastblock += r4->lastblockInc ;
 | |
|       }
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE) ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* NDX */
 | |
| int r4reindexTodisk( R4REINDEX *r4 )
 | |
| {
 | |
|    R4BLOCK_DATA *block ;
 | |
|    int iBlock ;
 | |
|    B4KEY_DATA *keyOn, *keyto ;
 | |
|    #ifdef E4MISC
 | |
|       long dif ;
 | |
|    #endif
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       char *swap, *swap_ptr ;
 | |
|       int i ;
 | |
|       long longVal ;
 | |
|       short shortVal ;
 | |
|    #endif
 | |
| 
 | |
|    /* Writes out the current block and adds references to higher blocks */
 | |
|    block  = r4->startBlock ;
 | |
|    iBlock= 0 ;
 | |
| 
 | |
|    keyOn = r4key( block, block->nKeys-1, r4->grouplen ) ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       dif = (char *) keyOn -  (char *) block ;
 | |
|       if ( dif+ r4->grouplen > B4BLOCK_SIZE || dif < 0 )
 | |
|          return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for(;;)
 | |
|    {
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          swap = (char *)u4allocEr( r4->tag->codeBase, B4BLOCK_SIZE ) ;
 | |
|          if ( swap == 0 )
 | |
|             return -1 ;
 | |
| 
 | |
|          memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
|                           /* position swap_ptr at beginning of pointers */
 | |
| 
 | |
|          swap_ptr += swap + 2 + sizeof(short) ;
 | |
| 
 | |
|          for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | |
|          {
 | |
|             longVal = x4reverseLong( (void *)swap_ptr ) ;
 | |
|             memcpy( swap_ptr, (void *) &longVal, sizeof(long) ) ;
 | |
|             longVal = x4reverseLong( (void *)(swap_ptr+sizeof(long)) ) ;
 | |
|             memcpy( swap_ptr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|             swap_ptr += r4->groupLen ;
 | |
|          }
 | |
| 
 | |
|          longVal = x4reverseLong( (void *)swap_ptr ) ;
 | |
|          memcpy( swap_ptr, (void *) &longVal, sizeof(long) ) ;
 | |
| 
 | |
|          shortVal = x4reverseShort( (void *)swap ) ;
 | |
|          memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|          if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 ) return -1 ;
 | |
|          u4free( swap ) ;
 | |
|       #else
 | |
|          if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0) return -1;
 | |
|       #endif
 | |
| 
 | |
|       if ( iBlock != 0 )
 | |
|          memset( block, 0, B4BLOCK_SIZE ) ;
 | |
|       r4->lastblock += r4->lastblockInc ;
 | |
| 
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE) ;
 | |
|       iBlock++ ;
 | |
|       #ifdef E4MISC
 | |
|          if ( iBlock >= r4->nBlocks )
 | |
|             return error4( r4->codeBase, e4info, E92102 ) ;
 | |
|       #endif
 | |
| 
 | |
|       keyto = r4key( block, block->nKeys, r4->grouplen) ;
 | |
|       #ifdef E4MISC
 | |
|          dif = (char *) keyto -  (char *) block  ;
 | |
|          if ( dif+sizeof(long) > B4BLOCK_SIZE || dif < 0 )
 | |
|             return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|       #endif
 | |
|       keyto->pointer = r4->lastblock ;
 | |
| 
 | |
|       if ( block->nKeys < r4->keysmax )
 | |
|       {
 | |
|          block->nKeys++ ;
 | |
|          #ifdef E4MISC
 | |
|             if ( dif+r4->grouplen > B4BLOCK_SIZE )
 | |
|                return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|          #endif
 | |
|          memcpy( keyto->value, keyOn->value, r4->valuelen ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    }
 | |
| }
 | |
| #endif  /* S4NDX */
 | |
| 
 | |
| #ifdef S4CLIPPER
 | |
| /* CLIPPER */
 | |
| int r4reindexFinish( R4REINDEX *r4 )
 | |
| {
 | |
|    B4KEY_DATA *keyTo ;
 | |
|    #ifdef E4MISC
 | |
|       long dif ;
 | |
|    #endif
 | |
|    int iBlock = 0, tBlock ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       char *swap, *swapPtr ;
 | |
|       int j ;
 | |
|       long longVal ;
 | |
|       short shortVal ;
 | |
|    #endif
 | |
| 
 | |
|    R4BLOCK_DATA *block = r4->startBlock, *temp_block ;
 | |
| 
 | |
|    short offset ;
 | |
|    int i ;
 | |
|    long pointer ;
 | |
| 
 | |
|    if ( r4->nBlocksUsed <= 1 )  /* empty database if nKeys = 0 */
 | |
|    {
 | |
|       if ( r4->startBlock->nKeys == 0 )   /* first, so add references */
 | |
|       {
 | |
|          offset = ( r4->keysmax + 2 + ( (r4->keysmax/2)*2 != r4->keysmax ) ) * sizeof(short) ;
 | |
|          r4->startBlock->blockIndex = &r4->startBlock->nKeys + 1 ;  /* 1 short off of nKeys */
 | |
|          for ( i = 0 ; i <= r4->keysmax ; i++ )
 | |
|              r4->startBlock->blockIndex[i] = r4->grouplen * i + offset ;
 | |
|          r4->startBlock->data = (char *) &r4->startBlock->nKeys + r4->startBlock->blockIndex[0] ;
 | |
|       }
 | |
|       iBlock ++ ;
 | |
|       r4->stranded = 0 ;
 | |
|       pointer = 0 ;
 | |
| 
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          swap = (char *)u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|          if ( swap == 0 )
 | |
|          {
 | |
|             e4error( r4->codeBase, e4memory, (char *) 0 ) ;
 | |
|             return -1 ;
 | |
|          }
 | |
| 
 | |
|          memcpy( (void *)swap, (void *)&r4->startBlock->nKeys, B4BLOCK_SIZE ) ;
 | |
|                           /* position swapPtr at beginning of pointers */
 | |
| 
 | |
|          shortVal = x4reverseShort( (void *)swap ) ;
 | |
|          memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|          swapPtr = swap + 2 ;
 | |
| 
 | |
|          for ( j = 0 ; j < r4->keysmax ; j++ )
 | |
|          {
 | |
|             shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|             swapPtr += sizeof(short) ;
 | |
|          }
 | |
| 
 | |
|          for ( j = 0 ; j < r4->keysmax ; j++ )
 | |
|          {
 | |
|             longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|             longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|             memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|             swapPtr += r4->grouplen ;
 | |
|          }
 | |
| 
 | |
|          if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|          u4free( swap ) ;
 | |
|       #else
 | |
|          if ( file4seqWrite( &r4->seqwrite, &r4->startBlock->nKeys, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|       #endif
 | |
| 
 | |
|       r4->lastblock += r4->lastblockInc ;
 | |
|    }
 | |
|    else if ( r4->startBlock->nKeys >= r4->keysHalf )
 | |
|    {
 | |
|       /* just grab the pointer for upward placement where belongs */
 | |
|       r4->stranded = 0 ;
 | |
| 
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          swap = (char *) u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|          if ( swap == 0 )
 | |
|             return -1 ;
 | |
| 
 | |
|          memcpy( (void *)swap, (void *)&r4->startBlock->nKeys, B4BLOCK_SIZE ) ;
 | |
|                           /* position swapPtr at beginning of pointers */
 | |
| 
 | |
|          shortVal = x4reverseShort( (void *)swap ) ;
 | |
|          memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|          swapPtr = swap + 2 ;
 | |
|                          /* swap the short pointers to B4KEY_DATA */
 | |
|          for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|          {
 | |
|             shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|             swapPtr += sizeof(short) ;
 | |
|          }
 | |
|                          /* swap the B4KEY_DATA's */
 | |
|          for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|          {
 | |
|             longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|             longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|             memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|             swapPtr += r4->grouplen ;
 | |
|          }
 | |
| 
 | |
|          if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|          u4free( swap ) ;
 | |
|       #else
 | |
|          if ( file4seqWrite( &r4->seqwrite, &r4->startBlock->nKeys, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|       #endif
 | |
| 
 | |
|       r4->lastblock += r4->lastblockInc ;
 | |
|       pointer = r4->lastblock*512 ;
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|       iBlock++ ;
 | |
|    }
 | |
|    else       /* stranded entry, so add after */
 | |
|    {
 | |
|       /* if less than 1/2 entries, will re-add the required keys later... */
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|       iBlock++ ;
 | |
|       while( block->nKeys == 0 && iBlock < r4->nBlocksUsed )
 | |
|       {
 | |
|          block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|          iBlock++ ;
 | |
|       }
 | |
| 
 | |
|       r4->stranded = r4key( block, block->nKeys - 1, 0 ) ;
 | |
|       block->nKeys -- ;
 | |
|       if( block->nKeys > 0 )
 | |
|       {
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             swap = (char *)u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|             if ( swap == 0 )
 | |
|                return -1 ;
 | |
| 
 | |
|             memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
|                              /* position swapPtr at beginning of pointers */
 | |
| 
 | |
|             shortVal = x4reverseShort( (void *)swap ) ;
 | |
|             memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|             swapPtr = swap + 2 ;
 | |
|                             /* swap the short pointers to B4KEY_DATA */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|                swapPtr += sizeof(short) ;
 | |
|             }
 | |
|                             /* swap the B4KEY_DATA's */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|                longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|                memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|                swapPtr += r4->grouplen ;
 | |
|             }
 | |
| 
 | |
|             if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|                return -1 ;
 | |
|             u4free( swap ) ;
 | |
|          #else
 | |
|             if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0 )
 | |
|                return -1 ;
 | |
|          #endif
 | |
| 
 | |
|          r4->lastblock += r4->lastblockInc ;
 | |
|          pointer = 0 ;
 | |
|       }
 | |
|       else
 | |
|          pointer = r4key( block, block->nKeys, 0 )->pointer ;
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|       iBlock++ ;
 | |
|    }
 | |
| 
 | |
|    /* now position to the last spot, and place the branch */
 | |
|    if( iBlock < r4->nBlocksUsed )
 | |
|    {
 | |
|       if( block->nKeys <= r4->keysmax && pointer != 0 )
 | |
|       {
 | |
|          temp_block = block ;
 | |
|          tBlock = iBlock ;
 | |
|          while ( temp_block->nKeys == 0 && tBlock < r4->nBlocksUsed )
 | |
|          {
 | |
|             offset = ( r4->keysmax + 2 + ( ( r4->keysmax / 2 ) * 2 != r4->keysmax ) ) * sizeof(short) ;
 | |
|             temp_block->blockIndex = &temp_block->nKeys + 1 ;  /* 1 short off of nKeys */
 | |
|             for ( i = 0 ; i <= r4->keysmax ; i++ )
 | |
|                temp_block->blockIndex[i] = r4->grouplen * i + offset ;
 | |
|             temp_block->data = (char *)&temp_block->nKeys + temp_block->blockIndex[0] ;
 | |
|             temp_block = (R4BLOCK_DATA *)((char *)temp_block + B4BLOCK_SIZE + 2 * sizeof(void *) ) ;
 | |
|             tBlock++ ;
 | |
|          }
 | |
| 
 | |
|          /* now place the pointer for data that goes rightward */
 | |
|          keyTo = r4key( block, block->nKeys, 0 ) ;
 | |
|          keyTo->pointer = pointer ;
 | |
|          pointer = 0 ;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             swap = (char *) u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|             if ( swap == 0 )
 | |
|                return -1 ;
 | |
| 
 | |
|             memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
| 
 | |
|             shortVal = x4reverseShort( (void *)swap ) ;
 | |
|             memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|             swapPtr = swap + 2 ;
 | |
|                             /* swap the short pointers to B4KEY_DATA */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|                swapPtr += sizeof(short) ;
 | |
|             }
 | |
|                             /* swap the B4KEY_DATA's */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|                longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|                memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|                swapPtr += r4->grouplen ;
 | |
|             }
 | |
| 
 | |
|             if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|                return -1 ;
 | |
|             u4free( swap ) ;
 | |
|          #else
 | |
|             if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0 ) return -1 ;
 | |
|          #endif
 | |
| 
 | |
|          r4->lastblock += r4->lastblockInc ;
 | |
|          block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|          iBlock++ ;
 | |
|       }
 | |
|    }
 | |
|    for(; iBlock < r4->nBlocksUsed; iBlock++ )
 | |
|    {
 | |
|       if ( block->nKeys == 0 )
 | |
|       {
 | |
|          offset = ( r4->keysmax + 2 + ( ( r4->keysmax / 2 ) * 2 != r4->keysmax ) ) * sizeof(short) ;
 | |
|          block->blockIndex = &block->nKeys + 1 ;  /* 1 short off of nKeys */
 | |
|          for ( i = 0 ; i <= r4->keysmax ; i++ )
 | |
|             block->blockIndex[i] = r4->grouplen * i + offset ;
 | |
|          block->data = (char *)&block->nKeys + block->blockIndex[0] ;
 | |
|       }
 | |
|       keyTo = r4key( block, block->nKeys, r4->grouplen ) ;
 | |
|       #ifdef E4MISC
 | |
|          dif = (char *)keyTo  -  (char *) block ;
 | |
|          if ( dif + sizeof( long ) > B4BLOCK_SIZE  ||  dif < 0 )
 | |
|             return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|       #endif
 | |
|       keyTo->pointer = r4->lastblock * 512 ;
 | |
| 
 | |
|       #ifdef S4BYTE_SWAP
 | |
|             swap = (char *)u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|             if ( swap == 0 )
 | |
|                return -1 ;
 | |
| 
 | |
|             memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
| 
 | |
|             /* position swapPtr at beginning of pointers */
 | |
|             shortVal = x4reverseShort( (void *)swap ) ;
 | |
|             memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|             swapPtr = swap + 2 ;
 | |
|             /* swap the short pointers to B4KEY_DATA */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|                swapPtr += sizeof(short) ;
 | |
|             }
 | |
|             /* swap the B4KEY_DATA's */
 | |
|             for ( i = 0 ; i < r4->keysmax ; i++ )
 | |
|             {
 | |
|                longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|                memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|                longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|                memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|                swapPtr += r4->grouplen ;
 | |
|             }
 | |
| 
 | |
|             if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 ) return -1 ;
 | |
|             u4free( swap ) ;
 | |
|       #else
 | |
|          if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0) return -1;
 | |
|       #endif
 | |
| 
 | |
|       r4->lastblock += r4->lastblockInc ;
 | |
|       block = (R4BLOCK_DATA *)( (char *)block + B4BLOCK_SIZE + 2 * sizeof(void *) ) ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* CLIPPER */
 | |
| int r4reindexTodisk( R4REINDEX *r4, long rec, const char *keyValue )
 | |
| {
 | |
|    R4BLOCK_DATA *block ;
 | |
|    int tnUsed, iBlock, i ;
 | |
|    B4KEY_DATA *keyTo ;
 | |
|    short offset ;
 | |
|    #ifdef E4MISC
 | |
|       long dif ;
 | |
|       B4KEY_DATA *keyOn ;
 | |
|    #endif
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       char *swap, *swapPtr ;
 | |
|       int j ;
 | |
|       long longVal ;
 | |
|       short shortVal ;
 | |
|    #endif
 | |
| 
 | |
|    tnUsed = 1 ;
 | |
| 
 | |
|    /* Writes out the current block and adds references to higher blocks */
 | |
|    block  = r4->startBlock ;
 | |
|    iBlock= 0 ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       keyOn = r4key( block, block->nKeys, r4->grouplen ) ;
 | |
|       dif = (char *) keyOn -  (char *) &block->nKeys ;
 | |
|       if ( dif+ r4->grouplen > B4BLOCK_SIZE || dif < 0 )
 | |
|          return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for(;;)
 | |
|    {
 | |
|       tnUsed++ ;
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          swap = (char *)u4allocEr( r4->codeBase, B4BLOCK_SIZE ) ;
 | |
|          if ( swap == 0 )
 | |
|             return -1 ;
 | |
| 
 | |
|          memcpy( (void *)swap, (void *)&block->nKeys, B4BLOCK_SIZE ) ;
 | |
| 
 | |
|          /* position swapPtr at beginning of pointers */
 | |
|          shortVal = x4reverseShort( (void *)swap ) ;
 | |
|          memcpy( swap, (void *) &shortVal, sizeof(short) ) ;
 | |
| 
 | |
|          swapPtr = swap + 2 ;
 | |
| 
 | |
|          /* swap the short pointers to B4KEY_DATA */
 | |
|          for ( j = 0 ; j < r4->keysmax ; j++ )
 | |
|          {
 | |
|             shortVal = x4reverseShort( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | |
|             swapPtr += sizeof(short) ;
 | |
|          }
 | |
| 
 | |
|          /* swap the B4KEY_DATA's */
 | |
|          for ( j = 0 ; j < r4->keysmax ; j++ )
 | |
|          {
 | |
|             longVal = x4reverseLong( (void *)swapPtr ) ;
 | |
|             memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | |
|             longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | |
|             memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | |
|             swapPtr += r4->grouplen ;
 | |
|          }
 | |
| 
 | |
|          if ( file4seqWrite( &r4->seqwrite, swap, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|          u4free( swap ) ;
 | |
|       #else
 | |
|          if ( file4seqWrite( &r4->seqwrite, &block->nKeys, B4BLOCK_SIZE) < 0 )
 | |
|             return -1 ;
 | |
|       #endif
 | |
|       if ( iBlock )
 | |
|          memset( block, 0, B4BLOCK_SIZE ) ;
 | |
|       r4->lastblock += r4->lastblockInc ;
 | |
| 
 | |
|       block = (R4BLOCK_DATA *) ((char *)block + B4BLOCK_SIZE + 2*sizeof(void *) ) ;
 | |
|       iBlock++ ;
 | |
|       #ifdef E4MISC
 | |
|          if ( iBlock >= r4->nBlocks )
 | |
|             return error4( r4->codeBase, e4info, E92102 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( block->nKeys == 0 )   /* set up the branch block... */
 | |
|       {
 | |
|          offset = ( r4->keysmax + 2 + ( ( r4->keysmax / 2 ) * 2 != r4->keysmax ) ) * sizeof(short) ;
 | |
|          block->blockIndex = &block->nKeys + 1 ;
 | |
|          for ( i = 0 ; i <= r4->keysmax ; i++ )
 | |
|             block->blockIndex[i] = r4->grouplen * i + offset ;
 | |
|          block->data = (char *) &block->nKeys + block->blockIndex[ 0 ] ;
 | |
|       }
 | |
| 
 | |
|       keyTo = r4key( block, block->nKeys, r4->grouplen ) ;
 | |
|       #ifdef E4MISC
 | |
|          dif = (char *) keyTo -  (char *) block  ;
 | |
|          if ( dif+sizeof(long) > B4BLOCK_SIZE || dif < 0 )
 | |
|             return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|       #endif
 | |
|       keyTo->pointer = r4->lastblock * 512 ;
 | |
| 
 | |
|       if ( block->nKeys < r4->keysmax )
 | |
|       {
 | |
|          if ( tnUsed > r4->nBlocksUsed )
 | |
|             r4->nBlocksUsed = tnUsed ;
 | |
|          #ifdef E4MISC
 | |
|             if ( dif+r4->grouplen > B4BLOCK_SIZE )
 | |
|                return error4( r4->codeBase, e4result, E92102 ) ;
 | |
|          #endif
 | |
|          keyTo->num = rec ;
 | |
|          memcpy( keyTo->value, keyValue, r4->valuelen ) ;
 | |
|          block->nKeys++ ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       #ifdef E4MISC
 | |
|          if ( block->nKeys > r4->keysmax )
 | |
|              return error4( r4->codeBase, e4info, E82104 ) ;
 | |
|       #endif
 | |
|    }
 | |
| }
 | |
| #endif  /* S4CLIPPER */
 | |
| #endif  /* N4OTHER */
 | |
| #endif  /* S4INDEX_OFF */
 | |
| #endif  /* S4WRITE_OFF */
 |