]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Update this branch with latest trunk changes.
authordan <dan@noemail.net>
Mon, 8 Dec 2014 07:50:31 +0000 (07:50 +0000)
committerdan <dan@noemail.net>
Mon, 8 Dec 2014 07:50:31 +0000 (07:50 +0000)
FossilOrigin-Name: 69a312ad3fe5b39bc394b9ce958cb63d734518c7

1  2 
manifest
manifest.uuid
src/btree.c
src/main.c
src/pager.c
src/pragma.c
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
src/wal.c
test/permutations.test

diff --cc manifest
index 61039ed68d6512acbea07a720a29323eaa369da2,2427334a1763e063b85241155c7bb0125ce06255..96dcf87dd3f3dba4b6f13c4c96b493068a3b482d
+++ b/manifest
@@@ -1,9 -1,9 +1,9 @@@
- 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
@@@ -188,7 -173,7 +188,7 @@@ F src/auth.c b56c78ebe40a2110fd361379f7
  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
@@@ -196,8 -181,8 +196,8 @@@ F src/callback.c 7b44ce59674338ad48b0e8
  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
@@@ -210,7 -195,7 +210,7 @@@ F src/journal.c b4124532212b6952f42eb2c
  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
@@@ -231,29 -216,29 +231,29 @@@ F src/os_setup.h c9d4553b5aaa6f73391448
  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
@@@ -310,16 -295,16 +310,16 @@@ F src/vdbe.c 1a9e671c9cfc259e4d2affc71f
  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
@@@ -792,7 -779,7 +795,7 @@@ F test/pagesize.test 1dd51367e752e742f5
  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
@@@ -1237,7 -1225,7 +1241,7 @@@ F tool/vdbe_profile.tcl 67746953071a9f8
  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
diff --cc manifest.uuid
index 85a4152dfba2957c9048d3c2e5b772a25ce897fc,7af512863643864b513e9b636ec2027913abd8cc..3420b8955c07c7f4752e5989189bac0eb3525a5a
@@@ -1,1 -1,1 +1,1 @@@
- 088a41eb8c18886a260cf53fa0cca3bd1958dc05
 -6aeece19a235344be2537e66a3fe08b1febfb5a0
++69a312ad3fe5b39bc394b9ce958cb63d734518c7
diff --cc src/btree.c
Simple merge
diff --cc src/main.c
Simple merge
diff --cc src/pager.c
index 3508a9f937c2cb74f8da5af04345c91f5519969b,a2ae9cc41082771464f7512e9ad850773122b257..a5bba528ee4d827bf3e49c5a8935fc7b6b6964d1
@@@ -7119,9 -7073,10 +7119,10 @@@ void sqlite3PagerClearCache(Pager *pPag
  */
  int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
    int rc = SQLITE_OK;
 -  if( pPager->pWal ){
 +  if( pPager->pWal && PagerOtaMode(pPager)==0 ){
      rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
-         pPager->xBusyHandler, pPager->pBusyHandlerArg,
+         (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
+         pPager->pBusyHandlerArg,
          pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
          pnLog, pnCkpt
      );
diff --cc src/pragma.c
Simple merge
diff --cc src/sqlite.h.in
Simple merge
diff --cc src/sqliteInt.h
Simple merge
diff --cc src/test1.c
Simple merge
diff --cc src/wal.c
index bb8c0f806e0a094ef4f99e0c807c97777c6f9a11,2b80c7a95e71e89998953921354ae26ff4cc2f9e..726afbeb2a32f3cbe53ae20bfab357d5d850f293
+++ b/src/wal.c
@@@ -1649,186 -1623,38 +1649,218 @@@ static int walPagesize(Wal *pWal)
    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);
        }
      }
@@@ -3081,7 -3016,11 +3135,7 @@@ int sqlite3WalCheckpoint
  
    /* 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 ){
Simple merge