- C Update\scomments\sin\ssqlite3ota.h\sto\sremove\sthe\s"must\shave\sPRIMARY\sKEY"\srestriction.
- D 2014-12-08T07:28:26.753
-C Avoid\saccessing\sa\ssingle\suninitialized\sbyte\swhen\smoving\sa\srare\s3-byte\scell\sfrom\san\sinternal\spage\sto\sa\sleaf.\sThis\swas\snot\sactually\scausing\sa\sproblem,\sjust\sa\svalgrind\swarning.
-D 2014-12-06T14:56:49.956
++C Update\sthis\sbranch\swith\slatest\strunk\schanges.
++D 2014-12-08T07:50:31.222
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
- F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb
+ F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
- F Makefile.msc 788f1288633a0c3c3cbbe0f3e4827d033f7ba530
+ F Makefile.msc 10720782f88648bf2b5dcedf4c1524b067d43e47
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION d846487aff892625eb8e75960234e7285f0462fe
F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
- F src/btree.c 1ab82a27ed4f1e8dc640b7ca0ffb074c4233e495
-F src/btree.c 9023963463b0b1876aea1abc6d208d9ffa0228ae
++F src/btree.c 7071995e9ab92173f43e9d1b8560a8db64a31e9a
F src/btree.h e31a3a3ebdedb1caf9bda3ad5dbab3db9b780f6e
F src/btreeInt.h 3363e18fd76f69a27a870b25221b2345b3fd4d21
F src/build.c 67bb05b1077e0cdaccb2e36bfcbe7a5df9ed31e8
F src/complete.c c4ba6e0626bb94bc77a0861735f3382fcf7cc818
F src/ctime.c df19848891c8a553c80e6f5a035e768280952d1a
F src/date.c 93594514aae68de117ca4a2a0d6cc63eddf26744
-F src/delete.c 0750b1eb4d96cd3fb2c798599a3a7c85e92f1417
+F src/delete.c 2d2c4ff24bda5d28000d0aeb05960ee2883a2d3a
- F src/expr.c 73de4c0da2eed6b149d40a05c589dfeb2c4a87a1
+ F src/expr.c 00da3072f362b06f39ce4052baa1d4ce2bb36d1c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
- F src/main.c cd819123ed552a15c37bd2fd5360db25015dc461
-F src/main.c e50203613fb77e2f28deb51425ee52b3879e85f8
++F src/main.c eac81ee5cb0f94b496c15f20fcbabe4530b9a8c1
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7
F src/os_win.c a9e500dd963fb1f67d7860e58b5772abe6123862
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
- F src/pager.c 9fe27a768be53dbe0a818ae10791dc36100a0e76
-F src/pager.c 7a5c5bc0e29b9b16834f5558a9d5d22bbae59a08
-F src/pager.h d1eee3c3f741be247ce6d82752a178515fc8578b
++F src/pager.c 47f13c194a980ed55dd4825f286d40d49c4a7093
+F src/pager.h c6157af66a9999797629968921133f67716f8f9f
F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45
F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
F src/pcache1.c facbdd3ecc09c8f750089d941305694301328e98
- F src/pragma.c 8e0087a5ae6e60ac9ed48df19025cb423e3c8c34
-F src/pragma.c d54cdd40b63d608f2d95b7482c710690e3593a73
++F src/pragma.c 294c31d79dfcb6f9cea49528b19e5f8b25e3d5ec
F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7
F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
- F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952
+ F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
- F src/select.c 428165951748151e87a15295b7357221433e311b
- F src/shell.c bc28d5992109717c87804e2eb1a08a7c8cc7a2fd
- F src/sqlite.h.in f60a24616a6a7e622266e723ed141f0c6131514e
+ F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75
+ F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf
-F src/sqlite.h.in 6ec654324cb490ea3d8a7be28b8c7d37fe4ad282
++F src/sqlite.h.in 8f704473c8301f3c9cc044d10020bb3d5955dfc3
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
- F src/sqliteInt.h 32d7becef5cbd9a1118608921ec99f00f96c6e5d
-F src/sqliteInt.h 28049b803b74a7f73242a8226915ea00ebb1309f
++F src/sqliteInt.h 9d7b1d5adfcc026971957d440b796f2b26b82d0c
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc
-F src/tclsqlite.c 0a874655dd39a9875e39c5d3c464db662171d228
-F src/test1.c ebb8cd3c94a2ac8851b7b0b1349284e73a8b4c7a
+F src/tclsqlite.c 8cf7d53aa1e1393b79457e4d49a29c18fa8403bd
- F src/test1.c 76b5cbefaac443f48f05d3621f5cedc7b2801c65
++F src/test1.c fed17ded5498378fea274f2de0fa7b0b89f855f7
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83
- F src/vdbeaux.c 5ce4f414147a3bc3cbcf00ec57f2606c25791629
+ F src/vdbeaux.c 6f7f39c3fcf0f5923758df8561bb5d843908a553
-F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778
+F src/vdbeblob.c 317c71482ed73b0966db2d1c4e20839be3e9fe79
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
- F src/vdbesort.c 87f3923483113d1c95d84640becb4e4946f27d9a
+ F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
- F src/vtab.c 2a30791bbd7926b589401bd09c3abb33de563793
- F src/wal.c d5c581b635951cf5513ec9699d118b32323443f3
+ F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9
-F src/wal.c 847692349eb6e1fb8543dbc97e69ddbfa4cc7ea7
-F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
++F src/wal.c 632d9afe19e11cc49a8b74ff52ec2a415568b958
+F src/wal.h 0d3ba0c3f1b4c25796cb213568a84b9f9063f465
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
- F src/where.c e275cb74731a3351a9da6ba8280bd5054db6192d
+ F src/where.c e914fdb9159bb36af4a673193bbda08aaf9e5a73
F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
- F test/permutations.test 19cc048448340952b08a897167ec7b7bc85142b9
-F test/permutations.test 4e12d43f4639ea8a0e366d9c64e0009afe2eb544
++F test/permutations.test 7828a776c70fccf83d2e35d0e1efc191b3e0c646
F test/pragma.test 49ac8a73c0daa574824538fed28727d1259fe735
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
- P 46069393b3141ab198f0fcc4f6c05229f06bf1e8
- R 2ff45547a2c264d0b419c476d87c1792
-P dd1dd4451f468599f7a0c2f7b5ee6125db3bb152
-R fd0e43f358120e3c011052c6be23c038
++P 088a41eb8c18886a260cf53fa0cca3bd1958dc05 6aeece19a235344be2537e66a3fe08b1febfb5a0
++R 22c55b7623330ec4e5635caf9d27c83c
U dan
- Z 50a00d12069d2404879b86db79315481
-Z 22968e22e0931f64edb1c44af2aed6b9
++Z 93c0d69763bbc98aa3e78f69481d4c3f
return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
}
+/*
+** Initialize the contents of the WalCkpt object indicated by the final
+** argument and begin a checkpoint operation. The CKPT lock must already
+** be held when this function is called.
+**
+** Return SQLITE_OK if successful or an error code otherwise.
+*/
+static int walCheckpointStart(
+ Wal *pWal, /* Wal connection */
+ u8 *aBuf, /* Page-sized temporary buffer */
+ int nBuf, /* Size of aBuf[] in bytes */
+ int (*xBusy)(void*), /* Function to call when busy (or NULL) */
+ void *pBusyArg, /* Context argument for xBusyHandler */
+ int sync_flags, /* Flags for OsSync() (or 0) */
+ WalCkpt *p /* Allocated object to populate */
+){
+ int rc; /* Return code */
+ int i; /* Iterator variable */
+
+ memset(p, 0, sizeof(WalCkpt));
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ p->szPage = walPagesize(pWal);
+ p->pWal = pWal;
+ p->aBuf = aBuf;
+ p->sync_flags = sync_flags;
+ testcase( p->szPage<=32768 );
+ testcase( p->szPage>=65536 );
+ p->pInfo = walCkptInfo(pWal);
+ if( p->pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
+
+ /* Allocate the iterator */
+ rc = walIteratorInit(pWal, &p->pIter);
+ if( rc!=SQLITE_OK ) return rc;
+ assert( p->pIter );
+
+ /* Compute in mxSafeFrame the index of the last frame of the WAL that is
+ ** safe to write into the database. Frames beyond mxSafeFrame might
+ ** overwrite database pages that are in use by active readers and thus
+ ** cannot be backfilled from the WAL.
+ */
+ p->mxSafeFrame = pWal->hdr.mxFrame;
+ p->mxPage = pWal->hdr.nPage;
+ for(i=1; i<WAL_NREADER; i++){
+ u32 y = p->pInfo->aReadMark[i];
+ if( p->mxSafeFrame>y ){
+ assert( y<=pWal->hdr.mxFrame );
+ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
+ if( rc==SQLITE_OK ){
+ p->pInfo->aReadMark[i] = (i==1 ? p->mxSafeFrame : READMARK_NOT_USED);
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ }else if( rc==SQLITE_BUSY ){
+ p->mxSafeFrame = y;
+ xBusy = 0;
+ }else{
+ walIteratorFree(p->pIter);
+ p->pIter = 0;
+ return rc;
+ }
+ }
+ }
+
+ if( p->pInfo->nBackfill>=p->mxSafeFrame
+ || (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))!=SQLITE_OK
+ ){
+ walIteratorFree(p->pIter);
+ p->pIter = 0;
+ }
+ if( rc==SQLITE_BUSY ) rc = SQLITE_OK;
+
+ if( rc==SQLITE_OK && p->pIter ){
+ /* Sync the WAL to disk */
+ if( sync_flags ){
+ rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
+ }
+
+ /* If the database may grow as a result of this checkpoint, hint
+ ** about the eventual size of the db file to the VFS layer. */
+ if( rc==SQLITE_OK ){
+ i64 nSize; /* Current size of database file */
+ i64 nReq = ((i64)p->mxPage * p->szPage);
+ rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
+ if( rc==SQLITE_OK && nSize<nReq ){
+ sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Attempt to copy the next frame from the wal file to the database file. If
+** there are no more frames to copy to the database file return SQLITE_DONE.
+** If the frame is successfully copied, return SQLITE_OK. Or, if an error
+** occurs, return an SQLite error code.
+*/
+static int walCheckpointStep(WalCkpt *p){
+ u32 iDbpage = 0; /* Next database page to write */
+ u32 iFrame = 0; /* Wal frame containing data for iDbpage */
+ int rc = SQLITE_DONE;
+
+ assert( p->rc==SQLITE_OK );
+ while( p->pIter && 0==walIteratorNext(p->pIter, &iDbpage, &iFrame) ){
+ i64 iOffset;
+ assert( walFramePgno(p->pWal, iFrame)==iDbpage );
+ p->nStep++;
+ if( iFrame<=p->pInfo->nBackfill
+ || iFrame>p->mxSafeFrame
+ || iDbpage>p->mxPage
+ ){
+ continue;
+ }
+
+ iOffset = walFrameOffset(iFrame, p->szPage) + WAL_FRAME_HDRSIZE;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+ rc = sqlite3OsRead(p->pWal->pWalFd, p->aBuf, p->szPage, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ iOffset = (iDbpage-1)*(i64)p->szPage;
+ testcase( IS_BIG_INT(iOffset) );
+ rc = sqlite3OsWrite(p->pWal->pDbFd, p->aBuf, p->szPage, iOffset);
+ break;
+ }
+
+ p->rc = rc;
+ return rc;
+}
+
+/*
+** The current round of checkpointing work using the object indicated by
+** the only argument is now finished. If no error occcurred, this function
+** saves the results to shared memory (i.e. updates the WalCkptInfo.nBackfill
+** variable), and truncates and syncs the database file as required.
+**
+** All dynamic resources currently held by the WalCkpt object are released.
+** It is the responsibility of the caller to delete the WalCkpt itself if
+** required.
+*/
+static int walCheckpointFinalize(WalCkpt *p){
+ if( p->pIter ){
+ int rc = p->rc;
+ Wal *pWal = p->pWal;
+
+ if( rc==SQLITE_DONE ){
+ /* If work was completed */
+ rc = SQLITE_OK;
+ if( p->mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
+ i64 szDb = pWal->hdr.nPage*(i64)p->szPage;
+ testcase( IS_BIG_INT(szDb) );
+ rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
+ if( rc==SQLITE_OK && p->sync_flags ){
+ rc = sqlite3OsSync(pWal->pDbFd, p->sync_flags);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ p->pInfo->nBackfill = p->mxSafeFrame;
+ }
+ p->rc = rc;
+ }else{
+#ifdef SQLITE_ENABLE_OTA
+ if( rc==SQLITE_OK && p->sync_flags ){
+ /* If work was not completed, but no error has occured. */
+ p->rc = sqlite3OsSync(pWal->pDbFd, p->sync_flags);
+ }
+#else
+ assert( rc!=SQLITE_OK );
+#endif
+ }
+
+ /* Release the reader lock held while backfilling */
+ walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
+ walIteratorFree(p->pIter);
+ p->pIter = 0;
+ }
+
+ return p->rc;
+}
+
+ /*
+ ** The following is guaranteed when this function is called:
+ **
+ ** a) the WRITER lock is held,
+ ** b) the entire log file has been checkpointed, and
+ ** c) any existing readers are reading exclusively from the database
+ ** file - there are no readers that may attempt to read a frame from
+ ** the log file.
+ **
+ ** This function updates the shared-memory structures so that the next
+ ** client to write to the database (which may be this one) does so by
+ ** writing frames into the start of the log file.
+ **
+ ** The value of parameter salt1 is used as the aSalt[1] value in the
+ ** new wal-index header. It should be passed a pseudo-random value (i.e.
+ ** one obtained from sqlite3_randomness()).
+ */
+ static void walRestartHdr(Wal *pWal, u32 salt1){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ int i; /* Loop counter */
+ u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
+ pWal->nCkpt++;
+ pWal->hdr.mxFrame = 0;
+ sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
+ memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
+ walIndexWriteHdr(pWal);
+ pInfo->nBackfill = 0;
+ pInfo->aReadMark[1] = 0;
+ for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+ assert( pInfo->aReadMark[0]==0 );
+ }
+
/*
** Copy as much content as we can from the WAL back into the database file
** in response to an sqlite3_wal_checkpoint() request or the equivalent.
static int walCheckpoint(
Wal *pWal, /* Wal connection */
int eMode, /* One of PASSIVE, FULL or RESTART */
- int (*xBusyCall)(void*), /* Function to call when busy */
+ int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
int sync_flags, /* Flags for OsSync() (or 0) */
- u8 *zBuf /* Temporary buffer to use */
+ u8 *zBuf, /* Temporary buffer to use */
+ int nBuf /* Size of zBuf in bytes */
){
int rc; /* Return code */
- int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */
- int szPage; /* Database page-size */
- WalIterator *pIter = 0; /* Wal iterator context */
- u32 iDbpage = 0; /* Next database page to write */
- u32 iFrame = 0; /* Wal frame containing data for iDbpage */
- u32 mxSafeFrame; /* Max frame that can be backfilled */
- u32 mxPage; /* Max database page to write */
- int i; /* Loop counter */
- volatile WalCkptInfo *pInfo; /* The checkpoint status information */
-
- szPage = walPagesize(pWal);
- testcase( szPage<=32768 );
- testcase( szPage>=65536 );
- pInfo = walCkptInfo(pWal);
- if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
-
- /* Allocate the iterator */
- rc = walIteratorInit(pWal, &pIter);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pIter );
+ WalCkpt sC;
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
+ /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
+ ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
+ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
+
- /* Compute in mxSafeFrame the index of the last frame of the WAL that is
- ** safe to write into the database. Frames beyond mxSafeFrame might
- ** overwrite database pages that are in use by active readers and thus
- ** cannot be backfilled from the WAL.
- */
- mxSafeFrame = pWal->hdr.mxFrame;
- mxPage = pWal->hdr.nPage;
- for(i=1; i<WAL_NREADER; i++){
- u32 y = pInfo->aReadMark[i];
- if( mxSafeFrame>y ){
- assert( y<=pWal->hdr.mxFrame );
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
- if( rc==SQLITE_OK ){
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- }else if( rc==SQLITE_BUSY ){
- mxSafeFrame = y;
- xBusy = 0;
- }else{
- goto walcheckpoint_out;
- }
- }
- }
-
- if( pInfo->nBackfill<mxSafeFrame
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
- ){
- i64 nSize; /* Current size of database file */
- u32 nBackfill = pInfo->nBackfill;
-
- /* Sync the WAL to disk */
- if( sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
- }
-
- /* If the database may grow as a result of this checkpoint, hint
- ** about the eventual size of the db file to the VFS layer.
- */
- if( rc==SQLITE_OK ){
- i64 nReq = ((i64)mxPage * szPage);
- rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
- if( rc==SQLITE_OK && nSize<nReq ){
- sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
- }
- }
-
+ rc = walCheckpointStart(pWal, zBuf, nBuf, xBusy, pBusyArg, sync_flags, &sC);
+ if( sC.pIter==0 ) goto walcheckpoint_out;
+ assert( rc==SQLITE_OK );
- /* Iterate through the contents of the WAL, copying data to the db file. */
- while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
- i64 iOffset;
- assert( walFramePgno(pWal, iFrame)==iDbpage );
- if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
- iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
- /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- iOffset = (iDbpage-1)*(i64)szPage;
- testcase( IS_BIG_INT(iOffset) );
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- }
-
- /* If work was actually accomplished... */
- if( rc==SQLITE_OK ){
- if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
- i64 szDb = pWal->hdr.nPage*(i64)szPage;
- testcase( IS_BIG_INT(szDb) );
- rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
- if( rc==SQLITE_OK && sync_flags ){
- rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
- }
- }
- if( rc==SQLITE_OK ){
- pInfo->nBackfill = mxSafeFrame;
- }
- }
-
- /* Release the reader lock held while backfilling */
- walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
- }
-
- if( rc==SQLITE_BUSY ){
- /* Reset the return code so as not to report a checkpoint failure
- ** just because there are active readers. */
- rc = SQLITE_OK;
- }
+ /* Step the checkpoint object until it reports something other than
+ ** SQLITE_OK. */
+ while( SQLITE_OK==(rc = walCheckpointStep(&sC)) );
+ rc = walCheckpointFinalize(&sC);
- /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal
- ** file has been copied into the database file, then block until all
- ** readers have finished using the wal file. This ensures that the next
- ** process to write to the database restarts the wal file.
+ /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
+ ** entire wal file has been copied into the database file, then block
+ ** until all readers have finished using the wal file. This ensures that
+ ** the next process to write to the database restarts the wal file.
*/
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
assert( pWal->writeLock );
- if( pInfo->nBackfill<pWal->hdr.mxFrame ){
+ if( sC.pInfo->nBackfill<pWal->hdr.mxFrame ){
rc = SQLITE_BUSY;
- }else if( eMode==SQLITE_CHECKPOINT_RESTART ){
+ }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
+ u32 salt1;
+ sqlite3_randomness(4, &salt1);
- assert( mxSafeFrame==pWal->hdr.mxFrame );
+ assert( sC.mxSafeFrame==pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
if( rc==SQLITE_OK ){
+ if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
+ /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as
+ ** SQLITE_CHECKPOINT_RESTART with the addition that it also
+ ** truncates the log file to zero bytes just prior to a
+ ** successful return.
+ **
+ ** In theory, it might be safe to do this without updating the
+ ** wal-index header in shared memory, as all subsequent reader or
+ ** writer clients should see that the entire log file has been
+ ** checkpointed and behave accordingly. This seems unsafe though,
+ ** as it would leave the system in a state where the contents of
+ ** the wal-index header do not match the contents of the
+ ** file-system. To avoid this, update the wal-index header to
+ ** indicate that the log file contains zero valid frames. */
+ walRestartHdr(pWal, salt1);
+ rc = sqlite3OsTruncate(pWal->pWalFd, 0);
+ }
walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
}
}
/* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){
- rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf, nBuf);
- if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
- }
++ rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf, nBuf);
/* If no error occurred, set the output variables. */
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){