campo-sirio/cb/source/d4append.c
alex 5432d61de9 Modifiche A.G.A.
git-svn-id: svn://10.65.10.50/trunk@4681 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-06-16 13:10:44 +00:00

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