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