5432d61de9
git-svn-id: svn://10.65.10.50/trunk@4681 c028cbd2-c16b-5b4b-a496-9718f37d4682
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 */
|