1065 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1065 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* d4append.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 S4OFF_WRITE
 | |
| 
 | |
| #ifndef S4OFF_MULTI
 | |
| #ifndef S4CLIENT
 | |
| static int d4lockAppendRecord( DATA4 *data )
 | |
| {
 | |
|    int rc, oldUnlock ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91101 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( d4lockTestFile( data ) == 1 )
 | |
|       return 0 ;
 | |
| 
 | |
|    rc = 0 ;
 | |
| 
 | |
|    switch( code4unlockAuto( data->codeBase ) )
 | |
|    {
 | |
|       case LOCK4ALL :
 | |
|          code4lockClear( data->codeBase ) ;
 | |
|          break ;
 | |
|       case LOCK4DATA :
 | |
|          rc = d4unlock( data ) ;
 | |
|          break ;
 | |
|       default:
 | |
|          break ;
 | |
|    }
 | |
| 
 | |
|    oldUnlock = code4unlockAuto( data->codeBase ) ;
 | |
|    if ( d4lockTestAppend( data ) == 0 )
 | |
|    {
 | |
|       #ifdef S4SERVER
 | |
|          rc = dfile4lockAppend( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|       #else
 | |
|          rc = d4lockAppend( data ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( rc == 0 )
 | |
|       {
 | |
|          data->dataFile->numRecs = -1 ;
 | |
|          code4unlockAutoSet( data->codeBase, 0 ) ;
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             data->codeBase->opt.forceCurrent = 1 ;  /* force the recCount to be current */
 | |
|          #endif
 | |
|          #ifdef S4SERVER
 | |
|             rc = dfile4lock( data->dataFile, data4clientId( data ), data4serverId( data ), d4recCount( data ) + 1 ) ;
 | |
|          #else
 | |
|             rc = d4lock( data, d4recCount( data ) + 1 ) ;
 | |
|          #endif
 | |
| 
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             data->codeBase->opt.forceCurrent = 0 ;
 | |
|          #endif
 | |
|       }
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       code4unlockAutoSet( data->codeBase, 0 ) ;
 | |
|       #ifdef S4SERVER
 | |
|          rc = dfile4lock( data->dataFile, data4clientId( data ), data4serverId( data ), d4recCount( data ) + 1 ) ;
 | |
|       #else
 | |
|          rc = d4lock( data, d4recCount( data ) + 1 ) ;
 | |
|       #endif
 | |
|    }
 | |
|    if ( rc )
 | |
|       #ifdef S4SERVER
 | |
|          dfile4unlockData( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|       #else
 | |
|          d4unlockData( data ) ;
 | |
|       #endif
 | |
| 
 | |
|    code4unlockAutoSet( data->codeBase, oldUnlock ) ;
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| #endif /* S4CLIENT */
 | |
| 
 | |
| #ifdef S4SERVER
 | |
| int dfile4lockAppendRecord( DATA4FILE *data, const long clientId, const long serverId )
 | |
| {
 | |
|    int rc, oldUnlock, wasLocked ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( dfile4lockTestFile( data, clientId, serverId ) == 1 )
 | |
|       return 0 ;
 | |
| 
 | |
|    wasLocked = dfile4lockTestAppend( data, clientId, serverId ) ;
 | |
|    if ( wasLocked == 1 )
 | |
|       rc = 0 ;
 | |
|    else
 | |
|       rc = dfile4lockAppend( data, clientId, serverId ) ;
 | |
| 
 | |
|    if ( rc == 0 )
 | |
|    {
 | |
|       oldUnlock = code4unlockAuto( data->c4 ) ;
 | |
|       code4unlockAutoSet( data->c4, 0 ) ;
 | |
| 
 | |
|       if ( wasLocked == 0 )
 | |
|       {
 | |
|          data->numRecs = -1 ;
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             data->c4->opt.forceCurrent = 1 ;  /* force the recCount to be current */
 | |
|          #endif
 | |
|       }
 | |
|       rc = dfile4lock( data, clientId, serverId, dfile4recCount( data, serverId ) + 1 ) ;
 | |
|       if ( wasLocked == 0 )
 | |
|       {
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             data->c4->opt.forceCurrent = 0 ;
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       if ( rc )
 | |
|          dfile4unlockData( data, clientId, serverId ) ;
 | |
|       code4unlockAutoSet( data->c4, oldUnlock ) ;
 | |
|    }
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| #endif
 | |
| #endif  /* S4OFF_MULTI */
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| static int dfile4appendData( DATA4FILE *data, const void *record, long *recNum )
 | |
| {
 | |
|    long pos, count ;
 | |
|    int  rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 || record == 0 || recNum == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4OFF_MULTI
 | |
|       count = dfile4recCount( data, 0L ) ;  /* returns -1 if error4code( codeBase ) < 0 */
 | |
|    #else
 | |
|       count = dfile4recCount( data, -2L ) ;  /* returns -1 if error4code( codeBase ) < 0 */
 | |
|    #endif
 | |
|    if ( count < 0L )
 | |
|       return -1 ;
 | |
|    data->fileChanged = 1 ;
 | |
|    pos = dfile4recordPosition( data, count + 1L ) ;
 | |
| 
 | |
|    #ifdef S4FOX
 | |
|       if ( data->version == 0x30 )   /* no eof marker */
 | |
|          rc = file4write( &data->file, pos, record, ( data->recWidth ) ) ;
 | |
|       else
 | |
|          rc = file4write( &data->file, pos, record, ( data->recWidth + 1 ) ) ;
 | |
|    #else
 | |
|       rc = file4write( &data->file, pos, record, ( data->recWidth + 1 ) ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( rc == 0 )
 | |
|    {
 | |
|       data->numRecs = count + 1L ;
 | |
|       *recNum = data->numRecs ;
 | |
|       #ifndef S4OFF_TRAN
 | |
|          /* 04/24/96 AS --> 2 lines below added so that server datafile has correct
 | |
|             min count when not a transaction.  t4commit.c */
 | |
|          if ( code4tranStatus( data->c4 ) != r4active )
 | |
|             data->minCount = data->numRecs ;
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| static int d4doAppend( DATA4 *data )
 | |
| #else
 | |
| int S4FUNCTION d4append( DATA4 *data )
 | |
| #endif  /* S4CLIENT */
 | |
| {
 | |
|    int rc , nTag;
 | |
|    CODE4 *c4 ;
 | |
|    DATA4FILE *d4file ;
 | |
|    #ifdef S4CLIENT
 | |
|       CONNECTION4 *connection ;
 | |
|       CONNECTION4APPEND_INFO_IN info ;
 | |
|       CONNECTION4APPEND_INFO_OUT *out ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          CONNECTION4MEMO memo ;
 | |
|       #endif
 | |
|    #else
 | |
|       #ifndef S4OFF_MEMO
 | |
|          long newId ;
 | |
|       #endif
 | |
|       #ifndef S4INDEX_OFF
 | |
|          int saveError ;
 | |
|          TAG4 *tagOn ;
 | |
|          TAG4FILE *t4file ;
 | |
|          #ifndef S4OFF_MULTI
 | |
|             int indexLocked ;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifndef S4OFF_MEMO
 | |
|       F4MEMO *mfield ;
 | |
|       int i ;
 | |
|    #endif /* S4OFF_MEMO */
 | |
|    #ifndef S4OFF_MULTI
 | |
|       long clientId, serverId ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4DEMO
 | |
|       if ( d4recCount( data ) >= 200L)
 | |
|       {
 | |
|          d4close( data ) ;
 | |
|          return error4( data->codeBase, e4demo, 0 ) ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( data, 2, E91103 ) )
 | |
|          return -1 ;
 | |
|    #endif  /* S4VBASIC */
 | |
| 
 | |
|    #ifndef S4SERVER
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E91103 ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    c4 = data->codeBase ;
 | |
|    d4file = data->dataFile ;
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       clientId = data4clientId( data ) ;
 | |
|       serverId = data4serverId( data ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( c4 == 0 )
 | |
|          return error4( 0, e4struct, E91103 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( c4 ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    if ( data->readOnly == 1 )
 | |
|       return error4describe( c4, e4write, E80606, d4alias( data ), 0, 0 ) ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       #ifdef E4MISC
 | |
|          if ( data->recNum )
 | |
|             return error4( c4, e4result, E81103 ) ;
 | |
|       #endif
 | |
| 
 | |
|       memset( &info, 0, sizeof( CONNECTION4APPEND_INFO_IN ) ) ;
 | |
| 
 | |
|       connection = d4file->connection ;
 | |
|       if ( connection == 0 )
 | |
|          return e4connection ;
 | |
|       connection4assign( connection, CON4APPEND, clientId, serverId ) ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          for ( i = 0 ; i < d4file->nFieldsMemo ; i++ )
 | |
|          {
 | |
|             mfield = data->fieldsMemo + i ;
 | |
|             if ( mfield->len > 0 )
 | |
|                info.numMemoFields++ ;
 | |
|          }
 | |
|       #endif
 | |
|       connection4addData( connection, &info, sizeof( CONNECTION4APPEND_INFO_IN ), 0 ) ;
 | |
|       connection4addData( connection, data->record, dfile4recWidth( d4file ), 0 ) ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          for ( i = 0 ; i < d4file->nFieldsMemo ; i++ )
 | |
|          {
 | |
|             mfield = data->fieldsMemo + i ;
 | |
|             if ( mfield->len > 0 )
 | |
|             {
 | |
|                memo.fieldNum = i ;
 | |
|                memo.memoLen = mfield->len ;
 | |
|                connection4addData( connection, &memo, sizeof( CONNECTION4MEMO ), 1 ) ;
 | |
|                if ( mfield->len > 0 )
 | |
|                   connection4addData( connection, mfield->contents, mfield->len, 1 ) ;
 | |
|             }
 | |
|          }
 | |
|       #endif
 | |
|       rc = connection4repeat( connection, -2, -1, -1, data ) ;
 | |
|       if ( rc < 0 )
 | |
|          return rc ;
 | |
|       if ( connection4len( connection ) != sizeof( CONNECTION4APPEND_INFO_OUT ) )
 | |
|          return error4( c4, e4packetLen, 91103 ) ;
 | |
|       out = (CONNECTION4APPEND_INFO_OUT *)connection4data( connection ) ;
 | |
|       data->bofFlag = out->bofFlag ;
 | |
|       data->eofFlag = out->eofFlag ;
 | |
|       data->recordChanged = out->recordChanged ;
 | |
|       data->recNum = out->recNum ;
 | |
|       if ( d4lockTestAppend( data ) == 1 && rc == 0 )
 | |
|       {
 | |
|          d4file->numRecs = out->recNum ;
 | |
|          if ( code4tranStatus( c4 ) != r4active )
 | |
|             d4file->minCount = out->recNum ;
 | |
|       }
 | |
|       else
 | |
|          d4file->numRecs = - 1 ;
 | |
|       rc = connection4status( connection ) ;
 | |
|       if ( rc != 0 )
 | |
|       {
 | |
|          if ( rc < 0 )
 | |
|             connection4error( connection, c4, rc, E91103 ) ;
 | |
|          return rc ;
 | |
|       }
 | |
|       if ( out->recordLocked == 1 )
 | |
|          d4localLockSet( data, out->recNum ) ;
 | |
|       if ( out->appendLocked == 1 )
 | |
|       {
 | |
|          d4file->numRecs = out->recNum ;
 | |
|          d4file->appendLock = data ;
 | |
|       }
 | |
|       #ifndef S4OFF_MEMO
 | |
|          for ( i = 0 ; i < d4file->nFieldsMemo ; i++ )
 | |
|          {
 | |
|             mfield = data->fieldsMemo + i ;
 | |
|             mfield->isChanged = 0 ;
 | |
|          }
 | |
|       #endif
 | |
|       return 0 ;
 | |
|    #else
 | |
|       /* 1. Update index file
 | |
|          2. Update memo File
 | |
|          3. Update data file */
 | |
| 
 | |
|       #ifndef S4INDEX_OFF
 | |
|          #ifdef N4OTHER
 | |
|             if ( l4numNodes( &data->indexes ) != 0 )   /* there are indexes, so do them */
 | |
|          #else
 | |
|             if ( l4numNodes( &d4file->indexes ) != 0 )   /* there are indexes, so do them */
 | |
|          #endif
 | |
|          {
 | |
|             #ifndef S4OFF_MULTI
 | |
|                #ifdef S4SERVER
 | |
|                   indexLocked = dfile4lockTestIndex( d4file, data4serverId( data ) ) ;
 | |
|                #else
 | |
|                   indexLocked = d4lockTestIndex( data ) ;
 | |
|                #endif
 | |
|                if ( !indexLocked )
 | |
|                {
 | |
|                   #ifdef S4SERVER
 | |
|                      rc = dfile4lockIndex( d4file, data4serverId( data ) ) ;
 | |
|                   #else
 | |
|                      rc = d4lockIndex( data ) ;
 | |
|                   #endif
 | |
|                   if ( rc )
 | |
|                   {
 | |
|                      #ifdef S4SERVER
 | |
|                         dfile4unlockAppend( d4file, clientId, serverId ) ;
 | |
|                      #else
 | |
|                         d4unlockAppend( data ) ;
 | |
|                      #endif
 | |
|                      return rc ;
 | |
|                   }
 | |
|                }
 | |
|             #endif  /* not S4OFF_MULTI */
 | |
| 
 | |
|             for( tagOn = 0, nTag =0 ;; nTag++)
 | |
|             {
 | |
|                tagOn = d4tagNext( data, tagOn ) ;
 | |
|                if ( !tagOn )
 | |
|                   break ;
 | |
|                t4file = tagOn->tagFile ;
 | |
| 
 | |
|                rc = expr4context( t4file->expr, data ) ;
 | |
|                if ( rc == 0 )
 | |
|                   if ( t4file->filter != 0 )
 | |
|                      rc = expr4context( t4file->filter, data ) ;
 | |
| 
 | |
|                if ( rc == 0 )
 | |
|                   rc = t4addCalc( tagOn, data->recNum ) ;
 | |
|                if ( rc < 0 || rc == r4unique )
 | |
|                {
 | |
|                   saveError = error4set( c4, 0 ) ;
 | |
|                   if (rc == r4unique)
 | |
|                     data->recNum = nTag; /* 2nd hammer shot */
 | |
| 
 | |
|                   /* Remove the keys which were just added */
 | |
|                   for(;;)
 | |
|                   {
 | |
|                      tagOn = d4tagPrev( data, tagOn ) ;
 | |
|                      if ( !tagOn )
 | |
|                         break ;
 | |
|                      tfile4removeCalc( tagOn->tagFile, data->recNum ) ;
 | |
|                   }
 | |
| 
 | |
|                   error4set( c4, (short)saveError ) ;
 | |
|                   data->recNum = 0 ;
 | |
|                   #ifndef S4OFF_MULTI
 | |
|                      #ifdef S4SERVER
 | |
|                         dfile4unlockAppend( d4file, clientId, serverId ) ;
 | |
|                      #else
 | |
|                         d4unlockAppend( data ) ;
 | |
|                      #endif
 | |
|                      if ( !indexLocked )
 | |
|                         dfile4unlockIndex( d4file, data4serverId( data ) ) ;
 | |
|                   #endif
 | |
|                   return rc ;
 | |
|                }
 | |
|             }
 | |
| 
 | |
|             #ifndef S4OFF_MULTI
 | |
|                if ( !indexLocked )
 | |
|                   dfile4unlockIndex( d4file, data4serverId( data ) ) ;
 | |
|             #endif  /* not S4OFF_MULTI */
 | |
|          }
 | |
|       #endif  /* not S4INDEX_OFF */
 | |
| 
 | |
| 
 | |
|       #ifndef S4OFF_MEMO
 | |
|          for ( i = 0 ; i < d4file->nFieldsMemo ; i++ )
 | |
|          {
 | |
|             mfield = data->fieldsMemo + i ;
 | |
|             mfield->isChanged = 0 ;
 | |
|             if ( mfield->len > 0 )
 | |
|             {
 | |
|                newId = 0L ;
 | |
|                if ( memo4fileWrite( &d4file->memoFile, &newId, mfield->contents, mfield->len ) )  /* positive value means fail, so don't update field, but append record */
 | |
|                   break ;
 | |
|                f4assignLong( mfield->field, newId ) ;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                #ifdef S4FOX
 | |
|                   if ( d4version ( data ) == 0x30 )
 | |
|                   {
 | |
|                      if ( !f4null( mfield->field ) )  /* if null, then don't assign since that will replace the null flag */
 | |
|                         f4assignLong( mfield->field, 0 ) ;
 | |
|                   }
 | |
|                   else
 | |
|                      f4assign( mfield->field, " " ) ;
 | |
|                #else
 | |
|                   f4assign( mfield->field, " " ) ;
 | |
|                #endif
 | |
|             }
 | |
|          }
 | |
|       #endif  /* S4OFF_MEMO */
 | |
| 
 | |
|       data->record[dfile4recWidth( d4file )] = 0x1A ;
 | |
|       rc = dfile4appendData( d4file, data->record, &data->recNum ) ;
 | |
|       if ( rc == 0 )
 | |
|       {
 | |
|          data->recordChanged = 0 ;
 | |
|          data->record[dfile4recWidth( d4file )] = 0 ;
 | |
|       }
 | |
| 
 | |
|       #ifndef S4OFF_INDEX
 | |
|          if ( rc != 0 )  /* must remove tag entries since the data append failed */
 | |
|          {
 | |
|             for( tagOn = 0 ;; )
 | |
|             {
 | |
|                tagOn = d4tagNext( data, tagOn ) ;
 | |
|                if ( !tagOn )
 | |
|                   break ;
 | |
| 
 | |
|                tfile4removeCalc( tagOn->tagFile, data->recNum ) ;
 | |
|             }
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4OFF_MULTI
 | |
|          if ( rc == 0 )
 | |
|             if ( d4file->file.lowAccessMode != OPEN4DENY_RW )
 | |
|                rc = dfile4updateHeader( d4file, 1, 1 ) ;
 | |
| 
 | |
|          #ifdef S4SERVER
 | |
|             dfile4unlockAppend( d4file, clientId, serverId ) ;
 | |
|          #else
 | |
|             d4unlockAppend( data ) ;
 | |
|          #endif
 | |
|       #endif  /* S4OFF_MULTI */
 | |
| 
 | |
|       return rc ;
 | |
|    #endif  /* S4CLIENT */
 | |
| }
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| int S4FUNCTION d4append( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4OFF_TRAN
 | |
|       TRAN4 *trans = 0 ;
 | |
|       int hasTran, saveRc ;
 | |
|       long connectionId = 0L ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          unsigned long len ;
 | |
|          long tempLong ;
 | |
|          int i ;
 | |
|       #endif
 | |
|       CODE4 *c4 ;
 | |
|    #endif
 | |
|    #ifndef S4OFF_MULTI
 | |
|       long count ;
 | |
|    #endif
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91103 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       c4 = data->codeBase ;
 | |
| 
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( c4 == 0 )
 | |
|             return error4( 0, e4struct, E91103 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return e4codeBase ;
 | |
| 
 | |
|       #ifdef E4MISC
 | |
|          if ( data->recNum )
 | |
|             return error4( c4, e4result, E81103 ) ;
 | |
|       #endif
 | |
| 
 | |
|       hasTran = 0 ;
 | |
|       if ( data->logVal != LOG4TRANS )
 | |
|          if ( code4transEnabled( c4 ) )
 | |
|             if ( ( code4tranStatus( c4 ) == r4inactive ) )  /* start a mini-transaction */
 | |
|             {
 | |
|                rc = code4tranStartSingle( c4 ) ;
 | |
|                if ( rc != 0 )
 | |
|                   return rc ;
 | |
|                hasTran = 1 ;
 | |
|             }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4OFF_MULTI
 | |
|       rc = 0 ;
 | |
|    #else
 | |
|       /* 09/27/95 AS - removed.  unlockAuto also applies to append
 | |
|          bytes (t4lock.c, tran-dep) - see d4append locking description */
 | |
|       /*
 | |
|          appendLocked = dfile4lockTestAppend( data->dataFile, data4clientId( data), data4serverId( data ), data ) ;
 | |
|       */
 | |
|       rc = d4lockAppendRecord( data ) ;
 | |
|    #endif  /* S4OFF_MULTI */
 | |
| 
 | |
|    if ( rc == 0 )
 | |
|    {
 | |
|       data->bofFlag = data->eofFlag = 0 ;
 | |
|       data->recordChanged = 0 ;
 | |
|       #ifdef S4OFF_MULTI
 | |
|          data->recNum = d4recCount( data ) + 1 ;
 | |
|       #else
 | |
|          count = d4recCount( data ) + 1 ;
 | |
|          data->recNum = count ;
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4OFF_TRAN
 | |
|          if ( code4transEnabled( c4 ) )
 | |
|             if ( code4tranStatus( c4 ) == r4active )
 | |
|             {
 | |
|                trans = code4trans( c4 ) ;
 | |
|                #ifdef S4STAND_ALONE
 | |
|                   connectionId = 0L ;
 | |
|                #else
 | |
|                   connectionId = connection4id( c4->currentClient->connection ) ;
 | |
|                #endif
 | |
|                rc = tran4set( trans, trans->currentTranStatus, -1L, connectionId, TRAN4APPEND,
 | |
|                              sizeof( data->recNum ) + (unsigned int)dfile4recWidth( data->dataFile ), data4clientId( data ), data4serverId( data ) ) ;
 | |
|                if ( rc < 0 )
 | |
|                {
 | |
|                   if ( hasTran )
 | |
|                      code4tranRollbackSingle( c4 ) ;
 | |
|                   return rc ;
 | |
|                }
 | |
|                if ( tran4putData( trans, &data->recNum, sizeof( data->recNum ) ) == e4memory )
 | |
|                {
 | |
|                   if ( hasTran )
 | |
|                      code4tranRollbackSingle( c4 ) ;
 | |
|                   return e4memory ;
 | |
|                }
 | |
|                if ( tran4putData( trans, d4record( data ), (unsigned int)dfile4recWidth( data->dataFile ) ) == e4memory )
 | |
|                {
 | |
|                   if ( hasTran )
 | |
|                      code4tranRollbackSingle( c4 ) ;
 | |
|                   return e4memory ;
 | |
|                }
 | |
|                #ifndef S4OFF_MEMO
 | |
|                   len = trans->header.dataLen ;
 | |
|                   for ( i = 0; i < data->dataFile->nFieldsMemo; i++ )
 | |
|                   {
 | |
|                      len += ( data->fieldsMemo[i].len + sizeof( unsigned long ) ) ;
 | |
|                      tempLong = data->fieldsMemo[i].len;
 | |
|                      if ( tran4putData( trans, &tempLong, sizeof( unsigned long ) ) == e4memory )
 | |
|                      {
 | |
|                         if ( hasTran )
 | |
|                            code4tranRollbackSingle( c4 ) ;
 | |
|                         return e4memory ;
 | |
|                      }
 | |
|                      if ( data->fieldsMemo[i].len != 0 )
 | |
|                         if ( tran4putData( trans, data->fieldsMemo[i].contents, data->fieldsMemo[i].len ) == e4memory )
 | |
|                         {
 | |
|                            if ( hasTran )
 | |
|                               code4tranRollbackSingle( c4 ) ;
 | |
|                            return e4memory ;
 | |
|                         }
 | |
|                   }
 | |
|                   trans->header.dataLen = len ;
 | |
|                #endif
 | |
|                if ( tran4lowAppend( trans, 0 ) != 0 )
 | |
|                {
 | |
|                   if ( hasTran )
 | |
|                      code4tranRollbackSingle( c4 ) ;
 | |
|                   return e4transAppend ;
 | |
|                }
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       rc = d4doAppend( data ) ;
 | |
| 
 | |
|       #ifndef S4OFF_TRAN
 | |
|          if ( rc < 0 || rc == r4unique )
 | |
|          {
 | |
|             if ( code4transEnabled( c4 ) )
 | |
|                if ( code4tranStatus( c4 ) == r4active )
 | |
|                {
 | |
|                   saveRc = tran4set( trans, trans->currentTranStatus, -1L, connectionId, TRAN4VOID, 0, data4clientId( data ), data4serverId( data ) ) ;
 | |
|                   if ( saveRc < 0 )
 | |
|                   {
 | |
|                      if ( hasTran )
 | |
|                         code4tranRollbackSingle( c4 ) ;
 | |
|                      return saveRc ;
 | |
|                   }
 | |
|                   if ( tran4lowAppend( trans, "\0" ) != 0 )
 | |
|                   {
 | |
|                      if ( hasTran )
 | |
|                         code4tranRollbackSingle( c4 ) ;
 | |
|                      return e4transAppend ;
 | |
|                   }
 | |
|                }
 | |
|          }
 | |
|       #endif
 | |
|    }
 | |
|    #ifndef S4OFF_MULTI
 | |
|       else
 | |
|          count = -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       if ( hasTran )
 | |
|       {
 | |
|          code4tranCommitSingle( c4 ) ;
 | |
|          #ifndef S4OFF_MULTI
 | |
|             if ( code4unlockAuto( c4 ) == LOCK4OFF )
 | |
|             {
 | |
|                /* 09/27/95 AS - removed.  unlockAuto also applies to append
 | |
|                   bytes (t4lock.c, tran-dep) - see d4append locking description */
 | |
|                /*
 | |
|                if ( appendLocked == 0 )
 | |
|                {
 | |
|                   code4unlockAutoSet( data->codeBase, 2 ) ;
 | |
|                   dfile4unlockAppend( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|                   code4unlockAutoSet( data->codeBase, 0 ) ;
 | |
|                }
 | |
|                */
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                #ifdef S4SERVER
 | |
|                   dfile4unlockAppend( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|                #else
 | |
|                   d4unlockAppend( data ) ;
 | |
|                #endif
 | |
|                #ifndef S4OFF_INDEX
 | |
|                   dfile4unlockIndex( data->dataFile, data4serverId( data ) ) ;
 | |
|                #endif
 | |
|             }
 | |
|          #endif /* S4OFF_MULTI */
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       if ( count != -1 && ( rc < 0 || rc == r4unique ) )   /* append failed, so unlock record */
 | |
|          dfile4unlockRecord( data->dataFile, data4clientId( data ), data4serverId( data ), count ) ;
 | |
|    #endif
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int S4FUNCTION d4appendBlank( DATA4 *data )
 | |
| {
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( data, 2, E91104 ) )
 | |
|          return -1 ;
 | |
|    #endif  /* S4VBASIC */
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91104 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4DEMO
 | |
|       if ( d4recCount( data ) >= 200L)
 | |
|       {
 | |
|          d4close( data ) ;
 | |
|          return error4( data->codeBase, e4demo, 0 ) ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    rc = d4appendStart( data, 0 ) ;  /* updates the record, returns -1 if error4code( codeBase ) < 0 */
 | |
|    if ( rc )
 | |
|       return rc ;
 | |
| 
 | |
|    d4blank( data ) ;   /* make sure goes through f4blank() for non-character field types */
 | |
|    return d4append( data ) ;
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int S4FUNCTION d4appendStart( DATA4 *data, int useMemoEntries )
 | |
| {
 | |
|    CODE4 *c4 ;
 | |
|    #ifndef S4SERVER
 | |
|       int rc ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          char *savePtr ;
 | |
|          int i, oldLockEnforce ;
 | |
|       #endif
 | |
|    #else
 | |
|       #ifndef S4OFF_MEMO
 | |
|          int i ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( data, 2, E91107 ) )
 | |
|          return -1 ;
 | |
|    #endif  /* S4VBASIC */
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91107 ) ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = data->codeBase ;
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( c4 == 0 )
 | |
|          return error4( 0, e4struct, E91107 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4DEMO
 | |
|       if ( d4recCount( data ) >= 200L)
 | |
|       {
 | |
|          d4close( data ) ;
 | |
|          return error4( c4, e4demo, 0 ) ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4SERVER
 | |
|       /* the client performs these operations seperately through d4appendStart
 | |
|          so the record should never be marked as changed at this point */
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( data->recordChanged != 0 || useMemoEntries != 0 )
 | |
|             return error4( c4, e4info, E91107 ) ;
 | |
|       #endif
 | |
|       data->recNum = 0 ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          for ( i = 0 ; i < data->dataFile->nFieldsMemo ; i++ )
 | |
|             f4memoReset( data->fieldsMemo[i].field ) ;
 | |
|       #endif
 | |
|    #else
 | |
|       rc = d4updateRecord( data, 1 ) ;   /* returns -1 if error4code( c4 ) < 0 */
 | |
|       if ( rc )
 | |
|          return rc ;
 | |
| 
 | |
|       #ifndef S4OFF_MEMO
 | |
|          if ( data->dataFile->nFieldsMemo != 0 )
 | |
|          {
 | |
|             for ( i = 0; i < data->dataFile->nFieldsMemo; i++ )
 | |
|                f4memoReset( data->fieldsMemo[i].field ) ;
 | |
| 
 | |
|             if ( useMemoEntries == 1 )
 | |
|             {
 | |
|                if ( data->recNum > 0 && !d4eof( data ) && !d4bof( data ) )
 | |
|                {
 | |
|                   #ifndef S4CLIENT
 | |
|                      #ifdef E4ANALYZE
 | |
|                         if ( !file4openTest( &data->dataFile->memoFile.file ) )
 | |
|                            return error4( c4, e4data, E81101 ) ;
 | |
|                      #endif
 | |
|                   #endif
 | |
| 
 | |
|                   /* Read in the current memo entries of the current record */
 | |
|                   #ifndef S4OFF_MULTI
 | |
|                      rc = d4lock( data, data->recNum ) ;
 | |
|                      if ( rc )
 | |
|                         return rc ;
 | |
|                   #endif  /* S4OFF_MULTI */
 | |
| 
 | |
|                   savePtr = data->record ;
 | |
|                   data->record = data->recordOld ;
 | |
| 
 | |
|                   #ifdef S4CLIENT
 | |
|                      d4go( data, data->recNum ) ;
 | |
|                   #else
 | |
|                      d4goData( data, data->recNum ) ;
 | |
|                   #endif
 | |
| 
 | |
|                   for ( i = 0 ; i < data->dataFile->nFieldsMemo ; i++ )
 | |
|                   {
 | |
|                      #ifdef S4CLIENT
 | |
|                         f4memoRead( data->fieldsMemo[i].field ) ;
 | |
|                      #else
 | |
|                         f4memoReadLow( data->fieldsMemo[i].field ) ;
 | |
|                      #endif
 | |
|                      data->fieldsMemo[i].status = 0 ;
 | |
|                   }
 | |
| 
 | |
|                   data->record = savePtr ;
 | |
| 
 | |
|                   if ( error4code( c4 ) < 0 )
 | |
|                      return error4stack( c4, error4code( c4 ), E91107 ) ;
 | |
|                }
 | |
|             }
 | |
|          }
 | |
| 
 | |
|          oldLockEnforce = c4->lockEnforce ;
 | |
|          c4->lockEnforce = 0 ;
 | |
|          /* no matter what, must clear the memo entries from the data file */
 | |
|          for ( i = 0 ; i < data->dataFile->nFieldsMemo ; i++ )
 | |
|             f4assignLong( data->fieldsMemo[i].field, 0 ) ;
 | |
|          c4->lockEnforce = oldLockEnforce ;
 | |
|       #endif  /* not S4OFF_MEMO */
 | |
| 
 | |
|       data->recNum = 0 ;
 | |
| 
 | |
|       #ifndef S4OFF_MULTI
 | |
|          #ifndef S4CLIENT
 | |
|             #ifdef S4SERVER
 | |
|                rc = dfile4unlockData( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|             #else
 | |
|                if ( d4lockTestFile( data ) != 1 )
 | |
|                   rc = d4unlockData( data ) ;
 | |
|             #endif
 | |
|             if ( rc )
 | |
|                return rc ;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif  /* S4SERVER */
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| #ifndef S4OFF_TRAN
 | |
| int S4FUNCTION d4unappend( DATA4 *data )
 | |
| {
 | |
|    int rc, saveError ;
 | |
|    CODE4 *c4 ;
 | |
|    #ifndef S4INDEX_OFF
 | |
|       TAG4 *tagOn ;
 | |
|       #ifndef S4OFF_MULTI
 | |
|          int indexLocked ;
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifndef S4OFF_MEMO
 | |
|       int i ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( data, 2, E91108 ) )
 | |
|          return -1 ;
 | |
|    #endif  /* S4VBASIC */
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91108 ) ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = data->codeBase ;
 | |
|    rc = 0 ;
 | |
|    if ( error4code( c4 ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    /* 0. Lock record count bytes
 | |
|       1. Update index file
 | |
|       2. Update memo File
 | |
|       3. Update data file */
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       #ifdef S4SERVER
 | |
|          #ifdef E4MISC
 | |
|             if ( dfile4lockTestAppend( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ) ) != 1 )
 | |
|                return error4( c4, e4struct, E91108 ) ;
 | |
|             if ( dfile4lockTest( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ), (unsigned long)data->dataFile->numRecs ) != 1 )
 | |
|                return error4( c4, e4struct, E91108 ) ;
 | |
|          #endif
 | |
| /*         dfile4lockAppend( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ), data ) ;*/
 | |
| /*         dfile4lock( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ), (unsigned long)data->dataFile->numRecs, data ) ;*/
 | |
|       #else
 | |
|          d4lockAppend( data ) ;
 | |
|          d4lock( data, data->dataFile->numRecs ) ;
 | |
|       #endif
 | |
|    #endif  /* S4OFF_MULTI */
 | |
| 
 | |
|    data->bofFlag = data->eofFlag = 0 ;
 | |
|    data->recordChanged = 1 ;
 | |
| 
 | |
|    data->recNum = d4recCount( data ) ;
 | |
|    if ( data->recNum < 0 )
 | |
|       return (int)data->recNum ;
 | |
|    data->count = data->recNum - 1 ; /* reset the count approximator */
 | |
|    data->dataFile->numRecs = data->count ;   /* put back in for t4comit3...double append/unappend requires */
 | |
|    saveError = 0 ;
 | |
| 
 | |
|    #ifndef S4INDEX_OFF
 | |
|       #ifndef S4OFF_MULTI
 | |
|          #ifdef S4SERVER
 | |
|             indexLocked = dfile4lockTestIndex( data->dataFile, tran4serverDataId( data->trans ) ) ;
 | |
|             if ( !indexLocked )
 | |
|             {
 | |
|                rc = dfile4lockIndex( data->dataFile, tran4serverDataId( data->trans ) ) ;
 | |
|                if ( rc )
 | |
|                {
 | |
|                   dfile4unlockAppend( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ) ) ;
 | |
|                   return rc ;
 | |
|                }
 | |
|             }
 | |
|          #else
 | |
|             indexLocked = d4lockTestIndex( data ) ;
 | |
|             if ( !indexLocked )
 | |
|             {
 | |
|                rc = d4lockIndex( data ) ;
 | |
|                if ( rc )
 | |
|                {
 | |
|                   d4unlockAppend( data ) ;
 | |
|                   return rc ;
 | |
|                }
 | |
|             }
 | |
|          #endif /* S4SERVER */
 | |
|       #endif  /* not S4OFF_MULTI */
 | |
| 
 | |
|       for( tagOn = 0 ;; )
 | |
|       {
 | |
|          tagOn = d4tagNext( data, tagOn ) ;
 | |
|          if ( !tagOn )
 | |
|             break ;
 | |
| 
 | |
|          rc = tfile4removeCalc( tagOn->tagFile, data->recNum ) ;
 | |
|          if ( rc < 0 )
 | |
|             saveError = error4set( c4, 0 ) ;
 | |
|       }
 | |
| 
 | |
|       #ifndef S4OFF_MULTI
 | |
|          if ( !indexLocked )
 | |
|             dfile4unlockIndex( data->dataFile, tran4serverDataId( data->trans ) ) ;
 | |
|       #endif
 | |
|    #endif  /* not S4INDEX_OFF */
 | |
| 
 | |
|    #ifndef S4OFF_MEMO
 | |
|       if ( data->dataFile->nFieldsMemo > 0 )
 | |
|       {
 | |
|          #ifndef S4OFF_MULTI
 | |
|             if ( ( rc = d4validateMemoIds( data ) ) != 0 )
 | |
|             {
 | |
|                data->recordChanged = 0 ;
 | |
|                return rc ;
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          /* Cycle through the fields to be flushed */
 | |
|          for ( i = 0; i < data->dataFile->nFieldsMemo; i++ )
 | |
|          {
 | |
|             f4memoAssignN( data->fieldsMemo[i].field, "\0", 0 ) ;
 | |
|             rc = f4memoUpdate( data->fieldsMemo[i].field ) ;
 | |
|             if ( rc < 0 )
 | |
|                saveError = error4set( c4, 0 ) ;
 | |
|          }
 | |
|       }
 | |
|    #endif  /* S4OFF_MEMO */
 | |
| 
 | |
|    data->record[dfile4recWidth( data->dataFile )] = 0x1A ;
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       #ifdef S4SERVER
 | |
|          rc = dfile4unappendData( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ) ) ;
 | |
|       #else
 | |
|          rc = dfile4unappendData( data->dataFile, data->dataFile->fileClientLock, data->dataFile->fileServerLock ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       if ( rc == 0 )
 | |
|          if ( data->dataFile->file.lowAccessMode != OPEN4DENY_RW )
 | |
|             rc = dfile4updateHeader( data->dataFile, 1, 1 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_MULTI
 | |
|       #ifdef S4SERVER
 | |
|          dfile4unlockAppend( data->dataFile, tran4clientDataId( data->trans ), tran4serverDataId( data->trans ) ) ;
 | |
|       #else
 | |
|          d4unlockAppend( data ) ;
 | |
|       #endif
 | |
|    #endif  /* S4OFF_MULTI */
 | |
| 
 | |
|    error4set( c4, (short)saveError ) ;
 | |
| 
 | |
|    /* reset to an invalid position */
 | |
|    data->recNum = data->recNumOld = -1 ;
 | |
|    data->recordChanged = 0 ;
 | |
|    data->bofFlag = data->eofFlag = 0 ;
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int dfile4unappendData( DATA4FILE *data, const long clientId, const long serverId )
 | |
| {
 | |
|    long pos, count ;
 | |
|    int  rc ;
 | |
|    char endMark;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( data == 0 )
 | |
|          return error4( 0, e4parm_null, E91102 ) ;
 | |
|    #endif
 | |
| 
 | |
|    count = dfile4recCount( data, serverId ) ;
 | |
|    if ( count < 0L )
 | |
|       return error4stack( data->c4, (int)count, E91102 ) ;
 | |
|    data->fileChanged = 1 ;
 | |
|    pos = dfile4recordPosition( data, count + 1 ) ;
 | |
| 
 | |
|    rc = file4lenSet( &data->file, pos ) ;
 | |
|    endMark = 0x1A;
 | |
|    rc = file4write( &data->file, pos, &endMark, 1 ) ;
 | |
| 
 | |
|    if ( rc >= 0 )
 | |
|    {
 | |
|       #ifndef S4OFF_MULTI
 | |
|          if ( dfile4lockTestAppend( data, clientId, serverId ) )
 | |
|       #endif  /* S4OFF_MULTI */
 | |
|       data->numRecs = count ;
 | |
|    }
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| #endif  /* S4OFF_TRAN */
 | |
| #endif  /* S4CLIENT */
 | |
| #endif  /* S4OFF_WRITE */
 |