/ Check-in [ac5d2e9d]
Login

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

Overview
Comment:Add the sqlite3_experimental_log_open() interface. This is for diagnostic use only and is not intended to ever go on trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimentalIoLog
Files: files | file ages | folders
SHA1: ac5d2e9d760bb376e828e3d39ee070b567e59d58
User & Date: drh 2015-08-10 20:22:07
Context
2015-08-10
20:53
Record when an allocated page is taken from the freelist trunk. check-in: bb5d7782 user: drh tags: experimentalIoLog
20:22
Add the sqlite3_experimental_log_open() interface. This is for diagnostic use only and is not intended to ever go on trunk. check-in: ac5d2e9d user: drh tags: experimentalIoLog
2015-08-08
23:30
Fix compiler warnings and remove unreachable code. check-in: fd5608fb user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

3190
3191
3192
3193
3194
3195
3196


3197
3198
3199
3200
3201
3202
3203
....
3678
3679
3680
3681
3682
3683
3684

3685
3686
3687
3688
3689
3690
3691
....
3720
3721
3722
3723
3724
3725
3726

3727
3728
3729
3730
3731
3732
3733
....
6100
6101
6102
6103
6104
6105
6106



6107
6108
6109
6110
6111
6112
6113
....
6700
6701
6702
6703
6704
6705
6706




6707
6708
6709
6710
6711
6712
6713
....
7323
7324
7325
7326
7327
7328
7329

7330
7331
7332
7333
7334
7335
7336
....
7693
7694
7695
7696
7697
7698
7699



7700
7701
7702
7703
7704
7705
7706
....
8162
8163
8164
8165
8166
8167
8168


8169
8170
8171
8172
8173
8174
8175
....
8199
8200
8201
8202
8203
8204
8205


8206
8207
8208
8209
8210
8211
8212
....
8276
8277
8278
8279
8280
8281
8282

8283
8284
8285
8286
8287
8288
8289
....
9574
9575
9576
9577
9578
9579
9580











        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }




trans_begun:
  if( rc==SQLITE_OK && wrflag ){
    /* This call makes sure that the pager has the correct number of
    ** open savepoints. If the second parameter is greater than 0 and
    ** the sub-journal is not already open, then it will be opened here.
................................................................................
        return rc;
      }
    }
    if( pBt->bDoTruncate ){
      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
    }
#endif

    rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
................................................................................
    }

    /* Set the current transaction state to TRANS_NONE and unlock the 
    ** pager if this call closed the only read or write transaction.  */
    p->inTrans = TRANS_NONE;
    unlockBtreeIfUnused(pBt);
  }


  btreeIntegrity(p);
}

/*
** Commit the transaction currently in progress.
**
................................................................................
          pgnoOvfl++;
        } while( 
          PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) 
        );
      }
#endif
      rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);



#ifndef SQLITE_OMIT_AUTOVACUUM
      /* If the database supports auto-vacuum, and the second or subsequent
      ** overflow page is being allocated, add an entry to the pointer-map
      ** for that page now. 
      **
      ** If this is the first overflow page, then write a partial entry 
      ** to the pointer-map. If we write nothing to this pointer-map slot,
................................................................................
  if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;

  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);





  if( rc==SQLITE_OK ){

    u8 *pOut = &pSpace[4];
    u8 *pCell = pPage->apOvfl[0];
    u16 szCell = pPage->xCellSize(pPage, pCell);
    u8 *pStop;
................................................................................
      rc = sqlite3PagerWrite(pNew->pDbPage);
      nNew++;
      if( rc ) goto balance_cleanup;
    }else{
      assert( i>0 );
      rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
      if( rc ) goto balance_cleanup;

      zeroPage(pNew, pageFlags);
      apNew[i] = pNew;
      nNew++;
      cntOld[i] = b.nCell;

      /* Set the pointer-map entry for the new sibling page. */
      if( ISAUTOVACUUM ){
................................................................................
  /* Make pRoot, the root page of the b-tree, writable. Allocate a new 
  ** page that will become the new right-child of pPage. Copy the contents
  ** of the node stored on pRoot into the new child page.
  */
  rc = sqlite3PagerWrite(pRoot->pDbPage);
  if( rc==SQLITE_OK ){
    rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);



    copyNodeContent(pRoot, pChild, &rc);
    if( ISAUTOVACUUM ){
      ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
    }
  }
  if( rc ){
    *ppChild = 0;
................................................................................
  assert( pBt->inTransaction==TRANS_WRITE );
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );

#ifdef SQLITE_OMIT_AUTOVACUUM
  rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
  if( rc ){
    return rc;


  }
#else
  if( pBt->autoVacuum ){
    Pgno pgnoMove;      /* Move a page here to make room for the root-page */
    MemPage *pPageMove; /* The page to move to. */

    /* Creating a new table may probably require moving an existing database
................................................................................
    /* Allocate a page. The page that currently resides at pgnoRoot will
    ** be moved to the allocated page (unless the allocated page happens
    ** to reside at pgnoRoot).
    */
    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
    if( rc!=SQLITE_OK ){
      return rc;


    }

    if( pgnoMove!=pgnoRoot ){
      /* pgnoRoot is the page that will be used for the root-page of
      ** the new table (assuming an error did not occur). But we were
      ** allocated pgnoMove. If required (i.e. if it was not allocated
      ** by extending the file), the current page at position pgnoMove
................................................................................
      releasePage(pRoot);
      return rc;
    }

  }else{
    rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
    if( rc ) return rc;

  }
#endif
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  if( createTabFlags & BTREE_INTKEY ){
    ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF;
  }else{
    ptfFlags = PTF_ZERODATA | PTF_LEAF;
................................................................................
  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}

/*
** Return the size of the header added to each page by this module.
*/
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }


















>
>







 







>







 







>







 







>
>
>







 







>
>
>
>







 







>







 







>
>
>







 







>
>







 







>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
....
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
....
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
....
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
....
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
....
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
....
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
....
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
....
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
....
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
....
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }
  sqlite3ExperimentalLog(p->pLog, "%s TM",
    wrflag==0 ? "begin-read" : (wrflag>2 ? "begin-exclusive" : "begin-write"));


trans_begun:
  if( rc==SQLITE_OK && wrflag ){
    /* This call makes sure that the pager has the correct number of
    ** open savepoints. If the second parameter is greater than 0 and
    ** the sub-journal is not already open, then it will be opened here.
................................................................................
        return rc;
      }
    }
    if( pBt->bDoTruncate ){
      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
    }
#endif
    sqlite3ExperimentalLog(p->pLog, "commit-start TM");
    rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
................................................................................
    }

    /* Set the current transaction state to TRANS_NONE and unlock the 
    ** pager if this call closed the only read or write transaction.  */
    p->inTrans = TRANS_NONE;
    unlockBtreeIfUnused(pBt);
  }
  sqlite3ExperimentalLog(p->pLog, "end-transaction TM");

  btreeIntegrity(p);
}

/*
** Commit the transaction currently in progress.
**
................................................................................
          pgnoOvfl++;
        } while( 
          PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) 
        );
      }
#endif
      rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
      if( rc==SQLITE_OK ){
        sqlite3ExperimentalLog(pBt->pLog, "allocate %d overflow", pgnoOvfl);
      }
#ifndef SQLITE_OMIT_AUTOVACUUM
      /* If the database supports auto-vacuum, and the second or subsequent
      ** overflow page is being allocated, add an entry to the pointer-map
      ** for that page now. 
      **
      ** If this is the first overflow page, then write a partial entry 
      ** to the pointer-map. If we write nothing to this pointer-map slot,
................................................................................
  if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;

  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
  if( rc==SQLITE_OK ){
    sqlite3ExperimentalLog(pPage->pBt->pLog,
                           "allocate %d quickbalance", pgnoNew);
  }

  if( rc==SQLITE_OK ){

    u8 *pOut = &pSpace[4];
    u8 *pCell = pPage->apOvfl[0];
    u16 szCell = pPage->xCellSize(pPage, pCell);
    u8 *pStop;
................................................................................
      rc = sqlite3PagerWrite(pNew->pDbPage);
      nNew++;
      if( rc ) goto balance_cleanup;
    }else{
      assert( i>0 );
      rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
      if( rc ) goto balance_cleanup;
      sqlite3ExperimentalLog(pBt->pLog, "allocate %d balance", pgno);
      zeroPage(pNew, pageFlags);
      apNew[i] = pNew;
      nNew++;
      cntOld[i] = b.nCell;

      /* Set the pointer-map entry for the new sibling page. */
      if( ISAUTOVACUUM ){
................................................................................
  /* Make pRoot, the root page of the b-tree, writable. Allocate a new 
  ** page that will become the new right-child of pPage. Copy the contents
  ** of the node stored on pRoot into the new child page.
  */
  rc = sqlite3PagerWrite(pRoot->pDbPage);
  if( rc==SQLITE_OK ){
    rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
    if( rc==SQLITE_OK ){
      sqlite3ExperimentalLog(pBt->pLog, "allocate %d balancedeeper", pgnoChild);
    }
    copyNodeContent(pRoot, pChild, &rc);
    if( ISAUTOVACUUM ){
      ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
    }
  }
  if( rc ){
    *ppChild = 0;
................................................................................
  assert( pBt->inTransaction==TRANS_WRITE );
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );

#ifdef SQLITE_OMIT_AUTOVACUUM
  rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
  if( rc ){
    return rc;
  }else{
    sqlite3ExperimentalLog(p->pLog, "allocate %d createtable", pgnoRoot);
  }
#else
  if( pBt->autoVacuum ){
    Pgno pgnoMove;      /* Move a page here to make room for the root-page */
    MemPage *pPageMove; /* The page to move to. */

    /* Creating a new table may probably require moving an existing database
................................................................................
    /* Allocate a page. The page that currently resides at pgnoRoot will
    ** be moved to the allocated page (unless the allocated page happens
    ** to reside at pgnoRoot).
    */
    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
    if( rc!=SQLITE_OK ){
      return rc;
    }else{
      sqlite3ExperimentalLog(p->pLog, "allocate %d createtable", pgnoMove);
    }

    if( pgnoMove!=pgnoRoot ){
      /* pgnoRoot is the page that will be used for the root-page of
      ** the new table (assuming an error did not occur). But we were
      ** allocated pgnoMove. If required (i.e. if it was not allocated
      ** by extending the file), the current page at position pgnoMove
................................................................................
      releasePage(pRoot);
      return rc;
    }

  }else{
    rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
    if( rc ) return rc;
    sqlite3ExperimentalLog(p->pLog, "allocate %d createtable", pgnoRoot);
  }
#endif
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  if( createTabFlags & BTREE_INTKEY ){
    ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF;
  }else{
    ptfFlags = PTF_ZERODATA | PTF_LEAF;
................................................................................
  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}

/*
** Return the size of the header added to each page by this module.
*/
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }


/*
** Set the Btree ExperimentalLog
*/
ExperimentalLog *sqlite3BtreeExperimentalLog(Btree *p, ExperimentalLog *pLog){
  ExperimentalLog *pOld = p->pLog;
  p->pLog = pLog;
  p->pBt->pLog = pLog;
  return pOld;
}

Changes to src/btree.h.

266
267
268
269
270
271
272

273
274
# define sqlite3BtreeLeaveAll(X)

# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeHoldsAllMutexes(X) 1
# define sqlite3SchemaMutexHeld(X,Y,Z) 1
#endif



#endif /* _BTREE_H_ */







>


266
267
268
269
270
271
272
273
274
275
# define sqlite3BtreeLeaveAll(X)

# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeHoldsAllMutexes(X) 1
# define sqlite3SchemaMutexHeld(X,Y,Z) 1
#endif

ExperimentalLog *sqlite3BtreeExperimentalLog(Btree*,ExperimentalLog*);

#endif /* _BTREE_H_ */

Changes to src/btreeInt.h.

359
360
361
362
363
364
365

366
367
368
369
370
371
372
...
410
411
412
413
414
415
416

417
418
419
420
421
422
423
  int nBackup;       /* Number of backup operations reading this btree */
  u32 iDataVersion;  /* Combines with pBt->pPager->iDataVersion */
  Btree *pNext;      /* List of other sharable Btrees from the same db */
  Btree *pPrev;      /* Back pointer of the same list */
#ifndef SQLITE_OMIT_SHARED_CACHE
  BtLock lock;       /* Object used to lock page 1 */
#endif

};

/*
** Btree.inTrans may take one of the following values.
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
................................................................................
**   transaction.
**
**   This feature is included to help prevent writer-starvation.
*/
struct BtShared {
  Pager *pPager;        /* The page cache */
  sqlite3 *db;          /* Database connection currently using this Btree */

  BtCursor *pCursor;    /* A list of all open cursors */
  MemPage *pPage1;      /* First page of the database */
  u8 openFlags;         /* Flags to sqlite3BtreeOpen() */
#ifndef SQLITE_OMIT_AUTOVACUUM
  u8 autoVacuum;        /* True if auto-vacuum is enabled */
  u8 incrVacuum;        /* True if incr-vacuum is enabled */
  u8 bDoTruncate;       /* True to truncate db on commit */







>







 







>







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  int nBackup;       /* Number of backup operations reading this btree */
  u32 iDataVersion;  /* Combines with pBt->pPager->iDataVersion */
  Btree *pNext;      /* List of other sharable Btrees from the same db */
  Btree *pPrev;      /* Back pointer of the same list */
#ifndef SQLITE_OMIT_SHARED_CACHE
  BtLock lock;       /* Object used to lock page 1 */
#endif
  ExperimentalLog *pLog; /* Write various actions to this experimental log */
};

/*
** Btree.inTrans may take one of the following values.
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
................................................................................
**   transaction.
**
**   This feature is included to help prevent writer-starvation.
*/
struct BtShared {
  Pager *pPager;        /* The page cache */
  sqlite3 *db;          /* Database connection currently using this Btree */
  ExperimentalLog *pLog; /* Log activities here */
  BtCursor *pCursor;    /* A list of all open cursors */
  MemPage *pPage1;      /* First page of the database */
  u8 openFlags;         /* Flags to sqlite3BtreeOpen() */
#ifndef SQLITE_OMIT_AUTOVACUUM
  u8 autoVacuum;        /* True if auto-vacuum is enabled */
  u8 incrVacuum;        /* True if incr-vacuum is enabled */
  u8 bDoTruncate;       /* True to truncate db on commit */

Changes to src/main.c.

974
975
976
977
978
979
980

981
982
983
984
985
986
987
....
3782
3783
3784
3785
3786
3787
3788































































    ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
    return SQLITE_OK;
  }
  if( !sqlite3SafetyCheckSickOrOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);


  /* Force xDisconnect calls on all virtual tables */
  disconnectAllVtab(db);

  /* If a transaction is open, the disconnectAllVtab() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
................................................................................
    (void)SQLITE_MISUSE_BKPT;
    return -1;
  }
#endif
  pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}






































































>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
....
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
    ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
    return SQLITE_OK;
  }
  if( !sqlite3SafetyCheckSickOrOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);
  sqlite3_experimental_log_open(db, 0);

  /* Force xDisconnect calls on all virtual tables */
  disconnectAllVtab(db);

  /* If a transaction is open, the disconnectAllVtab() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
................................................................................
    (void)SQLITE_MISUSE_BKPT;
    return -1;
  }
#endif
  pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}

/*
** Turn on logging for the main database of database connection db.
** Disable logging if zFilename is NULL.
*/
void sqlite3_experimental_log_open(sqlite3 *db, const char *zFilename){
  Btree *pBtree;
  Pager *pPager;
  ExperimentalLog *pLog;

  sqlite3_mutex_enter(db->mutex);
  pBtree = db->aDb[0].pBt;
  if( pBtree ){
    pPager = sqlite3BtreePager(pBtree);
    pLog = sqlite3BtreeExperimentalLog(pBtree, 0);
    if( pLog ){
      sqlite3ExperimentalLog(pLog, "close TM");
      fclose(pLog->out);
      sqlite3_free(pLog);
      pLog = 0;
    }
    if( zFilename ){
      pLog = sqlite3_malloc( sizeof(*pLog) );
      if( pLog ){ 
        pLog->out = fopen(zFilename, "a+");
        pLog->pVfs = db->pVfs;
        if( pLog->out==0 ){
          sqlite3_free(pLog);
          pLog = 0;
        }else{
          sqlite3ExperimentalLog(pLog, "open %s TM", zFilename);
        }
      }
    }
    db->pLog = pLog;
    sqlite3BtreeExperimentalLog(pBtree, pLog);
    sqlite3PagerExperimentalLog(pPager, pLog);
  }
  sqlite3_mutex_leave(db->mutex);
}

/*
** Write a message on the given ExperimentalLog if it is open
*/
void sqlite3ExperimentalLog(ExperimentalLog *pLog, const char *zFormat, ...){
  if( pLog ){
    va_list ap;
    StrAccum acc;
    sqlite3_int64 iTime = 0;
    char zMsg[200];
    va_start(ap, zFormat);
    sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
    sqlite3VXPrintf(&acc, 0, zFormat, ap);
    if( acc.nChar>2 && strncmp(zMsg+acc.nChar-2, "TM", 2)==0 ){
      acc.nChar -= 2;
      sqlite3OsCurrentTimeInt64(pLog->pVfs, &iTime);
      sqlite3XPrintf(&acc, 0, "%lld", iTime);
    }
    sqlite3StrAccumAppend(&acc, "\n", 1);
    sqlite3StrAccumFinish(&acc);
    fwrite(zMsg, 1, sqlite3Strlen30(zMsg), pLog->out);
  }
}

Changes to src/pager.c.

699
700
701
702
703
704
705

706
707
708
709
710
711
712
....
4423
4424
4425
4426
4427
4428
4429



4430
4431
4432
4433
4434
4435
4436
....
5264
5265
5266
5267
5268
5269
5270



5271
5272
5273
5274
5275
5276
5277
....
5699
5700
5701
5702
5703
5704
5705



5706
5707
5708
5709
5710
5711
5712
....
5884
5885
5886
5887
5888
5889
5890






5891
5892
5893
5894
5895
5896
5897
....
7084
7085
7086
7087
7088
7089
7090





7091
7092
7093
7094
7095
7096
7097
....
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
  PCache *pPCache;            /* Pointer to page cache object */
#ifndef SQLITE_OMIT_WAL
  Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
  char *zWal;                 /* File name for write-ahead log */
#endif

};

/*
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS 
** or CACHE_WRITE to sqlite3_db_status().
*/
................................................................................
  if( pPager->doNotSpill
   && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
      || (pPg->flags & PGHDR_NEED_SYNC)!=0)
  ){
    return SQLITE_OK;
  }




  pPg->pDirty = 0;
  if( pagerUseWal(pPager) ){
    /* Write a single frame for this page to the log. */
    rc = subjournalPageIfRequired(pPg); 
    if( rc==SQLITE_OK ){
      rc = pagerWalFrames(pPager, pPg, 0, 0);
    }
................................................................................
  assert( assert_pager_state(pPager) );
  assert( noContent==0 || bMmapOk==0 );

  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  pPager->hasBeenUsed = 1;




  /* If the pager is in the error state, return an error immediately. 
  ** Otherwise, request the page from the PCache layer. */
  if( pPager->errCode!=SQLITE_OK ){
    rc = pPager->errCode;
  }else{
    if( bMmapOk && pagerUseWal(pPager) ){
................................................................................
       || pPager->eState==PAGER_WRITER_CACHEMOD
       || pPager->eState==PAGER_WRITER_DBMOD
  );
  assert( assert_pager_state(pPager) );
  assert( pPager->errCode==0 );
  assert( pPager->readOnly==0 );
  CHECK_PAGE(pPg);




  /* The journal file needs to be opened. Higher level routines have already
  ** obtained the necessary locks to begin the write-transaction, but the
  ** rollback journal might not yet be open. Open it now if this is the case.
  **
  ** This is done before calling sqlite3PcacheMakeDirty() on the page. 
  ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
................................................................................
    return SQLITE_OK;
  }else if( pPager->sectorSize > (u32)pPager->pageSize ){
    return pagerWriteLargeSector(pPg);
  }else{
    return pager_write(pPg);
  }
}







/*
** Return TRUE if the page given in the argument was previously passed
** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
** to change the content of the page.
*/
#ifndef NDEBUG
................................................................................
  if( pPager->pWal ){
    rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
        (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
        pPager->pBusyHandlerArg,
        pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
        pnLog, pnCkpt
    );





  }
  return rc;
}

int sqlite3PagerWalCallback(Pager *pPager){
  return sqlite3WalCallback(pPager->pWal);
}
................................................................................
** is empty, return 0.
*/
int sqlite3PagerWalFramesize(Pager *pPager){
  assert( pPager->eState>=PAGER_READER );
  return sqlite3WalFramesize(pPager->pWal);
}
#endif


#endif /* SQLITE_OMIT_DISKIO */







>







 







>
>
>







 







>
>
>







 







>
>
>







 







>
>
>
>
>
>







 







>
>
>
>
>







 








<

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
....
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
....
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
....
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
....
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
....
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
....
7282
7283
7284
7285
7286
7287
7288
7289

7290
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
  PCache *pPCache;            /* Pointer to page cache object */
#ifndef SQLITE_OMIT_WAL
  Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
  char *zWal;                 /* File name for write-ahead log */
#endif
  ExperimentalLog *pLog;      /* Output logging */
};

/*
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS 
** or CACHE_WRITE to sqlite3_db_status().
*/
................................................................................
  if( pPager->doNotSpill
   && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
      || (pPg->flags & PGHDR_NEED_SYNC)!=0)
  ){
    return SQLITE_OK;
  }

  if( pPager->pLog ){
    sqlite3ExperimentalLog(pPager->pLog, "spill %d", pPg->pgno);
  }
  pPg->pDirty = 0;
  if( pagerUseWal(pPager) ){
    /* Write a single frame for this page to the log. */
    rc = subjournalPageIfRequired(pPg); 
    if( rc==SQLITE_OK ){
      rc = pagerWalFrames(pPager, pPg, 0, 0);
    }
................................................................................
  assert( assert_pager_state(pPager) );
  assert( noContent==0 || bMmapOk==0 );

  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  pPager->hasBeenUsed = 1;
  if( pPager->pLog ){
    sqlite3ExperimentalLog(pPager->pLog, "read %d", pgno);
  }

  /* If the pager is in the error state, return an error immediately. 
  ** Otherwise, request the page from the PCache layer. */
  if( pPager->errCode!=SQLITE_OK ){
    rc = pPager->errCode;
  }else{
    if( bMmapOk && pagerUseWal(pPager) ){
................................................................................
       || pPager->eState==PAGER_WRITER_CACHEMOD
       || pPager->eState==PAGER_WRITER_DBMOD
  );
  assert( assert_pager_state(pPager) );
  assert( pPager->errCode==0 );
  assert( pPager->readOnly==0 );
  CHECK_PAGE(pPg);
  if( pPager->pLog ){
    sqlite3ExperimentalLog(pPager->pLog, "write %d", pPg->pgno);
  }

  /* The journal file needs to be opened. Higher level routines have already
  ** obtained the necessary locks to begin the write-transaction, but the
  ** rollback journal might not yet be open. Open it now if this is the case.
  **
  ** This is done before calling sqlite3PcacheMakeDirty() on the page. 
  ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
................................................................................
    return SQLITE_OK;
  }else if( pPager->sectorSize > (u32)pPager->pageSize ){
    return pagerWriteLargeSector(pPg);
  }else{
    return pager_write(pPg);
  }
}

/* Set experimental logging for this pager
*/
void sqlite3PagerExperimentalLog(Pager *p, ExperimentalLog *pLog){
  p->pLog = pLog;
}

/*
** Return TRUE if the page given in the argument was previously passed
** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
** to change the content of the page.
*/
#ifndef NDEBUG
................................................................................
  if( pPager->pWal ){
    rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
        (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
        pPager->pBusyHandlerArg,
        pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
        pnLog, pnCkpt
    );
    if( pPager->pLog ){
      const char *azType[] = { "passive", "full", "restart", "truncate" };
      sqlite3ExperimentalLog(pPager->pLog, "checkpoint %s %d %d",
                             azType[eMode], *pnLog, *pnCkpt);
    }
  }
  return rc;
}

int sqlite3PagerWalCallback(Pager *pPager){
  return sqlite3WalCallback(pPager->pWal);
}
................................................................................
** is empty, return 0.
*/
int sqlite3PagerWalFramesize(Pager *pPager){
  assert( pPager->eState>=PAGER_READER );
  return sqlite3WalFramesize(pPager->pWal);
}
#endif


#endif /* SQLITE_OMIT_DISKIO */

Changes to src/pager.h.

188
189
190
191
192
193
194


195
196
197
198
199
200
201
void sqlite3PagerClearCache(Pager *);
int sqlite3SectorSize(sqlite3_file *);

/* Functions used to truncate the database file. */
void sqlite3PagerTruncateImage(Pager*,Pgno);

void sqlite3PagerRekey(DbPage*, Pgno, u16);



#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
void *sqlite3PagerCodec(DbPage *);
#endif

/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST)







>
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
void sqlite3PagerClearCache(Pager *);
int sqlite3SectorSize(sqlite3_file *);

/* Functions used to truncate the database file. */
void sqlite3PagerTruncateImage(Pager*,Pgno);

void sqlite3PagerRekey(DbPage*, Pgno, u16);

void sqlite3PagerExperimentalLog(Pager*, ExperimentalLog*);

#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
void *sqlite3PagerCodec(DbPage *);
#endif

/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST)

Changes to src/shell.c.

2844
2845
2846
2847
2848
2849
2850












2851
2852
2853
2854
2855
2856
2857
    }   
  }else

  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else













  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
    if(val == 1) {
      if(!p->normalMode.valid) {
        p->normalMode.valid = 1;
        p->normalMode.mode = p->mode;







>
>
>
>
>
>
>
>
>
>
>
>







2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
    }   
  }else

  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else

  if( c=='e' && strncmp(azArg[0], "explog", n)==0 ){
    open_db(p, 0);
    if( nArg!=2 ){
      fprintf(stderr, "Usage: .explog FILENAME|off\n");
      rc = 1;
    }else if( strcmp(azArg[1],"off")==0 ){
      sqlite3_experimental_log_open(p->db, 0);
    }else{
      sqlite3_experimental_log_open(p->db, azArg[1]);
    }
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
    if(val == 1) {
      if(!p->normalMode.valid) {
        p->normalMode.valid = 1;
        p->normalMode.mode = p->mode;

Changes to src/sqlite.h.in.

7724
7725
7726
7727
7728
7729
7730


7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);




/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif /* _SQLITE3_H_ */







>
>













7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);

/* Experimental logging APIs.  Not for release. */
void sqlite3_experimental_log_open(sqlite3*, const char *zFilename);

/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif /* _SQLITE3_H_ */

Changes to src/sqliteInt.h.

919
920
921
922
923
924
925

926
927
928
929
930
931
932
....
1243
1244
1245
1246
1247
1248
1249

1250
1251









1252
1253
1254
1255
1256
1257
1258
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct ExprSpan ExprSpan;

typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct IndexSample IndexSample;
................................................................................
  void *pUnlockArg;                     /* Argument to xUnlockNotify */
  void (*xUnlockNotify)(void **, int);  /* Unlock notify callback */
  sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
  sqlite3_userauth auth;        /* User authentication information */
#endif

};










/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db)        ((db)->enc)

/*







>







 







>


>
>
>
>
>
>
>
>
>







919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
....
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct ExprSpan ExprSpan;
typedef struct ExperimentalLog ExperimentalLog;
typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct IndexSample IndexSample;
................................................................................
  void *pUnlockArg;                     /* Argument to xUnlockNotify */
  void (*xUnlockNotify)(void **, int);  /* Unlock notify callback */
  sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
  sqlite3_userauth auth;        /* User authentication information */
#endif
  ExperimentalLog *pLog;        /* Write experimental log messages here */
};

/*
** Information needed by the experimental log
*/
struct ExperimentalLog {
  FILE *out;                    /* Write on this file descriptor */
  sqlite3_vfs *pVfs;            /* Used to get current time of day */
};
void sqlite3ExperimentalLog(ExperimentalLog*, const char *zFormat, ...);

/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db)        ((db)->enc)

/*

Changes to src/vdbe.c.

6517
6518
6519
6520
6521
6522
6523









6524
6525
6526
6527
6528
6529
6530
**
** If P2 is not zero, jump to instruction P2.
*/
case OP_Init: {          /* jump */
  char *zTrace;
  char *z;










#ifndef SQLITE_OMIT_TRACE
  if( db->xTrace
   && !p->doingRerun
   && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
    z = sqlite3VdbeExpandSql(p, zTrace);
    db->xTrace(db->pTraceArg, z);







>
>
>
>
>
>
>
>
>







6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
**
** If P2 is not zero, jump to instruction P2.
*/
case OP_Init: {          /* jump */
  char *zTrace;
  char *z;

  if( db->pLog && p->zSql ){
    char *z = sqlite3DbStrDup(db, p->zSql);
    int ii;
    for(ii=0; z[ii]; ii++){
      if( sqlite3Isspace(z[ii]) ) z[ii] = ' ';
    }
    sqlite3ExperimentalLog(db->pLog, "sql {%s}", z);
    sqlite3DbFree(db, z);
  }
#ifndef SQLITE_OMIT_TRACE
  if( db->xTrace
   && !p->doingRerun
   && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
    z = sqlite3VdbeExpandSql(p, zTrace);
    db->xTrace(db->pTraceArg, z);