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