Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -2594,16 +2594,17 @@ if( pCsr->iPage>=0 ){ MemPage *pPg = pCsr->apPage[0]; if( pPg && pPg->pDbPage->flags & PGHDR_MMAP ){ MemPage *pNew = 0; rc = getAndInitPage(pBt, pPg->pgno, &pNew, 0); - if( rc==SQLITE_OK && pCsr->iPage==0 ){ - pCsr->info.pCell = pNew->aData + (pCsr->info.pCell - pPg->aData); + if( rc==SQLITE_OK ){ + if( pCsr->iPage==0 ){ + pCsr->info.pCell = pNew->aData + (pCsr->info.pCell - pPg->aData); + } + pCsr->apPage[0] = pNew; + releasePage(pPg); } - pCsr->apPage[0] = pNew; - releasePage(pPg); - if( rc!=SQLITE_OK ) return rc; } } } return rc; Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -204,10 +204,18 @@ struct UnixUnusedFd { int fd; /* File descriptor to close */ int flags; /* Flags this file descriptor was opened with */ UnixUnusedFd *pNext; /* Next unused file descriptor on same file */ }; + +typedef struct unixMapping unixMapping; +struct unixMapping { + sqlite3_int64 mmapSize; + sqlite3_int64 mmapOrigsize; + void *pMapRegion; +}; + /* ** The unixFile structure is subclass of sqlite3_file specific to the unix ** VFS implementations. */ @@ -224,14 +232,14 @@ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ int nFetchOut; /* Number of outstanding xFetch refs */ - sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ - sqlite3_int64 mmapOrigsize; /* Actual size of mapping at pMapRegion */ sqlite3_int64 mmapLimit; /* Configured FCNTL_MMAP_LIMIT value */ - void *pMapRegion; /* Memory mapped region */ + int szSyspage; /* System page size */ + unixMapping aMmap[2]; /* Up to two memory mapped regions */ + #ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #endif #if SQLITE_ENABLE_LOCKING_STYLE @@ -310,10 +318,18 @@ #if SQLITE_THREADSAFE #define threadid pthread_self() #else #define threadid 0 #endif + +#if !defined(HAVE_MREMAP) +#if defined(__linux__) && defined(_GNU_SOURCE) +# define HAVE_MREMAP 1 +#else +# define HAVE_MREMAP 0 +#endif +#endif /* ** Different Unix systems declare open() in different ways. Same use ** open(const char*,int,mode_t). Others use open(const char*,int,...). ** The difference is important when using a pointer to the function. @@ -448,11 +464,11 @@ #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent) { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, #define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent) -#if defined(__linux__) && defined(_GNU_SOURCE) +#if HAVE_MREMAP { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, #else { "mremap", (sqlite3_syscall_ptr)0, 0 }, #endif #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent) @@ -1864,10 +1880,11 @@ ** Close a file. */ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; + unixUnmapfile(pFile); unixUnlock(id, NO_LOCK); unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close ** routine (e.g. nolockClose()) would be called instead. @@ -3095,10 +3112,12 @@ sqlite3_int64 offset ){ unixFile *pFile = (unixFile *)id; int got; assert( id ); + sqlite3_int64 iMap = 0; /* File offset of start of mapping i */ + int i; /* Used to iterate through mappings */ /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 assert( pFile->pUnused==0 @@ -3105,23 +3124,28 @@ || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); #endif - /* Deal with as much of this write request as possible by transfering - ** data to the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - return SQLITE_OK; - }else{ - int nCopy = pFile->mmapSize - offset; - memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } + /* Deal with as much of this read request as possible by transfering + ** data from the memory mapping using memcpy(). */ + for(i=0; i<2; i++){ + unixMapping *pMap = &pFile->aMmap[i]; + sqlite3_int64 iEnd = iMap + pMap->mmapSize; + if( offsetpMapRegion))[offset-iMap], amt); + return SQLITE_OK; + }else{ + int nCopy = iEnd - offset; + memcpy(pBuf, &((u8 *)(pMap->pMapRegion))[offset-iMap], nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } + iMap = pMap->mmapSize; } got = seekAndRead(pFile, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; @@ -3192,10 +3216,12 @@ ){ unixFile *pFile = (unixFile*)id; int wrote = 0; assert( id ); assert( amt>0 ); + int i; + sqlite3_int64 iMap = 0; /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 assert( pFile->pUnused==0 @@ -3224,23 +3250,26 @@ } } } #endif - /* Deal with as much of this write request as possible by transfering - ** data from the memory mapping using memcpy(). */ - if( offsetmmapSize ){ - if( offset+amt <= pFile->mmapSize ){ - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - return SQLITE_OK; - }else{ - int nCopy = pFile->mmapSize - offset; - memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); - pBuf = &((u8 *)pBuf)[nCopy]; - amt -= nCopy; - offset += nCopy; - } + for(i=0; i<2; i++){ + unixMapping *pMap = &pFile->aMmap[i]; + sqlite3_int64 iEnd = iMap + pMap->mmapSize; + if( offsetpMapRegion))[offset-iMap], pBuf, amt); + return SQLITE_OK; + }else{ + int nCopy = iEnd - offset; + memcpy(&((u8 *)(pMap->pMapRegion))[offset-iMap], pBuf, nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } + iMap = pMap->mmapSize; } while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; @@ -3508,10 +3537,12 @@ rc = robust_ftruncate(pFile->h, (off_t)nByte); if( rc ){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); }else{ + int i; + #ifdef SQLITE_DEBUG /* If we are doing a normal write to a database file (as opposed to ** doing a hot-journal rollback or a write to some file other than a ** normal database file) and we truncate the file to zero length, ** that effectively updates the change counter. This might happen @@ -3525,12 +3556,17 @@ /* If the file was just truncated to a size smaller than the currently ** mapped region, reduce the effective mapping size as well. SQLite will ** use read() and write() to access data beyond this point from now on. */ - if( nBytemmapSize ){ - pFile->mmapSize = nByte; + for(i=1; i>=0; i--){ + unixMapping *pMap = &pFile->aMmap[i]; + sqlite3_int64 iEnd = pMap->mmapSize + (i==1 ? pMap[-1].mmapSize : 0); + if( nBytemmapSize -= (iEnd - nByte); + if( pMap->mmapSize<0 ) pMap->mmapSize = 0; + } } return SQLITE_OK; } } @@ -3619,18 +3655,20 @@ } } if( pFile->mmapLimit>0 ){ int rc; + sqlite3_int64 nSz = nByte; if( pFile->szChunk<=0 ){ - if( robust_ftruncate(pFile->h, nByte) ){ + nSz = ((nSz+pFile->szSyspage-1) / pFile->szSyspage) * pFile->szSyspage; + if( robust_ftruncate(pFile->h, nSz) ){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); } } - rc = unixMapfile(pFile, nByte); + rc = unixMapfile(pFile, nSz); return rc; } return SQLITE_OK; } @@ -4507,18 +4545,35 @@ /* ** If it is currently memory mapped, unmap file pFd. */ static void unixUnmapfile(unixFile *pFd){ + int i; assert( pFd->nFetchOut==0 ); - if( pFd->pMapRegion ){ - osMunmap(pFd->pMapRegion, pFd->mmapOrigsize); - pFd->pMapRegion = 0; - pFd->mmapSize = 0; - pFd->mmapOrigsize = 0; + for(i=0; i<2; i++){ + unixMapping *pMap = &pFd->aMmap[i]; + if( pMap->pMapRegion ){ + osMunmap(pMap->pMapRegion, pMap->mmapOrigsize); + pMap->pMapRegion = 0; + pMap->mmapSize = 0; + pMap->mmapOrigsize = 0; + } } } + +/* +** Return the system page size somehow. +*/ +static int unixGetPagesize(void){ +#if HAVE_REMAP + return 512; +#elif _BSD_SOURCE + return getpagesize(); +#else + return (int)sysconf(_SC_PAGESIZE); +#endif +} /* ** Memory map or remap the file opened by file-descriptor pFd (if the file ** is already mapped, the existing mapping is replaced by the new). Or, if ** there already exists a mapping for this file, and there are still @@ -4533,16 +4588,21 @@ ** SQLITE_OK is returned if no error occurs (even if the mapping is not ** recreated as a result of outstanding references) or an SQLite error ** code otherwise. */ static int unixMapfile(unixFile *pFd, i64 nByte){ - i64 nMap = nByte; + i64 nMap; /* Number of bytes of file to map */ int rc; assert( nMap>=0 || pFd->nFetchOut==0 ); if( pFd->nFetchOut>0 ) return SQLITE_OK; + /* Set variable nMap to the number of bytes of the file to map. This is + ** the smaller of argument nByte and the limit configured by + ** SQLITE_FCNTL_MMAP_LIMIT. Or, if nByte is less than zero, the smaller + ** of the file size or the SQLITE_FCNTL_MMAP_LIMIT value. */ + nMap = nByte; if( nMap<0 ){ struct stat statbuf; /* Low-level file information */ rc = osFstat(pFd->h, &statbuf); if( rc!=SQLITE_OK ){ return SQLITE_IOERR_FSTAT; @@ -4551,33 +4611,75 @@ } if( nMap>pFd->mmapLimit ){ nMap = pFd->mmapLimit; } - if( nMap!=pFd->mmapSize ){ - void *pNew = 0; + if( nMap!=(pFd->aMmap[0].mmapSize + pFd->aMmap[1].mmapSize) ){ -#if defined(__linux__) && defined(_GNU_SOURCE) - if( pFd->pMapRegion && nMap>0 ){ - pNew = osMremap(pFd->pMapRegion, pFd->mmapOrigsize, nMap, MREMAP_MAYMOVE); - }else + /* If the request is for a mapping zero bytes in size, or there are + ** currently already two mapping regions, or there is already a mapping + ** region that is not a multiple of the page-size in size, unmap + ** everything. */ + if( nMap==0 +#if !HAVE_MREMAP + || (pFd->aMmap[0].pMapRegion && pFd->aMmap[1].pMapRegion) + || (pFd->aMmap[0].mmapSize % pFd->szSyspage) #endif - { + ){ unixUnmapfile(pFd); - if( nMap>0 ){ - int flags = PROT_READ; - if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; + } + assert( pFd->aMmap[1].pMapRegion==0 ); + + if( nMap>0 ){ + unixMapping *pMap = &pFd->aMmap[0]; /* First mapping object */ + void *pNew = 0; + int iNew = 0; + int flags = PROT_READ; + if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; + + /* If there are currently no mappings, create a new one */ + if( pMap->pMapRegion==0 ){ pNew = osMmap(0, nMap, flags, MAP_SHARED, pFd->h, 0); } - } - - if( pNew==MAP_FAILED ){ - return SQLITE_IOERR_MMAP; - } - pFd->pMapRegion = pNew; - pFd->mmapSize = nMap; - pFd->mmapOrigsize = nMap; +#if HAVE_MREMAP + /* If we have an mremap() call, resize the existing mapping. */ + else{ + pNew = osMremap( + pMap->pMapRegion, pMap->mmapOrigsize, nMap, MREMAP_MAYMOVE + ); + } +#else + /* Otherwise, create a second mapping. If the existing mapping is + ** a multiple of the page-size in size, then request that the new + ** mapping immediately follow the old in virtual memory. */ + else{ + i64 nNew; /* Bytes to map with this call */ + void *pAddr = 0; /* Virtual address to request mapping at */ + + nNew = nMap - pMap->mmapSize; + if( pMap->mmapSize==pMap->mmapOrigsize ){ + pAddr = (void *)&((u8 *)pMap->pMapRegion)[pMap->mmapSize]; + } + + pNew = osMmap(pAddr, nNew, flags, MAP_SHARED, pFd->h, pMap->mmapSize); + + if( pAddr && pNew==pAddr ){ + pNew = pMap->pMapRegion; + }else{ + iNew = 1; + nMap = nNew; + } + } +#endif + + if( pNew==MAP_FAILED ){ + return SQLITE_IOERR_MMAP; + } + pFd->aMmap[iNew].pMapRegion = pNew; + pFd->aMmap[iNew].mmapSize = nMap; + pFd->aMmap[iNew].mmapOrigsize = nMap; + } } return SQLITE_OK; } @@ -4596,17 +4698,26 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ unixFile *pFd = (unixFile *)fd; /* The underlying database file */ *pp = 0; if( pFd->mmapLimit>0 ){ - if( pFd->pMapRegion==0 ){ + int i; + sqlite3_int64 iMap = 0; + + if( pFd->aMmap[0].pMapRegion==0 ){ int rc = unixMapfile(pFd, -1); if( rc!=SQLITE_OK ) return rc; } - if( pFd->mmapSize >= iOff+nAmt ){ - *pp = &((u8 *)pFd->pMapRegion)[iOff]; - pFd->nFetchOut++; + + for(i=0; i<2; i++){ + unixMapping *pMap = &pFd->aMmap[i]; + if( iOff>=iMap && iOff+nAmt<=(iMap + pMap->mmapSize) ){ + *pp = &((u8 *)pMap->pMapRegion)[iOff-iMap]; + pFd->nFetchOut++; + break; + } + iMap = pMap->mmapSize; } } return SQLITE_OK; } @@ -4627,11 +4738,13 @@ ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), ** then there must be at least one outstanding. */ assert( (p==0)==(pFd->nFetchOut==0) ); /* If p!=0, it must match the iOff value. */ + #if 0 assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); + #endif if( p ){ pFd->nFetchOut--; }else{ unixUnmapfile(pFd); @@ -5589,10 +5702,11 @@ goto open_finished; } } #endif + p->szSyspage = unixGetPagesize(); rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); open_finished: if( rc!=SQLITE_OK ){ sqlite3_free(p->pUnused); Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -3358,14 +3358,12 @@ */ static void pagerFixMaplimit(Pager *pPager){ sqlite3_file *fd = pPager->fd; if( isOpen(fd) ){ pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->mxMmap>0; - if( pPager->bUseFetch ){ - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_LIMIT, + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_LIMIT, (void*)&pPager->mxMmap); - } } } /* ** Change the maximum size of any memory mapping made of the database file. @@ -3637,11 +3635,13 @@ int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ if( mxPage>0 ){ pPager->mxPgno = mxPage; } assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ + #if 0 assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ + #endif return pPager->mxPgno; } /* ** The following set of routines are used to disable the simulated Index: src/wal.c ================================================================== --- src/wal.c +++ src/wal.c @@ -1206,11 +1206,11 @@ ** problems caused by applications routinely shutting down without ** checkpointing the log file. */ if( pWal->hdr.nPage ){ sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s", - pWal->hdr.nPage, pWal->zWalName + pWal->hdr.mxFrame, pWal->zWalName ); } } recovery_error: Index: test/autovacuum.test ================================================================== --- test/autovacuum.test +++ test/autovacuum.test @@ -30,11 +30,11 @@ return [string range $str 0 [expr $len-1]] } # Return the number of pages in the file test.db by looking at the file system. proc file_pages {} { - return [expr [file size test.db] / 1024] + file_page_count test.db } #------------------------------------------------------------------------- # Test cases autovacuum-1.* work as follows: # @@ -612,11 +612,11 @@ INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 8 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 16 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 32 } - expr {[file size test.db] / 1024} + file_page_count test.db } {73} do_test autovacuum-7.2 { execsql { CREATE TABLE t2(a, b, PRIMARY KEY(a, b)); @@ -626,11 +626,11 @@ CREATE TABLE t4(a, b, PRIMARY KEY(a, b)); INSERT INTO t4 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 CREATE TABLE t5(a, b, PRIMARY KEY(a, b)); INSERT INTO t5 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 } - expr {[file size test.db] / 1024} + file_page_count test.db } {354} do_test autovacuum-7.3 { db close sqlite3 db test.db @@ -638,11 +638,11 @@ BEGIN; DELETE FROM t4; COMMIT; SELECT count(*) FROM t1; } - expr {[file size test.db] / 1024} + file_page_count test.db } {286} #------------------------------------------------------------------------ # Additional tests. # Index: test/backup.test ================================================================== --- test/backup.test +++ test/backup.test @@ -659,11 +659,11 @@ INSERT INTO t1 VALUES(5, randstr(1000,1000)); COMMIT; } } {} do_test backup-6.2 { - set nTotal [expr {[file size test.db]/1024}] + set nTotal [file_page_count test.db] sqlite3_backup B db2 main db main B step 1 } {SQLITE_OK} do_test backup-6.3 { B pagecount Index: test/backup4.test ================================================================== --- test/backup4.test +++ test/backup4.test @@ -61,11 +61,11 @@ # do_execsql_test 2.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } -do_test 2.2 { file size test.db } [expr $AUTOVACUUM ? 4096 : 3072] +do_test 2.2 { file_page_count test.db } [expr $AUTOVACUUM ? 4 : 3] do_test 2.3 { sqlite3 db1 test.db2 db1 backup test.db db1 close Index: test/corrupt2.test ================================================================== --- test/corrupt2.test +++ test/corrupt2.test @@ -332,11 +332,11 @@ INSERT INTO t1 VALUES(1, randomblob(2500)); INSERT INTO t1 VALUES(2, randomblob(2500)); INSERT INTO t1 VALUES(3, randomblob(2500)); DELETE FROM t1 WHERE a = 1; } -corrupt { - set nPage [expr [file size corrupt.db] / 1024] + set nPage [file_page_count corrupt.db] hexio_write corrupt.db [expr 1024 + ($nPage-3)*5] 010000000 } -test { do_test corrupt2-6.3 { catchsql " $::presql pragma incremental_vacuum = 1 " } {1 {database disk image is malformed}} Index: test/corrupt3.test ================================================================== --- test/corrupt3.test +++ test/corrupt3.test @@ -38,12 +38,12 @@ PRAGMA auto_vacuum=OFF; PRAGMA page_size=1024; CREATE TABLE t1(x); INSERT INTO t1 VALUES($bigstring); } - file size test.db -} [expr {1024*3}] + list [file_page_count test.db] [file_page_size test.db] +} {3 1024} # Verify that the file format is as we expect. The page size # should be 1024 bytes. The only record should have a single # overflow page. The overflow page is page 3. The pointer to # the overflow page is on the last 4 bytes of page 2. Index: test/corrupt6.test ================================================================== --- test/corrupt6.test +++ test/corrupt6.test @@ -39,12 +39,12 @@ PRAGMA page_size=1024; CREATE TABLE t1(x); INSERT INTO t1(x) VALUES('varint32-01234567890123456789012345678901234567890123456789'); INSERT INTO t1(x) VALUES('varint32-01234567890123456789012345678901234567890123456789'); } - file size test.db -} [expr {1024*2}] + file_page_count test.db +} {2} # Verify that the file format is as we expect. The page size # should be 1024 bytes. # do_test corrupt6-1.2 { Index: test/corrupt7.test ================================================================== --- test/corrupt7.test +++ test/corrupt7.test @@ -42,12 +42,12 @@ INSERT INTO t1(x) VALUES(2); INSERT INTO t1(x) SELECT x+2 FROM t1; INSERT INTO t1(x) SELECT x+4 FROM t1; INSERT INTO t1(x) SELECT x+8 FROM t1; } - file size test.db -} [expr {1024*2}] + file_page_count test.db +} {2} # Verify that the file format is as we expect. The page size # should be 1024 bytes. # do_test corrupt7-1.2 { Index: test/corruptC.test ================================================================== --- test/corruptC.test +++ test/corruptC.test @@ -268,11 +268,11 @@ sqlite3 db test.db set blob [string repeat abcdefghij 10000] execsql { INSERT INTO t1 VALUES (1, $blob) } sqlite3 db test.db - set filesize [file size test.db] + set filesize [expr [file_page_count test.db] * [file_page_size test.db]] hexio_write test.db [expr $filesize-2048] 00000001 catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)} } {1 {database disk image is malformed}} # At one point this particular corrupt database was causing a buffer Index: test/corruptF.test ================================================================== --- test/corruptF.test +++ test/corruptF.test @@ -54,11 +54,11 @@ do_test 1.1 { create_test_db } {} # Check the db is as we expect. 6 pages in total, with 3 and 4 on the free # list. Page 3 is the free list trunk and page 4 is a leaf. # -do_test 1.2 { file size test.db } [expr 6*1024] +do_test 1.2 { file_page_count test.db } 6 do_test 1.3 { hexio_read test.db 32 4 } 00000003 do_test 1.4 { hexio_read test.db [expr 2*1024] 12 } 000000000000000100000004 # Change the free-list entry to page 6 and reopen the db file. do_test 1.5 { @@ -107,11 +107,11 @@ } {} } } do_test 2.1 { create_test_db } {} -do_test 2.2 { file size test.db } [expr 6*1024] +do_test 2.2 { file_page_count test.db } 6 do_test 2.3 { hexio_read test.db 32 4 } 00000003 do_test 2.4 { hexio_read test.db [expr 2*1024] 12 } 000000000000000100000004 # Change the free-list entry to page 5 and reopen the db file. do_test 2.5 { Index: test/crash.test ================================================================== --- test/crash.test +++ test/crash.test @@ -328,11 +328,11 @@ INSERT INTO abc SELECT * FROM abc; INSERT INTO abc SELECT * FROM abc; } } {} do_test crash-5.2 { - expr [file size test.db] / 1024 + file_page_count test.db } [expr [string match [execsql {pragma auto_vacuum}] 1] ? 11 : 10] set sig [signature] do_test crash-5.3 { # The SQL below is used to expose a bug that existed in # sqlite3pager_movepage() during development of the auto-vacuum feature. It Index: test/createtab.test ================================================================== --- test/createtab.test +++ test/createtab.test @@ -50,12 +50,12 @@ ifcapable utf16 { set isUtf16 [expr {[execsql {PRAGMA encoding}] != "UTF-8"}] } do_test createtab-$av.2 { - file size test.db - } [expr {1024*(4+($av!=0)+(${isUtf16}*2))}] + file_page_count test.db + } [expr {4+($av!=0)+(${isUtf16}*2)}] # Start reading the table # do_test createtab-$av.3 { set STMT [sqlite3_prepare db {SELECT x FROM t1} -1 TAIL] Index: test/dbstatus2.test ================================================================== --- test/dbstatus2.test +++ test/dbstatus2.test @@ -18,10 +18,11 @@ set ::testprefix dbstatus2 do_execsql_test 1.0 { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; + PRAGMA mmap_limit = 0; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, randomblob(600)); INSERT INTO t1 VALUES(2, randomblob(600)); INSERT INTO t1 VALUES(3, randomblob(600)); Index: test/e_vacuum.test ================================================================== --- test/e_vacuum.test +++ test/e_vacuum.test @@ -40,11 +40,11 @@ CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); INSERT INTO t2 SELECT * FROM t1; } } - return [expr {[file size test.db] / 1024}] + return [file_page_count test.db] } # This proc returns the number of contiguous blocks of pages that make up # the table or index named by the only argument. For example, if the table # occupies database pages 3, 4, 8 and 9, then this command returns 2 (there Index: test/filefmt.test ================================================================== --- test/filefmt.test +++ test/filefmt.test @@ -63,10 +63,11 @@ && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue do_test filefmt-1.5.$pagesize.1 { db close forcedelete test.db sqlite3 db test.db + db eval "PRAGMA mmap_limit=0" db eval "PRAGMA auto_vacuum=OFF" db eval "PRAGMA page_size=$pagesize" db eval {CREATE TABLE t1(x)} file size test.db } [expr $pagesize*2] @@ -213,10 +214,11 @@ PRAGMA integrity_check; } {ok} reset_db do_execsql_test filefmt-4.1 { + PRAGMA mmap_limit = 0; PRAGMA auto_vacuum = 1; CREATE TABLE t1(x, y); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); Index: test/format4.test ================================================================== --- test/format4.test +++ test/format4.test @@ -44,22 +44,22 @@ INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; } - file size test.db + expr {1024 * [file_page_count test.db]} } $small do_test format4-1.2 { execsql { UPDATE t1 SET x0=1, x1=1, x2=1, x3=1, x4=1, x5=1, x6=1, x7=1, x8=1, x9=1 } - file size test.db + expr {1024 * [file_page_count test.db]} } $small do_test format4-1.3 { execsql { UPDATE t1 SET x0=2, x1=2, x2=2, x3=2, x4=2, x5=2, x6=2, x7=2, x8=2, x9=2 } - file size test.db + expr {1024 * [file_page_count test.db]} } $large finish_test Index: test/incrblob.test ================================================================== --- test/incrblob.test +++ test/incrblob.test @@ -617,11 +617,11 @@ set ::b [db incrblob -readonly t2 b 456] fconfigure $::b -translation binary read $::b } $::otherdata do_test incrblob-7.3.2 { - expr [file size test.db]/1024 + file_page_count test.db } 30 do_test incrblob-7.3.3 { execsql { DELETE FROM t1 WHERE a = 123; PRAGMA INCREMENTAL_VACUUM(0); Index: test/incrvacuum.test ================================================================== --- test/incrvacuum.test +++ test/incrvacuum.test @@ -147,25 +147,25 @@ # 2 -> first back-pointer page # 3 -> table abc # 4 -> table tbl2 # 5 -> table tbl2 overflow page. # - expr {[file size test.db] / 1024} + file_page_count test.db } {5} do_test incrvacuum-3.3 { execsql { DROP TABLE abc; DELETE FROM tbl2; } - expr {[file size test.db] / 1024} + file_page_count test.db } {5} do_test incrvacuum-3.4 { execsql { PRAGMA auto_vacuum = 1; INSERT INTO tbl2 VALUES('hello world'); } - expr {[file size test.db] / 1024} + file_page_count test.db } {3} #--------------------------------------------------------------------- # Try to run a very simple incremental vacuum. Also verify that # PRAGMA incremental_vacuum is a harmless no-op against a database that @@ -176,18 +176,18 @@ execsql { PRAGMA auto_vacuum = 2; INSERT INTO tbl2 VALUES($::str); CREATE TABLE tbl1(a, b, c); } - expr {[file size test.db] / 1024} + file_page_count test.db } {5} do_test incrvacuum-4.2 { execsql { DELETE FROM tbl2; DROP TABLE tbl1; } - expr {[file size test.db] / 1024} + file_page_count test.db } {5} do_test incrvacuum-4.3 { set ::nStep 0 db eval {pragma incremental_vacuum(10)} { incr ::nStep @@ -219,11 +219,11 @@ CREATE TABLE tbl1(a); INSERT INTO tbl1 VALUES($::str); PRAGMA incremental_vacuum; -- this is a no-op. COMMIT; } - expr {[file size test.db] / 1024} + file_page_count test.db } {4} do_test incrvacuum-5.2.2 { set ::str [string repeat abcdefghij 110] execsql { BEGIN; @@ -230,21 +230,21 @@ INSERT INTO tbl1 VALUES($::str); INSERT INTO tbl1 SELECT * FROM tbl1; DELETE FROM tbl1 WHERE oid%2; -- Put 2 overflow pages on free-list. COMMIT; } - expr {[file size test.db] / 1024} + file_page_count test.db } {7} do_test incrvacuum-5.2.3 { execsql { BEGIN; PRAGMA incremental_vacuum; -- Vacuum up the two pages. CREATE TABLE tbl2(b); -- Use one free page as a table root. INSERT INTO tbl2 VALUES('a nice string'); COMMIT; } - expr {[file size test.db] / 1024} + file_page_count test.db } {6} do_test incrvacuum-5.2.4 { execsql { SELECT * FROM tbl2; } @@ -253,11 +253,11 @@ execsql { DROP TABLE tbl1; DROP TABLE tbl2; PRAGMA incremental_vacuum; } - expr {[file size test.db] / 1024} + file_page_count test.db } {1} # Test cases incrvacuum-5.3.* use the following list as input data. # Two new databases are opened, one with incremental vacuum enabled, @@ -525,11 +525,11 @@ do_test incrvacuum-10.1 { execsql { DROP TABLE t1; DROP TABLE t2; } - expr [file size test.db] / 1024 + file_page_count test.db } {29} do_test incrvacuum-10.2 { execsql { PRAGMA incremental_vacuum(1); Index: test/io.test ================================================================== --- test/io.test +++ test/io.test @@ -416,12 +416,12 @@ list [expr [file size test.db]>20000] [nSync] } {1 0} do_test io-3.3 { # The COMMIT requires a single fsync() - to the database file. execsql { COMMIT } - list [file size test.db] [nSync] - } {39936 1} + list [file_page_count test.db] [nSync] + } {39 1} } #---------------------------------------------------------------------- # Test cases io-4.* test the IOCAP_SAFE_APPEND optimization. # @@ -486,11 +486,11 @@ INSERT INTO abc SELECT * FROM abc; INSERT INTO abc SELECT * FROM abc; INSERT INTO abc SELECT * FROM abc; INSERT INTO abc SELECT * FROM abc; } - expr {[file size test.db]/1024} + file_page_count test.db } {43} ifcapable pager_pragmas { do_test io-4.3.2 { execsql { PRAGMA synchronous = full; @@ -560,10 +560,12 @@ do_test io-5.$tn { execsql { CREATE TABLE abc(a, b, c); } expr {[file size test.db]/2} - } $pgsize + + list [file_page_count test.db] [file_page_size test.db] + } [list 2 $pgsize] } sqlite3_simulate_device -char {} -sectorsize 0 finish_test Index: test/jrnlmode.test ================================================================== --- test/jrnlmode.test +++ test/jrnlmode.test @@ -519,11 +519,13 @@ PRAGMA page_size = 1024; PRAGMA user_version = 5; PRAGMA user_version; } } {memory 5} - do_test jrnlmode-7.2 { file size test.db } {1024} + do_test jrnlmode-7.2 { + list [file_page_count test.db] [file_page_size test.db] + } {1 1024} } do_execsql_test jrnlmode-8.1 { PRAGMA locking_mode=EXCLUSIVE } {exclusive} do_execsql_test jrnlmode-8.2 { CREATE TABLE t1(x) } {} do_execsql_test jrnlmode-8.3 { INSERT INTO t1 VALUES(123) } {} Index: test/lock4.test ================================================================== --- test/lock4.test +++ test/lock4.test @@ -31,12 +31,12 @@ db2 eval { PRAGMA auto_vacuum=OFF; CREATE TABLE t2(x) } db2 close - list [file size test.db] [file size test2.db] -} {2048 2048} + list [file_page_count test.db] [file_page_count test2.db] +} {2 2} # Create a script to drive a separate process that will # # 1. Create a second database test2.db # 2. Get an exclusive lock on test2.db Index: test/mallocH.test ================================================================== --- test/mallocH.test +++ test/mallocH.test @@ -60,10 +60,11 @@ } # Malloc failure during integrity_check pragma. # do_malloc_test mallocH-5 -sqlprep { + PRAGMA mmap_limit = 0; CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); CREATE TABLE t2(x,y); INSERT INTO t1 VALUES(1,2); INSERT INTO t2 SELECT * FROM t1; } -sqlbody { Index: test/pager1.test ================================================================== --- test/pager1.test +++ test/pager1.test @@ -1107,10 +1107,11 @@ # The following tests work with "PRAGMA max_page_count" # do_test pager1-6.1 { faultsim_delete_and_reopen execsql { + PRAGMA page_size = 4096; PRAGMA auto_vacuum = none; PRAGMA max_page_count = 10; CREATE TABLE t2(a, b); CREATE TABLE t3(a, b); CREATE TABLE t4(a, b); @@ -1355,12 +1356,12 @@ } {SQLITE_DONE SQLITE_OK} do_test pager1-9.3.3 { db2 close db close tv delete - file size test.db2 -} [file size test.db] + file_page_count test.db2 +} [file_page_count test.db] do_test pager1-9.4.1 { faultsim_delete_and_reopen sqlite3 db2 test.db2 execsql { @@ -1469,12 +1470,12 @@ do_test pager1.10.x.2 { execsql { CREATE TABLE t2(x); DROP TABLE t2; } - file size test.db -} {33792} + list [file_page_count test.db] [file_page_size test.db] +} {33 1024} do_test pager1.10.x.3 { execsql { BEGIN; CREATE TABLE t2(x); } @@ -1550,11 +1551,11 @@ sqlite3 db2 test.db execsql " PRAGMA page_size = $pagesize; CREATE VIEW v AS SELECT * FROM sqlite_master; " db2 - file size test.db + file_page_size test.db } $eff do_test pager1-12.$pagesize.2 { sqlite3 db2 test.db execsql { SELECT count(*) FROM v; @@ -2386,19 +2387,19 @@ PRAGMA auto_vacuum = full; PRAGMA locking_mode=exclusive; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } - file size test.db -} [expr 1024*3] + list [file_page_count test.db] [file_page_size test.db] +} {3 1024} do_test pager1-29.2 { execsql { PRAGMA page_size = 4096; VACUUM; } - file size test.db -} [expr 4096*3] + list [file_page_count test.db] [file_page_size test.db] +} {3 4096} #------------------------------------------------------------------------- # Test that if an empty database file (size 0 bytes) is opened in # exclusive-locking mode, any journal file is deleted from the file-system # without being rolled back. And that the RESERVED lock obtained while Index: test/pagerfault.test ================================================================== --- test/pagerfault.test +++ test/pagerfault.test @@ -1199,16 +1199,17 @@ faultsim_test_result {0 {}} set contents [db eval {SELECT * FROM t1}] if {$contents != "1 2"} { error "Bad database contents ($contents)" } - set sz [file size test.db] - if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} { - error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes" + set nPg [file_page_count test.db] + set pgsz [file_page_size test.db] + if {$testrc!=0 && ($nPg!=3 || ($pgsz!=1024 && $pgsz!=4096))} { + error "File should be 3 pages. Page size 1024 or 4096 bytes. Is $nPg/$pgsz." } - if {$testrc==0 && $sz!=4096*3} { - error "Expected file size to be 12288 bytes - actual size $sz bytes" + if {$testrc==0 && ($nPg!=3 || $pgsz!=4096)} { + error "File should be 3 pages. Page size 4096 bytes. Is $nPg/$pgsz." } } do_test pagerfault-27-pre { faultsim_delete_and_reopen Index: test/pagesize.test ================================================================== --- test/pagesize.test +++ test/pagesize.test @@ -113,12 +113,12 @@ execsql { PRAGMA page_size } } $PGSZ do_test pagesize-2.$PGSZ.3 { - file size test.db - } [expr {$PGSZ*($AUTOVACUUM?3:2)}] + list [file_page_count test.db] [file_page_size test.db] + } [list [expr ($AUTOVACUUM?3:2)] $PGSZ] ifcapable {vacuum} { do_test pagesize-2.$PGSZ.4 { execsql {VACUUM} } {} } Index: test/permutations.test ================================================================== --- test/permutations.test +++ test/permutations.test @@ -166,11 +166,11 @@ test_suite "full" -prefix "" -description { Full test suite. Takes a long time. } -files [ test_set $alltests ] -initialize { - unset -nocomplain ::G(isquick) + # unset -nocomplain ::G(isquick) } test_suite "threads" -prefix "" -description { All multi-threaded tests. } -files { Index: test/pragma.test ================================================================== --- test/pragma.test +++ test/pragma.test @@ -260,10 +260,11 @@ do_test pragma-3.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { + PRAGMA mmap_limit=0; PRAGMA auto_vacuum=OFF; BEGIN; CREATE TABLE t2(a,b,c); CREATE INDEX i2 ON t2(a); INSERT INTO t2 VALUES(11,2,3); @@ -282,10 +283,11 @@ # set offset [expr {$pgsz*($rootpage-1)}] hexio_write test.db $offset 0a00000000040000000000 db close sqlite3 db test.db + execsql {PRAGMA mmap_limit=0} execsql {PRAGMA integrity_check} } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} do_test pragma-3.3 { execsql {PRAGMA integrity_check=1} } {{rowid 1 missing from index i2}} @@ -1249,12 +1251,12 @@ execsql {pragma PAGE_COUNT} } {3} do_test pragma-14.4 { set page_size [db one {pragma page_size}] - expr [file size test.db] / $page_size - } {2} + list [file_page_count test.db] $page_size + } [list 2 [file_page_size test.db]] do_test pragma-14.5 { execsql { ROLLBACK; PRAGMA page_count; Index: test/pragma2.test ================================================================== --- test/pragma2.test +++ test/pragma2.test @@ -84,12 +84,12 @@ INSERT INTO aux.abc VALUES(1, 2, $::val); PRAGMA aux.freelist_count; } } {0} do_test pragma2-2.4 { - expr {[file size test2.db] / 1024} - } {11} + list [file_page_count test2.db] [file_page_size test2.db] + } {11 1024} do_test pragma2-2.5 { execsql { DELETE FROM aux.abc; PRAGMA aux.freelist_count; } Index: test/quota.test ================================================================== --- test/quota.test +++ test/quota.test @@ -69,10 +69,11 @@ sqlite3_quota_set *test.db 4096 quota_check } {SQLITE_OK} do_test quota-2.1.2 { sqlite3 db test.db execsql { + PRAGMA mmap_limit=0; PRAGMA page_size=1024; PRAGMA auto_vacuum=OFF; PRAGMA journal_mode=DELETE; } set ::quota [list] @@ -141,10 +142,11 @@ sqlite3_quota_set *test.db 4096 quota_check } {SQLITE_OK} do_test quota-3.1.2 { sqlite3 db test.db execsql { + PRAGMA mmap_limit = 0; PRAGMA page_size = 1024; PRAGMA journal_mode = delete; PRAGMA auto_vacuum = off; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); @@ -152,10 +154,11 @@ file size test.db } {3072} do_test quota-3.1.3 { sqlite3 db2 test.db set ::quota [list] + execsql { PRAGMA mmap_limit=0 } db2 execsql { CREATE TABLE t2(a, b) } db2 set ::quota } {} do_test quota-3.1.4 { catchsql { CREATE TABLE t3(a, b) } @@ -177,10 +180,11 @@ sqlite3 db1a test.db sqlite3 db2a test2.db foreach db {db1a db2a} { execsql { + PRAGMA mmap_limit=0; PRAGMA page_size = 1024; PRAGMA journal_mode = delete; PRAGMA auto_vacuum = off; CREATE TABLE t1(a, b); } $db Index: test/sqllimits1.test ================================================================== --- test/sqllimits1.test +++ test/sqllimits1.test @@ -532,11 +532,11 @@ INSERT INTO abc SELECT a||b||c, b||c||a, c||a||b FROM abc; INSERT INTO abc SELECT a, b, c FROM abc; INSERT INTO abc SELECT b, a, c FROM abc; INSERT INTO abc SELECT c, b, a FROM abc; } - expr [file size test.db] / 1024 + file_page_count test.db } $fsize do_test sqllimits1-7.7.2 { db close sqlite3 db test.db execsql { @@ -548,11 +548,11 @@ } {6} do_test sqllimits1-7.7.3 { execsql { PRAGMA max_page_count; } -} $fsize +} [expr [file size test.db] / 1024] do_test sqllimits1-7.7.4 { execsql { DROP TABLE abc; } } {} Index: test/tester.tcl ================================================================== --- test/tester.tcl +++ test/tester.tcl @@ -1634,10 +1634,11 @@ # proc sql36231 {sql} { set B [hexio_read test.db 92 8] set A [hexio_read test.db 28 4] sqlite3 db36231 test.db + db36231 eval { PRAGMA mmap_limit = 0 } catch { db36231 func a_string a_string } execsql $sql db36231 db36231 close hexio_write test.db 28 $A hexio_write test.db 92 $B @@ -1671,10 +1672,39 @@ proc db_delete_and_reopen {{file test.db}} { catch { db close } foreach f [glob -nocomplain test.db*] { forcedelete $f } sqlite3 db $file } + +# Return the number of pages in the database file $zFile, according to +# the database header. +# +proc file_page_count {zFile} { + set nPg [hexio_get_int [hexio_read $zFile 28 4]] + set pgsz [file_page_size $zFile] + set filesz [file size $zFile] + set syspgsz 4096 + + # Check that the file size is consistent with the database page size, + # the page count, and the system page size. + if {($filesz < ($nPg * $pgsz)) + || ($filesz > (((($nPg * $pgsz)+$syspgsz-1) / $syspgsz) * $syspgsz)) + } { + error "file_size=$filesz. page_count=$nPg. page_size=$pgsz." + } + + return $nPg +} + +# Return the page size of database file $zFile, according to the database +# header. +# +proc file_page_size {zFile} { + set pgsz [hexio_get_int [hexio_read $zFile 16 2]] + if {$pgsz==1} {set pgsz 65536} + return $pgsz +} # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) Index: test/tkt1512.test ================================================================== --- test/tkt1512.test +++ test/tkt1512.test @@ -33,22 +33,22 @@ INSERT INTO t1 VALUES(3,4); SELECT * FROM t1 } } {1 2 3 4} do_test tkt1512-1.2 { - file size test.db -} {2048} + file_page_count test.db +} {2} do_test tkt1512-1.3 { execsql { DROP TABLE t1; } - file size test.db -} {2048} + file_page_count test.db +} {2} do_test tkt1512-1.4 { execsql { VACUUM; } - file size test.db -} {1024} + file_page_count test.db +} {1} finish_test Index: test/tkt2920.test ================================================================== --- test/tkt2920.test +++ test/tkt2920.test @@ -24,12 +24,12 @@ PRAGMA page_size=1024; PRAGMA max_page_count=40; PRAGMA auto_vacuum=0; CREATE TABLE filler (fill); } - file size test.db -} {2048} + list [file_page_count test.db] [file_page_size test.db] +} {2 1024} do_test tkt2920-1.2 { db eval BEGIN for {set i 0} {$i<34} {incr i} { db eval {INSERT INTO filler VALUES(randomblob(1024))} } Index: test/vacuum3.test ================================================================== --- test/vacuum3.test +++ test/vacuum3.test @@ -40,12 +40,12 @@ } {} do_test vacuum3-1.2 { execsql { PRAGMA page_size } } {1024} do_test vacuum3-1.3 { - file size test.db -} {2048} + file_page_count test.db +} {2} set I 4 foreach {request actual database} [list \ 2048 2048 4096 \ 1024 1024 2048 \ @@ -61,11 +61,12 @@ VACUUM; " execsql { PRAGMA page_size } } $actual do_test vacuum3-1.$I.2 { - file size test.db + set nPg [file_page_count test.db] + expr {$nPg * $actual} } $database do_test vacuum3-1.$I.3 { execsql { SELECT * FROM t1 } } {1 2 3} integrity_check vacuum3-1.$I.4 @@ -82,12 +83,12 @@ PRAGMA page_size = 1024; VACUUM; ALTER TABLE t1 ADD COLUMN d; UPDATE t1 SET d = randomblob(1000); } - file size test.db -} {3072} + file_page_count test.db +} {3} do_test vacuum3-2.2 { execsql { PRAGMA page_size } } {1024} do_test vacuum3-2.3 { set blob [db one {select d from t1}] Index: test/wal.test ================================================================== --- test/wal.test +++ test/wal.test @@ -65,22 +65,22 @@ execsql { PRAGMA auto_vacuum = 0 } execsql { PRAGMA synchronous = normal } execsql { PRAGMA journal_mode = wal } } {wal} do_test wal-0.2 { - file size test.db -} {1024} + file_page_count test.db +} {1} do_test wal-1.0 { execsql { BEGIN; CREATE TABLE t1(a, b); } list [file exists test.db-journal] \ [file exists test.db-wal] \ - [file size test.db] -} {0 1 1024} + [file_page_count test.db] +} {0 1 1} do_test wal-1.1 { execsql COMMIT list [file exists test.db-journal] [file exists test.db-wal] } {0 1} do_test wal-1.2 { @@ -345,12 +345,12 @@ execsql " CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); " db close - file size test.db - } [expr $pgsz*2] + list [file_page_count test.db] [file_page_size test.db] + } [list 2 $pgsz] do_test wal-6.$sector.$pgsz.2 { log_deleted test.db-wal } {1} } @@ -362,16 +362,20 @@ execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } - list [file size test.db] [file size test.db-wal] -} [list 1024 [wal_file_size 3 1024]] + list [file_page_count test.db] \ + [file_page_size test.db] \ + [file size test.db-wal] +} [list 1 1024 [wal_file_size 3 1024]] do_test wal-7.2 { execsql { PRAGMA wal_checkpoint } - list [file size test.db] [file size test.db-wal] -} [list 2048 [wal_file_size 3 1024]] + list [file_page_count test.db] \ + [file_page_size test.db] \ + [file size test.db-wal] +} [list 2 1024 [wal_file_size 3 1024]] # Execute some transactions in auto-vacuum mode to test database file # truncation. # do_test wal-8.1 { @@ -426,12 +430,12 @@ INSERT INTO t1 SELECT blob(900) FROM t1; /* 32 */ INSERT INTO t1 SELECT blob(900) FROM t1; /* 64 */ INSERT INTO t1 SELECT blob(900) FROM t1; /* 128 */ INSERT INTO t1 SELECT blob(900) FROM t1; /* 256 */ } - file size test.db -} 1024 + file_page_count test.db +} 1 do_test wal-9.2 { sqlite3_wal db2 test.db execsql {PRAGMA integrity_check } db2 } {ok} @@ -679,19 +683,19 @@ execsql { PRAGMA cache_size = 10; PRAGMA page_size = 1024; CREATE TABLE t1(x PRIMARY KEY); } - list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] + list [file_page_count test.db] [expr [file size test.db-wal]/1044] } {1 3} do_test wal-11.2 { execsql { PRAGMA wal_checkpoint } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 3 [wal_file_size 3 1024]] do_test wal-11.3 { execsql { INSERT INTO t1 VALUES( blob(900) ) } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 3 [wal_file_size 4 1024]] do_test wal-11.4 { execsql { BEGIN; @@ -698,35 +702,35 @@ INSERT INTO t1 SELECT blob(900) FROM t1; -- 2 INSERT INTO t1 SELECT blob(900) FROM t1; -- 4 INSERT INTO t1 SELECT blob(900) FROM t1; -- 8 INSERT INTO t1 SELECT blob(900) FROM t1; -- 16 } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 3 [wal_file_size 32 1024]] do_test wal-11.5 { execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {16 ok} do_test wal-11.6 { execsql COMMIT - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 3 [wal_file_size 41 1024]] do_test wal-11.7 { execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {16 ok} do_test wal-11.8 { execsql { PRAGMA wal_checkpoint } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 37 [wal_file_size 41 1024]] do_test wal-11.9 { db close - list [expr [file size test.db]/1024] [log_deleted test.db-wal] + list [file_page_count test.db] [log_deleted test.db-wal] } {37 1} sqlite3_wal db test.db set nWal 39 if {[permutation]=="nommap"} {set nWal 37} do_test wal-11.10 { @@ -734,31 +738,31 @@ PRAGMA cache_size = 10; BEGIN; INSERT INTO t1 SELECT blob(900) FROM t1; -- 32 SELECT count(*) FROM t1; } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 37 [wal_file_size $nWal 1024]] do_test wal-11.11 { execsql { SELECT count(*) FROM t1; ROLLBACK; SELECT count(*) FROM t1; } } {32 16} do_test wal-11.12 { - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 37 [wal_file_size $nWal 1024]] do_test wal-11.13 { execsql { INSERT INTO t1 VALUES( blob(900) ); SELECT count(*) FROM t1; PRAGMA integrity_check; } } {17 ok} do_test wal-11.14 { - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 37 [wal_file_size $nWal 1024]] #------------------------------------------------------------------------- # This block of tests, wal-12.*, tests the fix for a problem that @@ -771,24 +775,24 @@ PRAGMA page_size = 1024; CREATE TABLE t1(x, y); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES('A', 1); } - list [expr [file size test.db]/1024] [file size test.db-wal] + list [file_page_count test.db] [file size test.db-wal] } [list 1 [wal_file_size 5 1024]] do_test wal-12.2 { db close sqlite3 db test.db execsql { PRAGMA synchronous = normal; UPDATE t1 SET y = 0 WHERE x = 'A'; } - list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] + list [file_page_count test.db] [expr [file size test.db-wal]/1044] } {3 1} do_test wal-12.3 { execsql { INSERT INTO t2 VALUES('B', 1) } - list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] + list [file_page_count test.db] [expr [file size test.db-wal]/1044] } {3 2} do_test wal-12.4 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3_wal db2 test2.db @@ -849,11 +853,10 @@ puts $fd "" close $fd sqlite3 db test.db execsql { SELECT * FROM t2 } } {B 2} -breakpoint do_test wal-13.1.3 { db close file exists test.db-wal } {0} @@ -1020,12 +1023,12 @@ } {SQLITE_OK} do_test wal-15.4.5 { sqlite3_errmsg db } {not an error} do_test wal-15.4.6 { - file size test.db -} [expr 1024*2] + list [file_page_count test.db] [file_page_size test.db] +} {2 1024} catch { db2 close } catch { db close } #------------------------------------------------------------------------- @@ -1069,25 +1072,25 @@ INSERT INTO t2 VALUES(1, randomblob(1000)); INSERT INTO t2 VALUES(2, randomblob(1000)); INSERT INTO t1 SELECT * FROM t2; } - list [file size test.db] [file size test.db-wal] - } [list [expr 1*1024] [wal_file_size 10 1024]] + list [file_page_count test.db] [file size test.db-wal] + } [list 1 [wal_file_size 10 1024]] do_test wal-16.$tn.3 { - list [file size test2.db] [file size test2.db-wal] - } [list [expr 1*1024] [wal_file_size 13 1024]] + list [file_page_count test2.db] [file size test2.db-wal] + } [list 1 [wal_file_size 13 1024]] do_test wal-16.$tn.4 [list eval $ckpt_cmd] $ckpt_res do_test wal-16.$tn.5 { - list [file size test.db] [file size test.db-wal] - } [list [expr ($ckpt_main ? 7 : 1)*1024] [wal_file_size 10 1024]] + list [file_page_count test.db] [file size test.db-wal] + } [list [expr ($ckpt_main ? 7 : 1)] [wal_file_size 10 1024]] do_test wal-16.$tn.6 { - list [file size test2.db] [file size test2.db-wal] - } [list [expr ($ckpt_aux ? 7 : 1)*1024] [wal_file_size 13 1024]] + list [file_page_count test2.db] [file size test2.db-wal] + } [list [expr ($ckpt_aux ? 7 : 1)] [wal_file_size 13 1024]] catch { db close } } #------------------------------------------------------------------------- @@ -1143,17 +1146,17 @@ file size test.db-wal } $logsize do_test wal-17.$tn.2 { - file size test.db - } 512 + file_page_count test.db + } 1 do_test wal-17.$tn.3 { db close - file size test.db - } [expr 512*171] + file_page_count test.db + } 171 } sqlite3_test_control_pending_byte $old_pending_byte #------------------------------------------------------------------------- # This test - wal-18.* - verifies a couple of specific conditions that @@ -1184,12 +1187,12 @@ } forcecopy test.db testX.db forcecopy test.db-wal testX.db-wal db close - list [file size testX.db] [file size testX.db-wal] -} [list [expr 3*1024] [wal_file_size 6 1024]] + list [file_page_count testX.db] [file size testX.db-wal] +} [list 3 [wal_file_size 6 1024]] unset -nocomplain nFrame result foreach {nFrame result} { 0 {0 0} 1 {0 0} @@ -1265,11 +1268,11 @@ # Check that the database now exists and consists of three pages. And # that there is no associated wal file. # do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0 do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1 - do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3] + do_test wal-18.2.$tn.$pg.3 { file_page_count test.db } 3 do_test wal-18.2.$tn.$pg.4 { # Create a wal file that contains a single frame (database page # number $pg) with the commit flag set. The frame checksum is @@ -1507,12 +1510,12 @@ do_test wal-23.3 { db close set ::log [list] faultsim_restore_and_reopen - execsql { SELECT * FROM t1 } -} {1 2 3 4} + execsql { SELECT * FROM t1 ; PRAGMA page_size } +} {1 2 3 4 1024} set nPage [expr 2+$AUTOVACUUM] do_test wal-23.4 { set ::log } [list SQLITE_OK "Recovered $nPage frames from WAL file $walfile"] Index: test/wal5.test ================================================================== --- test/wal5.test +++ test/wal5.test @@ -19,11 +19,11 @@ source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } set testprefix wal5 -proc db_page_count {{file test.db}} { expr [file size $file] / 1024 } +proc db_page_count {{file test.db}} { file_page_count $file } proc wal_page_count {{file test.db}} { wal_frame_count ${file}-wal 1024 } # A checkpoint may be requested either using the C API or by executing # an SQL PRAGMA command. To test both methods, all tests in this file are @@ -99,12 +99,12 @@ PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(1, zeroblob(1200)); INSERT INTO t1 VALUES(2, zeroblob(1200)); INSERT INTO t1 VALUES(3, zeroblob(1200)); } - expr [file size test.db] / 1024 - } {2} + list [file_page_count test.db] [file_page_size test.db] + } {2 1024} # Have connection 2 grab a read-lock on the current snapshot. do_test 1.$tn.2 { sql2 { BEGIN; SELECT x FROM t1 } } {1 2 3} # Attempt a checkpoint. Index: test/wal9.test ================================================================== --- test/wal9.test +++ test/wal9.test @@ -61,11 +61,11 @@ # Check file sizes are as expected. The real requirement here is that # the *shm file is now more than one chunk (>32KiB). # # The sizes of various files are slightly different in normal and # auto-vacuum mode. -do_test 1.3 { file size test.db } {1024} +do_test 1.3 { file_page_count test.db } {1} do_test 1.4 { expr {[file size test.db-wal]>(1500*1024)} } {1} do_test 1.5 { expr {[file size test.db-shm]>32768} } {1} do_test 1.6 { foreach {a b c} [db eval {PRAGMA wal_checkpoint}] break list [expr {$a==0}] [expr {$b>14500}] [expr {$c>14500}] [expr {$b==$c}] Index: test/walbak.test ================================================================== --- test/walbak.test +++ test/walbak.test @@ -48,12 +48,12 @@ } } {wal} do_test walbak-1.1 { forcedelete bak.db bak.db-journal bak.db-wal db backup bak.db - file size bak.db -} [expr 3*1024] + file_page_count bak.db +} 3 do_test walbak-1.2 { sqlite3 db2 bak.db execsql { SELECT * FROM t1; PRAGMA main.journal_mode; @@ -71,12 +71,12 @@ VACUUM; PRAGMA main.journal_mode; } } {wal} do_test walbak-1.5 { - list [file size test.db] [file size test.db-wal] -} [list 1024 [wal_file_size 6 1024]] + list [file_page_count test.db] [file size test.db-wal] +} [list 1 [wal_file_size 6 1024]] do_test walbak-1.6 { execsql { PRAGMA wal_checkpoint } list [file size test.db] [file size test.db-wal] } [list [expr 3*1024] [wal_file_size 6 1024]] do_test walbak-1.6.1 { Index: test/walcksum.test ================================================================== --- test/walcksum.test +++ test/walcksum.test @@ -174,12 +174,12 @@ forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal db close - list [file size test2.db] [file size test2.db-wal] - } [list [expr 1024*3] [wal_file_size 6 1024]] + list [file_page_count test2.db] [file size test2.db-wal] + } [list 3 [wal_file_size 6 1024]] # Verify that the checksums are valid for all frames and that they # are calculated by interpreting data in native byte-order. # for {set f 1} {$f <= 6} {incr f} { @@ -211,12 +211,12 @@ do_test walcksum-1.$endian.5.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(34, 'thirtyfour'); } - list [file size test.db] [file size test.db-wal] - } [list [expr 1024*3] [wal_file_size 8 1024]] + list [file_page_count test.db] [file size test.db-wal] + } [list 3 [wal_file_size 8 1024]] for {set f 1} {$f <= 8} {incr f} { do_test walcksum-1.$endian.5.$f { log_checksum_verify test.db-wal $f $endian } {1} } @@ -235,12 +235,12 @@ do_test walcksum-1.$endian.7.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(55, 'fiftyfive'); } db2 - list [file size test.db] [file size test.db-wal] - } [list [expr 1024*3] [wal_file_size 10 1024]] + list [file_page_count test.db] [file size test.db-wal] + } [list 3 [wal_file_size 10 1024]] for {set f 1} {$f <= 10} {incr f} { do_test walcksum-1.$endian.7.$f { log_checksum_verify test.db-wal $f $endian } {1} } Index: test/walhook.test ================================================================== --- test/walhook.test +++ test/walhook.test @@ -47,12 +47,12 @@ set ::wal_hook } {main 5} do_test walhook-1.3 { proc wal_hook {args} { db eval {PRAGMA wal_checkpoint}; return 0 } execsql { INSERT INTO t1 VALUES(2, 'two') } - file size test.db -} [expr 3*1024] + file_page_count test.db +} 3 do_test walhook-1.4 { proc wal_hook {zDb nEntry} { execsql { PRAGMA wal_checkpoint } return 0 } Index: test/walmode.test ================================================================== --- test/walmode.test +++ test/walmode.test @@ -40,12 +40,12 @@ set sqlite_sync_count 0 execsql { PRAGMA page_size = 1024 } execsql { PRAGMA journal_mode = wal } } {wal} do_test walmode-1.2 { - file size test.db -} {1024} + file_page_count test.db +} {1} set expected_sync_count 3 if {$::tcl_platform(platform)!="windows"} { ifcapable dirsync { incr expected_sync_count @@ -58,12 +58,12 @@ do_test walmode-1.4 { file exists test.db-wal } {0} do_test walmode-1.5 { execsql { CREATE TABLE t1(a, b) } - file size test.db -} {1024} + file_page_count test.db +} {1} do_test walmode-1.6 { file exists test.db-wal } {1} do_test walmode-1.7 { db close