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