mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Get the new xShmLock interface design working on os_win.c.
FossilOrigin-Name: 149a7082e266edf0dc25c23823a9e240f5285215
This commit is contained in:
22
manifest
22
manifest
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Make\ssure\sWAL\salway\srequests\senough\sshared-memory\sspace.
|
||||
D 2010-05-31T14:39:32
|
||||
C Get\sthe\snew\sxShmLock\sinterface\sdesign\sworking\son\sos_win.c.
|
||||
D 2010-05-31T16:10:12
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@@ -155,8 +155,8 @@ F src/os.c 1516984144e26734f97748f891f1a04f9e294c2e
|
||||
F src/os.h 6f604986f0ef0ca288c2330b16051ff70b431e8c
|
||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
||||
F src/os_unix.c 824dc63f6732bdb1b4d38cc3a3ea22ffcd114a34
|
||||
F src/os_win.c 81dd8f5434b3b73b1f1567a784811601b6437ce3
|
||||
F src/os_unix.c 833dbeae0072d4574801f29873594fc988ba3c3a
|
||||
F src/os_win.c f815403c51a2adad30244374c801dd7fd2734567
|
||||
F src/pager.c f7128f02623beab9462ca6e73516cf73c49186f8
|
||||
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
||||
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
|
||||
@@ -227,7 +227,7 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
|
||||
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
|
||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
|
||||
F src/wal.c a5c23eb5a711011b3d9ce0e58e9c6826c1a42744
|
||||
F src/wal.c 07896216f11be3ebcf157af787f365dd0dfd8d5b
|
||||
F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
|
||||
@@ -818,14 +818,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P cdbb4e7ca7ec27e7e80dd66529d9d565f547887a
|
||||
R 0cd2d59cc635661a08e8f76abffdc3d2
|
||||
P 138f128317b6695530ca3fde7be4cdf22548cd22
|
||||
R 7584a8108fdae700d6960253d9b47a79
|
||||
U drh
|
||||
Z dc2c36f1d50f839e595b320efdcb8ab5
|
||||
Z 5881487644f0f020a550e6de04f99bce
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFMA8onoxKgR168RlERAomNAJ9Px0ZEOZ67oylLFVLVmToJYQgm1wCfRI4c
|
||||
30nVwH7EGnwL4KvwwqI5gwo=
|
||||
=gGIS
|
||||
iD8DBQFMA99noxKgR168RlERAv/LAJ9dsS3ANKFudhEPF8S1qwdmINbEKACfbwG4
|
||||
98NkRuZ55m2VyPR7Ra2saoY=
|
||||
=gfWw
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@@ -1 +1 @@
|
||||
138f128317b6695530ca3fde7be4cdf22548cd22
|
||||
149a7082e266edf0dc25c23823a9e240f5285215
|
@@ -3183,42 +3183,6 @@ struct unixShm {
|
||||
#define UNIX_SHM_BASE ((18+SQLITE_SHM_NLOCK)*4) /* first lock byte */
|
||||
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return a pointer to a nul-terminated string in static memory that
|
||||
** describes a locking mask. The string is of the form "MSABCD" with
|
||||
** each character representing a lock. "M" for MUTEX, "S" for DMS,
|
||||
** and "A" through "D" for the region locks. If a lock is held, the
|
||||
** letter is shown. If the lock is not held, the letter is converted
|
||||
** to ".".
|
||||
**
|
||||
** This routine is for debugging purposes only and does not appear
|
||||
** in a production build.
|
||||
*/
|
||||
static const char *unixShmLockString(u16 maskShared, u16 maskExclusive){
|
||||
static char zBuf[52];
|
||||
static int iBuf = 0;
|
||||
int i;
|
||||
u16 mask;
|
||||
char *z;
|
||||
|
||||
z = &zBuf[iBuf];
|
||||
iBuf += 16;
|
||||
if( iBuf>=sizeof(zBuf) ) iBuf = 0;
|
||||
for(i=0, mask=1; i<SQLITE_SHM_NLOCK; i++, mask += mask){
|
||||
if( mask & maskShared ){
|
||||
z[i] = 's';
|
||||
}else if( mask & maskExclusive ){
|
||||
z[i] = 'E';
|
||||
}else{
|
||||
z[i] = '.';
|
||||
}
|
||||
}
|
||||
z[i] = 0;
|
||||
return z;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
|
||||
**
|
||||
@@ -3283,8 +3247,8 @@ static int unixShmSystemLock(
|
||||
OSTRACE(("write-lock %d failed", ofst));
|
||||
}
|
||||
}
|
||||
OSTRACE((" - afterwards %s\n",
|
||||
unixShmLockString(pShmNode->sharedMask, pShmNode->exclMask)));
|
||||
OSTRACE((" - afterwards %03x,%03x\n",
|
||||
pShmNode->sharedMask, pShmNode->exclMask));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3707,8 +3671,8 @@ static int unixShmLock(
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
|
||||
p->id, getpid(), unixShmLockString(p->sharedMask, p->exclMask)));
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
||||
p->id, getpid(), p->sharedMask, p->exclMask));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
433
src/os_win.c
433
src/os_win.c
@@ -1227,8 +1227,6 @@ struct winShmNode {
|
||||
winShm *pFirst; /* All winShm objects pointing to this */
|
||||
winShmNode *pNext; /* Next in list of all winShmNode objects */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 exclMask; /* Mask of exclusive locks held */
|
||||
u8 sharedMask; /* Mask of shared locks held */
|
||||
u8 nextShmId; /* Next available winShm.id value */
|
||||
#endif
|
||||
};
|
||||
@@ -1253,70 +1251,21 @@ static winShmNode *winShmNodeList = 0;
|
||||
struct winShm {
|
||||
winShmNode *pShmNode; /* The underlying winShmNode object */
|
||||
winShm *pNext; /* Next winShm with the same winShmNode */
|
||||
u8 lockState; /* Current lock state */
|
||||
u8 hasMutex; /* True if holding the winShmNode mutex */
|
||||
u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
|
||||
u8 sharedMask; /* Mask of shared locks held */
|
||||
u8 exclMask; /* Mask of exclusive locks held */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 id; /* Id of this connection with its winShmNode */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Size increment by which shared memory grows
|
||||
*/
|
||||
#define SQLITE_WIN_SHM_INCR 4096
|
||||
|
||||
/*
|
||||
** Constants used for locking
|
||||
*/
|
||||
#define WIN_SHM_BASE 80 /* Byte offset of the first lock byte */
|
||||
#define WIN_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */
|
||||
#define WIN_SHM_A 0x10 /* Mask for region locks... */
|
||||
#define WIN_SHM_B 0x20
|
||||
#define WIN_SHM_C 0x40
|
||||
#define WIN_SHM_D 0x80
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return a pointer to a nul-terminated string in static memory that
|
||||
** describes a locking mask. The string is of the form "MSABCD" with
|
||||
** each character representing a lock. "M" for MUTEX, "S" for DMS,
|
||||
** and "A" through "D" for the region locks. If a lock is held, the
|
||||
** letter is shown. If the lock is not held, the letter is converted
|
||||
** to ".".
|
||||
**
|
||||
** This routine is for debugging purposes only and does not appear
|
||||
** in a production build.
|
||||
*/
|
||||
static const char *winShmLockString(u8 mask){
|
||||
static char zBuf[48];
|
||||
static int iBuf = 0;
|
||||
char *z;
|
||||
|
||||
z = &zBuf[iBuf];
|
||||
iBuf += 8;
|
||||
if( iBuf>=sizeof(zBuf) ) iBuf = 0;
|
||||
|
||||
z[0] = (mask & WIN_SHM_DMS) ? 'S' : '.';
|
||||
z[1] = (mask & WIN_SHM_A) ? 'A' : '.';
|
||||
z[2] = (mask & WIN_SHM_B) ? 'B' : '.';
|
||||
z[3] = (mask & WIN_SHM_C) ? 'C' : '.';
|
||||
z[4] = (mask & WIN_SHM_D) ? 'D' : '.';
|
||||
z[5] = 0;
|
||||
return z;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
#define WIN_SHM_BASE ((18+SQLITE_SHM_NLOCK)*4) /* first lock byte */
|
||||
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
|
||||
|
||||
/*
|
||||
** Apply posix advisory locks for all bytes identified in lockMask.
|
||||
**
|
||||
** lockMask might contain multiple bits but all bits are guaranteed
|
||||
** to be contiguous.
|
||||
**
|
||||
** Locks block if the mask is exactly WIN_SHM_C and are non-blocking
|
||||
** otherwise.
|
||||
** Apply advisory locks for all n bytes beginning at ofst.
|
||||
*/
|
||||
#define _SHM_UNLCK 1
|
||||
#define _SHM_RDLCK 2
|
||||
@@ -1324,235 +1273,38 @@ static const char *winShmLockString(u8 mask){
|
||||
static int winShmSystemLock(
|
||||
winShmNode *pFile, /* Apply locks to this open shared-memory segment */
|
||||
int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
|
||||
u8 lockMask /* Which bytes to lock or unlock */
|
||||
int ofst, /* Offset to first byte to be locked/unlocked */
|
||||
int nByte /* Number of bytes to lock or unlock */
|
||||
){
|
||||
OVERLAPPED ovlp;
|
||||
DWORD dwFlags;
|
||||
int nBytes; /* Number of bytes to lock */
|
||||
int i; /* Offset into the locking byte range */
|
||||
int rc = 0; /* Result code form Lock/UnlockFileEx() */
|
||||
u8 mask; /* Mask of bits in lockMask */
|
||||
|
||||
/* Access to the winShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
|
||||
|
||||
/* Initialize the locking parameters */
|
||||
if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
|
||||
dwFlags = 0;
|
||||
OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n",
|
||||
pFile->hFile.h,
|
||||
winShmLockString(lockMask)));
|
||||
}else{
|
||||
dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
|
||||
OSTRACE(("SHM-LOCK %d requesting %s %s\n",
|
||||
pFile->hFile.h,
|
||||
lockType!=_SHM_UNLCK ? "lock" : "unlock",
|
||||
winShmLockString(lockMask)));
|
||||
}
|
||||
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
|
||||
/* Find the first bit in lockMask that is set */
|
||||
for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
|
||||
assert( mask!=0 );
|
||||
memset(&ovlp, 0, sizeof(OVERLAPPED));
|
||||
ovlp.Offset = i+WIN_SHM_BASE;
|
||||
nBytes = 1;
|
||||
|
||||
/* Extend the locking range for each additional bit that is set */
|
||||
mask <<= 1;
|
||||
while( mask!=0 && (lockMask & mask)!=0 ){
|
||||
nBytes++;
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
/* Verify that all bits set in lockMask are contiguous */
|
||||
assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
|
||||
ovlp.Offset = ofst;
|
||||
|
||||
/* Release/Acquire the system-level lock */
|
||||
if( lockType==_SHM_UNLCK ){
|
||||
for(i=0; i<nBytes; i++, ovlp.Offset++){
|
||||
rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
|
||||
if( !rc ) break;
|
||||
}
|
||||
rc = UnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);
|
||||
}else{
|
||||
/* release old individual byte locks (if any)
|
||||
** and set new individual byte locks */
|
||||
for(i=0; i<nBytes; i++, ovlp.Offset++){
|
||||
UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
|
||||
rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
|
||||
if( !rc ) break;
|
||||
}
|
||||
rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
|
||||
}
|
||||
if( !rc ){
|
||||
OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n",
|
||||
pFile->hFile.h,
|
||||
lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
|
||||
GetLastError()));
|
||||
/* release individual byte locks (if any) */
|
||||
ovlp.Offset-=i;
|
||||
for(i=0; i<nBytes; i++, ovlp.Offset++){
|
||||
UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
|
||||
}
|
||||
}
|
||||
rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
|
||||
|
||||
/* Update the global lock state and do debug tracing */
|
||||
#ifdef SQLITE_DEBUG
|
||||
OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
|
||||
if( rc==SQLITE_OK ){
|
||||
if( lockType==_SHM_UNLCK ){
|
||||
OSTRACE(("unlock ok"));
|
||||
pFile->exclMask &= ~lockMask;
|
||||
pFile->sharedMask &= ~lockMask;
|
||||
}else if( lockType==_SHM_RDLCK ){
|
||||
OSTRACE(("read-lock ok"));
|
||||
pFile->exclMask &= ~lockMask;
|
||||
pFile->sharedMask |= lockMask;
|
||||
}else{
|
||||
assert( lockType==_SHM_WRLCK );
|
||||
OSTRACE(("write-lock ok"));
|
||||
pFile->exclMask |= lockMask;
|
||||
pFile->sharedMask &= ~lockMask;
|
||||
}
|
||||
}else{
|
||||
if( lockType==_SHM_UNLCK ){
|
||||
OSTRACE(("unlock failed"));
|
||||
}else if( lockType==_SHM_RDLCK ){
|
||||
OSTRACE(("read-lock failed"));
|
||||
}else{
|
||||
assert( lockType==_SHM_WRLCK );
|
||||
OSTRACE(("write-lock failed"));
|
||||
}
|
||||
}
|
||||
OSTRACE((" - change requested %s - afterwards %s:%s\n",
|
||||
winShmLockString(lockMask),
|
||||
winShmLockString(pFile->sharedMask),
|
||||
winShmLockString(pFile->exclMask)));
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** For connection p, unlock all of the locks identified by the unlockMask
|
||||
** parameter.
|
||||
*/
|
||||
static int winShmUnlock(
|
||||
winShmNode *pFile, /* The underlying shared-memory file */
|
||||
winShm *p, /* The connection to be unlocked */
|
||||
u8 unlockMask /* Mask of locks to be unlocked */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
winShm *pX; /* For looping over all sibling connections */
|
||||
u8 allMask; /* Union of locks held by connections other than "p" */
|
||||
|
||||
/* Access to the winShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
||||
|
||||
/* don't attempt to unlock anything we don't have locks for */
|
||||
if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
|
||||
OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
|
||||
pFile->hFile.h,
|
||||
winShmLockString(unlockMask),
|
||||
winShmLockString(p->exclMask|p->sharedMask)));
|
||||
unlockMask &= (p->exclMask|p->sharedMask);
|
||||
}
|
||||
|
||||
/* Compute locks held by sibling connections */
|
||||
allMask = 0;
|
||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
||||
if( pX==p ) continue;
|
||||
assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
|
||||
allMask |= pX->sharedMask;
|
||||
}
|
||||
|
||||
/* Unlock the system-level locks */
|
||||
if( (unlockMask & allMask)!=unlockMask ){
|
||||
rc = winShmSystemLock(pFile, _SHM_UNLCK, unlockMask & ~allMask);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Undo the local locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->exclMask &= ~unlockMask;
|
||||
p->sharedMask &= ~unlockMask;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get reader locks for connection p on all locks in the readMask parameter.
|
||||
*/
|
||||
static int winShmSharedLock(
|
||||
winShmNode *pFile, /* The underlying shared-memory file */
|
||||
winShm *p, /* The connection to get the shared locks */
|
||||
u8 readMask /* Mask of shared locks to be acquired */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
winShm *pX; /* For looping over all sibling connections */
|
||||
u8 allShared; /* Union of locks held by connections other than "p" */
|
||||
|
||||
/* Access to the winShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
||||
|
||||
/* Find out which shared locks are already held by sibling connections.
|
||||
** If any sibling already holds an exclusive lock, go ahead and return
|
||||
** SQLITE_BUSY.
|
||||
*/
|
||||
allShared = 0;
|
||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
||||
if( pX==p ) continue;
|
||||
if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
|
||||
allShared |= pX->sharedMask;
|
||||
}
|
||||
|
||||
/* Get shared locks at the system level, if necessary */
|
||||
if( (~allShared) & readMask ){
|
||||
rc = winShmSystemLock(pFile, _SHM_RDLCK, readMask);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Get the local shared locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask |= readMask;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** For connection p, get an exclusive lock on all locks identified in
|
||||
** the writeMask parameter.
|
||||
*/
|
||||
static int winShmExclusiveLock(
|
||||
winShmNode *pFile, /* The underlying shared-memory file */
|
||||
winShm *p, /* The connection to get the exclusive locks */
|
||||
u8 writeMask /* Mask of exclusive locks to be acquired */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
winShm *pX; /* For looping over all sibling connections */
|
||||
|
||||
/* Access to the winShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
||||
|
||||
/* Make sure no sibling connections hold locks that will block this
|
||||
** lock. If any do, return SQLITE_BUSY right away.
|
||||
*/
|
||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
||||
if( pX==p ) continue;
|
||||
if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
|
||||
if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
|
||||
}
|
||||
|
||||
/* Get the exclusive locks at the system level. Then if successful
|
||||
** also mark the local connection as being locked.
|
||||
*/
|
||||
rc = winShmSystemLock(pFile, _SHM_WRLCK, writeMask);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask &= ~writeMask;
|
||||
p->exclMask |= writeMask;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1680,11 +1432,12 @@ static int winShmOpen(
|
||||
/* Check to see if another process is holding the dead-man switch.
|
||||
** If not, truncate the file to zero length.
|
||||
*/
|
||||
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS)==SQLITE_OK ){
|
||||
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
|
||||
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS);
|
||||
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
|
||||
}
|
||||
if( rc ) goto shm_open_err;
|
||||
}
|
||||
@@ -1703,7 +1456,7 @@ static int winShmOpen(
|
||||
|
||||
/* Jump here on any error */
|
||||
shm_open_err:
|
||||
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS);
|
||||
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
winShmPurge(); /* This call frees pShmNode if required */
|
||||
sqlite3_free(p);
|
||||
sqlite3_free(pNew);
|
||||
@@ -1728,10 +1481,6 @@ static int winShmClose(
|
||||
p = pDbFd->pShm;
|
||||
pShmNode = p->pShmNode;
|
||||
|
||||
/* Verify that the connection being closed holds no locks */
|
||||
assert( p->exclMask==0 );
|
||||
assert( p->sharedMask==0 );
|
||||
|
||||
/* Remove connection p from the set of connections associated
|
||||
** with pShmNode */
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
@@ -1782,14 +1531,10 @@ static int winShmSize(
|
||||
if( reqSize>=0 ){
|
||||
sqlite3_int64 sz;
|
||||
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
|
||||
if( SQLITE_OK==rc ){
|
||||
reqSize = (reqSize + SQLITE_WIN_SHM_INCR - 1)/SQLITE_WIN_SHM_INCR;
|
||||
reqSize *= SQLITE_WIN_SHM_INCR;
|
||||
if( reqSize>sz ){
|
||||
if( SQLITE_OK==rc && reqSize>sz ){
|
||||
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( SQLITE_OK==rc ){
|
||||
sqlite3_int64 sz;
|
||||
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
|
||||
@@ -1833,14 +1578,14 @@ static int winShmGet(
|
||||
sqlite3_file *fd, /* The database file holding the shared memory */
|
||||
int reqMapSize, /* Requested size of mapping. -1 means don't care */
|
||||
int *pNewMapSize, /* Write new size of mapping here */
|
||||
void **ppBuf /* Write mapping buffer origin here */
|
||||
void volatile **ppBuf /* Write mapping buffer origin here */
|
||||
){
|
||||
winFile *pDbFd = (winFile*)fd;
|
||||
winShm *p = pDbFd->pShm;
|
||||
winShmNode *pShmNode = p->pShmNode;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
|
||||
if( p->hasMutexBuf==0 ){
|
||||
assert( sqlite3_mutex_notheld(pShmNode->mutex) );
|
||||
sqlite3_mutex_enter(pShmNode->mutexBuf);
|
||||
p->hasMutexBuf = 1;
|
||||
@@ -1920,7 +1665,7 @@ static int winShmGet(
|
||||
static int winShmRelease(sqlite3_file *fd){
|
||||
winFile *pDbFd = (winFile*)fd;
|
||||
winShm *p = pDbFd->pShm;
|
||||
if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
|
||||
if( p->hasMutexBuf ){
|
||||
winShmNode *pShmNode = p->pShmNode;
|
||||
assert( sqlite3_mutex_notheld(pShmNode->mutex) );
|
||||
sqlite3_mutex_leave(pShmNode->mutexBuf);
|
||||
@@ -1929,149 +1674,39 @@ static int winShmRelease(sqlite3_file *fd){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Symbolic names for LOCK states used for debugging.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
static const char *azLkName[] = {
|
||||
"UNLOCK",
|
||||
"READ",
|
||||
"READ_FULL",
|
||||
"WRITE",
|
||||
"PENDING",
|
||||
"CHECKPOINT",
|
||||
"RECOVER"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Change the lock state for a shared-memory segment.
|
||||
*/
|
||||
static int winShmLock(
|
||||
sqlite3_file *fd, /* Database holding the shared memory */
|
||||
int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */
|
||||
int *pGotLock /* The lock you actually got */
|
||||
sqlite3_file *fd, /* Database file holding the shared memory */
|
||||
int ofst, /* First lock to acquire or release */
|
||||
int n, /* Number of locks to acquire or release */
|
||||
int flags /* What to do with the lock */
|
||||
){
|
||||
winFile *pDbFd = (winFile*)fd;
|
||||
winShm *p = pDbFd->pShm;
|
||||
winShmNode *pShmNode = p->pShmNode;
|
||||
int rc = SQLITE_PROTOCOL;
|
||||
|
||||
/* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
|
||||
** directly requested; they are side effects from requesting
|
||||
** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
|
||||
*/
|
||||
assert( desiredLock==SQLITE_SHM_UNLOCK
|
||||
|| desiredLock==SQLITE_SHM_READ
|
||||
|| desiredLock==SQLITE_SHM_WRITE
|
||||
|| desiredLock==SQLITE_SHM_CHECKPOINT
|
||||
|| desiredLock==SQLITE_SHM_RECOVER );
|
||||
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
||||
assert( n>=1 );
|
||||
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
||||
|| flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
|
||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
||||
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
||||
|
||||
/* Return directly if this is just a lock state query, or if
|
||||
** the connection is already in the desired locking state.
|
||||
*/
|
||||
if( desiredLock==p->lockState
|
||||
|| (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
|
||||
){
|
||||
OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
|
||||
pShmNode->hFile.h,
|
||||
p->id, (int)GetCurrentProcessId(), azLkName[desiredLock],
|
||||
azLkName[p->lockState]));
|
||||
if( pGotLock ) *pGotLock = p->lockState;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
|
||||
pShmNode->hFile.h,
|
||||
p->id, (int)GetCurrentProcessId(), azLkName[p->lockState],
|
||||
azLkName[desiredLock]));
|
||||
|
||||
if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
|
||||
assert( sqlite3_mutex_notheld(pShmNode->mutex) );
|
||||
sqlite3_mutex_enter(pShmNode->mutexBuf);
|
||||
p->hasMutexBuf = 1;
|
||||
}
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
switch( desiredLock ){
|
||||
case SQLITE_SHM_UNLOCK: {
|
||||
assert( p->lockState!=SQLITE_SHM_RECOVER );
|
||||
winShmUnlock(pShmNode, p, WIN_SHM_A|WIN_SHM_B|WIN_SHM_C|WIN_SHM_D);
|
||||
rc = SQLITE_OK;
|
||||
p->lockState = SQLITE_SHM_UNLOCK;
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_READ: {
|
||||
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
||||
int nAttempt;
|
||||
rc = SQLITE_BUSY;
|
||||
assert( p->lockState==SQLITE_SHM_UNLOCK );
|
||||
for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
|
||||
rc = winShmSharedLock(pShmNode, p, WIN_SHM_A|WIN_SHM_B);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
rc = winShmSharedLock(pShmNode, p, WIN_SHM_D);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_READ_FULL;
|
||||
}
|
||||
if( flags & SQLITE_SHM_UNLOCK ){
|
||||
rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
|
||||
}else if( flags & SQLITE_SHM_SHARED ){
|
||||
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
|
||||
}else{
|
||||
winShmUnlock(pShmNode, p, WIN_SHM_B);
|
||||
p->lockState = SQLITE_SHM_READ;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
assert( p->lockState==SQLITE_SHM_WRITE
|
||||
|| p->lockState==SQLITE_SHM_RECOVER );
|
||||
rc = winShmSharedLock(pShmNode, p, WIN_SHM_A);
|
||||
winShmUnlock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
|
||||
p->lockState = SQLITE_SHM_READ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_WRITE: {
|
||||
assert( p->lockState==SQLITE_SHM_READ
|
||||
|| p->lockState==SQLITE_SHM_READ_FULL );
|
||||
rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_WRITE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_CHECKPOINT: {
|
||||
assert( p->lockState==SQLITE_SHM_UNLOCK
|
||||
|| p->lockState==SQLITE_SHM_PENDING
|
||||
);
|
||||
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
||||
rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_B|WIN_SHM_C);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_PENDING;
|
||||
}
|
||||
}
|
||||
if( p->lockState==SQLITE_SHM_PENDING ){
|
||||
rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_A);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_CHECKPOINT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( desiredLock==SQLITE_SHM_RECOVER );
|
||||
assert( p->lockState==SQLITE_SHM_READ
|
||||
|| p->lockState==SQLITE_SHM_READ_FULL
|
||||
);
|
||||
assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
|
||||
rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_RECOVER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
|
||||
pShmNode->hFile.h,
|
||||
p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
|
||||
if( pGotLock ) *pGotLock = p->lockState;
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d %s\n",
|
||||
p->id, (int)GetCurrentProcessId(), rc ? "failed" : "ok"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -2023,7 +2023,8 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
|
||||
sqlite3_randomness(4, &pWal->hdr.aSalt[1]);
|
||||
walIndexWriteHdr(pWal);
|
||||
pInfo->nBackfill = 0;
|
||||
memset(&pInfo->aReadMark[1], 0, sizeof(pInfo->aReadMark)-sizeof(u32));
|
||||
memset((void*)&pInfo->aReadMark[1], 0,
|
||||
sizeof(pInfo->aReadMark)-sizeof(u32));
|
||||
rc = sqlite3OsTruncate(pWal->pDbFd,
|
||||
((i64)pWal->hdr.nPage*(i64)pWal->szPage));
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
|
||||
|
Reference in New Issue
Block a user