1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-27 08:52:26 +03:00

Unix version of sqlite3OsLock(). (CVS 1520)

FossilOrigin-Name: 023d1760c1a720632b25c98d14bf521ab91861e2
This commit is contained in:
danielk1977
2004-06-01 14:09:28 +00:00
parent fedc8347c0
commit 9a1d0abed4
5 changed files with 303 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
C Fix\stypo\son\shomepage\s(CVS\s1519) C Unix\sversion\sof\ssqlite3OsLock().\s(CVS\s1520)
D 2004-06-01T12:59:50 D 2004-06-01T14:09:29
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -39,11 +39,11 @@ F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
F src/main.c 66c6c35e94f57a7505f7f44b5a9504fb60ca0730 F src/main.c 66c6c35e94f57a7505f7f44b5a9504fb60ca0730
F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481 F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67 F src/os.h 833b9639720d1602d9bfa4ca69c615ec2bfe625a
F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0 F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4 F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
F src/os_unix.c 585665eccd31a9bb4dc090bc6b5e29d8d42899f0 F src/os_unix.c 3dc2868d7ff477323f2eaedda0e05921afb6f124
F src/os_unix.h 426e1480f0847a7f8ba22aa9ac5115520875610b F src/os_unix.h 426e1480f0847a7f8ba22aa9ac5115520875610b
F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
@@ -59,7 +59,7 @@ F src/sqlite.h.in d8222d4a1f76468560b60f2b7f5b592995ebd5cf
F src/sqliteInt.h 8a3a6dc8ef5141563698a3b7a62fca7158cff1f5 F src/sqliteInt.h 8a3a6dc8ef5141563698a3b7a62fca7158cff1f5
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
F src/tclsqlite.c ed8663e7703346ace72ca3899dba15dbfc0883d7 F src/tclsqlite.c ed8663e7703346ace72ca3899dba15dbfc0883d7
F src/test1.c 42c494918ecfab5a86586a28a66a73968312aad1 F src/test1.c 4a3cc1b628a29f24c0a43227a035d0f2a96eb634
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872 F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
F src/test3.c 86117b74ec7353d76f5cd85c144c7cda23a7e11b F src/test3.c 86117b74ec7353d76f5cd85c144c7cda23a7e11b
F src/test4.c caf675e443460ec76b04d78e1688986c17c82cec F src/test4.c caf675e443460ec76b04d78e1688986c17c82cec
@@ -214,7 +214,7 @@ F www/support.tcl 67682848d6ddd283370451dc3da2e56cded9fc9a
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 915cba57123f859c7f128bd52580573877c502ba P a84ece250035d02e399ec208aded524c20c12737
R 869771be1ad6b0ff5d2cfdaa96e9bfc9 R 3b5d7842c2050c5f20aa6a72a163fd62
U drh U danielk1977
Z b8d78d36bfca5048d38c8cf79e8d6789 Z e93eb17e32e32c7486f10dc44fff52c2

View File

@@ -1 +1 @@
a84ece250035d02e399ec208aded524c20c12737 023d1760c1a720632b25c98d14bf521ab91861e2

View File

@@ -80,6 +80,14 @@
# define TEMP_FILE_PREFIX "sqlite_" # define TEMP_FILE_PREFIX "sqlite_"
#endif #endif
/*
** The following values may be passed as the second argument to
** sqlite3OsLock().
*/
#define SHARED_LOCK 1
#define RESERVED_LOCK 2
#define PENDING_LOCK 3
#define EXCLUSIVE_LOCK 4
int sqlite3OsDelete(const char*); int sqlite3OsDelete(const char*);
int sqlite3OsFileExists(const char*); int sqlite3OsFileExists(const char*);
@@ -105,5 +113,6 @@ int sqlite3OsCurrentTime(double*);
void sqlite3OsEnterMutex(void); void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void); void sqlite3OsLeaveMutex(void);
char *sqlite3OsFullPathname(const char*); char *sqlite3OsFullPathname(const char*);
int sqlite3OsLock(OsFile*, int);
#endif /* _SQLITE_OS_H_ */ #endif /* _SQLITE_OS_H_ */

View File

@@ -172,6 +172,7 @@ struct lockKey {
struct lockInfo { struct lockInfo {
struct lockKey key; /* The lookup key */ struct lockKey key; /* The lookup key */
int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */
int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
int nRef; /* Number of pointers to this structure */ int nRef; /* Number of pointers to this structure */
}; };
@@ -265,6 +266,7 @@ int findLockInfo(
pLock->key = key1; pLock->key = key1;
pLock->nRef = 1; pLock->nRef = 1;
pLock->cnt = 0; pLock->cnt = 0;
pLock->locktype = 0;
pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
if( pOld!=0 ){ if( pOld!=0 ){
assert( pOld==pLock ); assert( pOld==pLock );
@@ -648,36 +650,7 @@ int sqlite3OsFileSize(OsFile *id, off_t *pSize){
*/ */
int sqlite3OsReadLock(OsFile *id){ int sqlite3OsReadLock(OsFile *id){
int rc; int rc;
sqlite3OsEnterMutex(); return sqlite3OsLock(id, SHARED_LOCK);
if( id->pLock->cnt>0 ){
if( !id->locked ){
id->pLock->cnt++;
id->locked = 1;
id->pOpen->nLock++;
}
rc = SQLITE_OK;
}else if( id->locked || id->pLock->cnt==0 ){
struct flock lock;
int s;
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
s = fcntl(id->fd, F_SETLK, &lock);
if( s!=0 ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
rc = SQLITE_OK;
if( !id->locked ){
id->pOpen->nLock++;
id->locked = 1;
}
id->pLock->cnt = 1;
}
}else{
rc = SQLITE_BUSY;
}
sqlite3OsLeaveMutex();
return rc;
} }
/* /*
@@ -688,27 +661,132 @@ int sqlite3OsReadLock(OsFile *id){
*/ */
int sqlite3OsWriteLock(OsFile *id){ int sqlite3OsWriteLock(OsFile *id){
int rc; int rc;
return sqlite3OsLock(id, EXCLUSIVE_LOCK);
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** SHARED_LOCK
** RESERVED_LOCK
** PENDING_LOCK
** EXCLUSIVE_LOCK
*/
int sqlite3OsLock(OsFile *id, int locktype){
int rc = SQLITE_OK;
struct lockInfo *pLock = id->pLock;
struct flock lock;
int s;
/* It is an error to request any kind of lock before a shared lock */
if( locktype>SHARED_LOCK && id->locked==0 ){
rc = sqlite3OsLock(id, SHARED_LOCK);
if( rc!=SQLITE_OK ) return rc;
}
assert( locktype==SHARED_LOCK || id->locked!=0 );
/* If there is already a lock of this type or more restrictive on the
** OsFile, do nothing. Don't use the end_lock: exit path, as
** sqlite3OsEnterMutex() hasn't been called yet.
*/
if( id->locked>=locktype ){
return SQLITE_OK;
}
sqlite3OsEnterMutex(); sqlite3OsEnterMutex();
if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){
struct flock lock; /* If some thread using this PID has a lock via a different OsFile*
int s; ** handle that precludes the requested lock, return BUSY.
lock.l_type = F_WRLCK; */
lock.l_whence = SEEK_SET; if( (id->locked!=pLock->locktype &&
lock.l_start = lock.l_len = 0L; (pLock->locktype>RESERVED_LOCK || locktype!=SHARED_LOCK)) ||
(locktype>RESERVED_LOCK && pLock->cnt>1)
){
rc = SQLITE_BUSY;
goto end_lock;
}
/* If a SHARED lock is requested, and some thread using this PID already
** has a SHARED or RESERVED lock, then increment reference counts and
** return SQLITE_OK.
*/
if( locktype==SHARED_LOCK &&
(pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
assert( locktype==SHARED_LOCK );
assert( id->locked==0 );
id->locked = SHARED_LOCK;
pLock->cnt++;
id->pOpen->nLock++;
goto end_lock;
}
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
assert( pLock->cnt==0 );
assert( id->pOpen->nLock==0 );
assert( pLock->locktype==0 );
/* Grab a read-lock on byte 2. This ensures that no other process
** has a PENDING lock.
*/
lock.l_type = F_RDLCK;
lock.l_start = 2;
s = fcntl(id->fd, F_SETLK, &lock); s = fcntl(id->fd, F_SETLK, &lock);
if( s!=0 ){ if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
goto end_lock;
}
/* Now get a read-lock on byte 0 and renege on the byte 2 lock. */
lock.l_start = 0;
s = fcntl(id->fd, F_SETLK, &lock);
lock.l_start = 2;
lock.l_type = F_UNLCK;
fcntl(id->fd, F_SETLK, &lock);
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{ }else{
rc = SQLITE_OK; id->locked = SHARED_LOCK;
if( !id->locked ){ id->pOpen->nLock = 1;
id->pOpen->nLock++; pLock->cnt = 1;
id->locked = 1;
}
id->pLock->cnt = -1;
} }
}else{ }else{
rc = SQLITE_BUSY; /* The request was for a RESERVED, PENDING or EXCLUSIVE lock. It is
** assumed that there is a SHARED or greater lock on the file
** already.
*/
assert( 0!=id->locked );
lock.l_type = F_WRLCK;
switch( locktype ){
case RESERVED_LOCK:
lock.l_start = 1;
break;
case PENDING_LOCK:
lock.l_start = 2;
break;
case EXCLUSIVE_LOCK:
lock.l_start = 0;
break;
default:
assert(0);
}
s = fcntl(id->fd, F_SETLK, &lock);
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}
} }
id->locked = locktype;
pLock->locktype = locktype;
assert(pLock->locktype==RESERVED_LOCK||(id->pOpen->nLock==1&&pLock->cnt==1));
end_lock:
sqlite3OsLeaveMutex(); sqlite3OsLeaveMutex();
return rc; return rc;
} }
@@ -725,6 +803,7 @@ int sqlite3OsUnlock(OsFile *id){
sqlite3OsEnterMutex(); sqlite3OsEnterMutex();
assert( id->pLock->cnt!=0 ); assert( id->pLock->cnt!=0 );
if( id->pLock->cnt>1 ){ if( id->pLock->cnt>1 ){
id->locked = 0;
id->pLock->cnt--; id->pLock->cnt--;
rc = SQLITE_OK; rc = SQLITE_OK;
}else{ }else{
@@ -739,6 +818,8 @@ int sqlite3OsUnlock(OsFile *id){
}else{ }else{
rc = SQLITE_OK; rc = SQLITE_OK;
id->pLock->cnt = 0; id->pLock->cnt = 0;
id->pLock->locktype = 0;
id->locked = 0;
} }
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){

View File

@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test1.c,v 1.68 2004/05/31 23:56:43 danielk1977 Exp $ ** $Id: test1.c,v 1.69 2004/06/01 14:09:29 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@@ -117,6 +117,21 @@ static int getStmtPointer(
return TCL_OK; return TCL_OK;
} }
/*
** Decode a pointer to an sqlite3_stmt object.
*/
static int getFilePointer(
Tcl_Interp *interp,
const char *zArg,
OsFile **ppFile
){
if( sscanf(zArg, PTR_FMT, (void**)ppFile)!=1 ){
Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0);
return TCL_ERROR;
}
return TCL_OK;
}
/* /*
** Generate a text representation of a pointer that can be understood ** Generate a text representation of a pointer that can be understood
** by the getDbPointer and getVmPointer routines above. ** by the getDbPointer and getVmPointer routines above.
@@ -1677,7 +1692,144 @@ static int test_stmt_int(
return TCL_OK; return TCL_OK;
} }
/*
** Usage: sqlite3OsOpenReadWrite <filename>
*/
static int test_sqlite3OsOpenReadWrite(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
OsFile * pFile;
int rc;
int dummy;
char zBuf[100];
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetString(objv[0]), " filename", 0);
return TCL_ERROR;
}
pFile = sqliteMalloc(sizeof(OsFile));
rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
if( rc!=SQLITE_OK ){
sqliteFree(pFile);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_ERROR;
}
makePointerStr(interp, zBuf, pFile);
Tcl_SetResult(interp, zBuf, 0);
return TCL_ERROR;
}
/*
** Usage: sqlite3OsClose <file handle>
*/
static int test_sqlite3OsClose(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
OsFile * pFile;
int rc;
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetString(objv[0]), " filehandle", 0);
return TCL_ERROR;
}
if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
return TCL_ERROR;
}
rc = sqlite3OsClose(pFile);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_ERROR;
}
sqliteFree(pFile);
return TCL_OK;
}
/*
** Usage: sqlite3OsLock <file handle> <locktype>
*/
static int test_sqlite3OsLock(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
OsFile * pFile;
int rc;
if( objc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetString(objv[0]),
" filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
return TCL_ERROR;
}
if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
return TCL_ERROR;
}
if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
rc = sqlite3OsLock(pFile, SHARED_LOCK);
}
else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
rc = sqlite3OsLock(pFile, RESERVED_LOCK);
}
else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
rc = sqlite3OsLock(pFile, PENDING_LOCK);
}
else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
}else{
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetString(objv[0]),
" filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
return TCL_ERROR;
}
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: sqlite3OsUnlock <file handle>
*/
static int test_sqlite3OsUnlock(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
OsFile * pFile;
int rc;
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetString(objv[0]), " filehandle", 0);
return TCL_ERROR;
}
if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
return TCL_ERROR;
}
rc = sqlite3OsUnlock(pFile);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
/* /*
** Register commands with the TCL interpreter. ** Register commands with the TCL interpreter.
@@ -1753,6 +1905,12 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16},
{ "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16},
/* Functions from os.h */
{ "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
{ "sqlite3OsClose", test_sqlite3OsClose, 0 },
{ "sqlite3OsLock", test_sqlite3OsLock, 0 },
{ "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
}; };
int i; int i;