/ Check-in [9799241f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance the WAL header sync so that it honors the various synchronous pragmas, settings, and device characteristics.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal-header-sync
Files: files | file ages | folders
SHA1:9799241f7de952c4d1ea8bf6508b577d2b57a370
User & Date: drh 2011-12-16 21:26:26
Context
2011-12-17
13:45
Merge in changes that cause the first sector of the WAL file to be synced when the WAL restarts. This is a fix for the power-loss corruption problem described in ticket [ff5be73dee086] check-in: 44ca4d12 user: drh tags: trunk
2011-12-16
21:26
Enhance the WAL header sync so that it honors the various synchronous pragmas, settings, and device characteristics. Closed-Leaf check-in: 9799241f user: drh tags: wal-header-sync
19:34
Proposed changes that ensure that the WAL header is written prior to the first commit mark. check-in: 91d0437c user: drh tags: wal-header-sync
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

   612    612     u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
   613    613     u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
   614    614     u8 useJournal;              /* Use a rollback journal on this file */
   615    615     u8 noReadlock;              /* Do not bother to obtain readlocks */
   616    616     u8 noSync;                  /* Do not sync the journal if true */
   617    617     u8 fullSync;                /* Do extra syncs of the journal for robustness */
   618    618     u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
          619  +  u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
   619    620     u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
   620    621     u8 tempFile;                /* zFilename is a temporary file */
   621    622     u8 readOnly;                /* True for a read-only database */
   622    623     u8 memDb;                   /* True to inhibit all file I/O */
   623    624   
   624    625     /**************************************************************************
   625    626     ** The following block contains those class members that change during
................................................................................
   782    783   #ifndef SQLITE_OMIT_WAL
   783    784   static int pagerUseWal(Pager *pPager){
   784    785     return (pPager->pWal!=0);
   785    786   }
   786    787   #else
   787    788   # define pagerUseWal(x) 0
   788    789   # define pagerRollbackWal(x) 0
   789         -# define pagerWalFrames(v,w,x,y,z) 0
          790  +# define pagerWalFrames(v,w,x,y) 0
   790    791   # define pagerOpenWalIfPresent(z) SQLITE_OK
   791    792   # define pagerBeginReadTransaction(z) SQLITE_OK
   792    793   #endif
   793    794   
   794    795   #ifndef NDEBUG 
   795    796   /*
   796    797   ** Usage:
................................................................................
  2951   2952   ** The list of pages passed into this routine is always sorted by page number.
  2952   2953   ** Hence, if page 1 appears anywhere on the list, it will be the first page.
  2953   2954   */ 
  2954   2955   static int pagerWalFrames(
  2955   2956     Pager *pPager,                  /* Pager object */
  2956   2957     PgHdr *pList,                   /* List of frames to log */
  2957   2958     Pgno nTruncate,                 /* Database size after this commit */
  2958         -  int isCommit,                   /* True if this is a commit */
  2959         -  int syncFlags                   /* Flags to pass to OsSync() (or 0) */
         2959  +  int isCommit                    /* True if this is a commit */
  2960   2960   ){
  2961   2961     int rc;                         /* Return code */
  2962   2962   #if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
  2963   2963     PgHdr *p;                       /* For looping over pages */
  2964   2964   #endif
  2965   2965   
  2966   2966     assert( pPager->pWal );
................................................................................
  2983   2983         if( p->pgno<=nTruncate ) ppNext = &p->pDirty;
  2984   2984       }
  2985   2985       assert( pList );
  2986   2986     }
  2987   2987   
  2988   2988     if( pList->pgno==1 ) pager_write_changecounter(pList);
  2989   2989     rc = sqlite3WalFrames(pPager->pWal, 
  2990         -      pPager->pageSize, pList, nTruncate, isCommit, syncFlags
         2990  +      pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
  2991   2991     );
  2992   2992     if( rc==SQLITE_OK && pPager->pBackup ){
  2993   2993       PgHdr *p;
  2994   2994       for(p=pList; p; p=p->pDirty){
  2995   2995         sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
  2996   2996       }
  2997   2997     }
................................................................................
  3363   3363     }else if( bCkptFullFsync ){
  3364   3364       pPager->syncFlags = SQLITE_SYNC_NORMAL;
  3365   3365       pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
  3366   3366     }else{
  3367   3367       pPager->syncFlags = SQLITE_SYNC_NORMAL;
  3368   3368       pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
  3369   3369     }
         3370  +  pPager->walSyncFlags = pPager->syncFlags;
         3371  +  if( pPager->fullSync ){
         3372  +    pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
         3373  +  }
  3370   3374   }
  3371   3375   #endif
  3372   3376   
  3373   3377   /*
  3374   3378   ** The following global variable is incremented whenever the library
  3375   3379   ** attempts to open a temporary file.  This information is used for
  3376   3380   ** testing and analysis only.  
................................................................................
  4190   4194     pPg->pDirty = 0;
  4191   4195     if( pagerUseWal(pPager) ){
  4192   4196       /* Write a single frame for this page to the log. */
  4193   4197       if( subjRequiresPage(pPg) ){ 
  4194   4198         rc = subjournalPage(pPg); 
  4195   4199       }
  4196   4200       if( rc==SQLITE_OK ){
  4197         -      rc = pagerWalFrames(pPager, pPg, 0, 0, 0);
         4201  +      rc = pagerWalFrames(pPager, pPg, 0, 0);
  4198   4202       }
  4199   4203     }else{
  4200   4204     
  4201   4205       /* Sync the journal file if required. */
  4202   4206       if( pPg->flags&PGHDR_NEED_SYNC 
  4203   4207        || pPager->eState==PAGER_WRITER_CACHEMOD
  4204   4208       ){
................................................................................
  4529   4533     assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
  4530   4534     pPager->exclusiveMode = (u8)tempFile; 
  4531   4535     pPager->changeCountDone = pPager->tempFile;
  4532   4536     pPager->memDb = (u8)memDb;
  4533   4537     pPager->readOnly = (u8)readOnly;
  4534   4538     assert( useJournal || pPager->tempFile );
  4535   4539     pPager->noSync = pPager->tempFile;
  4536         -  pPager->fullSync = pPager->noSync ?0:1;
  4537         -  pPager->syncFlags = pPager->noSync ? 0 : SQLITE_SYNC_NORMAL;
  4538         -  pPager->ckptSyncFlags = pPager->syncFlags;
         4540  +  if( pPager->noSync ){
         4541  +    assert( pPager->fullSync==0 );
         4542  +    assert( pPager->syncFlags==0 );
         4543  +    assert( pPager->walSyncFlags==0 );
         4544  +    assert( pPager->ckptSyncFlags==0 );
         4545  +  }else{
         4546  +    pPager->fullSync = 1;
         4547  +    pPager->syncFlags = SQLITE_SYNC_NORMAL;
         4548  +    pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
         4549  +    pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
         4550  +  }
  4539   4551     /* pPager->pFirst = 0; */
  4540   4552     /* pPager->pFirstSynced = 0; */
  4541   4553     /* pPager->pLast = 0; */
  4542   4554     pPager->nExtra = (u16)nExtra;
  4543   4555     pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
  4544   4556     assert( isOpen(pPager->fd) || tempFile );
  4545   4557     setSectorSize(pPager);
................................................................................
  5761   5773           ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
  5762   5774           rc = sqlite3PagerGet(pPager, 1, &pPageOne);
  5763   5775           pList = pPageOne;
  5764   5776           pList->pDirty = 0;
  5765   5777         }
  5766   5778         assert( rc==SQLITE_OK );
  5767   5779         if( ALWAYS(pList) ){
  5768         -        rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, 
  5769         -            (pPager->fullSync ? pPager->syncFlags : 0)
  5770         -        );
         5780  +        rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
  5771   5781         }
  5772   5782         sqlite3PagerUnref(pPageOne);
  5773   5783         if( rc==SQLITE_OK ){
  5774   5784           sqlite3PcacheCleanAll(pPager->pPCache);
  5775   5785         }
  5776   5786       }else{
  5777   5787         /* The following block updates the change-counter. Exactly how it

Changes to src/wal.c.

   414    414     u32 iCallback;             /* Value to pass to log callback (or 0) */
   415    415     i64 mxWalSize;             /* Truncate WAL to this size upon reset */
   416    416     int nWiData;               /* Size of array apWiData */
   417    417     int szFirstBlock;          /* Size of first block written to WAL file */
   418    418     volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
   419    419     u32 szPage;                /* Database page size */
   420    420     i16 readLock;              /* Which read lock is being held.  -1 for none */
          421  +  u8 syncFlags;              /* Flags to use to sync header writes */
   421    422     u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
   422    423     u8 writeLock;              /* True if in a write transaction */
   423    424     u8 ckptLock;               /* True if holding a checkpoint lock */
   424    425     u8 readOnly;               /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
   425    426     u8 truncateOnCommit;       /* True to truncate WAL file on commit */
          427  +  u8 noSyncHeader;           /* Avoid WAL header fsyncs if true */
   426    428     WalIndexHdr hdr;           /* Wal-index header for current transaction */
   427    429     const char *zWalName;      /* Name of WAL file */
   428    430     u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
   429    431   #ifdef SQLITE_DEBUG
   430    432     u8 lockError;              /* True if a locking error has occurred */
   431    433   #endif
   432    434   };
................................................................................
  1293   1295     }
  1294   1296   
  1295   1297     if( rc!=SQLITE_OK ){
  1296   1298       walIndexClose(pRet, 0);
  1297   1299       sqlite3OsClose(pRet->pWalFd);
  1298   1300       sqlite3_free(pRet);
  1299   1301     }else{
         1302  +    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
         1303  +    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->noSyncHeader = 1; }
  1300   1304       *ppWal = pRet;
  1301   1305       WALTRACE(("WAL%d: opened\n", pRet));
  1302   1306     }
  1303   1307     return rc;
  1304   1308   }
  1305   1309   
  1306   1310   /*
................................................................................
  2629   2633   static int walWriteToLog(
  2630   2634     Wal *pWal,                 /* WAL to write to */
  2631   2635     void *pContent,            /* Content to be written */
  2632   2636     int iAmt,                  /* Number of bytes to write */
  2633   2637     sqlite3_int64 iOffset      /* Start writing at this offset */
  2634   2638   ){
  2635   2639     int rc;
  2636         -  if( iOffset>=pWal->szFirstBlock || iOffset+iAmt<pWal->szFirstBlock ){
         2640  +  if( iOffset>=pWal->szFirstBlock
         2641  +   || iOffset+iAmt<pWal->szFirstBlock
         2642  +   || pWal->syncFlags==0
         2643  +  ){
  2637   2644       /* The common and fast case.  Just write the data. */
  2638   2645       rc = sqlite3OsWrite(pWal->pWalFd, pContent, iAmt, iOffset);
  2639   2646     }else{
  2640   2647       /* If this write will cross the first sector boundary, it has to
  2641   2648       ** be split it two with a sync in between. */
  2642   2649       int iFirstAmt = pWal->szFirstBlock - iOffset;
  2643   2650       assert( iFirstAmt>0 && iFirstAmt<iAmt );
  2644   2651       rc = sqlite3OsWrite(pWal->pWalFd, pContent, iFirstAmt, iOffset);
  2645   2652       if( rc ) return rc;
  2646         -    rc = sqlite3OsSync(pWal->pWalFd, SQLITE_SYNC_NORMAL);
         2653  +    assert( pWal->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
         2654  +    rc = sqlite3OsSync(pWal->pWalFd, pWal->syncFlags);
  2647   2655       if( rc ) return rc;
  2648   2656       pContent = (void*)(iFirstAmt + (char*)pContent);
  2649   2657       rc = sqlite3OsWrite(pWal->pWalFd, pContent,
  2650   2658                           iAmt-iFirstAmt, iOffset+iFirstAmt);
  2651   2659     }
  2652   2660     return rc;
  2653   2661   }
................................................................................
  2717   2725       WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
  2718   2726       if( rc!=SQLITE_OK ){
  2719   2727         return rc;
  2720   2728       }
  2721   2729     }
  2722   2730     assert( (int)pWal->szPage==szPage );
  2723   2731   
  2724         -  /* The size of the block containing the WAL header */
  2725         -  pWal->szFirstBlock = sqlite3OsSectorSize(pWal->pWalFd);
  2726         -  if( szPage>pWal->szFirstBlock ) pWal->szFirstBlock = szPage;
         2732  +  /* Setup information needed to do the WAL header sync */
         2733  +  if( pWal->noSyncHeader ){
         2734  +    assert( pWal->szFirstBlock==0 );
         2735  +    assert( pWal->syncFlags==0 );
         2736  +  }else{
         2737  +    pWal->szFirstBlock = sqlite3OsSectorSize(pWal->pWalFd);
         2738  +    if( szPage>pWal->szFirstBlock ) pWal->szFirstBlock = szPage;
         2739  +    pWal->syncFlags = sync_flags & SQLITE_SYNC_MASK;
         2740  +  }
  2727   2741   
  2728   2742     /* Write the log file. */
  2729   2743     for(p=pList; p; p=p->pDirty){
  2730   2744       u32 nDbsize;                  /* Db-size field for frame header */
  2731   2745       i64 iOffset;                  /* Write offset in log file */
  2732   2746       void *pData;
  2733   2747      
................................................................................
  2752   2766       if( rc!=SQLITE_OK ){
  2753   2767         return rc;
  2754   2768       }
  2755   2769       pLast = p;
  2756   2770     }
  2757   2771   
  2758   2772     /* Sync the log file if the 'isSync' flag was specified. */
  2759         -  if( sync_flags ){
         2773  +  if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
  2760   2774       i64 iSegment = sqlite3OsSectorSize(pWal->pWalFd);
  2761   2775       i64 iOffset = walFrameOffset(iFrame+1, szPage);
  2762   2776   
  2763         -    assert( isCommit );
  2764   2777       assert( iSegment>0 );
  2765   2778   
  2766   2779       iSegment = (((iOffset+iSegment-1)/iSegment) * iSegment);
  2767   2780       while( iOffset<iSegment ){
  2768   2781         void *pData;
  2769   2782   #if defined(SQLITE_HAS_CODEC)
  2770   2783         if( (pData = sqlite3PagerCodec(pLast))==0 ) return SQLITE_NOMEM;
................................................................................
  2782   2795         if( rc!=SQLITE_OK ){
  2783   2796           return rc;
  2784   2797         }
  2785   2798         nLast++;
  2786   2799         iOffset += szPage;
  2787   2800       }
  2788   2801   
  2789         -    rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
         2802  +    rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
  2790   2803     }
  2791   2804   
  2792   2805     if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
  2793   2806       i64 sz = pWal->mxWalSize;
  2794   2807       if( walFrameOffset(iFrame+nLast+1, szPage)>pWal->mxWalSize ){
  2795   2808         sz = walFrameOffset(iFrame+nLast+1, szPage);
  2796   2809       }

Changes to src/wal.h.

    83     83   /* Move the write position of the WAL back to iFrame.  Called in
    84     84   ** response to a ROLLBACK TO command. */
    85     85   int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
    86     86   
    87     87   /* Write a frame or frames to the log. */
    88     88   int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
    89     89   
           90  +/* Additional values that can be added to the sync_flags argument of
           91  +** sqlite3WalFrames():
           92  +*/
           93  +#define WAL_SYNC_TRANSACTIONS  0x20   /* Sync at the end of each transaction */
           94  +#define SQLITE_SYNC_MASK       0x13   /* Mask off the SQLITE_SYNC_* values */
           95  +
    90     96   /* Copy pages from the log to the database file */ 
    91     97   int sqlite3WalCheckpoint(
    92     98     Wal *pWal,                      /* Write-ahead log connection */
    93     99     int eMode,                      /* One of PASSIVE, FULL and RESTART */
    94    100     int (*xBusy)(void*),            /* Function to call when busy */
    95    101     void *pBusyArg,                 /* Context argument for xBusyHandler */
    96    102     int sync_flags,                 /* Flags to sync db file with (or 0) */

Changes to test/wal2.test.

  1172   1172     }
  1173   1173   }
  1174   1174   
  1175   1175   #-------------------------------------------------------------------------
  1176   1176   # Test that "PRAGMA checkpoint_fullsync" appears to be working.
  1177   1177   #
  1178   1178   foreach {tn sql reslist} {
  1179         -  1 { }                                 {8 0 3 0 5 0}
  1180         -  2 { PRAGMA checkpoint_fullfsync = 1 } {8 4 3 2 5 2}
  1181         -  3 { PRAGMA checkpoint_fullfsync = 0 } {8 0 3 0 5 0}
         1179  +  1 { }                                 {10 0 4 0 6 0}
         1180  +  2 { PRAGMA checkpoint_fullfsync = 1 } {10 4 4 2 6 2}
         1181  +  3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0}
  1182   1182   } {
  1183   1183     faultsim_delete_and_reopen
  1184   1184   
  1185   1185     execsql {PRAGMA auto_vacuum = 0}
  1186   1186     execsql $sql
  1187   1187     do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal}
  1188   1188   
  1189   1189     set sqlite_sync_count 0
  1190   1190     set sqlite_fullsync_count 0
  1191   1191   
  1192   1192     do_execsql_test wal2-14.$tn.2 {
  1193   1193       PRAGMA wal_autocheckpoint = 10;
  1194   1194       CREATE TABLE t1(a, b);                -- 2 wal syncs
  1195         -    INSERT INTO t1 VALUES(1, 2);          -- 1 wal sync
         1195  +    INSERT INTO t1 VALUES(1, 2);          -- 2 wal sync
  1196   1196       PRAGMA wal_checkpoint;                -- 1 wal sync, 1 db sync
  1197   1197       BEGIN;
  1198   1198         INSERT INTO t1 VALUES(3, 4);
  1199   1199         INSERT INTO t1 VALUES(5, 6);
  1200         -    COMMIT;                               -- 1 wal sync
         1200  +    COMMIT;                               -- 2 wal sync
  1201   1201       PRAGMA wal_checkpoint;                -- 1 wal sync, 1 db sync
  1202   1202     } {10 0 5 5 0 2 2}
  1203   1203   
  1204   1204     do_test wal2-14.$tn.3 {
  1205   1205       cond_incr_sync_count 1
  1206   1206       list $sqlite_sync_count $sqlite_fullsync_count
  1207   1207     } [lrange $reslist 0 1]
................................................................................
  1229   1229   
  1230   1230   catch { db close }
  1231   1231   
  1232   1232   # PRAGMA checkpoint_fullsync
  1233   1233   # PRAGMA fullfsync
  1234   1234   # PRAGMA synchronous
  1235   1235   #
  1236         -foreach {tn settings commit_sync ckpt_sync} {
  1237         -  1  {0 0 off}     {0 0}  {0 0}
  1238         -  2  {0 0 normal}  {0 0}  {2 0}
  1239         -  3  {0 0 full}    {1 0}  {2 0}
         1236  +foreach {tn settings restart_sync commit_sync ckpt_sync} {
         1237  +  1  {0 0 off}     {0 0}  {0 0}  {0 0}
         1238  +  2  {0 0 normal}  {1 0}  {0 0}  {2 0}
         1239  +  3  {0 0 full}    {2 0}  {1 0}  {2 0}
         1240  +
         1241  +  4  {0 1 off}     {0 0}  {0 0}  {0 0}
         1242  +  5  {0 1 normal}  {0 1}  {0 0}  {0 2}
         1243  +  6  {0 1 full}    {0 2}  {0 1}  {0 2}
  1240   1244   
  1241         -  4  {0 1 off}     {0 0}  {0 0}
  1242         -  5  {0 1 normal}  {0 0}  {0 2}
  1243         -  6  {0 1 full}    {0 1}  {0 2}
         1245  +  7  {1 0 off}     {0 0}  {0 0}  {0 0}
         1246  +  8  {1 0 normal}  {1 0}  {0 0}  {0 2}
         1247  +  9  {1 0 full}    {2 0}  {1 0}  {0 2}
  1244   1248   
  1245         -  7  {1 0 off}     {0 0}  {0 0}
  1246         -  8  {1 0 normal}  {0 0}  {0 2}
  1247         -  9  {1 0 full}    {1 0}  {0 2}
  1248         -
  1249         -  10 {1 1 off}     {0 0}  {0 0}
  1250         -  11 {1 1 normal}  {0 0}  {0 2}
  1251         -  12 {1 1 full}    {0 1}  {0 2}
         1249  +  10 {1 1 off}     {0 0}  {0 0}  {0 0}
         1250  +  11 {1 1 normal}  {0 1}  {0 0}  {0 2}
         1251  +  12 {1 1 full}    {0 2}  {0 1}  {0 2}
  1252   1252   } {
  1253   1253     forcedelete test.db
  1254   1254   
  1255   1255     testvfs tvfs -default 1
  1256   1256     tvfs filter xSync
  1257   1257     tvfs script xSyncCb
  1258   1258     proc xSyncCb {method file fileid flags} {
  1259   1259       incr ::sync($flags)
  1260   1260     }
  1261   1261   
  1262   1262     sqlite3 db test.db
  1263   1263     do_execsql_test 15.$tn.1 "
  1264   1264       CREATE TABLE t1(x);
         1265  +    PRAGMA wal_autocheckpoint = OFF;
  1265   1266       PRAGMA journal_mode = WAL;
  1266   1267       PRAGMA checkpoint_fullfsync = [lindex $settings 0];
  1267   1268       PRAGMA fullfsync = [lindex $settings 1];
  1268   1269       PRAGMA synchronous = [lindex $settings 2];
  1269         -  " {wal}
         1270  +  " {0 wal}
  1270   1271   
  1271   1272     do_test 15.$tn.2 {
  1272   1273       set sync(normal) 0
  1273   1274       set sync(full) 0
  1274   1275       execsql { INSERT INTO t1 VALUES('abc') }
  1275   1276       list $::sync(normal) $::sync(full)
  1276         -  } $commit_sync
         1277  +  } $restart_sync
  1277   1278   
  1278   1279     do_test 15.$tn.3 {
         1280  +    set sync(normal) 0
         1281  +    set sync(full) 0
         1282  +    execsql { INSERT INTO t1 VALUES('abc') }
         1283  +    list $::sync(normal) $::sync(full)
         1284  +  } $commit_sync
         1285  +
         1286  +  do_test 15.$tn.4 {
  1279   1287       set sync(normal) 0
  1280   1288       set sync(full) 0
  1281   1289       execsql { INSERT INTO t1 VALUES('def') }
  1282   1290       list $::sync(normal) $::sync(full)
  1283   1291     } $commit_sync
  1284   1292   
  1285         -  do_test 15.$tn.4 {
         1293  +  do_test 15.$tn.5 {
  1286   1294       set sync(normal) 0
  1287   1295       set sync(full) 0
  1288   1296       execsql { PRAGMA wal_checkpoint }
  1289   1297       list $::sync(normal) $::sync(full)
  1290   1298     } $ckpt_sync
  1291   1299     
  1292   1300     db close
  1293   1301     tvfs delete
  1294   1302   }
  1295   1303   
  1296   1304   
  1297   1305   
  1298   1306   finish_test

Changes to test/wal3.test.

   213    213       testvfs T
   214    214       T filter {} 
   215    215       T script sync_counter
   216    216       sqlite3 db test.db -vfs T
   217    217     
   218    218       execsql "PRAGMA synchronous = $syncmode"
   219    219       execsql { PRAGMA journal_mode = WAL }
          220  +    execsql { CREATE TABLE filler(a,b,c); }
   220    221   
   221    222       set ::syncs [list]
   222    223       T filter xSync
   223    224       execsql {
   224    225         CREATE TABLE x(y);
   225    226         INSERT INTO x VALUES('z');
   226    227         PRAGMA wal_checkpoint;