mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Added sqlite3OsLock for win32. Assertion fault in attach.test. (CVS 1533)
FossilOrigin-Name: 9e6cd9ec75f726ef85e60f593aaa895791315071
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sthe\ssqlite3_set_auxdata()\sand\ssqlite3_get_auxdata()\sAPIs.\s(CVS\s1532)
|
C Added\ssqlite3OsLock\sfor\swin32.\s\sAssertion\sfault\sin\sattach.test.\s(CVS\s1533)
|
||||||
D 2004-06-05T10:22:17
|
D 2004-06-06T00:42:26
|
||||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -25,7 +25,7 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
|
|||||||
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||||
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
|
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
|
||||||
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
||||||
F src/btree.c b8a253fbbcca4da758d1d21232e873d8d5c46eb5
|
F src/btree.c 5ee4cad91bdf4e2f0a5dba3a8750283a965d6d27
|
||||||
F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
|
F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
|
||||||
F src/build.c e12e602f06e37a0fbcb49af17cba68ad85e101b6
|
F src/build.c e12e602f06e37a0fbcb49af17cba68ad85e101b6
|
||||||
F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
|
F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
|
||||||
@@ -45,8 +45,8 @@ F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
|
|||||||
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
|
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
|
||||||
F src/os_unix.c a4feb70b23fa5272f53cd2c74588484b54294800
|
F src/os_unix.c a4feb70b23fa5272f53cd2c74588484b54294800
|
||||||
F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
|
F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
|
||||||
F src/os_win.c 0f895f0491a983740c08af8e5d1986f3bc4629a4
|
F src/os_win.c a5ab6da08ee90922c3e150afb814d8010383aa96
|
||||||
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
|
F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c
|
||||||
F src/pager.c 944f6b071279887574081281f27bb2af88b42905
|
F src/pager.c 944f6b071279887574081281f27bb2af88b42905
|
||||||
F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
|
F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
|
||||||
F src/parse.y 27c1ce09f9d309be91f9e537df2fb00892990af4
|
F src/parse.y 27c1ce09f9d309be91f9e537df2fb00892990af4
|
||||||
@@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
|||||||
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 e82eb722b0e0b223ddaf7d85669792c33594f9da
|
P c2899b437366d879258ab4f6ae47868441010eca
|
||||||
R 89202e63414e4abff52f3cb8f1936bee
|
R 2034d14c2145fcc5ef775d02c0479e42
|
||||||
U danielk1977
|
U drh
|
||||||
Z d38834ee375024a85c02b119ebf3aa3d
|
Z 2f61e1823db0bf2026ec8a2b5fdc4a80
|
||||||
|
@@ -1 +1 @@
|
|||||||
c2899b437366d879258ab4f6ae47868441010eca
|
9e6cd9ec75f726ef85e60f593aaa895791315071
|
@@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.158 2004/06/05 00:01:45 drh Exp $
|
** $Id: btree.c,v 1.159 2004/06/06 00:42:26 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@@ -1151,6 +1151,12 @@ page1_init_failed:
|
|||||||
*/
|
*/
|
||||||
static void unlockBtreeIfUnused(Btree *pBt){
|
static void unlockBtreeIfUnused(Btree *pBt){
|
||||||
if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
|
if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
|
||||||
|
if( pBt->pPage1->aData==0 ){
|
||||||
|
MemPage *pPage = pBt->pPage1;
|
||||||
|
pPage->aData = &((char*)pPage)[-pBt->pageSize];
|
||||||
|
pPage->pBt = pBt;
|
||||||
|
pPage->pgno = 1;
|
||||||
|
}
|
||||||
releasePage(pBt->pPage1);
|
releasePage(pBt->pPage1);
|
||||||
pBt->pPage1 = 0;
|
pBt->pPage1 = 0;
|
||||||
pBt->inStmt = 0;
|
pBt->inStmt = 0;
|
||||||
@@ -1585,6 +1591,7 @@ static void getCellInfo(BtCursor *pCur){
|
|||||||
}else{
|
}else{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
CellInfo info;
|
CellInfo info;
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
parseCell(pCur->pPage, pCur->idx, &info);
|
parseCell(pCur->pPage, pCur->idx, &info);
|
||||||
assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
|
assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
|
||||||
#endif
|
#endif
|
||||||
|
308
src/os_win.c
308
src/os_win.c
@@ -35,6 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
int sqlite3OsDelete(const char *zFilename){
|
int sqlite3OsDelete(const char *zFilename){
|
||||||
DeleteFile(zFilename);
|
DeleteFile(zFilename);
|
||||||
|
TRACE2("DELETE \"%s\"\n", zFilename);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +89,9 @@ int sqlite3OsOpenReadWrite(
|
|||||||
*pReadonly = 0;
|
*pReadonly = 0;
|
||||||
}
|
}
|
||||||
id->h = h;
|
id->h = h;
|
||||||
id->locked = 0;
|
id->locktype = NO_LOCK;
|
||||||
OpenCounter(+1);
|
OpenCounter(+1);
|
||||||
|
TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +131,9 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
|
|||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
id->h = h;
|
id->h = h;
|
||||||
id->locked = 0;
|
id->locktype = NO_LOCK;
|
||||||
OpenCounter(+1);
|
OpenCounter(+1);
|
||||||
|
TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,8 +157,9 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
|
|||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
id->h = h;
|
id->h = h;
|
||||||
id->locked = 0;
|
id->locktype = NO_LOCK;
|
||||||
OpenCounter(+1);
|
OpenCounter(+1);
|
||||||
|
TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +210,7 @@ int sqlite3OsTempFileName(char *zBuf){
|
|||||||
zBuf[j] = 0;
|
zBuf[j] = 0;
|
||||||
if( !sqlite3OsFileExists(zBuf) ) break;
|
if( !sqlite3OsFileExists(zBuf) ) break;
|
||||||
}
|
}
|
||||||
|
TRACE2("TEMP FILENAME: %s\n", zBuf);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +231,7 @@ int sqlite3OsClose(OsFile *id){
|
|||||||
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
||||||
DWORD got;
|
DWORD got;
|
||||||
SimulateIOError(SQLITE_IOERR);
|
SimulateIOError(SQLITE_IOERR);
|
||||||
TRACE2("READ %d\n", last_page);
|
TRACE2("READ %d\n", id->h);
|
||||||
if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
|
if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
|
||||||
got = 0;
|
got = 0;
|
||||||
}
|
}
|
||||||
@@ -245,7 +250,7 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
|
|||||||
int rc;
|
int rc;
|
||||||
DWORD wrote;
|
DWORD wrote;
|
||||||
SimulateIOError(SQLITE_IOERR);
|
SimulateIOError(SQLITE_IOERR);
|
||||||
TRACE2("WRITE %d\n", last_page);
|
TRACE2("WRITE %d\n", id->h);
|
||||||
while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
|
while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
|
||||||
amt -= wrote;
|
amt -= wrote;
|
||||||
pBuf = &((char*)pBuf)[wrote];
|
pBuf = &((char*)pBuf)[wrote];
|
||||||
@@ -265,7 +270,7 @@ int sqlite3OsSeek(OsFile *id, off_t offset){
|
|||||||
DWORD rc;
|
DWORD rc;
|
||||||
SEEK(offset/1024 + 1);
|
SEEK(offset/1024 + 1);
|
||||||
rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
|
rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
|
||||||
/* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */
|
TRACE3("SEEK %d %lld\n", id->h, offset);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +278,7 @@ int sqlite3OsSeek(OsFile *id, off_t offset){
|
|||||||
** Make sure all writes to a particular file are committed to disk.
|
** Make sure all writes to a particular file are committed to disk.
|
||||||
*/
|
*/
|
||||||
int sqlite3OsSync(OsFile *id){
|
int sqlite3OsSync(OsFile *id){
|
||||||
|
TRACE2("SYNC %d\n", id->h);
|
||||||
if( FlushFileBuffers(id->h) ){
|
if( FlushFileBuffers(id->h) ){
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}else{
|
}else{
|
||||||
@@ -285,6 +291,7 @@ int sqlite3OsSync(OsFile *id){
|
|||||||
*/
|
*/
|
||||||
int sqlite3OsTruncate(OsFile *id, off_t nByte){
|
int sqlite3OsTruncate(OsFile *id, off_t nByte){
|
||||||
LONG upperBits = nByte>>32;
|
LONG upperBits = nByte>>32;
|
||||||
|
TRACE3("TRUNCATE %d %lld\n", id->h, nByte);
|
||||||
SimulateIOError(SQLITE_IOERR);
|
SimulateIOError(SQLITE_IOERR);
|
||||||
SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
|
SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
|
||||||
SetEndOfFile(id->h);
|
SetEndOfFile(id->h);
|
||||||
@@ -302,28 +309,6 @@ int sqlite3OsFileSize(OsFile *id, off_t *pSize){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
|
|
||||||
** Return false (zero) for Win95, Win98, or WinME.
|
|
||||||
**
|
|
||||||
** Here is an interesting observation: Win95, Win98, and WinME lack
|
|
||||||
** the LockFileEx() API. But we can still statically link against that
|
|
||||||
** API as long as we don't call it win running Win95/98/ME. A call to
|
|
||||||
** this routine is used to determine if the host is Win95/98/ME or
|
|
||||||
** WinNT/2K/XP so that we will know whether or not we can safely call
|
|
||||||
** the LockFileEx() API.
|
|
||||||
*/
|
|
||||||
int isNT(void){
|
|
||||||
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
|
|
||||||
if( osType==0 ){
|
|
||||||
OSVERSIONINFO sInfo;
|
|
||||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
|
||||||
GetVersionEx(&sInfo);
|
|
||||||
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
|
|
||||||
}
|
|
||||||
return osType==2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Windows file locking notes:
|
** Windows file locking notes:
|
||||||
**
|
**
|
||||||
@@ -337,24 +322,18 @@ int isNT(void){
|
|||||||
** end of the file where it is unlikely to ever interfere with an
|
** end of the file where it is unlikely to ever interfere with an
|
||||||
** actual read attempt.
|
** actual read attempt.
|
||||||
**
|
**
|
||||||
** A database read lock is obtained by locking a single randomly-chosen
|
** A SHARED_LOCK is obtained by locking a single randomly-chosen
|
||||||
** byte out of a specific range of bytes. The lock byte is obtained at
|
** byte out of a specific range of bytes. The lock byte is obtained at
|
||||||
** random so two separate readers can probably access the file at the
|
** random so two separate readers can probably access the file at the
|
||||||
** same time, unless they are unlucky and choose the same lock byte.
|
** same time, unless they are unlucky and choose the same lock byte.
|
||||||
** A database write lock is obtained by locking all bytes in the range.
|
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
|
||||||
** There can only be one writer.
|
** There can only be one writer. A RESERVED_LOCK is obtained by locking
|
||||||
**
|
** a single byte of the file that is designated as the reserved lock byte.
|
||||||
** A lock is obtained on the first byte of the lock range before acquiring
|
** A PENDING_LOCK is obtained by locking a designated byte different from
|
||||||
** either a read lock or a write lock. This prevents two processes from
|
** the RESERVED_LOCK byte.
|
||||||
** attempting to get a lock at a same time. The semantics of
|
|
||||||
** sqlite3OsReadLock() require that if there is already a write lock, that
|
|
||||||
** lock is converted into a read lock atomically. The lock on the first
|
|
||||||
** byte allows us to drop the old write lock and get the read lock without
|
|
||||||
** another process jumping into the middle and messing us up. The same
|
|
||||||
** argument applies to sqlite3OsWriteLock().
|
|
||||||
**
|
**
|
||||||
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
|
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
|
||||||
** which means we can use reader/writer locks. When reader writer locks
|
** which means we can use reader/writer locks. When reader/writer locks
|
||||||
** are used, the lock is placed on the same range of bytes that is used
|
** are used, the lock is placed on the same range of bytes that is used
|
||||||
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
|
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
|
||||||
** will support two or more Win95 readers or two or more WinNT readers.
|
** will support two or more Win95 readers or two or more WinNT readers.
|
||||||
@@ -362,107 +341,167 @@ int isNT(void){
|
|||||||
** WinNT reader will lock out all other Win95 readers.
|
** WinNT reader will lock out all other Win95 readers.
|
||||||
**
|
**
|
||||||
** The following #defines specify the range of bytes used for locking.
|
** The following #defines specify the range of bytes used for locking.
|
||||||
** N_LOCKBYTE is the number of bytes available for doing the locking.
|
** SHARED_SIZE is the number of bytes available in the pool from which
|
||||||
** The first byte used to hold the lock while the lock is changing does
|
** a random byte is selected for a shared lock. The pool of bytes for
|
||||||
** not count toward this number. FIRST_LOCKBYTE is the address of
|
** shared locks begins at SHARED_FIRST.
|
||||||
** the first byte in the range of bytes used for locking.
|
|
||||||
*/
|
*/
|
||||||
#define N_LOCKBYTE 10239
|
#define SHARED_SIZE 10238
|
||||||
#define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
|
#define SHARED_FIRST (0xffffffff - SHARED_SIZE + 1)
|
||||||
|
#define RESERVED_BYTE (SHARED_FIRST - 1)
|
||||||
int sqlite3OsLock(OsFile *id, int locktype){
|
#define PENDING_BYTE (RESERVED_BYTE - 1)
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sqlite3OsCheckWriteLock(OsFile *id){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the status of the lock on the file "id" to be a readlock.
|
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
|
||||||
** If the file was write locked, then this reduces the lock to a read.
|
** Return false (zero) for Win95, Win98, or WinME.
|
||||||
** If the file was read locked, then this acquires a new read lock.
|
|
||||||
**
|
**
|
||||||
** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
|
** Here is an interesting observation: Win95, Win98, and WinME lack
|
||||||
** library was compiled with large file support (LFS) but LFS is not
|
** the LockFileEx() API. But we can still statically link against that
|
||||||
** available on the host, then an SQLITE_NOLFS is returned.
|
** API as long as we don't call it win running Win95/98/ME. A call to
|
||||||
|
** this routine is used to determine if the host is Win95/98/ME or
|
||||||
|
** WinNT/2K/XP so that we will know whether or not we can safely call
|
||||||
|
** the LockFileEx() API.
|
||||||
*/
|
*/
|
||||||
int sqlite3OsReadLock(OsFile *id){
|
static int isNT(void){
|
||||||
int rc;
|
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
|
||||||
if( id->locked>0 ){
|
if( osType==0 ){
|
||||||
rc = SQLITE_OK;
|
OSVERSIONINFO sInfo;
|
||||||
|
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||||
|
GetVersionEx(&sInfo);
|
||||||
|
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
|
||||||
|
}
|
||||||
|
return osType==2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Acquire a reader lock on the range of bytes from iByte...iByte+nByte-1.
|
||||||
|
** Different API routines are called depending on whether or not this
|
||||||
|
** is Win95 or WinNT.
|
||||||
|
*/
|
||||||
|
static int getReadLock(HANDLE h, unsigned int iByte, unsigned int nByte){
|
||||||
|
int res;
|
||||||
|
if( isNT() ){
|
||||||
|
OVERLAPPED ovlp;
|
||||||
|
ovlp.Offset = iByte;
|
||||||
|
ovlp.OffsetHigh = 0;
|
||||||
|
ovlp.hEvent = 0;
|
||||||
|
res = LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, nByte, 0, &ovlp);
|
||||||
}else{
|
}else{
|
||||||
int lk;
|
res = LockFile(h, iByte, 0, nByte, 0);
|
||||||
int res;
|
}
|
||||||
int cnt = 100;
|
return res;
|
||||||
sqlite3Randomness(sizeof(lk), &lk);
|
}
|
||||||
lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
|
|
||||||
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
|
/*
|
||||||
|
** Undo a readlock
|
||||||
|
*/
|
||||||
|
static int unlockReadLock(OsFile *id){
|
||||||
|
int res;
|
||||||
|
if( isNT() ){
|
||||||
|
res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
||||||
|
}else{
|
||||||
|
res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Acquire a lock of the given type on the specified file. If an
|
||||||
|
** appropriate lock already exists, this routine is a no-op. Return
|
||||||
|
** SQLITE_OK on success and SQLITE_BUSY if another thread is already
|
||||||
|
** holding a conflicting lock.
|
||||||
|
*/
|
||||||
|
int sqlite3OsLock(OsFile *id, int locktype){
|
||||||
|
int rc = SQLITE_OK; /* Return code from subroutines */
|
||||||
|
int res = 1; /* Result of a windows lock call */
|
||||||
|
|
||||||
|
TRACE4("LOCK %d %d was %d\n", id->h, locktype, id->locktype);
|
||||||
|
|
||||||
|
/* 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->locktype>=locktype ){
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
|
||||||
|
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
|
||||||
|
** the PENDING_LOCK byte is temporary.
|
||||||
|
*/
|
||||||
|
if( id->locktype==NO_LOCK || locktype==PENDING_LOCK ){
|
||||||
|
int cnt = 4;
|
||||||
|
while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){
|
||||||
|
/* Try 4 times to get the pending lock. The pending lock might be
|
||||||
|
** held by another reader process who will release it momentarily.
|
||||||
|
*/
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
}
|
}
|
||||||
if( res ){
|
}
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
|
||||||
if( isNT() ){
|
/* Acquire a shared lock
|
||||||
OVERLAPPED ovlp;
|
*/
|
||||||
ovlp.Offset = FIRST_LOCKBYTE+1;
|
if( locktype>=SHARED_LOCK && id->locktype<SHARED_LOCK && res ){
|
||||||
ovlp.OffsetHigh = 0;
|
if( isNT() ){
|
||||||
ovlp.hEvent = 0;
|
res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE);
|
||||||
res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,
|
|
||||||
0, N_LOCKBYTE, 0, &ovlp);
|
|
||||||
}else{
|
|
||||||
res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
|
|
||||||
}
|
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
|
|
||||||
}
|
|
||||||
if( res ){
|
|
||||||
id->locked = lk;
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_BUSY;
|
int lk;
|
||||||
|
sqlite3Randomness(sizeof(lk), &lk);
|
||||||
|
id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
|
||||||
|
res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
|
||||||
}
|
}
|
||||||
|
if( locktype<PENDING_LOCK ){
|
||||||
|
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire a RESERVED lock
|
||||||
|
*/
|
||||||
|
if( locktype>=RESERVED_LOCK && id->locktype<RESERVED_LOCK && res ){
|
||||||
|
res = getReadLock(id->h, RESERVED_BYTE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire an EXCLUSIVE lock
|
||||||
|
*/
|
||||||
|
if( locktype==EXCLUSIVE_LOCK ){
|
||||||
|
if( id->locktype>=SHARED_LOCK ){
|
||||||
|
res = unlockReadLock(id);
|
||||||
|
}
|
||||||
|
if( res ){
|
||||||
|
res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
||||||
|
}else{
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the state of the lock has held in the file descriptor then
|
||||||
|
** return the appropriate result code.
|
||||||
|
*/
|
||||||
|
if( res ){
|
||||||
|
id->locktype = locktype;
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
}else{
|
||||||
|
TRACE2("LOCK FAILED %d\n", id->h);
|
||||||
|
rc = SQLITE_BUSY;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the lock status to be an exclusive or write lock. Return
|
** This routine checks if there is a RESERVED lock held on the specified
|
||||||
** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
|
** file by this or any other process. If such a lock is held, return
|
||||||
** library was compiled with large file support (LFS) but LFS is not
|
** non-zero, otherwise zero.
|
||||||
** available on the host, then an SQLITE_NOLFS is returned.
|
|
||||||
*/
|
*/
|
||||||
int sqlite3OsWriteLock(OsFile *id){
|
int sqlite3OsCheckWriteLock(OsFile *id){
|
||||||
int rc;
|
int rc;
|
||||||
if( id->locked<0 ){
|
if( id->locktype>=RESERVED_LOCK ){
|
||||||
rc = SQLITE_OK;
|
rc = 1;
|
||||||
}else{
|
}else{
|
||||||
int res;
|
rc = getReadLock(id->h, RESERVED_BYTE, 1);
|
||||||
int cnt = 100;
|
if( rc ){
|
||||||
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
|
UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
|
||||||
Sleep(1);
|
|
||||||
}
|
|
||||||
if( res ){
|
|
||||||
if( id->locked>0 ){
|
|
||||||
if( isNT() ){
|
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
|
||||||
}else{
|
|
||||||
res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( res ){
|
|
||||||
res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
|
||||||
}else{
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
|
|
||||||
}
|
|
||||||
if( res ){
|
|
||||||
id->locked = -1;
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
}else{
|
|
||||||
rc = SQLITE_BUSY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -473,18 +512,21 @@ int sqlite3OsWriteLock(OsFile *id){
|
|||||||
*/
|
*/
|
||||||
int sqlite3OsUnlock(OsFile *id){
|
int sqlite3OsUnlock(OsFile *id){
|
||||||
int rc;
|
int rc;
|
||||||
if( id->locked==0 ){
|
TRACE3("UNLOCK %d was %d\n", id->h, id->locktype);
|
||||||
rc = SQLITE_OK;
|
if( id->locktype>=EXCLUSIVE_LOCK ){
|
||||||
}else if( isNT() || id->locked<0 ){
|
UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
id->locked = 0;
|
|
||||||
}else{
|
|
||||||
UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
id->locked = 0;
|
|
||||||
}
|
}
|
||||||
return rc;
|
if( id->locktype>=PENDING_LOCK ){
|
||||||
|
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
|
||||||
|
}
|
||||||
|
if( id->locktype>=RESERVED_LOCK ){
|
||||||
|
UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
|
||||||
|
}
|
||||||
|
if( id->locktype==SHARED_LOCK ){
|
||||||
|
unlockReadLock(id);
|
||||||
|
}
|
||||||
|
id->locktype = NO_LOCK;
|
||||||
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -38,7 +38,8 @@
|
|||||||
typedef struct OsFile OsFile;
|
typedef struct OsFile OsFile;
|
||||||
struct OsFile {
|
struct OsFile {
|
||||||
HANDLE h; /* Handle for accessing the file */
|
HANDLE h; /* Handle for accessing the file */
|
||||||
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
int locktype; /* Type of lock currently held on this file */
|
||||||
|
int sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user