1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-01 06:27:03 +03:00

Use mmap() to read from the database file in rollback mode. This branch is unix only for now.

FossilOrigin-Name: 6f21d9cbf5d457e63a7282015a89ae785526cf6d
This commit is contained in:
dan
2013-03-14 18:34:37 +00:00
parent 27e6df4e41
commit b2d3de3bf4
8 changed files with 182 additions and 15 deletions

View File

@ -1,5 +1,5 @@
C Enhance\stests\sfor\sticket\s[4dd95f6943]. C Use\smmap()\sto\sread\sfrom\sthe\sdatabase\sfile\sin\srollback\smode.\sThis\sbranch\sis\sunix\sonly\sfor\snow.
D 2013-03-13T07:02:04.083 D 2013-03-14T18:34:37.796
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5 F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -121,7 +121,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c b2cac9f7993f3f9588827b824b1501d0c820fa68 F src/backup.c b2cac9f7993f3f9588827b824b1501d0c820fa68
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 746c4dafae8565b3be6fb9ce3bb1fa9f1e67cc59 F src/btree.c c1a956c6762f2a45188c945e1070daec29f5253f
F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05 F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05
@ -160,13 +160,13 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57 F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c f6387eef0cf8f6b808738f4f3aa47e6132af0940 F src/os_unix.c 2a4cd96aabf413f39cf562baebb27aa9993f6f54
F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6 F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6
F src/pager.c 582f8da52d0bd4b43d3bdaeba0ea7702c1f23702 F src/pager.c 4e7e66c2959ee43caf8a7000712d6a4121b0888a
F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0 F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0
F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95 F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9 F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
F src/pragma.c 9f0ee3d74a7f33eeeff40a4b014fc3abf8182ce2 F src/pragma.c 9f0ee3d74a7f33eeeff40a4b014fc3abf8182ce2
F src/prepare.c 78cd7ae8cd0d8de8ef8a8b5352fc5f38693a0852 F src/prepare.c 78cd7ae8cd0d8de8ef8a8b5352fc5f38693a0852
@ -176,7 +176,7 @@ F src/resolve.c 9079da7d59aed2bb14ec8315bc7f720dd85b5b65
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c e1c6f6abdf9f359f4e735cb8ae11d2f359bf52a9 F src/select.c e1c6f6abdf9f359f4e735cb8ae11d2f359bf52a9
F src/shell.c 7c41bfcd9e5bf9d96b9215f79b03a5b2b44a3bca F src/shell.c 7c41bfcd9e5bf9d96b9215f79b03a5b2b44a3bca
F src/sqlite.h.in f2fa32f440dda59ca47e22889966b2a6eb3b491c F src/sqlite.h.in 9a5c737a1feb4495d351c56883587d4fda52e81e
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
F src/sqlite3ext.h 7183ab832e23db0f934494f16928da127a571d75 F src/sqlite3ext.h 7183ab832e23db0f934494f16928da127a571d75
F src/sqliteInt.h 0f8f05ee4db4ba9120b38f7a3992b325698f6e8a F src/sqliteInt.h 0f8f05ee4db4ba9120b38f7a3992b325698f6e8a
@ -656,7 +656,7 @@ F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test 360b92859c0af814b3fe10b68746936389606501 F test/permutations.test eb49937dca270b2c3f62d4c91fc7034ca905b7f1
F test/pragma.test 60d29cd3d8098a2c20bf4c072810f99e3bf2757a F test/pragma.test 60d29cd3d8098a2c20bf4c072810f99e3bf2757a
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@ -1038,7 +1038,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 839aa91faf1db7025d90fa3c65e50efb829b053b P 0b452734faa0839c817f040322e7733e423bfce2
R ad71abb6cd4a6ebc6857153126653bad R d4c281f6a900c9b41816881ffb3c2331
T *branch * experimental-mmap
T *sym-experimental-mmap *
T -sym-trunk *
U dan U dan
Z 69b39b8becc09fc4758d1b797bf5f4f2 Z f16a594407ec9e95c26319dfbc751443

View File

@ -1 +1 @@
0b452734faa0839c817f040322e7733e423bfce2 6f21d9cbf5d457e63a7282015a89ae785526cf6d

View File

@ -2564,6 +2564,34 @@ int sqlite3BtreeNewDb(Btree *p){
return rc; return rc;
} }
/*
** If the shared-btree passed as the only argument is holding references
** to mmap pages, replace them with read/write pages. Return SQLITE_OK
** if successful, or an error code otherwise.
*/
static int btreeSwapOutMmap(BtShared *pBt){
BtCursor *pCsr;
for(pCsr=pBt->pCursor; pCsr; pCsr=pCsr->pNext){
int i;
for(i=0; i<=pCsr->iPage; i++){
MemPage *pPg = pCsr->apPage[i];
if( pPg->pDbPage->flags & PGHDR_MMAP ){
int rc;
MemPage *pNew = 0;
rc = btreeGetPage(pBt, pPg->pgno, &pNew, 0);
if( rc==SQLITE_OK && i==pCsr->iPage ){
pCsr->info.pCell = pNew->aData + (pCsr->info.pCell - pPg->aData);
}
pCsr->apPage[i] = pNew;
releasePage(pPg);
if( rc!=SQLITE_OK ) return rc;
}
}
}
return SQLITE_OK;
}
/* /*
** Attempt to start a new transaction. A write-transaction ** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read- ** is started if the second argument is nonzero, otherwise a read-
@ -2670,6 +2698,9 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
rc = SQLITE_READONLY; rc = SQLITE_READONLY;
}else{ }else{
rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
if( rc==SQLITE_OK ){
rc = btreeSwapOutMmap(pBt);
}
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = newDatabase(pBt); rc = newDatabase(pBt);
} }

View File

@ -3623,6 +3623,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
} }
return SQLITE_OK; return SQLITE_OK;
} }
case SQLITE_FCNTL_GETFD: {
*(int*)pArg = pFile->h;
return SQLITE_OK;
}
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
/* The pager calls this method to signal that it has done /* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and ** a rollback and that the database is therefore unchanged and

View File

@ -655,6 +655,11 @@ struct Pager {
PagerSavepoint *aSavepoint; /* Array of active savepoints */ PagerSavepoint *aSavepoint; /* Array of active savepoints */
int nSavepoint; /* Number of elements in aSavepoint[] */ int nSavepoint; /* Number of elements in aSavepoint[] */
char dbFileVers[16]; /* Changes whenever database file changes */ char dbFileVers[16]; /* Changes whenever database file changes */
void *pMap; /* Memory mapped prefix of database file */
i64 nMap; /* Size of mapping at pMap in bytes */
int nMmapOut; /* Number of mmap pages currently outstanding */
PgHdr *pFree; /* List of free mmap page headers (pDirty) */
/* /*
** End of the routinely-changing class members ** End of the routinely-changing class members
***************************************************************************/ ***************************************************************************/
@ -3803,6 +3808,105 @@ static int pagerSyncHotJournal(Pager *pPager){
return rc; return rc;
} }
#include <sys/mman.h>
/*
** Unmap any mapping of the database file.
*/
static int pagerUnmap(Pager *pPager){
if( pPager->pMap ){
munmap(pPager->pMap, pPager->nMap);
pPager->pMap = 0;
pPager->nMap = 0;
}
return SQLITE_OK;
}
static int pagerMap(Pager *pPager){
int rc;
i64 sz = 0;
assert( pPager->pMap==0 && pPager->nMap==0 );
rc = sqlite3OsFileSize(pPager->fd, &sz);
if( rc==SQLITE_OK && sz>0 ){
int fd;
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_GETFD, (void *)&fd);
if( rc==SQLITE_OK ){
void *pMap = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);
if( pMap==MAP_FAILED ){
assert( 0 );
return SQLITE_IOERR;
}
pPager->pMap = pMap;
pPager->nMap = sz;
}
}
return rc;
}
static int pagerAcquireMapPage(Pager *pPager, Pgno pgno, PgHdr **ppPage){
int rc;
*ppPage = 0;
assert( pPager->pWal==0 );
if( MEMDB==0 && pPager->tempFile==0 ){
if( pPager->pMap==0 ){
rc = pagerMap(pPager);
if( rc!=SQLITE_OK ) return rc;
}
if( pgno!=1 && pPager->pMap && pPager->nMap>=((i64)pgno*pPager->pageSize) ){
PgHdr *p;
if( pPager->pFree ){
p = pPager->pFree;
pPager->pFree = p->pDirty;
p->pDirty = 0;
memset(p->pExtra, 0, pPager->nExtra);
}else{
p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
if( p==0 ) return SQLITE_NOMEM;
p->pExtra = (void *)&p[1];
p->flags = PGHDR_MMAP;
p->nRef = 1;
p->pPager = pPager;
}
assert( p->pExtra==(void *)&p[1] );
assert( p->pPage==0 );
assert( p->flags==PGHDR_MMAP );
assert( p->pPager==pPager );
assert( p->nRef==1 );
p->pData = &((u8 *)pPager->pMap)[(i64)(pgno-1) * pPager->pageSize];
p->pgno = pgno;
pPager->nMmapOut++;
*ppPage = p;
}
}
return SQLITE_OK;
}
static void pagerReleaseMapPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
pPager->nMmapOut--;
pPg->pDirty = pPager->pFree;
pPager->pFree = pPg;
}
static void pagerFreeMapHdrs(Pager *pPager){
PgHdr *p;
PgHdr *pNext;
for(p=pPager->pFree; p; p=pNext){
pNext = p->pDirty;
sqlite3_free(p);
}
}
/* /*
** Shutdown the page cache. Free all memory and close all files. ** Shutdown the page cache. Free all memory and close all files.
** **
@ -3823,6 +3927,8 @@ int sqlite3PagerClose(Pager *pPager){
assert( assert_pager_state(pPager) ); assert( assert_pager_state(pPager) );
disable_simulated_io_errors(); disable_simulated_io_errors();
sqlite3BeginBenignMalloc(); sqlite3BeginBenignMalloc();
pagerUnmap(pPager);
pagerFreeMapHdrs(pPager);
/* pPager->errCode = 0; */ /* pPager->errCode = 0; */
pPager->exclusiveMode = 0; pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL #ifndef SQLITE_OMIT_WAL
@ -4966,6 +5072,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
pager_reset(pPager); pager_reset(pPager);
pagerUnmap(pPager);
} }
} }
@ -5007,7 +5114,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
** nothing to rollback, so this routine is a no-op. ** nothing to rollback, so this routine is a no-op.
*/ */
static void pagerUnlockIfUnused(Pager *pPager){ static void pagerUnlockIfUnused(Pager *pPager){
if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ if( (sqlite3PcacheRefCount(pPager->pPCache)==0) && pPager->nMmapOut==0 ){
pagerUnlockAndRollback(pPager); pagerUnlockAndRollback(pPager);
} }
} }
@ -5083,6 +5190,15 @@ int sqlite3PagerAcquire(
if( pPager->errCode!=SQLITE_OK ){ if( pPager->errCode!=SQLITE_OK ){
rc = pPager->errCode; rc = pPager->errCode;
}else{ }else{
if( pPager->eState==PAGER_READER && pPager->pWal==0 ){
rc = pagerAcquireMapPage(pPager, pgno, &pPg);
if( rc!=SQLITE_OK ) goto pager_acquire_err;
if( pPg ){
*ppPage = pPg;
return SQLITE_OK;
}
}
rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
} }
@ -5196,7 +5312,11 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
void sqlite3PagerUnref(DbPage *pPg){ void sqlite3PagerUnref(DbPage *pPg){
if( pPg ){ if( pPg ){
Pager *pPager = pPg->pPager; Pager *pPager = pPg->pPager;
if( pPg->flags & PGHDR_MMAP ){
pagerReleaseMapPage(pPg);
}else{
sqlite3PcacheRelease(pPg); sqlite3PcacheRelease(pPg);
}
pagerUnlockIfUnused(pPager); pagerUnlockIfUnused(pPager);
} }
} }
@ -5313,6 +5433,8 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR ); assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
pPager->subjInMemory = (u8)subjInMemory; pPager->subjInMemory = (u8)subjInMemory;
pagerUnmap(pPager);
if( ALWAYS(pPager->eState==PAGER_READER) ){ if( ALWAYS(pPager->eState==PAGER_READER) ){
assert( pPager->pInJournal==0 ); assert( pPager->pInJournal==0 );
@ -5535,6 +5657,9 @@ int sqlite3PagerWrite(DbPage *pDbPage){
assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState!=PAGER_ERROR );
assert( assert_pager_state(pPager) ); assert( assert_pager_state(pPager) );
/* There must not be any outstanding mmap pages at this point */
assert( pPager->nMmapOut==0 );
if( nPagePerSector>1 ){ if( nPagePerSector>1 ){
Pgno nPageCount; /* Total number of pages in database file */ Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */ Pgno pg1; /* First page of the sector pPg is located on. */

View File

@ -53,6 +53,8 @@ struct PgHdr {
#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ #define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
#define PGHDR_MMAP 0x040 /* This is an mmap page object */
/* Initialize and shutdown the page cache subsystem */ /* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void); int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void); void sqlite3PcacheShutdown(void);

View File

@ -900,6 +900,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_PRAGMA 14
#define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_BUSYHANDLER 15
#define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_TEMPFILENAME 16
#define SQLITE_FCNTL_GETFD 17
/* /*
** CAPI3REF: Mutex Handle ** CAPI3REF: Mutex Handle

View File

@ -135,7 +135,8 @@ test_suite "veryquick" -prefix "" -description {
This test suite is the same as the "quick" tests, except that some files This test suite is the same as the "quick" tests, except that some files
that test malloc and IO errors are omitted. that test malloc and IO errors are omitted.
} -files [ } -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* test_set $allquicktests -exclude *malloc* *ioerr* *fault* \
multiplex* server1.test shared2.test shared6.test
] ]
test_suite "valgrind" -prefix "" -description { test_suite "valgrind" -prefix "" -description {