-C Enhance\stests\sfor\sticket\s[4dd95f6943].
-D 2013-03-13T07:02:04.083
+C Use\smmap()\sto\sread\sfrom\sthe\sdatabase\sfile\sin\srollback\smode.\sThis\sbranch\sis\sunix\sonly\sfor\snow.
+D 2013-03-14T18:34:37.796
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/backup.c b2cac9f7993f3f9588827b824b1501d0c820fa68
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c 746c4dafae8565b3be6fb9ce3bb1fa9f1e67cc59
+F src/btree.c c1a956c6762f2a45188c945e1070daec29f5253f
F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
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/pager.c 582f8da52d0bd4b43d3bdaeba0ea7702c1f23702
+F src/pager.c 4e7e66c2959ee43caf8a7000712d6a4121b0888a
F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0
F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
-F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
+F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
F src/pragma.c 9f0ee3d74a7f33eeeff40a4b014fc3abf8182ce2
F src/prepare.c 78cd7ae8cd0d8de8ef8a8b5352fc5f38693a0852
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c e1c6f6abdf9f359f4e735cb8ae11d2f359bf52a9
F src/shell.c 7c41bfcd9e5bf9d96b9215f79b03a5b2b44a3bca
-F src/sqlite.h.in f2fa32f440dda59ca47e22889966b2a6eb3b491c
+F src/sqlite.h.in 9a5c737a1feb4495d351c56883587d4fda52e81e
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
F src/sqlite3ext.h 7183ab832e23db0f934494f16928da127a571d75
F src/sqliteInt.h 0f8f05ee4db4ba9120b38f7a3992b325698f6e8a
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
-F test/permutations.test 360b92859c0af814b3fe10b68746936389606501
+F test/permutations.test eb49937dca270b2c3f62d4c91fc7034ca905b7f1
F test/pragma.test 60d29cd3d8098a2c20bf4c072810f99e3bf2757a
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 839aa91faf1db7025d90fa3c65e50efb829b053b
-R ad71abb6cd4a6ebc6857153126653bad
+P 0b452734faa0839c817f040322e7733e423bfce2
+R d4c281f6a900c9b41816881ffb3c2331
+T *branch * experimental-mmap
+T *sym-experimental-mmap *
+T -sym-trunk *
U dan
-Z 69b39b8becc09fc4758d1b797bf5f4f2
+Z f16a594407ec9e95c26319dfbc751443
-0b452734faa0839c817f040322e7733e423bfce2
\ No newline at end of file
+6f21d9cbf5d457e63a7282015a89ae785526cf6d
\ No newline at end of file
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
** is started if the second argument is nonzero, otherwise a read-
rc = SQLITE_READONLY;
}else{
rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
+ if( rc==SQLITE_OK ){
+ rc = btreeSwapOutMmap(pBt);
+ }
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
}
return SQLITE_OK;
}
+ case SQLITE_FCNTL_GETFD: {
+ *(int*)pArg = pFile->h;
+ return SQLITE_OK;
+ }
#ifdef SQLITE_DEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
PagerSavepoint *aSavepoint; /* Array of active savepoints */
int nSavepoint; /* Number of elements in aSavepoint[] */
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
***************************************************************************/
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.
**
assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
+ pagerUnmap(pPager);
+ pagerFreeMapHdrs(pPager);
/* pPager->errCode = 0; */
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
pager_reset(pPager);
+ pagerUnmap(pPager);
}
}
** nothing to rollback, so this routine is a no-op.
*/
static void pagerUnlockIfUnused(Pager *pPager){
- if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+ if( (sqlite3PcacheRefCount(pPager->pPCache)==0) && pPager->nMmapOut==0 ){
pagerUnlockAndRollback(pPager);
}
}
if( pPager->errCode!=SQLITE_OK ){
rc = pPager->errCode;
}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);
}
void sqlite3PagerUnref(DbPage *pPg){
if( pPg ){
Pager *pPager = pPg->pPager;
- sqlite3PcacheRelease(pPg);
+ if( pPg->flags & PGHDR_MMAP ){
+ pagerReleaseMapPage(pPg);
+ }else{
+ sqlite3PcacheRelease(pPg);
+ }
pagerUnlockIfUnused(pPager);
}
}
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
pPager->subjInMemory = (u8)subjInMemory;
+ pagerUnmap(pPager);
+
if( ALWAYS(pPager->eState==PAGER_READER) ){
assert( pPager->pInJournal==0 );
assert( pPager->eState!=PAGER_ERROR );
assert( assert_pager_state(pPager) );
+ /* There must not be any outstanding mmap pages at this point */
+ assert( pPager->nMmapOut==0 );
+
if( nPagePerSector>1 ){
Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */
#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
#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 */
int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void);
#define SQLITE_FCNTL_PRAGMA 14
#define SQLITE_FCNTL_BUSYHANDLER 15
#define SQLITE_FCNTL_TEMPFILENAME 16
+#define SQLITE_FCNTL_GETFD 17
/*
** CAPI3REF: Mutex Handle
This test suite is the same as the "quick" tests, except that some files
that test malloc and IO errors are omitted.
} -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 {