Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Delay opening temporary pager files until they are first written. (CVS 4260) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3fb97a63ef70662abdba18ce8b480e6b |
User & Date: | danielk1977 2007-08-21 14:27:02.000 |
Context
2007-08-21
| ||
15:13 | Readded the sqlite3_open_v2() interface. No test cases yet. Additional progress toward adding mutexes to all interfaces. (CVS 4261) (check-in: 3787563e90 user: drh tags: trunk) | |
14:27 | Delay opening temporary pager files until they are first written. (CVS 4260) (check-in: 3fb97a63ef user: danielk1977 tags: trunk) | |
13:51 | Remove the obsolete static mutexes. Use only the lastest static mutex code. (CVS 4259) (check-in: 6225cd461c 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.364 2007/08/21 14:27:02 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
544 545 546 547 548 549 550 551 552 553 554 555 556 557 | ** on success or an error code is something goes wrong. */ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ char ac[4]; put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4, offset); } /* ** This function should be called when an error occurs within the pager ** code. The first argument is a pointer to the pager structure, the ** second the error-code about to be returned by a pager API function. ** The value returned is a copy of the second argument to this function. ** | > > > > > > > > > > | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | ** on success or an error code is something goes wrong. */ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ char ac[4]; put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4, offset); } /* ** If file pFd is open, call sqlite3OsUnlock() on it. */ static int osUnlock(sqlite3_file *pFd, int eLock){ if( !pFd->pMethods ){ return SQLITE_OK; } return sqlite3OsUnlock(pFd, eLock); } /* ** This function should be called when an error occurs within the pager ** code. The first argument is a pointer to the pager structure, the ** second the error-code about to be returned by a pager API function. ** The value returned is a copy of the second argument to this function. ** |
︙ | ︙ | |||
926 927 928 929 930 931 932 | /* ** Unlock the database file. */ static void pager_unlock(Pager *pPager){ if( !pPager->exclusiveMode ){ if( !MEMDB ){ | | | 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 | /* ** Unlock the database file. */ static void pager_unlock(Pager *pPager){ if( !pPager->exclusiveMode ){ if( !MEMDB ){ osUnlock(pPager->fd, NO_LOCK); pPager->dbSize = -1; IOTRACE(("UNLOCK %p\n", pPager)) } pPager->state = PAGER_UNLOCK; pPager->changeCountDone = 0; } } |
︙ | ︙ | |||
1041 1042 1043 1044 1045 1046 1047 | pPager->nRec = 0; }else{ assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } if( !pPager->exclusiveMode ){ | | | 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 | pPager->nRec = 0; }else{ assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } if( !pPager->exclusiveMode ){ rc2 = osUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; }else if( pPager->state==PAGER_SYNCED ){ pPager->state = PAGER_EXCLUSIVE; } pPager->origDbSize = 0; pPager->setMaster = 0; pPager->needSync = 0; |
︙ | ︙ | |||
1314 1315 1316 1317 1318 1319 1320 | /* ** Truncate the main file of the given pager to the number of pages ** indicated. Also truncate the cached representation of the file. */ static int pager_truncate(Pager *pPager, int nPage){ int rc = SQLITE_OK; | | > > > > > > | > | 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 | /* ** Truncate the main file of the given pager to the number of pages ** indicated. Also truncate the cached representation of the file. */ static int pager_truncate(Pager *pPager, int nPage){ int rc = SQLITE_OK; if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){ rc = sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); } if( rc==SQLITE_OK ){ pPager->dbSize = nPage; pager_truncate_cache(pPager); } return rc; } /* ** Set the sectorSize for the given pager. ** ** The sector size is the larger of the sector size reported ** by sqlite3OsSectorSize() and the pageSize. */ 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<pPager->pageSize ){ pPager->sectorSize = pPager->pageSize; } } /* ** Playback the journal and thus restore the database file to |
︙ | ︙ | |||
1819 1820 1821 1822 1823 1824 1825 | int fout = 0; rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, oflag, &fout); readOnly = (fout&SQLITE_OPEN_READONLY); } } } }else{ | > > > > | < | < > | 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | int fout = 0; rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, oflag, &fout); readOnly = (fout&SQLITE_OPEN_READONLY); } } } }else{ /* If a temporary file is requested, it is not opened immediately. ** In this case we accept the default page size and delay actually ** opening the file until the first call to OsWrite(). */ /* rc = sqlite3PagerOpentemp(pVfs, pPager->fd, pPager->zFilename); */ tempFile = 1; pPager->state = PAGER_EXCLUSIVE; } if( pPager && rc==SQLITE_OK ){ pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE); } /* If an error occured in either of the blocks above, free the memory |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 | pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); pPager->sync_flags = SQLITE_SYNC_NORMAL; /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); | | | 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 | pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); pPager->sync_flags = SQLITE_SYNC_NORMAL; /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); assert(pPager->fd->pMethods||memDb||tempFile); if( !memDb ){ setSectorSize(pPager); } /* pPager->pBusyHandler = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
︙ | ︙ | |||
1995 1996 1997 1998 1999 2000 2001 | ** these cases sqlite3OsRead() will return an error, to which the correct ** response is to zero the memory at pDest and continue. A real IO error ** will presumably recur and be picked up later (Todo: Think about this). */ int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ int rc = SQLITE_OK; memset(pDest, 0, N); | > | | > > | | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 | ** these cases sqlite3OsRead() will return an error, to which the correct ** response is to zero the memory at pDest and continue. A real IO error ** will presumably recur and be picked up later (Todo: Think about this). */ int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ int rc = SQLITE_OK; memset(pDest, 0, N); assert(MEMDB||pPager->fd->pMethods||pPager->tempFile); if( pPager->fd->pMethods ){ IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) rc = sqlite3OsRead(pPager->fd, pDest, N, 0); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } } return rc; } /* ** Return the total number of pages in the disk file associated with ** pPager. ** ** If the PENDING_BYTE lies on the page directly after the end of the ** file, then consider this page part of the file too. For example, if ** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the ** file is 4096 bytes, 5 is returned instead of 4. */ int sqlite3PagerPagecount(Pager *pPager){ i64 n = 0; int rc; assert( pPager!=0 ); if( pPager->errCode ){ return 0; } if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { assert(pPager->fd->pMethods||pPager->tempFile); if( (pPager->fd->pMethods) && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){ pager_error(pPager, rc); return 0; } if( n>0 && n<pPager->pageSize ){ n = 1; }else{ n /= pPager->pageSize; |
︙ | ︙ | |||
2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 | rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } pList = sort_pagelist(pList); while( pList ){ assert( pList->dirty ); /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ | > > > > > > > > | 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 | rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } pList = sort_pagelist(pList); while( pList ){ /* If the file has not yet been opened, open it now. */ if( !pPager->fd->pMethods ){ assert(pPager->tempFile); rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->fd, pPager->zFilename); if( rc ) return rc; } assert( pList->dirty ); /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ |
︙ | ︙ | |||
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 | /* ** Read the content of page pPg out of the database file. */ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ int rc; i64 offset; assert( MEMDB==0 ); offset = (pgno-1)*(i64)pPager->pageSize; rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset); PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); IOTRACE(("PGIN %p %d\n", pPager, pgno)); if( pgno==1 ){ memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24], | > > > > | 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 | /* ** Read the content of page pPg out of the database file. */ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ int rc; i64 offset; assert( MEMDB==0 ); assert(pPager->fd->pMethods||pPager->tempFile); if( !pPager->fd->pMethods ){ return SQLITE_IOERR_SHORT_READ; } offset = (pgno-1)*(i64)pPager->pageSize; rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset); PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); IOTRACE(("PGIN %p %d\n", pPager, pgno)); if( pgno==1 ){ memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24], |
︙ | ︙ |
Changes to test/conflict.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the conflict resolution extension # to SQLite. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the conflict resolution extension # to SQLite. # # $Id: conflict.test,v 1.30 2007/08/21 14:27:02 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !conflict { finish_test return |
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 | # cmd An UPDATE command to execute against table t1 # t0 True if there is an error from $cmd # t1 Content of "b" column of t1 assuming no error in $cmd # t2 Content of "x" column of t3 # t3 Number of temporary files for tables # t4 Number of temporary files for statement journals # foreach {i conf1 cmd t0 t1 t2 t3 t4} { 1 {} UPDATE 1 {6 7 8 9} 1 0 1 | > > > | | | | | | | | | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | # cmd An UPDATE command to execute against table t1 # t0 True if there is an error from $cmd # t1 Content of "b" column of t1 assuming no error in $cmd # t2 Content of "x" column of t3 # t3 Number of temporary files for tables # t4 Number of temporary files for statement journals # # Update: Since temporary table files are now opened lazily, and none # of the following tests use large quantities of data, t3 is always 0. # foreach {i conf1 cmd t0 t1 t2 t3 t4} { 1 {} UPDATE 1 {6 7 8 9} 1 0 1 2 REPLACE UPDATE 0 {7 6 9} 1 0 0 3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0 4 FAIL UPDATE 1 {6 7 3 4} 1 0 0 5 ABORT UPDATE 1 {1 2 3 4} 1 0 1 6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0 7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 9 FAIL {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 11 ROLLBACK {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0 14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1 16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0 } { if {$t0} {set t1 {column a is not unique}} if {[info exists TEMP_STORE] && $TEMP_STORE>=2} { set t3 $t4 |
︙ | ︙ |