af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
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
|
|
}
|
|
|