Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.226 2005/01/07 08:56:44 danielk1977 Exp $ +** $Id: btree.c,v 1.227 2005/01/08 12:42:39 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -4485,10 +4485,11 @@ } }else{ pRoot = pPageMove; } + /* Update the pointer-map and meta-data with the new root-page number. */ rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); if( rc ){ releasePage(pRoot); return rc; } @@ -4495,10 +4496,11 @@ rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot); if( rc ){ releasePage(pRoot); return rc; } + }else{ rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0); if( rc ) return rc; } #endif Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -16,11 +16,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.179 2004/11/24 01:16:43 drh Exp $ +** @(#) $Id: pager.c,v 1.180 2005/01/08 12:42:39 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include "pager.h" #include @@ -242,10 +242,11 @@ int psAligned; /* pageSize rounded up to a multiple of 8 */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ + int nRead,nWrite; /* Database pages read/written */ void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ @@ -2065,10 +2066,11 @@ if( pList->pgno<=pPager->dbSize ){ CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); + pPager->nWrite++; } #ifndef NDEBUG else{ TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); } @@ -2348,10 +2350,12 @@ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); } + }else{ + pPager->nRead++; } } }else{ /* The requested page is in the page cache. */ pPager->nHit++; @@ -3004,20 +3008,22 @@ /* ** This routine is used for testing and analysis only. */ int *sqlite3pager_stats(Pager *pPager){ - static int a[9]; + static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; a[5] = pPager->errMask; a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; + a[9] = pPager->nRead; + a[10] = pPager->nWrite; return a; } /* ** Set the statement rollback point. Index: src/test3.c ================================================================== --- src/test3.c +++ src/test3.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing the btree.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.57 2004/11/10 11:55:12 danielk1977 Exp $ +** $Id: test3.c,v 1.58 2005/01/08 12:42:39 danielk1977 Exp $ */ #include "sqliteInt.h" #include "pager.h" #include "btree.h" #include "tcl.h" @@ -512,14 +512,14 @@ " ID\"", 0); return TCL_ERROR; } pBt = sqlite3TextToPtr(argv[1]); a = sqlite3pager_stats(sqlite3BtreePager(pBt)); - for(i=0; i<9; i++){ + for(i=0; i<11; i++){ static char *zName[] = { "ref", "page", "max", "size", "state", "err", - "hit", "miss", "ovfl", + "hit", "miss", "ovfl", "read", "write" }; char zBuf[100]; Tcl_AppendElement(interp, zName[i]); sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); Tcl_AppendElement(interp, zBuf); @@ -1317,10 +1317,49 @@ } in += incr; } return TCL_OK; } + +/* +** usage: btree_from_db DB-HANDLE +** +** This command returns the btree handle for the main database associated +** with the database-handle passed as the argument. Example usage: +** +** sqlite3 db test.db +** set bt [btree_from_db db] +*/ +static int btree_from_db( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + char zBuf[100]; + Tcl_CmdInfo info; + sqlite3 *db; + Btree *pBt; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB-HANDLE\"", 0); + return TCL_ERROR; + } + + if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){ + Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0); + return TCL_ERROR; + } + db = *((sqlite3 **)info.objClientData); + assert( db ); + + pBt = db->aDb[0].pBt; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt); + Tcl_SetResult(interp, zBuf, TCL_VOLATILE); + return TCL_OK; +} /* ** Register commands with the TCL interpreter. */ int Sqlitetest3_Init(Tcl_Interp *interp){ @@ -1364,10 +1403,11 @@ { "btree_breakpoint", (Tcl_CmdProc*)btree_breakpoint }, { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test }, { "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement }, { "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement }, { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement }, + { "btree_from_db", (Tcl_CmdProc*)btree_from_db }, }; int i; for(i=0; iaDb[db->nDb-1].pBt; sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), sqlite3BtreeGetReserve(pMain)); assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); + +#ifndef SQLITE_OMIT_AUTOVACUUM + sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain)); +#endif /* Begin a transaction */ rc = execSql(db, "BEGIN;"); if( rc!=SQLITE_OK ) goto end_of_vacuum;