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:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\stypo\son\shomepage\s(CVS\s1519)
|
||||
D 2004-06-01T12:59:50
|
||||
C Unix\sversion\sof\ssqlite3OsLock().\s(CVS\s1520)
|
||||
D 2004-06-01T14:09:29
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -39,11 +39,11 @@ F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
|
||||
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
|
||||
F src/main.c 66c6c35e94f57a7505f7f44b5a9504fb60ca0730
|
||||
F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
|
||||
F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67
|
||||
F src/os.h 833b9639720d1602d9bfa4ca69c615ec2bfe625a
|
||||
F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
|
||||
F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
|
||||
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_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
|
||||
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
|
||||
@@ -59,7 +59,7 @@ F src/sqlite.h.in d8222d4a1f76468560b60f2b7f5b592995ebd5cf
|
||||
F src/sqliteInt.h 8a3a6dc8ef5141563698a3b7a62fca7158cff1f5
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c ed8663e7703346ace72ca3899dba15dbfc0883d7
|
||||
F src/test1.c 42c494918ecfab5a86586a28a66a73968312aad1
|
||||
F src/test1.c 4a3cc1b628a29f24c0a43227a035d0f2a96eb634
|
||||
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
|
||||
F src/test3.c 86117b74ec7353d76f5cd85c144c7cda23a7e11b
|
||||
F src/test4.c caf675e443460ec76b04d78e1688986c17c82cec
|
||||
@@ -214,7 +214,7 @@ F www/support.tcl 67682848d6ddd283370451dc3da2e56cded9fc9a
|
||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P 915cba57123f859c7f128bd52580573877c502ba
|
||||
R 869771be1ad6b0ff5d2cfdaa96e9bfc9
|
||||
U drh
|
||||
Z b8d78d36bfca5048d38c8cf79e8d6789
|
||||
P a84ece250035d02e399ec208aded524c20c12737
|
||||
R 3b5d7842c2050c5f20aa6a72a163fd62
|
||||
U danielk1977
|
||||
Z e93eb17e32e32c7486f10dc44fff52c2
|
||||
|
||||
@@ -1 +1 @@
|
||||
a84ece250035d02e399ec208aded524c20c12737
|
||||
023d1760c1a720632b25c98d14bf521ab91861e2
|
||||
9
src/os.h
9
src/os.h
@@ -80,6 +80,14 @@
|
||||
# define TEMP_FILE_PREFIX "sqlite_"
|
||||
#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 sqlite3OsFileExists(const char*);
|
||||
@@ -105,5 +113,6 @@ int sqlite3OsCurrentTime(double*);
|
||||
void sqlite3OsEnterMutex(void);
|
||||
void sqlite3OsLeaveMutex(void);
|
||||
char *sqlite3OsFullPathname(const char*);
|
||||
int sqlite3OsLock(OsFile*, int);
|
||||
|
||||
#endif /* _SQLITE_OS_H_ */
|
||||
|
||||
165
src/os_unix.c
165
src/os_unix.c
@@ -172,6 +172,7 @@ struct lockKey {
|
||||
struct lockInfo {
|
||||
struct lockKey key; /* The lookup key */
|
||||
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 */
|
||||
};
|
||||
|
||||
@@ -265,6 +266,7 @@ int findLockInfo(
|
||||
pLock->key = key1;
|
||||
pLock->nRef = 1;
|
||||
pLock->cnt = 0;
|
||||
pLock->locktype = 0;
|
||||
pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
|
||||
if( pOld!=0 ){
|
||||
assert( pOld==pLock );
|
||||
@@ -648,36 +650,7 @@ int sqlite3OsFileSize(OsFile *id, off_t *pSize){
|
||||
*/
|
||||
int sqlite3OsReadLock(OsFile *id){
|
||||
int rc;
|
||||
sqlite3OsEnterMutex();
|
||||
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;
|
||||
return sqlite3OsLock(id, SHARED_LOCK);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -688,27 +661,132 @@ int sqlite3OsReadLock(OsFile *id){
|
||||
*/
|
||||
int sqlite3OsWriteLock(OsFile *id){
|
||||
int rc;
|
||||
sqlite3OsEnterMutex();
|
||||
if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){
|
||||
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;
|
||||
lock.l_type = F_WRLCK;
|
||||
|
||||
/* 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();
|
||||
|
||||
/* If some thread using this PID has a lock via a different OsFile*
|
||||
** handle that precludes the requested lock, return BUSY.
|
||||
*/
|
||||
if( (id->locked!=pLock->locktype &&
|
||||
(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;
|
||||
lock.l_start = lock.l_len = 0L;
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
if( !id->locked ){
|
||||
id->pOpen->nLock++;
|
||||
id->locked = 1;
|
||||
}
|
||||
id->pLock->cnt = -1;
|
||||
id->locked = SHARED_LOCK;
|
||||
id->pOpen->nLock = 1;
|
||||
pLock->cnt = 1;
|
||||
}
|
||||
}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();
|
||||
return rc;
|
||||
}
|
||||
@@ -725,6 +803,7 @@ int sqlite3OsUnlock(OsFile *id){
|
||||
sqlite3OsEnterMutex();
|
||||
assert( id->pLock->cnt!=0 );
|
||||
if( id->pLock->cnt>1 ){
|
||||
id->locked = 0;
|
||||
id->pLock->cnt--;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
@@ -739,6 +818,8 @@ int sqlite3OsUnlock(OsFile *id){
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
id->pLock->cnt = 0;
|
||||
id->pLock->locktype = 0;
|
||||
id->locked = 0;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
160
src/test1.c
160
src/test1.c
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** 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 "tcl.h"
|
||||
@@ -117,6 +117,21 @@ static int getStmtPointer(
|
||||
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
|
||||
** by the getDbPointer and getVmPointer routines above.
|
||||
@@ -1677,7 +1692,144 @@ static int test_stmt_int(
|
||||
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.
|
||||
@@ -1753,6 +1905,12 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16},
|
||||
{ "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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user