Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improve coverage of pager.c. (CVS 6158) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
855c4093cf331496d9ef508011ad814e |
User & Date: | danielk1977 2009-01-10 16:15:09.000 |
Context
2009-01-10
| ||
16:15 | When compiled with SQLITE_DEBUG (in other words, when assert() is enabled) the ALWAYS and NEVER macros will throw an assertion if their arguments are not true or false, respectively. (CVS 6159) (check-in: 64a8dcd8d6 user: drh tags: trunk) | |
16:15 | Improve coverage of pager.c. (CVS 6158) (check-in: 855c4093cf user: danielk1977 tags: trunk) | |
15:34 | Fix a bug caused by overzealous code test coverage simplifications. Bug found by TH3. (CVS 6157) (check-in: 3da5578726 user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** 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. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** 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.545 2009/01/10 16:15:09 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" /* ** Macros for troubleshooting. Normally turned off */ |
︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | # define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } # define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) #else # define CODEC1(P,D,N,X) /* NO-OP */ # define CODEC2(P,D,N,X) ((char*)D) #endif /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures ** are stored in the Pager.aSavepoint[] array, which is allocated and ** resized using sqlite3Realloc(). ** ** When a savepoint is created, the PagerSavepoint.iHdrOffset field is | > > > > > > > > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } # define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) #else # define CODEC1(P,D,N,X) /* NO-OP */ # define CODEC2(P,D,N,X) ((char*)D) #endif /* ** The maximum allowed sector size. 16MB. If the xSectorsize() method ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. ** This could conceivably cause corruption following a power failure on ** such a system. This is currently an undocumented limit. */ #define MAX_SECTOR_SIZE 0x0100000 /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures ** are stored in the Pager.aSavepoint[] array, which is allocated and ** resized using sqlite3Realloc(). ** ** When a savepoint is created, the PagerSavepoint.iHdrOffset field is |
︙ | ︙ | |||
397 398 399 400 401 402 403 | int dc; /* Device characteristics */ int nSector; /* Sector size */ int szPage; /* Page size */ sqlite3_file *fd = pPager->fd; if( fd->pMethods ){ dc = sqlite3OsDeviceCharacteristics(fd); | | | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | int dc; /* Device characteristics */ int nSector; /* Sector size */ int szPage; /* Page size */ sqlite3_file *fd = pPager->fd; if( fd->pMethods ){ dc = sqlite3OsDeviceCharacteristics(fd); nSector = pPager->sectorSize; szPage = pPager->pageSize; } assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); if( !fd->pMethods || |
︙ | ︙ | |||
756 757 758 759 760 761 762 | i64 journalSize, u32 *pNRec, u32 *pDbSize ){ int rc; unsigned char aMagic[8]; /* A buffer to hold the magic header */ i64 jrnlOff; | | > | 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | i64 journalSize, u32 *pNRec, u32 *pDbSize ){ int rc; unsigned char aMagic[8]; /* A buffer to hold the magic header */ i64 jrnlOff; u32 iPageSize; u32 iSectorSize; seekJournalHdr(pPager); if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ return SQLITE_DONE; } jrnlOff = pPager->journalOff; |
︙ | ︙ | |||
781 782 783 784 785 786 787 | rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit); if( rc ) return rc; rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); if( rc ) return rc; | > | | > | | | | > > > > > > | | > | | | | | | | | | | | > | | > | > > | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 | rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit); if( rc ) return rc; rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); if( rc ) return rc; if( pPager->journalOff==0 ){ rc = read32bits(pPager->jfd, jrnlOff+16, &iPageSize); if( rc ) return rc; if( iPageSize<512 || iPageSize>SQLITE_MAX_PAGE_SIZE || ((iPageSize-1)&iPageSize)!=0 ){ /* If the page-size in the journal-header is invalid, then the process ** that wrote the journal-header must have crashed before the header ** was synced. In this case stop reading the journal file here. */ rc = SQLITE_DONE; }else{ u16 pagesize = (u16)iPageSize; rc = sqlite3PagerSetPagesize(pPager, &pagesize); assert( rc!=SQLITE_OK || pagesize==(u16)iPageSize ); } if( rc ) return rc; /* Update the assumed sector-size to match the value used by ** the process that created this journal. If this journal was ** created by a process other than this one, then this routine ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ rc = read32bits(pPager->jfd, jrnlOff+12, &iSectorSize); if( rc ) return rc; if( (iSectorSize&(iSectorSize-1)) || iSectorSize<512 || iSectorSize>MAX_SECTOR_SIZE ){ return SQLITE_DONE; } pPager->sectorSize = iSectorSize; } pPager->journalOff += JOURNAL_HDR_SZ(pPager); return SQLITE_OK; } |
︙ | ︙ | |||
1499 1500 1501 1502 1503 1504 1505 | return rc; } /* ** Set the sectorSize for the given pager. ** ** The sector size is at least as big as the sector size reported | | > > > | 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 | return rc; } /* ** Set the sectorSize for the given pager. ** ** The sector size is at least as big as the sector size reported ** by sqlite3OsSectorSize(). The minimum sector size is 512. */ static void setSectorSize(Pager *pPager){ assert(pPager->fd->pMethods||pPager->tempFile); if( !pPager->tempFile ){ /* Sector size doesn't matter for temporary files. Also, the file ** may not have been opened yet, in whcih case the OsSectorSize() ** call will segfault. */ pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); } if( pPager->sectorSize<512 ){ pPager->sectorSize = 512; } if( pPager->sectorSize>MAX_SECTOR_SIZE ){ pPager->sectorSize = MAX_SECTOR_SIZE; } } /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. ** |
︙ | ︙ | |||
2018 2019 2020 2021 2022 2023 2024 | ** database file. The default page size is the maximum of: ** ** + SQLITE_DEFAULT_PAGE_SIZE, ** + The value returned by sqlite3OsSectorSize() ** + The largest page size that can be written atomically. */ if( rc==SQLITE_OK && !readOnly ){ | | | | | 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | ** database file. The default page size is the maximum of: ** ** + SQLITE_DEFAULT_PAGE_SIZE, ** + The value returned by sqlite3OsSectorSize() ** + The largest page size that can be written atomically. */ if( rc==SQLITE_OK && !readOnly ){ setSectorSize(pPager); if( szPageDflt<pPager->sectorSize ){ szPageDflt = pPager->sectorSize; } #ifdef SQLITE_ENABLE_ATOMIC_WRITE { int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); int ii; assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); |
︙ | ︙ |
Changes to src/sqliteLimit.h.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. ** ** @(#) $Id: sqliteLimit.h,v 1.10 2009/01/10 16:15:09 danielk1977 Exp $ */ /* ** The maximum length of a TEXT or BLOB in bytes. This also ** limits the size of a row in a table or index. ** ** The hard limit is the ability of a 32-bit signed integer |
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 32768. This a limit ** imposed by the necessity of storing the value in a 2-byte unsigned integer ** and the fact that the page size must be a power of 2. */ #ifndef SQLITE_MAX_PAGE_SIZE # define SQLITE_MAX_PAGE_SIZE 32768 #endif /* | > > > > > > > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 32768. This a limit ** imposed by the necessity of storing the value in a 2-byte unsigned integer ** and the fact that the page size must be a power of 2. ** ** If this limit is changed, then the compiled library is technically ** incompatible with an SQLite library compiled with a different limit. If ** a process operating on a database with a page-size of 65536 bytes ** crashes, then an instance of SQLite compiled with the default page-size ** limit will not be able to rollback the aborted transaction. This could ** lead to database corruption. */ #ifndef SQLITE_MAX_PAGE_SIZE # define SQLITE_MAX_PAGE_SIZE 32768 #endif /* |
︙ | ︙ |
Changes to test/crash8.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # # This test verifies a couple of specific potential data corruption # scenarios involving crashes or power failures. # # Later: Also, some other specific scenarios required for coverage # testing that do not lead to corruption. # | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # # This test verifies a couple of specific potential data corruption # scenarios involving crashes or power failures. # # Later: Also, some other specific scenarios required for coverage # testing that do not lead to corruption. # # $Id: crash8.test,v 1.3 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !crashtest { finish_test |
︙ | ︙ | |||
114 115 116 117 118 119 120 121 122 123 124 125 | proc read_file {zFile} { set fd [open $zFile] fconfigure $fd -translation binary set zData [read $fd] close $fd return $zData } # The following tests check that SQLite will not roll back a hot-journal # file if the sector-size field in the first journal file header is # suspect. Definition of suspect: # | > > > > > > | | > > > > > > > > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | proc read_file {zFile} { set fd [open $zFile] fconfigure $fd -translation binary set zData [read $fd] close $fd return $zData } proc write_file {zFile zData} { set fd [open $zFile w] fconfigure $fd -translation binary puts -nonewline $fd $zData close $fd } # The following tests check that SQLite will not roll back a hot-journal # file if the sector-size field in the first journal file header is # suspect. Definition of suspect: # # a) Not a power of 2, or (crash8-3.5) # b) Greater than 0x01000000 (16MB), or (crash8-3.6) # c) Less than 512. (crash8-3.7) # # Also test that SQLite will not rollback a hot-journal file with a # suspect page-size. In this case "suspect" means: # # a) Not a power of 2, or # b) Less than 512, or # c) Greater than SQLITE_MAX_PAGE_SIZE # do_test crash8-3.1 { list [file exists test.db-joural] [file exists test.db] } {0 1} do_test crash8-3.2 { execsql { PRAGMA synchronous = off; |
︙ | ︙ | |||
144 145 146 147 148 149 150 151 | SELECT count(*) FROM t1; } } {0} do_test crash8-3.4 { binary scan [string range $zJournal 20 23] I nSector set nSector } {512} do_test crash8-3.5 { | > < | < | < < < | < | < | < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | SELECT count(*) FROM t1; } } {0} do_test crash8-3.4 { binary scan [string range $zJournal 20 23] I nSector set nSector } {512} do_test crash8-3.5 { set zJournal2 [string replace $zJournal 20 23 [binary format I 513]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.6 { set zJournal2 [string replace $zJournal 20 23 [binary format I 0x2000000]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.7 { set zJournal2 [string replace $zJournal 20 23 [binary format I 256]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.8 { set zJournal2 [string replace $zJournal 24 27 [binary format I 513]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.9 { set big [expr $SQLITE_MAX_PAGE_SIZE * 2] set zJournal2 [string replace $zJournal 24 27 [binary format I $big]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.10 { set zJournal2 [string replace $zJournal 24 27 [binary format I 256]] write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.11 { set fd [open test.db-journal w] fconfigure $fd -translation binary puts -nonewline $fd $zJournal close $fd execsql { SELECT count(*) FROM t1; PRAGMA integrity_check |
︙ | ︙ |
Changes to test/jrnlmode.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2008 April 17 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2008 April 17 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # # $Id: jrnlmode.test,v 1.11 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return |
︙ | ︙ | |||
415 416 417 418 419 420 421 422 423 424 425 426 427 428 | expr {$journalsize>30000} } {1} do_test jrnlmode-5.19 { execsql COMMIT set sz [file size test.db-journal] expr {$sz>=$journalsize} } {1} } ifcapable pragma { do_test jrnlmode-6.1 { execsql { PRAGMA journal_mode = truncate; CREATE TABLE t4(a, b); | > > > > > > > > > > > > > > > > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | expr {$journalsize>30000} } {1} do_test jrnlmode-5.19 { execsql COMMIT set sz [file size test.db-journal] expr {$sz>=$journalsize} } {1} # Test a size-limit of 0. # do_test jrnlmode-5.20 { execsql { PRAGMA journal_size_limit = 0; BEGIN; UPDATE t1 SET a = randomblob(1000); } } {0} do_test jrnlmode-5.21 { expr {[file size test.db-journal] > 1024} } {1} do_test jrnlmode-5.22 { execsql COMMIT list [file exists test.db-journal] [file size test.db-journal] } {1 0} } ifcapable pragma { do_test jrnlmode-6.1 { execsql { PRAGMA journal_mode = truncate; CREATE TABLE t4(a, b); |
︙ | ︙ |
Changes to test/malloc.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # This file attempts to check the behavior of the SQLite library in # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) # which causes the N-th malloc to fail. This special feature is used # to see what happens in the library if a malloc were to really fail # due to an out-of-memory situation. # | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # This file attempts to check the behavior of the SQLite library in # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) # which causes the N-th malloc to fail. This special feature is used # to see what happens in the library if a malloc were to really fail # due to an out-of-memory situation. # # $Id: malloc.test,v 1.73 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # |
︙ | ︙ | |||
674 675 676 677 678 679 680 | do_malloc_test 29 -sqlprep { CREATE TABLE t1(a TEXT, b TEXT); } -sqlbody { INSERT INTO t1 VALUES(1, -234); INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1; } | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | do_malloc_test 29 -sqlprep { CREATE TABLE t1(a TEXT, b TEXT); } -sqlbody { INSERT INTO t1 VALUES(1, -234); INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1; } do_malloc_test 30 -tclprep { db eval { CREATE TABLE t1(x PRIMARY KEY); INSERT INTO t1 VALUES(randstr(500,500)); INSERT INTO t1 VALUES(randstr(500,500)); INSERT INTO t1 VALUES(randstr(500,500)); } db close |
︙ | ︙ | |||
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | -- statement above. When requesting the pages, the content is loaded -- from the database file. The point of this test case is to test handling -- of malloc errors (including SQLITE_IOERR_NOMEM errors) when loading -- the content. SELECT * FROM t1 ORDER BY x; } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} puts open-file-count=$sqlite_open_file_count finish_test | > > > > > > > > > > > > | 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | -- statement above. When requesting the pages, the content is loaded -- from the database file. The point of this test case is to test handling -- of malloc errors (including SQLITE_IOERR_NOMEM errors) when loading -- the content. SELECT * FROM t1 ORDER BY x; } # After committing a transaction in persistent-journal mode, if a journal # size limit is configured SQLite may attempt to truncate the journal file. # This test verifies the libraries response to a malloc() failure during # this operation. # do_malloc_test 31 -sqlprep { PRAGMA journal_mode = persist; PRAGMA journal_size_limit = 1024; CREATE TABLE t1(a PRIMARY KEY, b); } -sqlbody { INSERT INTO t1 VALUES(1, 2); } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} puts open-file-count=$sqlite_open_file_count finish_test |