From 9ad3ee40f29ff62fbbb9bb55fd6956d0931e3f72 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 24 Mar 2012 20:06:14 +0000 Subject: [PATCH] Add SQLITE_DBSTATUS_CACHE_WRITE. Used to query a database connection for the cumulative number of database pages written. FossilOrigin-Name: 05f98d4eec0f029b76fd471f8d9edf2807de6b55 --- manifest | 20 ++++++++--------- manifest.uuid | 2 +- src/pager.c | 52 ++++++++++++++++++++++++++++++--------------- src/sqlite.h.in | 14 +++++++++++- src/status.c | 4 +++- src/test_malloc.c | 3 ++- test/dbstatus2.test | 25 +++++++++++++++++++++- 7 files changed, 88 insertions(+), 32 deletions(-) diff --git a/manifest b/manifest index 2a0edd6018..898b762958 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\san\sincremental\sblob\scursor\sis\sinvalidated\s(occurs\swhen\san\sSQL\sstatement\smodifies\sor\sdeletes\sthe\srow\sthe\sblob\scursor\spoints\sto)\srelease\sall\spage\sreferences\sheld\sby\sthe\scursor.\sOtherwise,\sthe\spresence\sof\sthese\sreferences\smay\scause\sother\scode\sin\sbtree.c\sto\sincorrectly\sinfer\sthat\sthe\sdatabase\sis\scorrupt. -D 2012-03-23T14:23:52.727 +C Add\sSQLITE_DBSTATUS_CACHE_WRITE.\sUsed\sto\squery\sa\sdatabase\sconnection\sfor\sthe\scumulative\snumber\sof\sdatabase\spages\swritten. +D 2012-03-24T20:06:14.659 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 F src/os_unix.c 0e3d2942d228d0366fb80a3640f35caf413b66d1 F src/os_win.c 5ac061ae1326a71500cee578ed0fd9113b4f6a37 -F src/pager.c 3955b62cdb5bb64559607cb474dd12a6c8e1d4a5 +F src/pager.c 85988507fa20acc60defb834722eddf4633e4aeb F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5 F src/parse.y 1ddd71ae55f4b7cbb2672526ea4de023de0f519e F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 @@ -182,11 +182,11 @@ F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c 44ccdcb5d2a1c48622c179b2d72167b716388581 F src/shell.c 55e09ef7126768b940427d95dc0a8cb7138e95da -F src/sqlite.h.in 6af2d92925bfed3dfd2c022fef48469762ccd435 +F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h e65429a6f19b41720561b9434b2192574a91cfa2 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d -F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a +F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c 086dfdd72e5892de223968a258e1ccbd9693e717 F src/test1.c 07f30e8714bab94d8de8a88865d9c59bc512a1a8 @@ -213,7 +213,7 @@ F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c a6a6baf343f79b942331f13378d045e7e270ae64 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e -F src/test_malloc.c cfe25d74333892ababde61196821a889b4756dee +F src/test_malloc.c 3f5903a1528fd32fe4c472a3bd0259128d8faaef F src/test_multiplex.c 0404a61d7795438be5ee5fd3711eed80724df34d F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e @@ -365,7 +365,7 @@ F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47 F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff F test/dbstatus.test 207e5b63fcb7b9c3bb8e1fdf38ebd4654ad0e54b -F test/dbstatus2.test dc57b0d9610851c0ff58a8e1b5b191678398b72a +F test/dbstatus2.test b1de8250fde1f3474d6b86f0e89de38d84794f56 F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701 F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa @@ -993,7 +993,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 638b71150281a211f89b4057b0d5d32d3fbcf323 -R bf4ea56b709d8c66bd287b12bb865310 +P 341b703ce16361a64ed8bba64ff46792132c0b56 +R 5fc0d309f5291091fecac64a52bbafac U drh -Z 71976091f9202f9aa459dff852dbcf55 +Z 8ee550c76390e8fc0f8077b27e0ba8b4 diff --git a/manifest.uuid b/manifest.uuid index a8830b75fe..f125a8941b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -341b703ce16361a64ed8bba64ff46792132c0b56 \ No newline at end of file +05f98d4eec0f029b76fd471f8d9edf2807de6b55 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 66252aa0f7..2d603122d5 100644 --- a/src/pager.c +++ b/src/pager.c @@ -670,9 +670,9 @@ struct Pager { char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int nHit, nMiss; /* Total cache hits and misses */ + int aStat[3]; /* Total cache hits, misses and writes */ #ifdef SQLITE_TEST - int nRead, nWrite; /* Database pages read/written */ + int nRead; /* Database pages read */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ #ifdef SQLITE_HAS_CODEC @@ -689,6 +689,15 @@ struct Pager { #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(). +*/ +#define PAGER_STAT_HIT 0 +#define PAGER_STAT_MISS 1 +#define PAGER_STAT_WRITE 2 + /* ** The following global variables hold counters used for ** testing purposes only. These variables do not exist in @@ -2971,6 +2980,7 @@ static int pagerWalFrames( int isCommit /* True if this is a commit */ ){ int rc; /* Return code */ + int nList; /* Number of pages in pList */ #if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) PgHdr *p; /* For looping over pages */ #endif @@ -2984,6 +2994,7 @@ static int pagerWalFrames( } #endif + assert( pList->pDirty==0 || isCommit ); if( isCommit ){ /* If a WAL transaction is being committed, there is no point in writing ** any pages with page numbers greater than nTruncate into the WAL file. @@ -2991,11 +3002,18 @@ static int pagerWalFrames( ** list here. */ PgHdr *p; PgHdr **ppNext = &pList; + nList = 0; for(p=pList; (*ppNext = p); p=p->pDirty){ - if( p->pgno<=nTruncate ) ppNext = &p->pDirty; + if( p->pgno<=nTruncate ){ + ppNext = &p->pDirty; + nList++; + } } assert( pList ); + }else{ + nList = 1; } + pPager->aStat[PAGER_STAT_WRITE] += nList; if( pList->pgno==1 ) pager_write_changecounter(pList); rc = sqlite3WalFrames(pPager->pWal, @@ -4063,6 +4081,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } + pPager->aStat[PAGER_STAT_WRITE]++; /* Update any backup objects copying the contents of this pager. */ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); @@ -4071,7 +4090,6 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ PAGERID(pPager), pgno, pager_pagehash(pList))); IOTRACE(("PGOUT %p %d\n", pPager, pgno)); PAGER_INCR(sqlite3_pager_writedb_count); - PAGER_INCR(pPager->nWrite); }else{ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); } @@ -5029,7 +5047,7 @@ int sqlite3PagerAcquire( /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); - pPager->nHit++; + pPager->aStat[PAGER_STAT_HIT]++; return SQLITE_OK; }else{ @@ -5071,7 +5089,7 @@ int sqlite3PagerAcquire( IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); - pPager->nMiss++; + pPager->aStat[PAGER_STAT_MISS]++; rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; @@ -5656,6 +5674,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); + pPager->aStat[PAGER_STAT_WRITE]++; } if( rc==SQLITE_OK ){ pPager->changeCountDone = 1; @@ -6099,11 +6118,11 @@ int *sqlite3PagerStats(Pager *pPager){ a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; a[4] = pPager->eState; a[5] = pPager->errCode; - a[6] = pPager->nHit; - a[7] = pPager->nMiss; + a[6] = pPager->aStat[PAGER_STAT_HIT]; + a[7] = pPager->aStat[PAGER_STAT_MISS]; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; - a[10] = pPager->nWrite; + a[10] = pPager->aStat[PAGER_STAT_WRITE]; return a; } #endif @@ -6116,20 +6135,19 @@ int *sqlite3PagerStats(Pager *pPager){ ** returning. */ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ - int *piStat; assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS + || eStat==SQLITE_DBSTATUS_CACHE_WRITE ); - if( eStat==SQLITE_DBSTATUS_CACHE_HIT ){ - piStat = &pPager->nHit; - }else{ - piStat = &pPager->nMiss; - } - *pnVal += *piStat; + assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); + assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); + + *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; if( reset ){ - *piStat = 0; + pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; } } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 15a1b603a3..2f9c196860 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6001,6 +6001,17 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. ** +** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
+**
This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -6012,7 +6023,8 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 -#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ /* diff --git a/src/status.c b/src/status.c index b23238bb14..04b7656afe 100644 --- a/src/status.c +++ b/src/status.c @@ -224,10 +224,12 @@ int sqlite3_db_status( ** to zero. */ case SQLITE_DBSTATUS_CACHE_HIT: - case SQLITE_DBSTATUS_CACHE_MISS: { + case SQLITE_DBSTATUS_CACHE_MISS: + case SQLITE_DBSTATUS_CACHE_WRITE:{ int i; int nRet = 0; assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); + assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ diff --git a/src/test_malloc.c b/src/test_malloc.c index 037dfd140a..09b8f738e8 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -1323,7 +1323,8 @@ static int test_db_status( { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, - { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS } + { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }, + { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE } }; Tcl_Obj *pResult; if( objc!=4 ){ diff --git a/test/dbstatus2.test b/test/dbstatus2.test index 4dfa9b8ed2..b2ec156655 100644 --- a/test/dbstatus2.test +++ b/test/dbstatus2.test @@ -9,7 +9,7 @@ # #*********************************************************************** # -# Tests for the sqlite3_stmt_status() function +# Tests for the sqlite3_db_status() function # set testdir [file dirname $argv0] @@ -33,6 +33,10 @@ proc db_hit_miss {db {reset 0}} { list $nHit $nMiss } +proc db_write {db {reset 0}} { + sqlite3_db_status $db CACHE_WRITE $reset +} + do_test 1.1 { db close sqlite3 db test.db @@ -72,5 +76,24 @@ do_test 1.7 { do_test 1.8 { sqlite3_db_status db CACHE_HIT 0 } {0 2 0} do_test 1.9 { sqlite3_db_status db CACHE_MISS 0 } {0 1 0} +do_test 2.1 { db_write db } {0 0 0} +do_test 2.2 { + execsql { INSERT INTO t1 VALUES(4, randomblob(600)) } + db_write db +} {0 4 0} +do_test 2.3 { db_write db 1 } {0 4 0} +do_test 2.4 { db_write db 0 } {0 0 0} +do_test 2.5 { db_write db 1 } {0 0 0} + +do_test 2.6 { + execsql { PRAGMA journal_mode = WAL } + db_write db 1 +} {0 1 0} +do_test 2.7 { + execsql { INSERT INTO t1 VALUES(5, randomblob(600)) } + db_write db +} {0 4 0} +do_test 2.8 { db_write db 1 } {0 4 0} +do_test 2.9 { db_write db 0 } {0 0 0} finish_test