478 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* d4unlock.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| static int d4hasLocks( DATA4 *data, long clientId, long serverId )
 | |
| {
 | |
|    #ifdef S4CLIENT
 | |
|       LOCK4LINK *lock ;
 | |
| 
 | |
|       #ifdef L4LOCK_CHECK
 | |
|          at return time, make sure call server to see if the expected lock matches...
 | |
|       #endif
 | |
| 
 | |
|       if ( serverId == 0 )   /* likely failed open */
 | |
|          return 0 ;
 | |
| 
 | |
|       if ( data->dataFile->fileLock != data && data->dataFile->appendLock != data )
 | |
|       {
 | |
|          for ( lock = 0 ;; )
 | |
|          {
 | |
|             lock = (LOCK4LINK *)l4next( &data->dataFile->lockedRecords, lock ) ;
 | |
|             if ( lock == 0 )
 | |
|                return 0 ;
 | |
|             if ( lock->data == data )
 | |
|                return 1 ;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       return 1 ;
 | |
|    #else
 | |
|       LOCK4 *lock ;
 | |
| 
 | |
|       if ( serverId == 0 )   /* likely failed open */
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       if ( ( data->dataFile->fileServerLock == serverId && ( data->dataFile->fileClientLock == clientId || clientId == 0 ) ) ||
 | |
|            ( ( data->dataFile->appendClientLock == clientId || clientId == 0 ) && data->dataFile->appendServerLock == serverId ) )
 | |
|          return 1 ;
 | |
| 
 | |
|       for ( lock = 0 ;; )
 | |
|       {
 | |
|          lock = (LOCK4 *)l4next( &data->dataFile->lockedRecords, lock ) ;
 | |
|          if ( lock == 0 )
 | |
|             return 0 ;
 | |
|          if ( ( lock->id.clientId == clientId || clientId == 0 ) && lock->id.serverId == serverId )
 | |
|             return 1 ;
 | |
|       }
 | |
|    #endif
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef S4CLIENT
 | |
| void d4unlockClientData( DATA4 *data )
 | |
| {
 | |
|    DATA4FILE *dfile ;
 | |
|    LOCK4LINK *lock, *nextLock ;
 | |
| 
 | |
|    #ifdef S4SERVER
 | |
|       if ( data->accessMode == OPEN4DENY_RW )
 | |
|          return ;
 | |
|    #endif
 | |
| 
 | |
|    dfile = data->dataFile ;
 | |
| 
 | |
|    if ( dfile->fileLock == data )
 | |
|    {
 | |
|       data->dataFile->numRecs = -1 ;
 | |
|       dfile->fileLock = 0 ;
 | |
|    }
 | |
|    if ( dfile->appendLock == data )
 | |
|    {
 | |
|       data->dataFile->numRecs = -1 ;
 | |
|       dfile->appendLock = 0 ;
 | |
|    }
 | |
|    lock = (LOCK4LINK *)l4first( &dfile->lockedRecords ) ;
 | |
|    if ( lock != 0 )
 | |
|       for ( ;; )
 | |
|       {
 | |
|          nextLock = (LOCK4LINK *)l4next( &dfile->lockedRecords, lock ) ;
 | |
|          if ( lock->data == data )
 | |
|          {
 | |
|             l4remove( &dfile->lockedRecords, lock ) ;
 | |
|             mem4free( data->codeBase->lockLinkMemory, lock ) ;
 | |
|          }
 | |
|          if ( nextLock == 0 )
 | |
|             break ;
 | |
|          lock = nextLock ;
 | |
|       }
 | |
| 
 | |
|    return ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| /* clientId if set to 0 will unlock all client instance of the data file,
 | |
|    if set to a value will only unlock the given client instance */
 | |
| static int d4unlockDo( DATA4 *data, const long clientId )
 | |
| {
 | |
|    CODE4 *c4 ;
 | |
|    #ifdef S4CLIENT
 | |
|       int rc ;
 | |
|       CONNECTION4 *connection ;
 | |
|    #else
 | |
|       int rc, saveUnlockAuto ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = data->codeBase ;
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       #ifndef S4OFF_WRITE
 | |
|          if ( code4transEnabled( c4 ) )
 | |
|             if ( code4tranStatus( c4 ) == r4active )
 | |
|                return error4( c4, e4transViolation, E92801 ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    if ( d4hasLocks( data, clientId, data4serverId( data ) ) == 0 )  /* first make sure there are locks to undo */
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       rc =  d4update( data ) ;  /* returns -1 if error4code( codeBase ) < 0 */
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( c4, (short int)rc, E92801 ) ;
 | |
| 
 | |
|       /* in case of rollback and exclusive files, make sure count set to -1 */
 | |
|       data->dataFile->numRecs = -1 ;
 | |
| 
 | |
|       connection = data->dataFile->connection ;
 | |
|       if ( connection == 0 )
 | |
|          return error4stack( c4, e4connection, E92801 ) ;
 | |
|       connection4assign( connection, CON4UNLOCK, clientId, data4serverId( data ) ) ;
 | |
| 
 | |
|       connection4send( connection ) ;
 | |
|       rc = connection4receive( connection ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( c4, rc, E92801 ) ;
 | |
| 
 | |
|       rc = connection4status( connection ) ;
 | |
|       if ( rc < 0 )
 | |
|          return connection4error( connection, c4, rc, E92801 ) ;
 | |
| 
 | |
|       if ( code4trans( c4 )->unlockAuto == 2 )  /* cb51 compat, remove lock */
 | |
|          d4unlockClientData( data ) ;
 | |
| 
 | |
|       return rc ;
 | |
|    #else
 | |
|       #ifndef S4OFF_WRITE
 | |
|          #ifndef S4OFF_TRAN
 | |
|             if ( code4transEnabled( c4 ) )
 | |
|                if ( code4tranStatus( c4 ) != r4inactive )
 | |
|                   return 0 ;
 | |
|          #endif
 | |
| 
 | |
|          rc =  d4update( data ) ;  /* returns -1 if error4code( codeBase ) < 0 */
 | |
|          if ( rc < 0 )
 | |
|             return error4stack( c4, (short int)rc, E92801 ) ;
 | |
|       #else
 | |
|          rc = 0 ;
 | |
|       #endif
 | |
| 
 | |
|       saveUnlockAuto = code4unlockAuto( c4 ) ;
 | |
|       if ( saveUnlockAuto == 0 )   /* leave if 1 or 2 -- don't change 2 */
 | |
|          code4unlockAutoSet( c4, 1 ) ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          dfile4unlockData( data->dataFile, clientId, data4serverId( data ) ) ;
 | |
|          if ( code4unlockAuto( c4 ) == LOCK4DATA )
 | |
|             if ( c4->currentClient->connection != 0 )
 | |
|                if ( c4->currentClient->connection->message != 0 )
 | |
|                   packet4setDidUnlockData( c4->currentClient->connection->message->packet, 1 ) ;
 | |
|       #else
 | |
|          d4unlockData( data ) ;
 | |
|       #endif
 | |
|       #ifndef N4OTHER
 | |
|          #ifndef S4OFF_MEMO
 | |
|             dfile4memoUnlock( data->dataFile ) ;
 | |
|          #endif
 | |
|       #endif
 | |
|       #ifndef S4OFF_INDEX
 | |
|          dfile4unlockIndex( data->dataFile, data4serverId( data ) ) ;
 | |
|       #endif
 | |
| 
 | |
|       code4unlockAutoSet( c4, saveUnlockAuto ) ;
 | |
| 
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return -1 ;
 | |
|       return rc ;
 | |
|    #endif
 | |
| }
 | |
| #endif /* S4SINGLE */
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int S4FUNCTION d4unlock( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       #ifdef S4CLIENT
 | |
|          int oldLock ;
 | |
|       #endif
 | |
|       int rc ;
 | |
| 
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92801 ) ;
 | |
|       #endif
 | |
| 
 | |
|       #ifdef S4CLIENT
 | |
|          oldLock = code4unlockAuto( data->codeBase ) ;
 | |
|          code4unlockAutoSet( data->codeBase, LOCK4DATA ) ;
 | |
|       #endif
 | |
|       rc = d4unlockDo( data, data4clientId( data ) ) ;
 | |
|       #ifdef S4CLIENT
 | |
|          code4unlockAutoSet( data->codeBase, oldLock ) ;
 | |
|       #endif
 | |
| 
 | |
|       return rc ;
 | |
|    #else
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| /*#ifdef S4STAND_ALONE*/
 | |
| #ifndef S4CLIENT
 | |
| 
 | |
| /* only unlocks the append byte */
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int d4unlockAppend( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92802 ) ;
 | |
|       #endif
 | |
|       if ( code4unlockAuto( data->codeBase ) == LOCK4OFF )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       return dfile4unlockAppend( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|    #else
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int d4unlockData( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92803 ) ;
 | |
|       #endif
 | |
|       if ( code4unlockAuto( data->codeBase ) == LOCK4OFF )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       d4unlockFile( data ) ;
 | |
|       d4unlockAppend( data ) ;
 | |
|       d4unlockRecords( data ) ;
 | |
|       if ( error4code( data->codeBase ) < 0 )
 | |
|          return error4code( data->codeBase ) ;
 | |
|    #endif
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int d4unlockFile( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       int rc ;
 | |
|       #ifdef S4VBASIC
 | |
|          if ( c4parm_check( data, 2, E92804 ) )
 | |
|             return -1 ;
 | |
|       #endif
 | |
| 
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92804 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( code4unlockAuto( data->codeBase ) == LOCK4OFF )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       rc = dfile4unlockFile( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( data->codeBase, rc, E92804 ) ;
 | |
| 
 | |
|       data->recNumOld =  -1 ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          data->memoValidated =  0 ;
 | |
|       #endif
 | |
|    #endif
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int S4FUNCTION d4unlockRecord( DATA4 *data, long rec )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92805 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( code4unlockAuto( data->codeBase ) == LOCK4OFF )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       if ( rec == data->recNum )
 | |
|       {
 | |
|          data->recNumOld =  -1 ;
 | |
|          #ifndef S4OFF_MEMO
 | |
|             data->memoValidated =  0 ;
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       return dfile4unlockRecord( data->dataFile, data4clientId( data ), data4serverId( data ), rec ) ;
 | |
|    #else
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int d4unlockRecords( DATA4 *data )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       #ifdef E4PARM_HIGH
 | |
|          if ( data == 0 )
 | |
|             return error4( 0, e4parm_null, E92806 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( code4unlockAuto( data->codeBase ) == LOCK4OFF )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          if ( data->accessMode == OPEN4DENY_RW )
 | |
|             return 0 ;
 | |
|       #endif
 | |
| 
 | |
|       data->recNumOld = -1 ;
 | |
|       #ifndef S4OFF_MEMO
 | |
|          data->memoValidated =  0 ;
 | |
|       #endif
 | |
| 
 | |
|       return dfile4unlockRecords( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | |
|    #else
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| #endif /* S4CLIENT */
 | |
| /*#endif  */ /* S4STAND_ALONE */
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| int code4unlockDo( LIST4 *dataList )
 | |
| {
 | |
|    DATA4 *dataOn ;
 | |
|    CODE4 *c4 ;
 | |
|    #ifdef S4CLIENT
 | |
|       int oldLock ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = 0 ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( dataList == 0 )
 | |
|          return error4( 0, e4parm_null, E92807 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       /* for client, any request with LOCK4ALL should cause complete
 | |
|          unlocking of everything at the lower level.
 | |
|          Therefore, only need to call on a single database--but that
 | |
|          database better have a lock.  if none have locks, call is
 | |
|          avioded. */
 | |
|       for( dataOn = 0 ;; )
 | |
|       {
 | |
|          dataOn = (DATA4 *)l4next( dataList, dataOn ) ;
 | |
|          if ( dataOn == 0 )
 | |
|             break ;
 | |
|          if ( d4hasLocks( dataOn, data4clientId( dataOn ), data4serverId( dataOn ) ) != 0 )
 | |
|          {
 | |
|             c4 = dataOn->codeBase ;
 | |
|             oldLock = code4unlockAuto( c4 ) ;
 | |
|             code4unlockAutoSet( c4, LOCK4ALL ) ;
 | |
|             d4unlockDo( dataOn, 0 ) ;
 | |
|             code4unlockAutoSet( c4, oldLock ) ;
 | |
|             break ;
 | |
|          }
 | |
|       }
 | |
|    #else
 | |
|       for ( dataOn = 0 ;; )
 | |
|       {
 | |
|          dataOn = (DATA4 *)l4next( dataList, dataOn ) ;
 | |
|          if ( dataOn == 0 )
 | |
|             break ;
 | |
|          /* reset record count because this function is likely called due to a transaction rollback */
 | |
|          d4unlockDo( dataOn, 0 ) ;
 | |
|          c4 = dataOn->codeBase ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( c4 != 0 )
 | |
|    {
 | |
|       #ifdef S4SERVER
 | |
|          if ( c4->currentClient->connection != 0 )
 | |
|             packet4setDidUnlock( c4->currentClient->connection->message->packet, 1 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return error4code( c4 ) ;
 | |
|    }
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4SINGLE */
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int S4FUNCTION code4unlock( CODE4 *c4 )
 | |
| {
 | |
|    #ifdef S4SINGLE
 | |
|       return 0 ;
 | |
|    #else
 | |
|       #ifndef S4OFF_WRITE
 | |
|          #ifndef S4OFF_TRAN
 | |
|             if ( code4transEnabled( c4 ) )
 | |
|                if ( code4tranStatus( c4 ) == r4active )
 | |
|                   return error4( c4, e4transViolation, E92807 ) ;
 | |
|          #endif
 | |
|       #endif
 | |
| 
 | |
|       #ifdef S4SERVER
 | |
|          return server4clientUnlock( c4->currentClient ) ;
 | |
|       #else
 | |
|          return code4unlockDo( tran4dataList( (&(c4->c4trans.trans)) ) ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| }
 | |
| 
 |