/ Check-in [32fb1784]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Modify the way some internal file-controls are invoked. In order to support multi-file transactions in the zipvfs extension.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | zipvfs-multifile-commit
Files: files | file ages | folders
SHA1: 32fb1784af4594161d954343e3787db702000a4d
User & Date: dan 2013-12-09 20:42:03
Context
2013-12-10
16:27
Fix handling of errors returned by the SQLITE_FCNTL_OMIT_SYNCED file-control. check-in: d9a5f44f user: dan tags: zipvfs-multifile-commit
2013-12-09
20:42
Modify the way some internal file-controls are invoked. In order to support multi-file transactions in the zipvfs extension. check-in: 32fb1784 user: dan tags: zipvfs-multifile-commit
12:24
Fix an incorrect test number in the output of the speedtest1.c program. No changes to the test algorithms. check-in: fbfc075a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

   522    522             }
   523    523             if( rc==SQLITE_OK ){
   524    524               rc = backupTruncateFile(pFile, iSize);
   525    525             }
   526    526   
   527    527             /* Sync the database file to disk. */
   528    528             if( rc==SQLITE_OK ){
   529         -            rc = sqlite3PagerSync(pDestPager);
          529  +            rc = sqlite3PagerSync(pDestPager, 0);
   530    530             }
   531    531           }else{
   532    532             sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
   533    533             rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
   534    534           }
   535    535       
   536    536           /* Finish committing the transaction to the destination database. */

Changes to src/pager.c.

  1245   1245     unsigned char aMagic[8];   /* A buffer to hold the magic header */
  1246   1246     zMaster[0] = '\0';
  1247   1247   
  1248   1248     if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
  1249   1249      || szJ<16
  1250   1250      || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
  1251   1251      || len>=nMaster 
         1252  +   || len==0 
  1252   1253      || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
  1253   1254      || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
  1254   1255      || memcmp(aMagic, aJournalMagic, 8)
  1255   1256      || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
  1256   1257     ){
  1257   1258       return rc;
  1258   1259     }
................................................................................
  2013   2014       ** At this point the journal has been finalized and the transaction 
  2014   2015       ** successfully committed, but the EXCLUSIVE lock is still held on the
  2015   2016       ** file. So it is safe to truncate the database file to its minimum
  2016   2017       ** required size.  */
  2017   2018       assert( pPager->eLock==EXCLUSIVE_LOCK );
  2018   2019       rc = pager_truncate(pPager, pPager->dbSize);
  2019   2020     }
         2021  +
         2022  +  if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
         2023  +    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
         2024  +    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
         2025  +  }
  2020   2026   
  2021   2027     if( !pPager->exclusiveMode 
  2022   2028      && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
  2023   2029     ){
  2024   2030       rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
  2025   2031       pPager->changeCountDone = 0;
  2026   2032     }
................................................................................
  2827   2833       zMaster = pPager->pTmpSpace;
  2828   2834       rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
  2829   2835       testcase( rc!=SQLITE_OK );
  2830   2836     }
  2831   2837     if( rc==SQLITE_OK
  2832   2838      && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
  2833   2839     ){
  2834         -    rc = sqlite3PagerSync(pPager);
         2840  +    rc = sqlite3PagerSync(pPager, 0);
  2835   2841     }
  2836   2842     if( rc==SQLITE_OK ){
  2837   2843       rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
  2838   2844       testcase( rc!=SQLITE_OK );
  2839   2845     }
  2840   2846     if( rc==SQLITE_OK && zMaster[0] && res ){
  2841   2847       /* If there was a master journal and this routine will return success,
................................................................................
  6002   6008   /*
  6003   6009   ** Sync the database file to disk. This is a no-op for in-memory databases
  6004   6010   ** or pages with the Pager.noSync flag set.
  6005   6011   **
  6006   6012   ** If successful, or if called on a pager for which it is a no-op, this
  6007   6013   ** function returns SQLITE_OK. Otherwise, an IO error code is returned.
  6008   6014   */
  6009         -int sqlite3PagerSync(Pager *pPager){
         6015  +int sqlite3PagerSync(Pager *pPager, const char *zMaster){
  6010   6016     int rc = SQLITE_OK;
         6017  +
         6018  +  if( isOpen(pPager->fd) ){
         6019  +    void *pArg = (void*)zMaster;
         6020  +    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, pArg);
         6021  +    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
         6022  +  }
  6011   6023     if( !pPager->noSync ){
  6012   6024       assert( !MEMDB );
  6013   6025       rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
  6014         -  }else if( isOpen(pPager->fd) ){
  6015         -    assert( !MEMDB );
  6016         -    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
  6017         -    if( rc==SQLITE_NOTFOUND ){
  6018         -      rc = SQLITE_OK;
  6019         -    }
  6020   6026     }
  6021   6027     return rc;
  6022   6028   }
  6023   6029   
  6024   6030   /*
  6025   6031   ** This function may only be called while a write-transaction is active in
  6026   6032   ** rollback. If the connection is in WAL mode, this call is a no-op. 
................................................................................
  6211   6217           assert( pPager->eState==PAGER_WRITER_DBMOD );
  6212   6218           rc = pager_truncate(pPager, nNew);
  6213   6219           if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
  6214   6220         }
  6215   6221     
  6216   6222         /* Finally, sync the database file. */
  6217   6223         if( !noSync ){
  6218         -        rc = sqlite3PagerSync(pPager);
         6224  +        rc = sqlite3PagerSync(pPager, zMaster);
  6219   6225         }
  6220   6226         IOTRACE(("DBSYNC %p\n", pPager))
  6221   6227       }
  6222   6228     }
  6223   6229   
  6224   6230   commit_phase_one_exit:
  6225   6231     if( rc==SQLITE_OK && !pagerUseWal(pPager) ){

Changes to src/pager.h.

   146    146   void *sqlite3PagerGetExtra(DbPage *); 
   147    147   
   148    148   /* Functions used to manage pager transactions and savepoints. */
   149    149   void sqlite3PagerPagecount(Pager*, int*);
   150    150   int sqlite3PagerBegin(Pager*, int exFlag, int);
   151    151   int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
   152    152   int sqlite3PagerExclusiveLock(Pager*);
   153         -int sqlite3PagerSync(Pager *pPager);
          153  +int sqlite3PagerSync(Pager *pPager, const char *zMaster);
   154    154   int sqlite3PagerCommitPhaseTwo(Pager*);
   155    155   int sqlite3PagerRollback(Pager*);
   156    156   int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
   157    157   int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
   158    158   int sqlite3PagerSharedLock(Pager *pPager);
   159    159   
   160    160   #ifndef SQLITE_OMIT_WAL

Changes to src/sqlite.h.in.

   941    941   #define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
   942    942   #define SQLITE_FCNTL_PRAGMA                 14
   943    943   #define SQLITE_FCNTL_BUSYHANDLER            15
   944    944   #define SQLITE_FCNTL_TEMPFILENAME           16
   945    945   #define SQLITE_FCNTL_MMAP_SIZE              18
   946    946   #define SQLITE_FCNTL_TRACE                  19
   947    947   #define SQLITE_FCNTL_HAS_MOVED              20
          948  +
          949  +#define SQLITE_FCNTL_COMMIT_PHASETWO        21
   948    950   
   949    951   /*
   950    952   ** CAPI3REF: Mutex Handle
   951    953   **
   952    954   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   953    955   ** abstract type for a mutex object.  The SQLite core never looks
   954    956   ** at the internal representation of an [sqlite3_mutex].  It only

Changes to src/test6.c.

   405    405   static int cfRead(
   406    406     sqlite3_file *pFile, 
   407    407     void *zBuf, 
   408    408     int iAmt, 
   409    409     sqlite_int64 iOfst
   410    410   ){
   411    411     CrashFile *pCrash = (CrashFile *)pFile;
          412  +  int nCopy = (int)MIN((i64)iAmt, (pCrash->iSize - iOfst));
          413  +
          414  +  if( nCopy>0 ){
          415  +    memcpy(zBuf, &pCrash->zData[iOfst], nCopy);
          416  +  }
   412    417   
   413    418     /* Check the file-size to see if this is a short-read */
   414         -  if( pCrash->iSize<(iOfst+iAmt) ){
          419  +  if( nCopy<iAmt ){
   415    420       return SQLITE_IOERR_SHORT_READ;
   416    421     }
   417    422   
   418         -  memcpy(zBuf, &pCrash->zData[iOfst], iAmt);
   419    423     return SQLITE_OK;
   420    424   }
   421    425   
   422    426   /*
   423    427   ** Write data to a crash-file.
   424    428   */
   425    429   static int cfWrite(

Changes to test/tester.tcl.

  1247   1247   #   crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql
  1248   1248   #
  1249   1249   proc crashsql {args} {
  1250   1250   
  1251   1251     set blocksize ""
  1252   1252     set crashdelay 1
  1253   1253     set prngseed 0
         1254  +  set opendb { sqlite3 db test.db -vfs crash }
  1254   1255     set tclbody {}
  1255   1256     set crashfile ""
  1256   1257     set dc ""
  1257   1258     set sql [lindex $args end]
  1258   1259   
  1259   1260     for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
  1260   1261       set z [lindex $args $ii]
  1261   1262       set n [string length $z]
  1262   1263       set z2 [lindex $args [expr $ii+1]]
  1263   1264   
  1264   1265       if     {$n>1 && [string first $z -delay]==0}     {set crashdelay $z2} \
         1266  +    elseif {$n>1 && [string first $z -opendb]==0}    {set opendb $z2} \
  1265   1267       elseif {$n>1 && [string first $z -seed]==0}      {set prngseed $z2} \
  1266   1268       elseif {$n>1 && [string first $z -file]==0}      {set crashfile $z2}  \
  1267   1269       elseif {$n>1 && [string first $z -tclbody]==0}   {set tclbody $z2}  \
  1268   1270       elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
  1269   1271       elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
  1270   1272       else   { error "Unrecognized option: $z" }
  1271   1273     }
................................................................................
  1279   1281     # default, so here we force it to the "nativename" format.
  1280   1282     set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
  1281   1283   
  1282   1284     set f [open crash.tcl w]
  1283   1285     puts $f "sqlite3_crash_enable 1"
  1284   1286     puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
  1285   1287     puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
  1286         -  puts $f "sqlite3 db test.db -vfs crash"
         1288  +  puts $f $opendb 
  1287   1289   
  1288   1290     # This block sets the cache size of the main database to 10
  1289   1291     # pages. This is done in case the build is configured to omit
  1290   1292     # "PRAGMA cache_size".
  1291   1293     puts $f {db eval {SELECT * FROM sqlite_master;}}
  1292   1294     puts $f {set bt [btree_from_db db]}
  1293   1295     puts $f {btree_set_cache_size $bt 10}
         1296  +
  1294   1297     if {$prngseed} {
  1295   1298       set seed [expr {$prngseed%10007+1}]
  1296   1299       # puts seed=$seed
  1297   1300       puts $f "db eval {SELECT randomblob($seed)}"
  1298   1301     }
  1299   1302   
  1300   1303     if {[string length $tclbody]>0} {