Initial code for incremental checkpoint in WAL mode. This check-in compiles
on unix and runs as long as you do not engage WAL mode. WAL mode crashes and burns. Consider this check-in a baseline implementation for getting the new capability up and running. FossilOrigin-Name: ef3ba7a17ff90674d702e5694b9e792851ab6998
This commit is contained in:
parent
a7a0c615d7
commit
73b64e4d2e
48
manifest
48
manifest
@ -1,5 +1,8 @@
|
||||
C Add\stests\sto\sfkey2.test\sto\scheck\sthat\sON\sCONFLICT\sclauses\sdo\snot\saffect\sSQLite's\sbehaviour\swhen\san\sFK\sconstraint\sis\sviolated.
|
||||
D 2010-05-29T08:40:38
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Initial\scode\sfor\sincremental\scheckpoint\sin\sWAL\smode.\s\sThis\scheck-in\scompiles\non\sunix\sand\sruns\sas\slong\sas\syou\sdo\snot\sengage\sWAL\smode.\s\sWAL\smode\scrashes\sand\nburns.\s\sConsider\sthis\scheck-in\sa\sbaseline\simplementation\sfor\sgetting\sthe\snew\ncapability\sup\sand\srunning.
|
||||
D 2010-05-30T19:55:16
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -148,13 +151,13 @@ F src/mutex_os2.c 20477db50cf3817c2f1cd3eb61e5c177e50231db
|
||||
F src/mutex_unix.c becb8c4e07616abf84650d3687d62a1461d5d9cd
|
||||
F src/mutex_w32.c fb1cf87c5a88b56c7df0d9ddb796ed9641046c3d
|
||||
F src/notify.c cbfa66a836da3a51567209636e6a94059c137930
|
||||
F src/os.c 2285265f7e8035ba77e8e8ec93adf3c3c61fc60e
|
||||
F src/os.h efcc7f0072ae362b44eab8588b43a943da61504e
|
||||
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 683ba91de68419771b13f2b9a3dc0e439147e199
|
||||
F src/os_unix.c df0c87b2d55772d55de8158fb43d107d2f7a98a9
|
||||
F src/os_win.c 81dd8f5434b3b73b1f1567a784811601b6437ce3
|
||||
F src/pager.c 5d693cc6273c5406a21f1a2afa18309457273549
|
||||
F src/pager.c f7128f02623beab9462ca6e73516cf73c49186f8
|
||||
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
||||
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
|
||||
F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf
|
||||
@ -168,7 +171,7 @@ F src/resolve.c ac5f1a713cd1ae77f08b83cc69581e11bf5ae6f9
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c c03d8a0565febcde8c6a12c5d77d065fddae889b
|
||||
F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714
|
||||
F src/sqlite.h.in a7d351d5ae015179e7ef97a1060c7213b50efd9b
|
||||
F src/sqlite.h.in c77dd6f7391c7d780622abd221c49d926d32b3b6
|
||||
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
|
||||
F src/sqliteInt.h c1ca9bed7c963343f90edaf0ec31b8ff4b43fb01
|
||||
F src/sqliteLimit.h 196e2f83c3b444c4548fc1874f52f84fdbda40f3
|
||||
@ -180,7 +183,7 @@ F src/test2.c 31f1b9d076b4774a22d2605d0af1f34e14a9a7bd
|
||||
F src/test3.c 4c21700c73a890a47fc685c1097bfb661346ac94
|
||||
F src/test4.c ad03bb987ddedce928f4258c1e7fa4109a73497d
|
||||
F src/test5.c cc55900118fa4add8ec9cf69fc4225a4662f76b1
|
||||
F src/test6.c e524e36b10c4cd8fa08899f6245194045e78edbe
|
||||
F src/test6.c d3e1a771a7b445ec771e64f2af70df5285da8e4c
|
||||
F src/test7.c 3f2d63e4ccf97f8c2cf1a7fa0a3c8e2e2a354e6e
|
||||
F src/test8.c f959db9a22d882013b64c92753fa793b2ce3bdea
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
@ -190,7 +193,7 @@ F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
|
||||
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
|
||||
F src/test_config.c 6210f501d358bde619ae761f06f123529c6ba24f
|
||||
F src/test_demovfs.c da81a5f7785bb352bda7911c332a983ec4f17f27
|
||||
F src/test_devsym.c 265e0c6a196e4b9cf880946b031483446a8033c3
|
||||
F src/test_devsym.c 709712f5157667410cd0dad1b7b1b54319c122c5
|
||||
F src/test_func.c 13b582345fb1185a93e46c53310fae8547dcce20
|
||||
F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2
|
||||
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
|
||||
@ -201,13 +204,13 @@ F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_malloc.c 2842c922b8e8d992aba722214952204ca025b411
|
||||
F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3
|
||||
F src/test_onefile.c 4ce8c753c0240f010f0f2af89604875967d20945
|
||||
F src/test_osinst.c 18b342b0979a78788af91e6b48b0fdcf0c4b340c
|
||||
F src/test_osinst.c 280876b040c19d0a8fcd1852cb94e2f630c59bac
|
||||
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c aa9919c885a1fe53eafc73492f0898ee6c0a0726
|
||||
F src/test_vfs.c a2d320ea9afc0d520b68eb4998f789b4f8007bfc
|
||||
F src/test_vfs.c 4f4f121f7d508101a2b33d166567f4ccd226b5ad
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
|
||||
F src/trigger.c 8927588cb9e6d47f933b53bfe74200fbb504100d
|
||||
@ -224,8 +227,8 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
|
||||
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
|
||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
|
||||
F src/wal.c ce631adb92c0c53d87bb86913dc6714cca825e3a
|
||||
F src/wal.h 111c6f3efd83fe2fc707b29e26431e8eff4c6f28
|
||||
F src/wal.c ef02a5f4d4d652ee4d94ac88822a73a1411d10d6
|
||||
F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -815,7 +818,18 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 60c22bde52121993d4bea11eef38ab285c737e2c
|
||||
R 132966a7c0563e76b2849379585e861e
|
||||
U dan
|
||||
Z 9c5f2213670b38101b8556211a758e4d
|
||||
P e9e5b1001986348ef0f88c19de87b94559a5451e
|
||||
R 3cb5cfcba75aef739a2ee45b712a8927
|
||||
T *bgcolor * #d0c0ff
|
||||
T *branch * wal-incr-ckpt
|
||||
T *sym-wal-incr-ckpt *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z ed18a54c191ab99d049f2d0a8d31b002
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFMAsKpoxKgR168RlERAvtWAJ99mBxnLNXe1beJRyx/6q6ucCHBKgCfaA4I
|
||||
OHb/Ln2lM1z/XtiNWshOkow=
|
||||
=bcY+
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -1 +1 @@
|
||||
e9e5b1001986348ef0f88c19de87b94559a5451e
|
||||
ef3ba7a17ff90674d702e5694b9e792851ab6998
|
4
src/os.c
4
src/os.c
@ -110,8 +110,8 @@ int sqlite3OsShmGet(sqlite3_file *id,int reqSize,int *pSize,void volatile **pp){
|
||||
int sqlite3OsShmRelease(sqlite3_file *id){
|
||||
return id->pMethods->xShmRelease(id);
|
||||
}
|
||||
int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
|
||||
return id->pMethods->xShmLock(id, desiredLock, pGotLock);
|
||||
int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
|
||||
return id->pMethods->xShmLock(id, offset, n, flags);
|
||||
}
|
||||
void sqlite3OsShmBarrier(sqlite3_file *id){
|
||||
id->pMethods->xShmBarrier(id);
|
||||
|
2
src/os.h
2
src/os.h
@ -247,7 +247,7 @@ int sqlite3OsShmOpen(sqlite3_file *id);
|
||||
int sqlite3OsShmSize(sqlite3_file *id, int, int*);
|
||||
int sqlite3OsShmGet(sqlite3_file *id, int, int*, void volatile**);
|
||||
int sqlite3OsShmRelease(sqlite3_file *id);
|
||||
int sqlite3OsShmLock(sqlite3_file *id, int, int*);
|
||||
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
|
||||
void sqlite3OsShmBarrier(sqlite3_file *id);
|
||||
int sqlite3OsShmClose(sqlite3_file *id, int);
|
||||
|
||||
|
439
src/os_unix.c
439
src/os_unix.c
@ -3168,30 +3168,20 @@ struct unixShmNode {
|
||||
struct unixShm {
|
||||
unixShmNode *pShmNode; /* The underlying unixShmNode object */
|
||||
unixShm *pNext; /* Next unixShm with the same unixShmNode */
|
||||
u8 lockState; /* Current lock state */
|
||||
u8 hasMutex; /* True if holding the unixShmNode mutex */
|
||||
u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
|
||||
u8 sharedMask; /* Mask of shared locks held */
|
||||
u8 exclMask; /* Mask of exclusive locks held */
|
||||
u16 sharedMask; /* Mask of shared locks held */
|
||||
u16 exclMask; /* Mask of exclusive locks held */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 id; /* Id of this connection within its unixShmNode */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Size increment by which shared memory grows
|
||||
*/
|
||||
#define SQLITE_UNIX_SHM_INCR 4096
|
||||
|
||||
/*
|
||||
** Constants used for locking
|
||||
*/
|
||||
#define UNIX_SHM_BASE 80 /* Byte offset of the first lock byte */
|
||||
#define UNIX_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */
|
||||
#define UNIX_SHM_A 0x10 /* Mask for region locks... */
|
||||
#define UNIX_SHM_B 0x20
|
||||
#define UNIX_SHM_C 0x40
|
||||
#define UNIX_SHM_D 0x80
|
||||
#define UNIX_SHM_DMS 80 /* The deadman switch lock */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
@ -3205,30 +3195,32 @@ struct unixShm {
|
||||
** This routine is for debugging purposes only and does not appear
|
||||
** in a production build.
|
||||
*/
|
||||
static const char *unixShmLockString(u8 mask){
|
||||
static char zBuf[48];
|
||||
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 += 8;
|
||||
iBuf += 16;
|
||||
if( iBuf>=sizeof(zBuf) ) iBuf = 0;
|
||||
|
||||
z[0] = (mask & UNIX_SHM_DMS) ? 'S' : '.';
|
||||
z[1] = (mask & UNIX_SHM_A) ? 'A' : '.';
|
||||
z[2] = (mask & UNIX_SHM_B) ? 'B' : '.';
|
||||
z[3] = (mask & UNIX_SHM_C) ? 'C' : '.';
|
||||
z[4] = (mask & UNIX_SHM_D) ? 'D' : '.';
|
||||
z[5] = 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 identified in lockMask.
|
||||
**
|
||||
** lockMask might contain multiple bits but all bits are guaranteed
|
||||
** to be contiguous.
|
||||
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
|
||||
**
|
||||
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
|
||||
** otherwise.
|
||||
@ -3236,198 +3228,69 @@ static const char *unixShmLockString(u8 mask){
|
||||
static int unixShmSystemLock(
|
||||
unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
|
||||
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
|
||||
u8 lockMask /* Which bytes to lock or unlock */
|
||||
int ofst, /* First byte of the locking range */
|
||||
int n /* Number of bytes to lock */
|
||||
){
|
||||
struct flock f; /* The posix advisory locking structure */
|
||||
int lockOp; /* The opcode for fcntl() */
|
||||
int i; /* Offset into the locking byte range */
|
||||
int rc; /* Result code form fcntl() */
|
||||
u8 mask; /* Mask of bits in lockMask */
|
||||
int rc = SQLITE_OK; /* Result code form fcntl() */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
|
||||
|
||||
/* Shared locks never span more than one byte */
|
||||
assert( n==1 || lockType!=F_RDLCK );
|
||||
|
||||
/* Locks are within range */
|
||||
assert( n>=1 && ofst>=0 && ofst+n<SQLITE_SHM_NLOCK );
|
||||
|
||||
/* Initialize the locking parameters */
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.l_type = lockType;
|
||||
f.l_whence = SEEK_SET;
|
||||
if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
|
||||
lockOp = F_SETLKW;
|
||||
OSTRACE(("SHM-LOCK requesting blocking lock\n"));
|
||||
}else{
|
||||
lockOp = F_SETLK;
|
||||
}
|
||||
f.l_start = ofst+UNIX_SHM_BASE;
|
||||
f.l_len = n;
|
||||
|
||||
/* 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 );
|
||||
f.l_start = i+UNIX_SHM_BASE;
|
||||
f.l_len = 1;
|
||||
|
||||
/* Extend the locking range for each additional bit that is set */
|
||||
mask <<= 1;
|
||||
while( mask!=0 && (lockMask & mask)!=0 ){
|
||||
f.l_len++;
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
/* Verify that all bits set in lockMask are contiguous */
|
||||
assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
|
||||
|
||||
/* Acquire the system-level lock */
|
||||
rc = fcntl(pShmNode->h, lockOp, &f);
|
||||
rc = fcntl(pShmNode->h, F_SETLK, &f);
|
||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||
|
||||
/* Update the global lock state and do debug tracing */
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ u16 mask;
|
||||
OSTRACE(("SHM-LOCK "));
|
||||
mask = (1<<(ofst+n)) - (1<<ofst);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( lockType==F_UNLCK ){
|
||||
OSTRACE(("unlock ok"));
|
||||
pShmNode->exclMask &= ~lockMask;
|
||||
pShmNode->sharedMask &= ~lockMask;
|
||||
OSTRACE(("unlock %d ok", ofst));
|
||||
pShmNode->exclMask &= ~mask;
|
||||
pShmNode->sharedMask &= ~mask;
|
||||
}else if( lockType==F_RDLCK ){
|
||||
OSTRACE(("read-lock ok"));
|
||||
pShmNode->exclMask &= ~lockMask;
|
||||
pShmNode->sharedMask |= lockMask;
|
||||
OSTRACE(("read-lock %d ok", ofst));
|
||||
pShmNode->exclMask &= ~mask;
|
||||
pShmNode->sharedMask |= mask;
|
||||
}else{
|
||||
assert( lockType==F_WRLCK );
|
||||
OSTRACE(("write-lock ok"));
|
||||
pShmNode->exclMask |= lockMask;
|
||||
pShmNode->sharedMask &= ~lockMask;
|
||||
OSTRACE(("write-lock %d ok", ofst));
|
||||
pShmNode->exclMask |= mask;
|
||||
pShmNode->sharedMask &= ~mask;
|
||||
}
|
||||
}else{
|
||||
if( lockType==F_UNLCK ){
|
||||
OSTRACE(("unlock failed"));
|
||||
OSTRACE(("unlock %d failed", ofst));
|
||||
}else if( lockType==F_RDLCK ){
|
||||
OSTRACE(("read-lock failed"));
|
||||
}else{
|
||||
assert( lockType==F_WRLCK );
|
||||
OSTRACE(("write-lock failed"));
|
||||
OSTRACE(("write-lock %d failed", ofst));
|
||||
}
|
||||
}
|
||||
OSTRACE((" - change requested %s - afterwards %s:%s\n",
|
||||
unixShmLockString(lockMask),
|
||||
unixShmLockString(pShmNode->sharedMask),
|
||||
unixShmLockString(pShmNode->exclMask)));
|
||||
OSTRACE((" - afterwards %s\n",
|
||||
unixShmLockString(pShmNode->sharedMask, pShmNode->exclMask)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** For connection p, unlock all of the locks identified by the unlockMask
|
||||
** parameter.
|
||||
*/
|
||||
static int unixShmUnlock(
|
||||
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||
unixShm *p, /* The connection to be unlocked */
|
||||
u8 unlockMask /* Mask of locks to be unlocked */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
unixShm *pX; /* For looping over all sibling connections */
|
||||
u8 allMask; /* Union of locks held by connections other than "p" */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pShmNode->mutex) );
|
||||
|
||||
/* Compute locks held by sibling connections */
|
||||
allMask = 0;
|
||||
for(pX=pShmNode->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 = unixShmSystemLock(pShmNode, F_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 unixShmSharedLock(
|
||||
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||
unixShm *p, /* The connection to get the shared locks */
|
||||
u8 readMask /* Mask of shared locks to be acquired */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
unixShm *pX; /* For looping over all sibling connections */
|
||||
u8 allShared; /* Union of locks held by connections other than "p" */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pShmNode->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=pShmNode->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 = unixShmSystemLock(pShmNode, F_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 unixShmExclusiveLock(
|
||||
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||
unixShm *p, /* The connection to get the exclusive locks */
|
||||
u8 writeMask /* Mask of exclusive locks to be acquired */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
unixShm *pX; /* For looping over all sibling connections */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
assert( sqlite3_mutex_held(pShmNode->mutex) );
|
||||
|
||||
/* Make sure no sibling connections hold locks that will block this
|
||||
** lock. If any do, return SQLITE_BUSY right away.
|
||||
*/
|
||||
for(pX=pShmNode->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 = unixShmSystemLock(pShmNode, F_WRLCK, writeMask);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask &= ~writeMask;
|
||||
p->exclMask |= writeMask;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
|
||||
@ -3520,13 +3383,13 @@ static int unixShmOpen(
|
||||
** If not, truncate the file to zero length.
|
||||
*/
|
||||
rc = SQLITE_OK;
|
||||
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
|
||||
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
||||
if( ftruncate(pShmNode->h, 0) ){
|
||||
rc = SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS);
|
||||
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
|
||||
}
|
||||
if( rc ) goto shm_open_err;
|
||||
}
|
||||
@ -3687,7 +3550,7 @@ static int unixShmGet(
|
||||
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||
assert( pShmNode->pInode==pDbFd->pInode );
|
||||
|
||||
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;
|
||||
@ -3731,7 +3594,7 @@ static int unixShmRelease(sqlite3_file *fd){
|
||||
unixFile *pDbFd = (unixFile*)fd;
|
||||
unixShm *p = pDbFd->pShm;
|
||||
|
||||
if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
|
||||
if( p->hasMutexBuf ){
|
||||
assert( sqlite3_mutex_notheld(p->pShmNode->mutex) );
|
||||
sqlite3_mutex_leave(p->pShmNode->mutexBuf);
|
||||
p->hasMutexBuf = 0;
|
||||
@ -3739,147 +3602,113 @@ static int unixShmRelease(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 unixShmLock(
|
||||
sqlite3_file *fd, /* Database file holding the shared memory */
|
||||
int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */
|
||||
int *pGotLock /* The lock you actually got */
|
||||
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 */
|
||||
){
|
||||
unixFile *pDbFd = (unixFile*)fd;
|
||||
unixShm *p = pDbFd->pShm;
|
||||
unixShmNode *pShmNode = p->pShmNode;
|
||||
int rc = SQLITE_PROTOCOL;
|
||||
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
|
||||
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
|
||||
unixShm *pX; /* For looping over all siblings */
|
||||
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
u16 mask; /* Mask of locks to take or release */
|
||||
|
||||
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||
assert( pShmNode->pInode==pDbFd->pInode );
|
||||
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 );
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* 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 shmid-%d, pid-%d request %s and got %s\n",
|
||||
p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
|
||||
if( pGotLock ) *pGotLock = p->lockState;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
|
||||
p->id, getpid(), 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;
|
||||
}
|
||||
mask = (1<<(ofst+n+1)) - (1<<(ofst+1));
|
||||
assert( n>1 || mask==(1<<ofst) );
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
switch( desiredLock ){
|
||||
case SQLITE_SHM_UNLOCK: {
|
||||
assert( p->lockState!=SQLITE_SHM_RECOVER );
|
||||
unixShmUnlock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
|
||||
if( flags & SQLITE_SHM_UNLOCK ){
|
||||
u16 allMask = 0; /* Mask of locks held by siblings */
|
||||
|
||||
/* See if any siblings hold this same lock */
|
||||
for(pX=pShmNode->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( (mask & allMask)==0 ){
|
||||
rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+1, n);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
p->lockState = SQLITE_SHM_UNLOCK;
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_READ: {
|
||||
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
||||
int nAttempt;
|
||||
|
||||
/* Undo the local locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->exclMask &= ~mask;
|
||||
p->sharedMask &= ~mask;
|
||||
}
|
||||
}else if( flags & SQLITE_SHM_SHARED ){
|
||||
u16 allShared = 0; /* Union of locks held by connections other than "p" */
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||
if( pX==p ) continue;
|
||||
if( (pX->exclMask & mask)!=0 ){
|
||||
rc = SQLITE_BUSY;
|
||||
assert( p->lockState==SQLITE_SHM_UNLOCK );
|
||||
for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
|
||||
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_D);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_READ_FULL;
|
||||
}
|
||||
}else{
|
||||
unixShmUnlock(pShmNode, p, UNIX_SHM_B);
|
||||
p->lockState = SQLITE_SHM_READ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
allShared |= pX->sharedMask;
|
||||
}
|
||||
|
||||
/* Get shared locks at the system level, if necessary */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (allShared & mask)==0 ){
|
||||
rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+1, n);
|
||||
}else{
|
||||
assert( p->lockState==SQLITE_SHM_WRITE
|
||||
|| p->lockState==SQLITE_SHM_RECOVER );
|
||||
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A);
|
||||
unixShmUnlock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
|
||||
p->lockState = SQLITE_SHM_READ;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_WRITE: {
|
||||
assert( p->lockState==SQLITE_SHM_READ
|
||||
|| p->lockState==SQLITE_SHM_READ_FULL );
|
||||
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
|
||||
|
||||
/* Get the local shared locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask |= mask;
|
||||
}
|
||||
}else{
|
||||
/* Make sure no sibling connections hold locks that will block this
|
||||
** lock. If any do, return SQLITE_BUSY right away.
|
||||
*/
|
||||
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||
if( pX==p ) continue;
|
||||
if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
|
||||
rc = SQLITE_BUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the exclusive locks at the system level. Then if successful
|
||||
** also mark the local connection as being locked.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+1, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_WRITE;
|
||||
p->sharedMask &= ~mask;
|
||||
p->exclMask |= mask;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_SHM_CHECKPOINT: {
|
||||
assert( p->lockState==SQLITE_SHM_UNLOCK
|
||||
|| p->lockState==SQLITE_SHM_PENDING
|
||||
);
|
||||
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
||||
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_B|UNIX_SHM_C);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_PENDING;
|
||||
}
|
||||
}
|
||||
if( p->lockState==SQLITE_SHM_PENDING ){
|
||||
rc = unixShmExclusiveLock(pShmNode, p, UNIX_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 = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->lockState = SQLITE_SHM_RECOVER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
|
||||
p->id, getpid(), azLkName[p->lockState]));
|
||||
if( pGotLock ) *pGotLock = p->lockState;
|
||||
p->id, getpid(), unixShmLockString(p->sharedMask, p->exclMask)));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
26
src/pager.c
26
src/pager.c
@ -1203,7 +1203,7 @@ static int pagerUseWal(Pager *pPager){
|
||||
# define pagerRollbackWal(x) 0
|
||||
# define pagerWalFrames(v,w,x,y,z) 0
|
||||
# define pagerOpenWalIfPresent(z) SQLITE_OK
|
||||
# define pagerOpenSnapshot(z) SQLITE_OK
|
||||
# define pagerBeginReadTransaction(z) SQLITE_OK
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -1238,7 +1238,7 @@ static void pager_unlock(Pager *pPager){
|
||||
pPager->dbSizeValid = 0;
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
sqlite3WalCloseSnapshot(pPager->pWal);
|
||||
sqlite3WalEndReadTransaction(pPager->pWal);
|
||||
}else{
|
||||
rc = osUnlock(pPager->fd, NO_LOCK);
|
||||
}
|
||||
@ -1437,7 +1437,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
rc2 = sqlite3WalWriteLock(pPager->pWal, 0);
|
||||
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
|
||||
pPager->state = PAGER_SHARED;
|
||||
|
||||
/* If the connection was in locking_mode=exclusive mode but is no longer,
|
||||
@ -2362,15 +2362,20 @@ static int pagerWalFrames(
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a WAL snapshot on the log file this pager is connected to.
|
||||
** Begin a read transaction on the WAL.
|
||||
**
|
||||
** This routine used to be called "pagerOpenSnapshot()" because it essentially
|
||||
** makes a snapshot of the database at the current point in time and preserves
|
||||
** that snapshot for use by the reader in spite of concurrently changes by
|
||||
** other writers or checkpointers.
|
||||
*/
|
||||
static int pagerOpenSnapshot(Pager *pPager){
|
||||
static int pagerBeginReadTransaction(Pager *pPager){
|
||||
int rc; /* Return code */
|
||||
int changed = 0; /* True if cache must be reset */
|
||||
|
||||
assert( pagerUseWal(pPager) );
|
||||
|
||||
rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed);
|
||||
rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
|
||||
if( rc==SQLITE_OK ){
|
||||
int dummy;
|
||||
if( changed ){
|
||||
@ -2428,7 +2433,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
|
||||
pager_reset(pPager);
|
||||
rc = sqlite3PagerOpenWal(pPager, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pagerOpenSnapshot(pPager);
|
||||
rc = pagerBeginReadTransaction(pPager);
|
||||
}
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
|
||||
@ -4002,7 +4007,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
}
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
rc = pagerOpenSnapshot(pPager);
|
||||
rc = pagerBeginReadTransaction(pPager);
|
||||
}else if( pPager->state==PAGER_UNLOCK || isErrorReset ){
|
||||
sqlite3_vfs * const pVfs = pPager->pVfs;
|
||||
int isHotJournal = 0;
|
||||
@ -4561,7 +4566,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
|
||||
** may copy data from the sub-journal into the database file as well
|
||||
** as into the page cache. Which would be incorrect in WAL mode.
|
||||
*/
|
||||
rc = sqlite3WalWriteLock(pPager->pWal, 1);
|
||||
rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
|
||||
if( rc==SQLITE_OK ){
|
||||
pPager->dbOrigSize = pPager->dbSize;
|
||||
pPager->state = PAGER_RESERVED;
|
||||
@ -5892,8 +5897,7 @@ int sqlite3PagerCheckpoint(Pager *pPager){
|
||||
u8 *zBuf = (u8 *)pPager->pTmpSpace;
|
||||
rc = sqlite3WalCheckpoint(pPager->pWal,
|
||||
(pPager->noSync ? 0 : pPager->sync_flags),
|
||||
pPager->pageSize, zBuf,
|
||||
pPager->xBusyHandler, pPager->pBusyHandlerArg
|
||||
pPager->pageSize, zBuf
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
|
@ -444,7 +444,8 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
||||
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
||||
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8) )
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@ -658,7 +659,7 @@ struct sqlite3_io_methods {
|
||||
int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
|
||||
int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void volatile**);
|
||||
int (*xShmRelease)(sqlite3_file*);
|
||||
int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
|
||||
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
|
||||
void (*xShmBarrier)(sqlite3_file*);
|
||||
int (*xShmClose)(sqlite3_file*, int deleteFlag);
|
||||
/* Methods above are valid for version 2 */
|
||||
@ -888,16 +889,40 @@ struct sqlite3_vfs {
|
||||
/*
|
||||
** CAPI3REF: Flags for the xShmLock VFS method
|
||||
**
|
||||
** These integer constants define the various locking states that
|
||||
** an sqlite3_shm object can be in.
|
||||
** These integer constants define the various locking operations
|
||||
** allowed by the xShmLock method of [sqlite3_io_methods]. The
|
||||
** following are the only legal combinations of flags to the
|
||||
** xShmLock method:
|
||||
**
|
||||
** <ul>
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** </ul>
|
||||
**
|
||||
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
|
||||
** was given no the corresponding lock.
|
||||
**
|
||||
** The xShmLock method can transition between unlocked and SHARED or
|
||||
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
|
||||
** and EXCLUSIVE.
|
||||
*/
|
||||
#define SQLITE_SHM_UNLOCK 0
|
||||
#define SQLITE_SHM_READ 1
|
||||
#define SQLITE_SHM_READ_FULL 2
|
||||
#define SQLITE_SHM_WRITE 3
|
||||
#define SQLITE_SHM_PENDING 4
|
||||
#define SQLITE_SHM_CHECKPOINT 5
|
||||
#define SQLITE_SHM_RECOVER 6
|
||||
#define SQLITE_SHM_UNLOCK 1
|
||||
#define SQLITE_SHM_LOCK 2
|
||||
#define SQLITE_SHM_SHARED 4
|
||||
#define SQLITE_SHM_EXCLUSIVE 8
|
||||
|
||||
/*
|
||||
** CAPI3REF: Maximum xShmLock index
|
||||
**
|
||||
** The xShmLock method on [sqlite3_io_methods] may use values
|
||||
** between 0 and this upper bound as its "offset" argument.
|
||||
** The SQLite core will never attempt to acquire or release a
|
||||
** lock outside of this range
|
||||
*/
|
||||
#define SQLITE_SHM_NLOCK 8
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Initialize The SQLite Library
|
||||
|
@ -540,8 +540,8 @@ static int cfShmGet(
|
||||
static int cfShmRelease(sqlite3_file *pFile){
|
||||
return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile);
|
||||
}
|
||||
static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){
|
||||
return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot);
|
||||
static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
|
||||
}
|
||||
static void cfShmBarrier(sqlite3_file *pFile){
|
||||
sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
|
||||
|
@ -54,7 +54,7 @@ static int devsymShmOpen(sqlite3_file*);
|
||||
static int devsymShmSize(sqlite3_file*,int,int*);
|
||||
static int devsymShmGet(sqlite3_file*,int,int*,volatile void**);
|
||||
static int devsymShmRelease(sqlite3_file*);
|
||||
static int devsymShmLock(sqlite3_file*,int,int*);
|
||||
static int devsymShmLock(sqlite3_file*,int,int,int);
|
||||
static void devsymShmBarrier(sqlite3_file*);
|
||||
static int devsymShmClose(sqlite3_file*,int);
|
||||
|
||||
@ -263,9 +263,9 @@ static int devsymShmRelease(sqlite3_file *pFile){
|
||||
devsym_file *p = (devsym_file *)pFile;
|
||||
return sqlite3OsShmRelease(p->pReal);
|
||||
}
|
||||
static int devsymShmLock(sqlite3_file *pFile, int desired, int *pGot){
|
||||
static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
devsym_file *p = (devsym_file *)pFile;
|
||||
return sqlite3OsShmLock(p->pReal, desired, pGot);
|
||||
return sqlite3OsShmLock(p->pReal, ofst, n, flags);
|
||||
}
|
||||
static void devsymShmBarrier(sqlite3_file *pFile){
|
||||
devsym_file *p = (devsym_file *)pFile;
|
||||
|
@ -155,7 +155,7 @@ static int vfslogShmOpen(sqlite3_file *pFile);
|
||||
static int vfslogShmSize(sqlite3_file *pFile, int reqSize, int *pNewSize);
|
||||
static int vfslogShmGet(sqlite3_file *pFile, int,int*,volatile void **);
|
||||
static int vfslogShmRelease(sqlite3_file *pFile);
|
||||
static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock);
|
||||
static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags);
|
||||
static void vfslogShmBarrier(sqlite3_file*);
|
||||
static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag);
|
||||
|
||||
@ -460,12 +460,12 @@ static int vfslogShmRelease(sqlite3_file *pFile){
|
||||
vfslog_call(p->pVfslog, OS_SHMRELEASE, p->iFileId, t, rc, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock){
|
||||
static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
int rc;
|
||||
sqlite3_uint64 t;
|
||||
VfslogFile *p = (VfslogFile *)pFile;
|
||||
t = vfslog_time();
|
||||
rc = p->pReal->pMethods->xShmLock(p->pReal, desiredLock, gotLock);
|
||||
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
|
||||
t = vfslog_time() - t;
|
||||
vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0);
|
||||
return rc;
|
||||
|
@ -102,7 +102,7 @@ static int tvfsShmOpen(sqlite3_file*);
|
||||
static int tvfsShmSize(sqlite3_file*, int , int *);
|
||||
static int tvfsShmGet(sqlite3_file*, int , int *, volatile void **);
|
||||
static int tvfsShmRelease(sqlite3_file*);
|
||||
static int tvfsShmLock(sqlite3_file*, int , int *);
|
||||
static int tvfsShmLock(sqlite3_file*, int , int, int);
|
||||
static void tvfsShmBarrier(sqlite3_file*);
|
||||
static int tvfsShmClose(sqlite3_file*, int);
|
||||
|
||||
@ -544,31 +544,34 @@ static int tvfsShmRelease(sqlite3_file *pFile){
|
||||
|
||||
static int tvfsShmLock(
|
||||
sqlite3_file *pFile,
|
||||
int desiredLock,
|
||||
int *gotLock
|
||||
int ofst,
|
||||
int n,
|
||||
int flags
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
char *zLock = "";
|
||||
int nLock;
|
||||
char zLock[80];
|
||||
|
||||
switch( desiredLock ){
|
||||
case SQLITE_SHM_READ: zLock = "READ"; break;
|
||||
case SQLITE_SHM_WRITE: zLock = "WRITE"; break;
|
||||
case SQLITE_SHM_CHECKPOINT: zLock = "CHECKPOINT"; break;
|
||||
case SQLITE_SHM_RECOVER: zLock = "RECOVER"; break;
|
||||
case SQLITE_SHM_PENDING: zLock = "PENDING"; break;
|
||||
case SQLITE_SHM_UNLOCK: zLock = "UNLOCK"; break;
|
||||
sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
|
||||
nLock = strlen(zLock);
|
||||
if( flags & SQLITE_SHM_LOCK ){
|
||||
strcpy(&zLock[nLock], " lock");
|
||||
}else{
|
||||
strcpy(&zLock[nLock], " unlock");
|
||||
}
|
||||
nLock += strlen(&zLock[nLock]);
|
||||
if( flags & SQLITE_SHM_SHARED ){
|
||||
strcpy(&zLock[nLock], " shared");
|
||||
}else{
|
||||
strcpy(&zLock[nLock], " exclusive");
|
||||
}
|
||||
tvfsExecTcl(p, "xShmLock",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
|
||||
Tcl_NewStringObj(zLock, -1)
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
*gotLock = desiredLock;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -716,9 +719,7 @@ static void testvfs_obj_del(ClientData cd){
|
||||
**
|
||||
** SCRIPT xShmLock FILENAME ID LOCK
|
||||
**
|
||||
** where LOCK is one of "UNLOCK", "READ", "READ_FULL", "WRITE", "PENDING",
|
||||
** "CHECKPOINT" or "RECOVER". The script should return an SQLite error
|
||||
** code.
|
||||
** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive"
|
||||
*/
|
||||
static int testvfs_cmd(
|
||||
ClientData cd,
|
||||
|
34
src/wal.h
34
src/wal.h
@ -20,19 +20,20 @@
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
# define sqlite3WalOpen(x,y,z) 0
|
||||
# define sqlite3WalClose(w,x,y,z) 0
|
||||
# define sqlite3WalOpenSnapshot(y,z) 0
|
||||
# define sqlite3WalCloseSnapshot(z)
|
||||
# define sqlite3WalRead(v,w,x,y,z) 0
|
||||
# define sqlite3WalOpen(x,y,z) 0
|
||||
# define sqlite3WalClose(w,x,y,z) 0
|
||||
# define sqlite3WalBeginReadTransaction(y,z) 0
|
||||
# define sqlite3WalEndReadTransaction(z)
|
||||
# define sqlite3WalRead(v,w,x,y,z) 0
|
||||
# define sqlite3WalDbsize(y,z)
|
||||
# define sqlite3WalWriteLock(y,z) 0
|
||||
# define sqlite3WalUndo(x,y,z) 0
|
||||
# define sqlite3WalBeginWriteTransaction(y) 0
|
||||
# define sqlite3WalEndWRiteTransaction(x) 0
|
||||
# define sqlite3WalUndo(x,y,z) 0
|
||||
# define sqlite3WalSavepoint(y,z)
|
||||
# define sqlite3WalSavepointUndo(y,z) 0
|
||||
# define sqlite3WalFrames(u,v,w,x,y,z) 0
|
||||
# define sqlite3WalCheckpoint(u,v,w,x,y,z) 0
|
||||
# define sqlite3WalCallback(z) 0
|
||||
# define sqlite3WalSavepointUndo(y,z) 0
|
||||
# define sqlite3WalFrames(u,v,w,x,y,z) 0
|
||||
# define sqlite3WalCheckpoint(u,v,w,x) 0
|
||||
# define sqlite3WalCallback(z) 0
|
||||
#else
|
||||
|
||||
#define WAL_SAVEPOINT_NDATA 3
|
||||
@ -53,8 +54,8 @@ int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
|
||||
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
|
||||
** transaction and releases the lock.
|
||||
*/
|
||||
int sqlite3WalOpenSnapshot(Wal *pWal, int *);
|
||||
void sqlite3WalCloseSnapshot(Wal *pWal);
|
||||
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
|
||||
void sqlite3WalEndReadTransaction(Wal *pWal);
|
||||
|
||||
/* Read a page from the write-ahead log, if it is present. */
|
||||
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
|
||||
@ -64,7 +65,8 @@ int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
|
||||
void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno);
|
||||
|
||||
/* Obtain or release the WRITER lock. */
|
||||
int sqlite3WalWriteLock(Wal *pWal, int op);
|
||||
int sqlite3WalBeginWriteTransaction(Wal *pWal);
|
||||
int sqlite3WalEndWriteTransaction(Wal *pWal);
|
||||
|
||||
/* Undo any frames written (but not committed) to the log */
|
||||
int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
|
||||
@ -85,9 +87,7 @@ int sqlite3WalCheckpoint(
|
||||
Wal *pWal, /* Write-ahead log connection */
|
||||
int sync_flags, /* Flags to sync db file with (or 0) */
|
||||
int nBuf, /* Size of buffer nBuf */
|
||||
u8 *zBuf, /* Temporary buffer to use */
|
||||
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
|
||||
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
|
||||
u8 *zBuf /* Temporary buffer to use */
|
||||
);
|
||||
|
||||
/* Return the value to pass to a sqlite3_wal_hook callback, the
|
||||
|
Loading…
Reference in New Issue
Block a user