diff --git a/manifest b/manifest index 5c6840dc7b..7a9a109583 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sability\sto\sturn\sof\scalls\sto\sfsync()\susing\sthe\s"synchronous"\spragma.\nIncreased\sthe\sdefault\scache\ssize\sfrom\s100\sto\s2000\sand\smade\sthe\s"cache_size"\npragma\spersistent.\s(CVS\s418) -D 2002-03-05T01:11:13 +C Change\sthe\spager\slocking\smechanism\sso\sthat\swe\sdon't\shave\sto\swrite\spage\s1\nto\sthe\sjournal\sand\sto\sthe\sdatabase\sunless\sit\sactually\schanges.\s(CVS\s419) +D 2002-03-05T12:41:20 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -19,7 +19,7 @@ F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360 F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 -F src/btree.c d25ea795a0f7017bc2099c437e6cc01d4c31b22d +F src/btree.c b7d1b8875113ab4061a6a8cc759f75728ae7daf0 F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 F src/build.c 0f3c6b6482e0b74284b22661de1b813a0bfb0197 F src/delete.c 577da499162291c1855f0b304b211bffcf9da945 @@ -32,8 +32,8 @@ F src/main.c 3015c23faeff1709b1528f07c0bfe839284090a8 F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/os.c db969ecd1bcb4fef01b0b541b8b17401b0eb7ed2 F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6 -F src/pager.c 41af87908cd76a50d7e22cf3c7a4d479e3c9a512 -F src/pager.h feb18aab2f6dea439393f23a382699b9b1053c32 +F src/pager.c e1419353e68c45aaae2555d2000f72de6525faac +F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e F src/parse.y f7483ccff7b8f16d3655df59775d85b62b06897e F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe @@ -108,7 +108,7 @@ F tool/opNames.awk 5ba1f48aa854ee3b7c3d2b54233665bc3e649ea2 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9 F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816 -F tool/speedtest.tcl 31a2f06e3d2153f4311b13cd6fd5e19b7adc8373 +F tool/speedtest.tcl 1c151e27d7ca10c6a2509bf6e816116744c3199e F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b @@ -128,7 +128,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 36a8fe0ad0ee2a67afafc04125dcc085ec1b5a13 -R e93330a0aa7a7fa6a56e7a5c31b63757 +P 414da4af1f4aebc3936ca339fbc7932add081912 +R 0b32113f5a809c11a2af16e72cce2c93 U drh -Z b84940384f009522e2520b7d71139ff4 +Z d718da112d32fa4d0c0cf7ece4f5da88 diff --git a/manifest.uuid b/manifest.uuid index 36d2035611..ba69187ab8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -414da4af1f4aebc3936ca339fbc7932add081912 \ No newline at end of file +480eef1a3a4f049bc0d0cbee32dc8a8d138597c6 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index de288f9b45..a3a269e315 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.58 2002/03/03 23:06:01 drh Exp $ +** $Id: btree.c,v 1.59 2002/03/05 12:41:20 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -762,7 +762,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){ if( sqlitepager_isreadonly(pBt->pPager) ){ return SQLITE_READONLY; } - rc = sqlitepager_write(pBt->page1); + rc = sqlitepager_begin(pBt->page1); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } diff --git a/src/pager.c b/src/pager.c index de332cba02..1f0fb3aed8 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.42 2002/03/05 01:11:14 drh Exp $ +** @(#) $Id: pager.c,v 1.43 2002/03/05 12:41:20 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -988,6 +988,63 @@ int sqlitepager_unref(void *pData){ return SQLITE_OK; } +/* +** Acquire a write-lock on the database. The lock is removed when +** the any of the following happen: +** +** * sqlitepager_commit() is called. +** * sqlitepager_rollback() is called. +** * sqlitepager_close() is called. +** * sqlitepager_unref() is called to on every outstanding page. +** +** The parameter to this routine is a pointer to any open page of the +** database file. Nothing changes about the page - it is used merely +** to acquire a pointer to the Pager structure and as proof that there +** is already a read-lock on the database. +** +** If the database is already write-locked, this routine is a no-op. +*/ +int sqlitepager_begin(void *pData){ + PgHdr *pPg = DATA_TO_PGHDR(pData); + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + assert( pPg->nRef>0 ); + assert( pPager->state!=SQLITE_UNLOCK ); + if( pPager->state==SQLITE_READLOCK ){ + assert( pPager->aInJournal==0 ); + rc = sqliteOsWriteLock(&pPager->fd); + if( rc!=SQLITE_OK ){ + return rc; + } + pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( pPager->aInJournal==0 ){ + sqliteOsReadLock(&pPager->fd); + return SQLITE_NOMEM; + } + rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd, 0); + if( rc!=SQLITE_OK ){ + sqliteFree(pPager->aInJournal); + pPager->aInJournal = 0; + sqliteOsReadLock(&pPager->fd); + return SQLITE_CANTOPEN; + } + pPager->journalOpen = 1; + pPager->needSync = !pPager->noSync; + pPager->state = SQLITE_WRITELOCK; + sqlitepager_pagecount(pPager); + pPager->origDbSize = pPager->dbSize; + rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + if( rc==SQLITE_OK ){ + rc = sqliteOsWrite(&pPager->jfd, &pPager->dbSize, sizeof(Pgno)); + } + if( rc!=SQLITE_OK ){ + rc = pager_unwritelock(pPager); + if( rc==SQLITE_OK ) rc = SQLITE_FULL; + } + } + return rc; +} + /* ** Mark a data page as writeable. The page is written into the journal ** if it is not there already. This routine must be called before making @@ -1035,39 +1092,8 @@ int sqlitepager_write(void *pData){ ** create it if it does not. */ assert( pPager->state!=SQLITE_UNLOCK ); - if( pPager->state==SQLITE_READLOCK ){ - assert( pPager->aInJournal==0 ); - rc = sqliteOsWriteLock(&pPager->fd); - if( rc!=SQLITE_OK ){ - return rc; - } - pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); - if( pPager->aInJournal==0 ){ - sqliteOsReadLock(&pPager->fd); - return SQLITE_NOMEM; - } - rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd, 0); - if( rc!=SQLITE_OK ){ - sqliteFree(pPager->aInJournal); - pPager->aInJournal = 0; - sqliteOsReadLock(&pPager->fd); - return SQLITE_CANTOPEN; - } - pPager->journalOpen = 1; - pPager->needSync = 0; - pPager->state = SQLITE_WRITELOCK; - sqlitepager_pagecount(pPager); - pPager->origDbSize = pPager->dbSize; - rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); - if( rc==SQLITE_OK ){ - rc = sqliteOsWrite(&pPager->jfd, &pPager->dbSize, sizeof(Pgno)); - } - if( rc!=SQLITE_OK ){ - rc = pager_unwritelock(pPager); - if( rc==SQLITE_OK ) rc = SQLITE_FULL; - return rc; - } - } + rc = sqlitepager_begin(pData); + if( rc!=SQLITE_OK ) return rc; assert( pPager->state==SQLITE_WRITELOCK ); assert( pPager->journalOpen ); @@ -1247,6 +1273,9 @@ commit_abort: int sqlitepager_rollback(Pager *pPager){ int rc; if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ + if( pPager->state>=SQLITE_WRITELOCK ){ + pager_playback(pPager); + } return pager_errcode(pPager); } if( pPager->state!=SQLITE_WRITELOCK ){ diff --git a/src/pager.h b/src/pager.h index 91b3f8b0c1..d10d0d119c 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.15 2002/03/02 20:41:59 drh Exp $ +** @(#) $Id: pager.h,v 1.16 2002/03/05 12:41:20 drh Exp $ */ /* @@ -59,6 +59,7 @@ Pgno sqlitepager_pagenumber(void*); int sqlitepager_write(void*); int sqlitepager_iswriteable(void*); int sqlitepager_pagecount(Pager*); +int sqlitepager_begin(void*); int sqlitepager_commit(Pager*); int sqlitepager_rollback(Pager*); int sqlitepager_isreadonly(Pager*); diff --git a/tool/speedtest.tcl b/tool/speedtest.tcl index 8de470249c..420eb35e6f 100644 --- a/tool/speedtest.tcl +++ b/tool/speedtest.tcl @@ -6,11 +6,12 @@ # Run a test # -set cnt 0 -proc runtest {title sqlfile} { +set cnt 1 +proc runtest {title} { global cnt - incr cnt + set sqlfile test$cnt.sql puts "

Test $cnt: $title

" + incr cnt set fd [open $sqlfile r] set sql [string trim [read $fd [file size $sqlfile]]] close $fd @@ -28,11 +29,14 @@ proc runtest {title sqlfile} { } puts "
" puts "$sql" - puts "
" - set format {} + puts "
%s%.3f
" + set format {} + set delay 1000 + exec sync; after $delay; set t [time "exec psql drh <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format PostgreSQL: $t] + exec sync; after $delay; set t [time "exec mysql drh <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format MySQL: $t] @@ -42,12 +46,17 @@ proc runtest {title sqlfile} { # set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] # set t [expr {[lindex $t 0]/1000000.0}] # puts [format $format {SQLite 2.4 (cache=100):} $t] + exec sync; after $delay; set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] - puts [format $format {SQLite 2.4 (cache=2000):} $t] + puts [format $format {SQLite 2.4:} $t] + exec sync; after $delay; set t [time "exec ./sqlite240 sns.db <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format {SQLite 2.4 (nosync):} $t] +# set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1] +# set t [expr {[lindex $t 0]/1000000.0}] +# puts [format $format {SQLite 2.4 (test):} $t] puts "
%s   %.3f
" } @@ -67,6 +76,7 @@ set fd [open 2kinit.sql w] puts $fd {PRAGMA cache_size=2000; PRAGMA synchronous=on;} close $fd exec ./sqlite240 s2k.db <2kinit.sql +exec ./sqlite-t1 st1.db <2kinit.sql set fd [open nosync-init.sql w] puts $fd {PRAGMA cache_size=2000; PRAGMA synchronous=off;} close $fd @@ -82,11 +92,11 @@ proc number_name {n} { } else { set txt {} } - if {$n>100} { + if {$n>=100} { append txt " [lindex $::ones [expr {$n/100}]] hundred" set n [expr {$n%100}] } - if {$n>19} { + if {$n>=20} { append txt " [lindex $::tens [expr {$n/10}]]" set n [expr {$n%10}] } @@ -98,20 +108,20 @@ proc number_name {n} { return $txt } -# TEST 1 -# -set fd [open test1.sql w] + + +set fd [open test$cnt.sql w] puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));" for {set i 1} {$i<=1000} {incr i} { set r [expr {int(rand()*100000)}] puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" } close $fd -runtest {1000 INSERTs} test1.sql +runtest {1000 INSERTs} -# TEST 2 -# -set fd [open test2.sql w] + + +set fd [open test$cnt.sql w] puts $fd "BEGIN;" puts $fd "CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));" for {set i 1} {$i<=25000} {incr i} { @@ -120,41 +130,50 @@ for {set i 1} {$i<=25000} {incr i} { } puts $fd "COMMIT;" close $fd -runtest {25000 INSERTs in a transaction} test2.sql +runtest {25000 INSERTs in a transaction} -# TEST 3 -# -set fd [open test3.sql w] + + +set fd [open test$cnt.sql w] for {set i 0} {$i<100} {incr i} { set lwr [expr {$i*100}] set upr [expr {($i+10)*100}] puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" } close $fd -runtest {100 SELECTs without an index} test3.sql +runtest {100 SELECTs without an index} -# TEST 4 -# -set fd [open test4.sql w] + + +set fd [open test$cnt.sql w] +for {set i 1} {$i<=100} {incr i} { + puts $fd "SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%[number_name $i]%';" +} +close $fd +runtest {100 SELECTs on a string comparison} + + + +set fd [open test$cnt.sql w] puts $fd {CREATE INDEX i2a ON t2(a);} puts $fd {CREATE INDEX i2b ON t2(b);} close $fd -runtest {Creating an index} test4.sql +runtest {Creating an index} -# TEST 5 -# -set fd [open test5.sql w] + + +set fd [open test$cnt.sql w] for {set i 0} {$i<5000} {incr i} { set lwr [expr {$i*100}] set upr [expr {($i+1)*100}] puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" } close $fd -runtest {5000 SELECTs with an index} test5.sql +runtest {5000 SELECTs with an index} -# TEST 6 -# -set fd [open test6.sql w] + + +set fd [open test$cnt.sql w] puts $fd "BEGIN;" for {set i 0} {$i<100} {incr i} { set lwr [expr {$i*10}] @@ -163,52 +182,53 @@ for {set i 0} {$i<100} {incr i} { } puts $fd "COMMIT;" close $fd -runtest {100 UPDATEs without an index} test6.sql +runtest {100 UPDATEs without an index} -# TEST 7 -set fd [open test7.sql w] + +set fd [open test$cnt.sql w] puts $fd "BEGIN;" for {set i 1} {$i<=25000} {incr i} { puts $fd "UPDATE t2 SET b=b+a WHERE a=$i;" } puts $fd "COMMIT;" close $fd -runtest {25000 UPDATEs with an index} test7.sql +runtest {25000 UPDATEs with an index} -# TEST 8 -set fd [open test8.sql w] + + +set fd [open test$cnt.sql w] puts $fd "BEGIN;" puts $fd "INSERT INTO t1 SELECT * FROM t2;" puts $fd "INSERT INTO t2 SELECT * FROM t1;" puts $fd "COMMIT;" close $fd -runtest {INSERTs from a SELECT} test8.sql +runtest {INSERTs from a SELECT} -# TEST 9 -# -set fd [open test9.sql w] + + +set fd [open test$cnt.sql w] puts $fd {DELETE FROM t2 WHERE c LIKE '%fifty%';} close $fd -runtest {DELETE without an index} test9.sql +runtest {DELETE without an index} -# TEST 10 -# -set fd [open test10.sql w] + + +set fd [open test$cnt.sql w] puts $fd {DELETE FROM t2 WHERE a>10 AND a<20000;} close $fd -runtest {DELETE with an index} test10.sql +runtest {DELETE with an index} -# TEST 11 -# -set fd [open test11.sql w] + + +set fd [open test$cnt.sql w] puts $fd {INSERT INTO t2 SELECT * FROM t1;} close $fd -runtest {A big INSERT after a big DELETE} test11.sql +runtest {A big INSERT after a big DELETE} -# TEST 12 -# -set fd [open test12.sql w] + + +set fd [open test$cnt.sql w] puts $fd {BEGIN;} puts $fd {DELETE FROM t1;} for {set i 1} {$i<=1000} {incr i} { @@ -217,12 +237,12 @@ for {set i 1} {$i<=1000} {incr i} { } puts $fd {COMMIT;} close $fd -runtest {A big DELETE followed by many small INSERTs} test12.sql +runtest {A big DELETE followed by many small INSERTs} -# TEST 13 -# -set fd [open test13.sql w] + + +set fd [open test$cnt.sql w] puts $fd {DROP TABLE t1;} puts $fd {DROP TABLE t2;} close $fd -runtest {DROP TABLE} test13.sql +runtest {DROP TABLE}