-C Add\sa\sversion\snumber\sto\sthe\ssqlite3_pcache_methods2\sobject.\s\sOther\sPCACHE2\ndocumentation\simprovements.
-D 2011-11-13T21:44:03.995
+C Begin\smaking\sexperimental\schanges\sto\suse\smmap()\sfor\sreading\scontent\sfrom\na\sdatabase.\s\sThe\scode\scompiles,\sbut\scrashes\son\sthe\stest\ssuite.
+D 2011-11-14T01:55:02.731
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/backup.c 4368158da74d4711888e03264105c5c527d76caf
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c 149cccf2134f555583d0825e47b17104aa06cb84
+F src/btree.c 2d943dc55e9828b017a2f3fe696a54ff91f51eaf
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h ea863a819224d3e6845ad1e39954d41558b8cd8b
F src/build.c 8af67a08a852ff4c63701963cb1ab7166f577814
F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
-F src/os.c 5d9b02782ed36345348d6fe21d7762ed3a9cfd2a
-F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
+F src/os.c ac54d2199b0bd16543a179d8376deccbe2b4f699
+F src/os.h 1e4f937e1315710bd4a34347d7ddffc1f8cb9055
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
-F src/os_unix.c 4fbb91726165e105c1679a2660f49a3f4c376e4f
+F src/os_unix.c f2c4cfdc350f9b1c5b6ff5079b65c875dc5ea35d
F src/os_win.c d6cf718667c4d89d930f30caa6cdc7f7753e259a
-F src/pager.c db33d4bf1e3e019c34c220971cc6c3aa07c30f54
-F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d
+F src/pager.c 6b3a7765ac98a32e125a7f0214fe65e9b578aac8
+F src/pager.h a29eabed35775666fbbcdf91d6a6811f42efdd54
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
-F src/pcache.c b9d52e9f844d91c27c161279234f273fc02abc71
-F src/pcache.h c770382f9fae4ca5025c5523bd0aa13cd6ddc6f8
+F src/pcache.c ccbd5b12806d8fd8a4652b26a5be42d8eee1e962
+F src/pcache.h f8a98a37dd4f7c8bb4ffbdbd6284457c6b78b16e
F src/pcache1.c 0ac7b63db83a705787f4ababf1e4cff27b5f8064
F src/pragma.c 65d1d63d64f8b7350f28d5ee6d40f7985deccdfe
F src/prepare.c ec4989f7f480544bdc4192fe663470d2a2d7d61e
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
F src/shell.c 29812a900a780eb0f835c4bc65e216272689def8
-F src/sqlite.h.in 557f4113a649f15d13e566aaa85820509b4daa52
+F src/sqlite.h.in e08f84145c049bef7a235221f1b5dc65a79db9ad
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h f87f241b9821a9d466c2711b7345d30ef3624249
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/superlock.test 7b1167925e9d30a5d1f0701d24812fdda42c3a86
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
-F test/syscall.test 2a922050dbee032f587249b070fb42692f5e1e22
+F test/syscall.test e97f53ebfcc93fe89c61e1a3b5f120f28ec671b7
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P ceee03c79a55ea39866758aa76b78b10e5f4246d
-R d08ae8acf53f2cb149aeb898f50b49c8
+P 9f839ac05a9f3cfe587d2ccdccd50dac41baedbe
+R b9e47a24ac1e99bdba7ee295a969cbe5
+T *branch * mmap-experimental
+T *sym-mmap-experimental *
+T -sym-experimental-pcache *
U drh
-Z af6f24cf5b51e20dd59385851602a05e
+Z 12fb6642b5e5f67ae442ddd38187142a
-9f839ac05a9f3cfe587d2ccdccd50dac41baedbe
\ No newline at end of file
+09be42d5fa7ef692428579d4d8d48b3316190945
\ No newline at end of file
return SQLITE_OK;
}
+/*
+** Make a btree page is writable.
+*/
+static int btreeMakePageWriteable(MemPage *pPage){
+ int rc;
+ if( sqlite3PagerIswriteable(pPage->pDbPage) ) return SQLITE_OK;
+ rc = sqlite3PagerWrite(pPage->pDbPage);
+ pPage->aData = sqlite3PagerGetData(pPage->pDbPage);
+ pPage->aDataEnd = &pPage->aData[pPage->pBt->usableSize];
+ pPage->aCellIdx = &pPage->aData[pPage->cellOffset];
+ return rc;
+}
+
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Given a page number of a regular database page, return the page
** If the noContent flag is set, it means that we do not care about
** the content of the page at this time. So do not go to the disk
** to fetch the content. Just fill in the content with zeros for now.
-** If in the future we call sqlite3PagerWrite() on this page, that
+** If in the future we call btreeMakePageWriteable() on this page, that
** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
}
pP1 = pBt->pPage1;
assert( pP1!=0 );
- rc = sqlite3PagerWrite(pP1->pDbPage);
+ rc = btreeMakePageWriteable(pP1);
if( rc ) return rc;
data = pP1->aData;
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
** rollback occurs within the transaction.
*/
if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){
- rc = sqlite3PagerWrite(pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pPage1);
if( rc==SQLITE_OK ){
put4byte(&pPage1->aData[28], pBt->nPage);
}
if( rc!=SQLITE_OK ){
return rc;
}
- rc = sqlite3PagerWrite(pPtrPage->pDbPage);
+ rc = btreeMakePageWriteable(pPtrPage);
if( rc!=SQLITE_OK ){
releasePage(pPtrPage);
return rc;
}while( nFin!=0 && iFreePg>nFin );
assert( iFreePg<iLastPg );
- rc = sqlite3PagerWrite(pLastPg->pDbPage);
+ rc = btreeMakePageWriteable(pLastPg);
if( rc==SQLITE_OK ){
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
}
if( rc!=SQLITE_OK ){
return rc;
}
- rc = sqlite3PagerWrite(pPg->pDbPage);
+ rc = btreeMakePageWriteable(pPg);
releasePage(pPg);
if( rc!=SQLITE_OK ){
return rc;
invalidateAllOverflowCache(pBt);
rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pBt->pPage1);
put4byte(&pBt->pPage1->aData[28], pBt->nPage);
}
}
rc = incrVacuumStep(pBt, nFin, iFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pBt->pPage1);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
put4byte(&pBt->pPage1->aData[28], nFin);
a = pCur->info.nLocal - offset;
}
if( eOp ){
- if( (rc = sqlite3PagerWrite(pPage->pDbPage))!=SQLITE_OK ) return rc;
+ if( (rc = btreeMakePageWriteable(pPage))!=SQLITE_OK ) return rc;
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
memcpy(aPayload+offset, pBuf, a);
/*
** Allocate a new page from the database file.
**
-** The new page is marked as dirty. (In other words, sqlite3PagerWrite()
+** The new page is marked as dirty. (In other words, btreeMakePageWriteable()
** has already been called on the new page.) The new page has also
** been referenced and the calling routine is responsible for calling
** sqlite3PagerUnref() on the new page when it is done.
/* Decrement the free-list count by 1. Set iTrunk to the index of the
** first free-list trunk page. iPrevTrunk is initially 1.
*/
- rc = sqlite3PagerWrite(pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pPage1);
if( rc ) return rc;
put4byte(&pPage1->aData[36], n-1);
** So extract the trunk page itself and use it as the newly
** allocated page */
assert( pPrevTrunk==0 );
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pTrunk);
if( rc ){
goto end_allocate_page;
}
assert( *pPgno==iTrunk );
*ppPage = pTrunk;
searchList = 0;
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pTrunk);
if( rc ){
goto end_allocate_page;
}
if( !pPrevTrunk ){
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
}else{
- rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pPrevTrunk);
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
- rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pNewTrunk);
if( rc!=SQLITE_OK ){
releasePage(pNewTrunk);
goto end_allocate_page;
assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
put4byte(&pPage1->aData[32], iNewTrunk);
}else{
- rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pPrevTrunk);
if( rc ){
goto end_allocate_page;
}
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
": %d more free pages\n",
*pPgno, closest+1, k, pTrunk->pgno, n-1));
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pTrunk);
if( rc ) goto end_allocate_page;
if( closest<k-1 ){
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
noContent = !btreeGetHasContent(pBt, *pPgno);
rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+ rc = btreeMakePageWriteable(*ppPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
}
}else{
/* There are no pages on the freelist, so create a new page at the
** end of the file */
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pBt->pPage1);
if( rc ) return rc;
pBt->nPage++;
if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pPg->pDbPage);
+ rc = btreeMakePageWriteable(pPg);
releasePage(pPg);
}
if( rc ) return rc;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
if( rc ) return rc;
- rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+ rc = btreeMakePageWriteable(*ppPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
}
}
/* Increment the free page count on pPage1 */
- rc = sqlite3PagerWrite(pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pPage1);
if( rc ) goto freepage_out;
nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], nFree+1);
** always fully overwrite deleted information with zeros.
*/
if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
- || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
+ || ((rc = btreeMakePageWriteable(pPage))!=0)
){
goto freepage_out;
}
** to 3.6.0 or later) we should consider fixing the conditional above
** to read "usableSize/4-2" instead of "usableSize/4-8".
*/
- rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ rc = btreeMakePageWriteable(pTrunk);
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
goto freepage_out;
}
- rc = sqlite3PagerWrite(pPage->pDbPage);
+ rc = btreeMakePageWriteable(pPage);
if( rc!=SQLITE_OK ){
goto freepage_out;
}
pPage->aOvfl[j].pCell = pCell;
pPage->aOvfl[j].idx = (u16)i;
}else{
- int rc = sqlite3PagerWrite(pPage->pDbPage);
+ int rc = btreeMakePageWriteable(pPage);
if( rc!=SQLITE_OK ){
*pRC = rc;
return;
if( i<nOld ){
pNew = apNew[i] = apOld[i];
apOld[i] = 0;
- rc = sqlite3PagerWrite(pNew->pDbPage);
+ rc = btreeMakePageWriteable(pNew);
nNew++;
if( rc ) goto balance_cleanup;
}else{
** page that will become the new right-child of pPage. Copy the contents
** of the node stored on pRoot into the new child page.
*/
- rc = sqlite3PagerWrite(pRoot->pDbPage);
+ rc = btreeMakePageWriteable(pRoot);
if( rc==SQLITE_OK ){
rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
copyNodeContent(pRoot, pChild, &rc);
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
- rc = sqlite3PagerWrite(pParent->pDbPage);
+ rc = btreeMakePageWriteable(pParent);
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
if( pPage->hasData
if( loc==0 ){
u16 szOld;
assert( idx<pPage->nCell );
- rc = sqlite3PagerWrite(pPage->pDbPage);
+ rc = btreeMakePageWriteable(pPage);
if( rc ){
goto end_insert;
}
*/
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
- rc = sqlite3PagerWrite(pPage->pDbPage);
+ rc = btreeMakePageWriteable(pPage);
if( rc ) return rc;
rc = clearCell(pPage, pCell);
dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
allocateTempSpace(pBt);
pTmp = pBt->pTmpSpace;
- rc = sqlite3PagerWrite(pLeaf->pDbPage);
+ rc = btreeMakePageWriteable(pLeaf);
insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
if( rc ) return rc;
if( rc!=SQLITE_OK ){
return rc;
}
- rc = sqlite3PagerWrite(pRoot->pDbPage);
+ rc = btreeMakePageWriteable(pRoot);
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
if( freePageFlag ){
freePage(pPage, &rc);
- }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
+ }else if( (rc = btreeMakePageWriteable(pPage))==0 ){
zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
}
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
assert( pBt->pPage1!=0 );
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pBt->pPage1);
if( rc==SQLITE_OK ){
put4byte(&pBt->pPage1->aData[36 + idx*4], iMeta);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
rc = sqlite3BtreeBeginTrans(pBtree, 2);
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ rc = btreeMakePageWriteable(pBt->pPage1);
if( rc==SQLITE_OK ){
aData = pBt->pPage1->aData;
aData[18] = (u8)iVersion;
return rc;
}
+/* Attempt to map all or part of a file into memory. VFSes are not
+** required to implement this. The VFS might be an older version (less then
+** 3) that does not have an xMap pointer. Or the xMap pointer might be NULL.
+*/
+int sqlite3OsMap(
+ sqlite3_file *pFile, /* The file to be mapped into memory */
+ sqlite3_int64 ofst, /* Index of the first byte to map */
+ sqlite3_int64 len, /* Number of bytes to be mapped */
+ int mmapFlags, /* Map control flags */
+ void **ppMemObj, /* Write a mapping object here */
+ void **ppMem /* Write the start of the mapped file here */
+){
+ int rc;
+
+ /* The current implementation only does read-only mmap. This could change
+ ** in the future. */
+ assert( mmapFlags==SQLITE_OPEN_READONLY );
+
+ /* The current implementation currently only maps the whole file. This
+ ** could change in the future. */
+ assert( ofst==0 );
+
+ if( pFile->pMethods==0 || pFile->pMethods->iVersion<3
+ || pFile->pMethods->xMap==0 ){
+ *ppMemObj = 0;
+ *ppMem = 0;
+ rc = SQLITE_CANTOPEN;
+ }else{
+ rc = pFile->pMethods->xMap(pFile, ofst, len, mmapFlags, ppMemObj, ppMem);
+ }
+ return rc;
+}
+
+/* Undo a mapping.
+**
+** The pMemObj parameter will have been obtained by a prior call to
+** sqlite3OsMap(). So if pMemObj is not NULL, we know that the current
+** VFS does support xMap and xUnmap.
+*/
+int sqlite3OsUnmap(sqlite3_file *pFile, void *pMemObj){
+ int rc = SQLITE_OK;
+ if( pMemObj ) rc = pFile->pMethods->xUnmap(pFile, pMemObj);
+ return rc;
+}
+
+
int sqlite3OsOpenMalloc(
sqlite3_vfs *pVfs,
const char *zFile,
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int);
+int sqlite3OsMap(sqlite3_file*,sqlite3_int64,sqlite3_int64,int,void**,void**);
+int sqlite3OsUnmap(sqlite3_file*,void*);
/*
** Functions for accessing sqlite3_vfs methods
#include <time.h>
#include <sys/time.h>
#include <errno.h>
-#ifndef SQLITE_OMIT_WAL
#include <sys/mman.h>
-#endif
#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
+ { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
+#define osMmap ((int(*)(void*,size_t,int,int,int,off_t))aSyscall[20].pCurrent)
+
+ { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
+#define osMunmap ((int(*)(void*,size_t))aSyscall[21].pCurrent)
+
+
+
}; /* End of the overrideable system calls */
/*
# define unixShmUnmap 0
#endif /* #ifndef SQLITE_OMIT_WAL */
+/*
+** An object used to record enough information about a file mapping to
+** undo that mapping.
+*/
+struct unixMapping {
+ sqlite3_int64 len;
+ void *p;
+};
+
+/*
+** Try to map some or all of a file into memory
+*/
+static int unixMap(
+ sqlite3_file *pFile, /* File to be mapped */
+ sqlite3_int64 ofst, /* Offset of start of section to be mapped */
+ sqlite3_int64 len, /* Length of the section to be mapped */
+ int mmapFlags, /* Flags controlling the mapping */
+ void **ppMapObj, /* Write here an object to undo the mapping */
+ void **ppMem /* Write here a pointer to the mapped file */
+){
+ struct unixMapping *pNew;
+ unixFile *pUFile = (unixFile*)pFile;
+
+ assert( mmapFlags==SQLITE_OPEN_READONLY );
+ sqlite3BeginBenignMalloc();
+ pNew = sqlite3_malloc( sizeof(*pNew) );
+ sqlite3EndBenignMalloc();
+ if( pNew==0 ){
+ *ppMapObj = 0;
+ *ppMem = 0;
+ return SQLITE_CANTOPEN;
+ }
+ pNew->len = len;
+ pNew->p = *ppMem = mmap(0, len, PROT_READ, MAP_SHARED, pUFile->h, 0);
+ if( pNew->p==0 ){
+ sqlite3_free(pNew);
+ return SQLITE_CANTOPEN;
+ }else{
+ *ppMapObj = pNew;
+ return SQLITE_OK;
+ }
+}
+
+/*
+** Undo a prior memory mapping.
+*/
+static int unixUnmap(
+ sqlite3_file *pFile,
+ void *pMapObj
+){
+ struct unixMapping *pMap = (struct unixMapping*)pMapObj;
+ assert( pMap!=0 );
+ munmap(pMap->p, pMap->len);
+ sqlite3_free(pMap);
+ return SQLITE_OK;
+}
+
/*
** Here ends the implementation of all sqlite3_file methods.
**
** * An I/O method finder function called FINDER that returns a pointer
** to the METHOD object in the previous bullet.
*/
-#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
+#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \
static const sqlite3_io_methods METHOD = { \
- VERSION, /* iVersion */ \
+ 3, /* iVersion */ \
CLOSE, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics, /* xDeviceCapabilities */ \
- unixShmMap, /* xShmMap */ \
+ SHMMAP, /* xShmMap */ \
unixShmLock, /* xShmLock */ \
unixShmBarrier, /* xShmBarrier */ \
- unixShmUnmap /* xShmUnmap */ \
+ unixShmUnmap, /* xShmUnmap */ \
+ unixMap, /* xMap */ \
+ unixUnmap /* xUnmap */ \
}; \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
IOMETHODS(
posixIoFinder, /* Finder function name */
posixIoMethods, /* sqlite3_io_methods object name */
- 2, /* shared memory is enabled */
unixClose, /* xClose method */
unixLock, /* xLock method */
unixUnlock, /* xUnlock method */
- unixCheckReservedLock /* xCheckReservedLock method */
+ unixCheckReservedLock, /* xCheckReservedLock method */
+ unixShmMap /* Shared memory enabled */
)
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
- nolockCheckReservedLock /* xCheckReservedLock method */
+ nolockCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
IOMETHODS(
dotlockIoFinder, /* Finder function name */
dotlockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
dotlockClose, /* xClose method */
dotlockLock, /* xLock method */
dotlockUnlock, /* xUnlock method */
- dotlockCheckReservedLock /* xCheckReservedLock method */
+ dotlockCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
flockClose, /* xClose method */
flockLock, /* xLock method */
flockUnlock, /* xUnlock method */
- flockCheckReservedLock /* xCheckReservedLock method */
+ flockCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#endif
IOMETHODS(
semIoFinder, /* Finder function name */
semIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
semClose, /* xClose method */
semLock, /* xLock method */
semUnlock, /* xUnlock method */
- semCheckReservedLock /* xCheckReservedLock method */
+ semCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#endif
IOMETHODS(
afpIoFinder, /* Finder function name */
afpIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
afpClose, /* xClose method */
afpLock, /* xLock method */
afpUnlock, /* xUnlock method */
- afpCheckReservedLock /* xCheckReservedLock method */
+ afpCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#endif
IOMETHODS(
proxyIoFinder, /* Finder function name */
proxyIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
- proxyCheckReservedLock /* xCheckReservedLock method */
+ proxyCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#endif
IOMETHODS(
nfsIoFinder, /* Finder function name */
nfsIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
unixClose, /* xClose method */
unixLock, /* xLock method */
nfsUnlock, /* xUnlock method */
- unixCheckReservedLock /* xCheckReservedLock method */
+ unixCheckReservedLock, /* xCheckReservedLock method */
+ 0 /* Shared memory disabled */
)
#endif
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==20 );
+ assert( ArraySize(aSyscall)==22 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
PagerSavepoint *aSavepoint; /* Array of active savepoints */
int nSavepoint; /* Number of elements in aSavepoint[] */
char dbFileVers[16]; /* Changes whenever database file changes */
+ u8 *aFileContent; /* File mapped into memory */
+ sqlite3_int64 nFileContent; /* Bytes of memory mapped into aFileContent */
+ void *pMapObject; /* Used to unmap the file */
/*
** End of the routinely-changing class members
***************************************************************************/
** it can safely move back to PAGER_OPEN state. This happens in both
** normal and exclusive-locking mode.
*/
- if( pPager->errCode ){
+ if( pPager->errCode || pPager->pMapObject ){
assert( !MEMDB );
pager_reset(pPager);
pPager->changeCountDone = pPager->tempFile;
pPager->eState = PAGER_OPEN;
pPager->errCode = SQLITE_OK;
+ sqlite3OsUnmap(pPager->fd, pPager->pMapObject);
+ pPager->pMapObject = 0;
+ pPager->aFileContent = 0;
+ pPager->nFileContent = 0;
}
pPager->journalOff = 0;
pPager->journalHdr = 0;
pPager->setMaster = 0;
+
}
/*
assert( pPager->eState>=PAGER_READER && !MEMDB );
assert( isOpen(pPager->fd) );
-
- if( NEVER(!isOpen(pPager->fd)) ){
- assert( pPager->tempFile );
- memset(pPg->pData, 0, pPager->pageSize);
- return SQLITE_OK;
- }
+ assert( pPg->pBuf==pPg->pData );
if( pagerUseWal(pPager) ){
/* Try to pull the page from the write-ahead log. */
rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
}
if( rc==SQLITE_OK && !isInWal ){
- i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
+ i64 iOffset = (pgno-1)*(i64)pgsz;
+ if( iOffset+pgsz <= pPager->nFileContent ){
+ pPg->pData = &pPager->aFileContent[iOffset];
+ }else{
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
}
}
rc = pagerPagecount(pPager, &pPager->dbSize);
}
+ assert( pPager->aFileContent==0 );
+ pPager->nFileContent = pPager->dbSize*(sqlite3_int64)pPager->pageSize;
+ sqlite3OsMap(pPager->fd, 0, pPager->nFileContent,
+ SQLITE_OPEN_READONLY, (void**)&pPager->pMapObject,
+ (void**)&pPager->aFileContent);
+ if( pPager->aFileContent==0 ) pPager->nFileContent = 0;
+
failed:
if( rc!=SQLITE_OK ){
assert( !MEMDB );
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
assert( assert_pager_state(pPager) );
+ /* Make sure page content is held in malloced memory */
+ if( pPg->pData!=pPg->pBuf ){
+ memcpy(pPg->pBuf, pPg->pData, pPager->pageSize);
+ pData = pPg->pData = pPg->pBuf;
+ }
+
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
** to sqlite3PagerWrite(). In other words, return TRUE if it is ok
** to change the content of the page.
*/
-#ifndef NDEBUG
int sqlite3PagerIswriteable(DbPage *pPg){
return pPg->flags&PGHDR_DIRTY;
}
-#endif
/*
** A call to this routine tells the pager that it is not necessary to
/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST)
Pgno sqlite3PagerPagenumber(DbPage*);
- int sqlite3PagerIswriteable(DbPage*);
#endif
+int sqlite3PagerIswriteable(DbPage*);
#ifdef SQLITE_TEST
int *sqlite3PagerStats(Pager*);
void sqlite3PagerRefdump(Pager*);
if( !pPgHdr->pPage ){
memset(pPgHdr, 0, sizeof(PgHdr));
pPgHdr->pPage = pPage;
- pPgHdr->pData = pPage->pBuf;
+ pPgHdr->pData = pPgHdr->pBuf = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, pCache->szExtra);
pPgHdr->pCache = pCache;
}
assert( pPgHdr->pCache==pCache );
assert( pPgHdr->pgno==pgno );
- assert( pPgHdr->pData==pPage->pBuf );
+ assert( pPgHdr->pBuf==pPage->pBuf );
assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
if( 0==pPgHdr->nRef ){
*/
struct PgHdr {
sqlite3_pcache_page *pPage; /* Pcache object page handle */
- void *pData; /* Page data */
+ void *pData; /* Page data to actually use */
+ void *pBuf; /* Malloced buffer to hold pData */
void *pExtra; /* Extra content */
PgHdr *pDirty; /* Transient list of dirty pages */
Pgno pgno; /* Page number for this page */
void (*xShmBarrier)(sqlite3_file*);
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
/* Methods above are valid for version 2 */
+ int (*xMap)(sqlite3_file*, sqlite3_int64 ofst, sqlite3_int64 len,
+ int mmapFlags, void **ppMemObj, void **ppMem);
+ int (*xUnmap)(sqlite3_file*, void *pMemObj);
+ /* Methods above are valid for version 3 */
/* Additional methods may be added in future releases */
};
open close access getcwd stat fstat ftruncate
fcntl read pread write pwrite fchmod fallocate
pread64 pwrite64 unlink openDirectory mkdir rmdir
+ mmap munmap
} {
if {[test_syscall exists $s]} {lappend syscall_list $s}
}