240 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* d4file.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif  /* __TUROBC__ */
 | |
| #endif  /* S4UNIX */
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| /* fromDisk set to 1 if ensure that a disk read is done, instead of a buffer read */
 | |
| int dfile4read( DATA4FILE *data, long recNum, char *ptr, int fromDisk )
 | |
| {
 | |
|    #ifdef S4CLIENT
 | |
|       return dfile4goData( data, recNum, ptr, 1 ) ;
 | |
|    #else
 | |
|       unsigned len ;
 | |
| 
 | |
|       #ifdef E4PARM_LOW
 | |
|          if ( data == 0 || recNum <= 0 || ptr == 0 )
 | |
|             return error4( 0, e4parm_null, E91102 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( data->c4 ) < 0 )
 | |
|          return e4codeBase ;
 | |
| 
 | |
|       #ifndef S4OPTIMIZE_OFF
 | |
|          /* make sure read from disk unless file locked, etc. */
 | |
|          if ( fromDisk )
 | |
|             if ( data->file.doBuffer )
 | |
|                data->c4->opt.forceCurrent = 1 ;
 | |
|       #endif
 | |
|       len = file4read( &data->file, dfile4recordPosition( data, recNum ), ptr, data->recWidth ) ;
 | |
|       #ifndef S4OPTIMIZE_OFF
 | |
|          if ( fromDisk )
 | |
|             if ( data->file.doBuffer )
 | |
|                data->c4->opt.forceCurrent = 0 ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( data->c4 ) < 0 )
 | |
|          return error4code( data->c4 ) ;
 | |
| 
 | |
|       if ( len != data->recWidth )
 | |
|          return r4entry ;
 | |
| 
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| #endif  /* S4CLIENT */
 | |
| 
 | |
| /* set serverId to -2 to get the actual count if possible for example,
 | |
|    b4leafInit needs to know how many may potentially exist */
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| long S4FUNCTION dfile4recCount( DATA4FILE *data, const long serverId )
 | |
| {
 | |
|    #ifdef S4CLIENT
 | |
|       int rc ;
 | |
|       CONNECTION4 *connection ;
 | |
|       CONNECTION4RECCOUNT_INFO_OUT *info ;
 | |
|    #else
 | |
|       unsigned len ;
 | |
|    #endif
 | |
|    S4LONG tmpCount ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       /* PARM_HIGH because called directly in S4OFF_MULTI case */
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( data->c4 ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    /* client checks current count in d4recCount */
 | |
|    #ifndef S4CLIENT
 | |
|       if ( data->numRecs >= 0L )
 | |
|       {
 | |
|          #ifndef S4SINGLE
 | |
|             if ( serverId == -2L )
 | |
|                return data->numRecs ;
 | |
|             if ( dfile4lockTestAppend( data, 0L, serverId ) != 1 )
 | |
|                return data->minCount ;
 | |
|             else
 | |
|          #endif
 | |
|                return data->numRecs ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       connection = data->connection ;
 | |
|       if ( connection == 0 )
 | |
|          return e4connection ;
 | |
| 
 | |
|       connection4assign( connection, CON4RECCOUNT, 0, data->serverId ) ;
 | |
|       connection4send( connection ) ;
 | |
|       rc = connection4receive( connection ) ;
 | |
|       if ( rc < 0 )
 | |
|          return rc ;
 | |
|       rc = connection4status( connection ) ;
 | |
|       if ( rc != 0 )
 | |
|          return connection4error( connection, data->c4, rc, E91102 ) ;
 | |
| 
 | |
|       if ( connection4len( connection ) != sizeof( CONNECTION4RECCOUNT_INFO_OUT ) )
 | |
|          return error4( data->c4, e4packetLen, E91102 ) ;
 | |
|       info = (CONNECTION4RECCOUNT_INFO_OUT *)connection4data( connection ) ;
 | |
|       tmpCount = info->recCount ;
 | |
|       if ( info->recCount < 0 )
 | |
|          return -1L ;
 | |
|       data->minCount = tmpCount ;
 | |
|       #ifndef S4SINGLE
 | |
|          if ( info->appendLocked == 1 )
 | |
|       #endif  /* S4SINGLE */
 | |
|             data->numRecs = tmpCount ;
 | |
|    #else
 | |
|       #ifdef S464BIT
 | |
|          len = file4read( &data->file, 4L, &tmpCount, sizeof(S4LONG) ) ;
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             tmpCount = x4reverseLong((void *)&tmpCount) ;
 | |
|          #endif
 | |
|       #else
 | |
|          len = file4read( &data->file, 4L, &tmpCount, sizeof( long ) ) ;
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             tmpCount = x4reverseLong((void *)&tmpCount) ;
 | |
|          #endif
 | |
|       #endif
 | |
|       if ( tmpCount < 0L || len != 4 )
 | |
|          return -1L ;
 | |
| 
 | |
|       #ifndef S4SINGLE
 | |
|          if ( dfile4lockTestAppend( data, 0L, 0L ) )
 | |
|       #endif  /* S4SINGLE */
 | |
|             data->numRecs = tmpCount ;
 | |
| 
 | |
|       /* this minCount is used as the actual record count in instances where
 | |
|          transactions are taking place and the append bytes are locked, and
 | |
|          data handles of other datafiles are performing the access */
 | |
|       data->minCount = tmpCount ;    /* used for multi-user ensured sequencing */
 | |
|    #endif
 | |
| 
 | |
|    return tmpCount ;
 | |
| }
 | |
| 
 | |
| #ifndef S4INLINE
 | |
| unsigned long dfile4recordPosition( DATA4FILE *data, const long rec )
 | |
| {
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 || rec <= 0L )
 | |
|          return error4( 0, e4parm, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    return (unsigned long)data->headerLen + (unsigned long)data->recWidth * ( rec - 1 ) ;
 | |
| }
 | |
| 
 | |
| unsigned int dfile4recWidth( DATA4FILE *data )
 | |
| {
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    return (unsigned int)data->recWidth ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| S4CONST char *dfile4name( S4CONST DATA4FILE *data )
 | |
| {
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E93205 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
|    #ifdef S4CLIENT
 | |
|       return data->accessName ;
 | |
|    #else
 | |
|       return data->file.name ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| #ifndef S4OFF_WRITE
 | |
| int dfile4updateHeader( DATA4FILE *data, int doTimeStamp, int doCount )
 | |
| {
 | |
|    long pos ;
 | |
|    unsigned len ;
 | |
| 
 | |
|    if ( code4trans( data->c4 )->currentTranStatus == r4active || code4trans( data->c4 )->currentTranStatus == r4rollback )   /* delay to avoid append rollback problems */
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       #ifndef S4SINGLE
 | |
|          #ifndef S4SERVER
 | |
|             /* note that the server doesn't need it locked since that is a data level, not
 | |
|                a data4file level lock for server --> can't make this check */
 | |
|             if  ( doCount && ( dfile4lockTestAppend( data, 0, 0 ) == 0 ) )
 | |
|                return error4( data->c4, e4info, E83201 ) ;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    pos = 0L ;
 | |
|    len = 4 + ( sizeof(S4LONG) ) + ( sizeof( short ) ) ;
 | |
|    if ( doTimeStamp )
 | |
|       data->doDate = 1 ;
 | |
|    else
 | |
|    {
 | |
|       pos += 4 ;
 | |
|       len -= 4 ;
 | |
|    }
 | |
| 
 | |
|    if ( !doCount || data->numRecs < 0 )
 | |
|       len -= (sizeof( data->numRecs ) + sizeof( data->headerLen ) ) ;
 | |
| 
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       data->numRecs = x4reverseLong( (void *)&data->numRecs ) ;
 | |
|       data->headerLen = x4reverseShort( (void *)&data->headerLen ) ;
 | |
|    #endif
 | |
|       if ( file4write( &data->file, pos, (char *)&data->version + pos, len ) < 0 )
 | |
|          return -1 ;
 | |
|    #ifdef S4BYTE_SWAP
 | |
|       data->numRecs = x4reverseLong( (void *)&data->numRecs ) ;
 | |
|       data->headerLen = x4reverseShort( (void *)&data->headerLen ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( doCount )
 | |
|       data->minCount = data->numRecs ;
 | |
|    data->fileChanged = 0 ;
 | |
|    return 0 ;
 | |
| }
 | |
| #endif
 | |
| #endif  /* S4OFF_WRITE */
 |