465 lines
12 KiB
C
Executable File
465 lines
12 KiB
C
Executable File
/* d4close.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 S4MEMO_OFF
|
|
extern char f4memoNullChar ;
|
|
#endif /* not S4MEMO_OFF */
|
|
|
|
#ifndef S4CLIENT
|
|
/* closes the given datafile if it's user count is zero */
|
|
int dfile4closeLow( DATA4FILE *data )
|
|
{
|
|
int finalRc ;
|
|
CODE4 *c4 ;
|
|
#ifndef S4OFF_INDEX
|
|
#ifdef N4OTHER
|
|
TAG4FILE *t4 ;
|
|
#else
|
|
INDEX4FILE *i4 ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E91102 ) ;
|
|
#endif
|
|
|
|
c4 = data->c4 ;
|
|
|
|
if ( data->userCount > 0 )
|
|
return 0 ;
|
|
|
|
if ( data->info != 0 )
|
|
{
|
|
u4free( data->info ) ;
|
|
data->info = 0 ;
|
|
}
|
|
|
|
finalRc = error4set( c4, 0 ) ;
|
|
|
|
if ( file4openTest( &data->file ) )
|
|
{
|
|
#ifndef S4SERVER
|
|
if ( c4->doRemove == 1 )
|
|
data->file.isTemp = 1 ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_WRITE
|
|
if ( data->fileChanged && data->file.isTemp != 1 && data->file.isReadOnly == 0 )
|
|
{
|
|
#ifdef S4OFF_MULTI
|
|
dfile4updateHeader( data, 1, 1 ) ;
|
|
#else
|
|
if ( data->file.lowAccessMode == OPEN4DENY_RW )
|
|
dfile4updateHeader( data, 1, 1 ) ;
|
|
#endif
|
|
if ( data->doDate == 1 )
|
|
{
|
|
u4yymmdd( &data->yy ) ;
|
|
data->doDate = 0 ;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifndef S4MEMO_OFF
|
|
if ( file4openTest( &data->memoFile.file ) )
|
|
{
|
|
#ifndef S4SERVER
|
|
if ( c4->doRemove == 1 )
|
|
data->memoFile.file.isTemp = 1 ;
|
|
#endif
|
|
if ( file4close( &data->memoFile.file ) < 0 )
|
|
finalRc = error4set( c4, 0 ) ;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4OFF_INDEX
|
|
for ( ;; )
|
|
{
|
|
#ifdef N4OTHER
|
|
t4 = (TAG4FILE *)l4first( &data->tagfiles ) ;
|
|
if ( t4 == 0 )
|
|
break ;
|
|
tfile4close( t4, data ) ;
|
|
#else
|
|
i4 = (INDEX4FILE *)l4first( &data->indexes ) ;
|
|
if ( i4 == 0 )
|
|
break ;
|
|
index4close( i4 ) ;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
if ( data->link.n != 0 )
|
|
l4remove( &c4->dataFileList, data ) ;
|
|
|
|
if ( file4openTest( &data->file ) )
|
|
if ( file4close( &data->file ) < 0 )
|
|
finalRc = error4set( c4, 0 ) ;
|
|
|
|
data->record = 0 ;
|
|
|
|
mem4free( c4->data4fileMemory, data ) ;
|
|
error4set( c4, (short)finalRc ) ;
|
|
return finalRc ;
|
|
}
|
|
|
|
/* closes all datafiles for which the user count is zero */
|
|
int code4dataFileCloseAll( CODE4 *c4 )
|
|
{
|
|
DATA4FILE *data ;
|
|
int rc ;
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( c4 == 0 )
|
|
return error4( 0, e4parm_null, E91304 ) ;
|
|
#endif
|
|
|
|
for( ;; )
|
|
{
|
|
for ( data = (DATA4FILE *)l4first( &c4->dataFileList ) ;; )
|
|
{
|
|
if ( data == 0 )
|
|
break ;
|
|
if ( data->userCount > 0 )
|
|
data = (DATA4FILE *)l4next( &c4->dataFileList, data ) ;
|
|
else
|
|
break ;
|
|
}
|
|
if ( data == 0 )
|
|
break ;
|
|
rc = dfile4closeLow( data ) ;
|
|
if ( rc < 0 ) /* need to return in order to avoid endless loop */
|
|
return error4stack( c4, (short)rc, E91304 ) ;
|
|
}
|
|
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
int dfile4close( DATA4FILE *data )
|
|
{
|
|
#ifndef S4STAND_ALONE
|
|
CODE4 *c4 ;
|
|
#endif
|
|
#ifdef S4CLIENT
|
|
int finalRc ;
|
|
INDEX4FILE *i4 ;
|
|
CONNECTION4 *connection ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_LOW
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E91102 ) ;
|
|
#endif
|
|
|
|
#ifdef E4ANALYZE
|
|
if ( data->userCount <= 0 )
|
|
return error4( 0, e4struct, E91102 ) ;
|
|
#endif
|
|
|
|
#ifndef S4STAND_ALONE
|
|
c4 = data->c4 ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
finalRc = error4set( c4, 0 ) ;
|
|
#endif
|
|
|
|
data->userCount-- ;
|
|
if ( data->userCount == 0 )
|
|
{
|
|
#ifdef S4CLIENT
|
|
if ( data->info != 0 )
|
|
{
|
|
u4free( data->info ) ;
|
|
data->info = 0 ;
|
|
}
|
|
|
|
connection = data->connection ;
|
|
if ( connection == 0 )
|
|
finalRc = e4connection ;
|
|
else
|
|
{
|
|
connection4assign( connection, CON4CLOSE, 0, data->serverId ) ;
|
|
connection4send( connection ) ;
|
|
finalRc = connection4receive( connection ) ;
|
|
if ( finalRc == 0 )
|
|
finalRc = connection4status( connection ) ;
|
|
}
|
|
#ifndef S4OFF_INDEX
|
|
for ( ;; )
|
|
{
|
|
i4 = (INDEX4FILE *)l4first( &data->indexes ) ;
|
|
if ( i4 == 0 )
|
|
break ;
|
|
index4close( i4 ) ;
|
|
}
|
|
#endif
|
|
|
|
l4remove( &c4->dataFileList, data ) ;
|
|
mem4free( c4->data4fileMemory, data ) ;
|
|
error4set( c4, finalRc ) ;
|
|
return finalRc ;
|
|
#else
|
|
#ifdef S4SERVER
|
|
if ( c4->server->keepOpen == 0 || data->valid != 1 ) /* not a valid datafile (failure in dfile4open) so close */
|
|
return dfile4closeLow( data ) ;
|
|
if ( data->file.isTemp && c4->server->keepOpen != 2 ) /* cannot leave temp files open or they will never close */
|
|
return dfile4closeLow( data ) ;
|
|
data->singleClient = 0 ;
|
|
time( &data->nullTime ) ;
|
|
#else
|
|
return dfile4closeLow( data ) ;
|
|
#endif
|
|
#endif /* S4CLIENT */
|
|
}
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
#ifdef P4ARGS_USED
|
|
#pragma argsused
|
|
#endif
|
|
/* clears all locks for a given DATA4 from the list (useful when closing a file) */
|
|
void code4lockClearData( CODE4 *c4, DATA4 *data )
|
|
{
|
|
#ifndef S4SINGLE
|
|
LOCK4 *lock, *lockNext ;
|
|
TRAN4 *trans ;
|
|
|
|
#ifdef S4SERVER
|
|
trans = &c4->currentClient->trans ;
|
|
#else
|
|
trans = &c4->c4trans.trans ;
|
|
#endif
|
|
|
|
for ( lockNext = (LOCK4 *)l4first( &trans->locks ) ;; )
|
|
{
|
|
lock = lockNext ;
|
|
if ( lock == 0 )
|
|
break ;
|
|
lockNext = (LOCK4 *)l4next( &trans->locks, lock ) ;
|
|
#ifdef S4SERVER
|
|
if ( lock->id.clientId != data4clientId( data ) || lock->id.serverId != data4serverId( data ) )
|
|
continue ;
|
|
#else
|
|
#ifdef S4CLIENT
|
|
if ( lock->data != data )
|
|
#else
|
|
if ( lock->data != data->dataFile )
|
|
#endif
|
|
continue ;
|
|
#endif
|
|
l4remove( &trans->locks, lock ) ;
|
|
mem4free( c4->lockMemory, lock ) ;
|
|
}
|
|
#endif /* S4SINGLE */
|
|
return ;
|
|
}
|
|
|
|
int S4FUNCTION d4close( DATA4 *data )
|
|
{
|
|
int rc, saveRc, saveRc2 ;
|
|
CODE4 *c4 ;
|
|
#ifndef S4CLIENT
|
|
#ifndef S4OFF_WRITE
|
|
#ifndef S4OFF_TRAN
|
|
long connectionId ;
|
|
TRAN4 *trans = 0 ;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#ifndef S4INDEX_OFF
|
|
INDEX4 *indexNext, *indexOn ;
|
|
#endif
|
|
#ifdef E4ANALYZE
|
|
LINK4 compareLink ;
|
|
#endif
|
|
#ifndef S4MEMO_OFF
|
|
int i ;
|
|
#endif
|
|
#ifndef S4SINGLE
|
|
int saveAttempts ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E91302 ) ;
|
|
#endif
|
|
|
|
c4 = data->codeBase ;
|
|
saveRc = 0 ;
|
|
|
|
#ifndef S4SINGLE
|
|
saveAttempts = c4->lockAttempts ;
|
|
c4->lockAttempts = WAIT4EVER ;
|
|
#endif
|
|
if ( error4code( c4 ) == e4unique )
|
|
data->recordChanged = 0 ;
|
|
|
|
if ( error4code( c4 ) < 0 )
|
|
saveRc2 = error4set( c4, 0 ) ;
|
|
else
|
|
saveRc2 = 0 ;
|
|
|
|
if ( data->dataFile != 0 )
|
|
{
|
|
/* need to remove any references to any code4lock() calls */
|
|
code4lockClearData( c4, data ) ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
saveRc = d4update( data ) ;
|
|
if ( saveRc == e4unique )
|
|
data->recordChanged = 0 ;
|
|
#endif
|
|
|
|
#ifndef S4OFF_TRAN
|
|
#ifndef S4OFF_WRITE
|
|
#ifndef S4CLIENT
|
|
#ifdef S4SERVER
|
|
if ( c4->currentClient != 0 )
|
|
#endif
|
|
if ( code4transEnabled( c4 ) )
|
|
{
|
|
trans = code4trans( c4 ) ;
|
|
#ifdef S4STAND_ALONE
|
|
connectionId = 0L ;
|
|
#else
|
|
connectionId = connection4id( c4->currentClient->connection ) ;
|
|
#endif
|
|
|
|
if ( trans->currentTranStatus != r4active )
|
|
{
|
|
rc = tran4set( trans, trans->currentTranStatus, -1L, connectionId, TRAN4CLOSE,
|
|
0, data4clientId( data ), data4serverId( data ) ) ;
|
|
if ( rc < 0 )
|
|
saveRc = rc ;
|
|
if ( tran4lowAppend( trans, "\0" ) != 0 )
|
|
saveRc = e4transAppend ;
|
|
}
|
|
}
|
|
else
|
|
trans = 0 ;
|
|
#endif
|
|
#endif /* S4OFF_WRITE */
|
|
#endif /* S4OFF_TRAN */
|
|
|
|
#ifndef S4OFF_TRAN
|
|
#ifndef S4OFF_WRITE
|
|
#ifdef S4CLIENT
|
|
if ( code4transEnabled( c4 ) ) /* can't unlock in this instance */
|
|
if ( code4tranStatus( c4 ) == r4active )
|
|
#else
|
|
if ( trans != 0 ) /* just add to list */
|
|
if ( trans->currentTranStatus == r4active )
|
|
#endif
|
|
{
|
|
l4remove( tran4dataList( data->trans ), data ) ;
|
|
l4add( &(code4trans( c4 )->closedDataFiles), data ) ;
|
|
#ifndef S4SINGLE
|
|
c4->lockAttempts = saveAttempts ;
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4SINGLE
|
|
if ( d4unlock( data ) < 0 )
|
|
saveRc = error4set( c4, 0 ) ;
|
|
#endif /* S4SINGLE */
|
|
|
|
#ifndef S4INDEX_OFF
|
|
for( indexNext = (INDEX4 *)l4first( &data->indexes );; )
|
|
{
|
|
indexOn = indexNext ;
|
|
indexNext = (INDEX4 *)l4next( &data->indexes, indexOn ) ;
|
|
if ( !indexOn )
|
|
break ;
|
|
|
|
rc = i4close( indexOn ) ;
|
|
if ( rc < 0 )
|
|
{
|
|
saveRc = rc ;
|
|
error4set( c4, 0 ) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef S4MEMO_OFF
|
|
if ( data->fieldsMemo != 0 )
|
|
{
|
|
for ( i = 0; i < data->dataFile->nFieldsMemo ; i++ )
|
|
if ( data->fieldsMemo[i].contents != &f4memoNullChar )
|
|
{
|
|
u4free( data->fieldsMemo[i].contents ) ;
|
|
data->fieldsMemo[i].contents = &f4memoNullChar ;
|
|
}
|
|
u4free( data->fieldsMemo ) ;
|
|
data->fieldsMemo = 0 ;
|
|
}
|
|
#endif /* S4MEMO_OFF */
|
|
|
|
#ifdef S4CLIENT
|
|
if ( c4->doRemove == 1 )
|
|
rc = dfile4remove( data->dataFile ) ;
|
|
else
|
|
#endif
|
|
rc = dfile4close( data->dataFile ) ;
|
|
if ( rc < 0 )
|
|
saveRc = rc ;
|
|
data->dataFile = 0 ;
|
|
|
|
if ( data->groupRecordAlloc != 0 )
|
|
{
|
|
u4free( data->groupRecordAlloc ) ;
|
|
data->record = 0 ;
|
|
data->recordOld = 0 ;
|
|
data->fields = 0 ;
|
|
}
|
|
else
|
|
{
|
|
u4free( data->record ) ;
|
|
u4free( data->recordOld ) ;
|
|
u4free( data->fields ) ;
|
|
}
|
|
|
|
if ( data->trans != 0 )
|
|
l4remove( tran4dataList( data->trans ), data ) ;
|
|
#ifdef E4ANALYZE
|
|
else
|
|
{
|
|
memset( &compareLink, 0, sizeof( LINK4 ) ) ;
|
|
if ( c4memcmp( &data->link, &compareLink, sizeof( LINK4 ) ) != 0 )
|
|
saveRc = error4( c4, e4struct, E81305 ) ;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
if ( data->trans != 0 )
|
|
l4remove( tran4dataList( data->trans ), data ) ;
|
|
|
|
mem4free( c4->dataMemory, data ) ;
|
|
|
|
if ( saveRc != 0 )
|
|
error4set( c4, (short)saveRc ) ;
|
|
|
|
#ifndef S4SINGLE
|
|
c4->lockAttempts = saveAttempts ;
|
|
#endif
|
|
if ( saveRc2 < 0 )
|
|
{
|
|
error4set( c4, (short)saveRc2 ) ;
|
|
return saveRc2 ;
|
|
}
|
|
return saveRc ;
|
|
}
|