/* 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 */