1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Add the sqlite3_io_methods.xMremap() method to the VFS interface. Also "PRAGMA mmap_size".

FossilOrigin-Name: 6183f1bd86ceed76d22d9762f3d7eb33262c62d1
This commit is contained in:
dan
2013-03-19 19:28:06 +00:00
parent a72014faf5
commit 5d8a137218
18 changed files with 263 additions and 110 deletions

View File

@@ -1,5 +1,5 @@
C When\spossible,\suse\smemcpy()\sto\sand\sfrom\sthe\smapped\sregion\sinstead\sof\sxWrite()\sand\sxRead(). C Add\sthe\ssqlite3_io_methods.xMremap()\smethod\sto\sthe\sVFS\sinterface.\sAlso\s"PRAGMA\smmap_size".
D 2013-03-16T20:19:21.766 D 2013-03-19T19:28:06.473
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,8 +121,8 @@ 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 934921ec91456c264f61ce671ca62cb826af977a F src/btree.c d4d551f05a555926a7c0f49c2e263f7ee2b1c59f
F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btree.h d3259057a38494c4c4358e377032158c762e3d8b
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05 F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
@@ -157,18 +157,18 @@ F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
F src/mutex_w32.c 32a9b3841e2d757355f0012b860b1bc5e01eafa0 F src/mutex_w32.c 32a9b3841e2d757355f0012b860b1bc5e01eafa0
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c F src/os.c 81a82a736b8a461a656f9b3e401a39768fe73a79
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57 F src/os.h 4681261aa24a9d2187aaf4cb963880e6cddb1f48
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c 2a4cd96aabf413f39cf562baebb27aa9993f6f54 F src/os_unix.c 0c7b0d076f2ac6279b0b280a26bcae8c89f36f4f
F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6 F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6
F src/pager.c 495c5344392d5932ea5072f20bfbd8a58cf19d67 F src/pager.c 78b65bf9685bf21b787ce2a7389c2b96102942dc
F src/pager.h 81ac95f4fcfe21981f495146f6d7f2fe51afd110 F src/pager.h 81ac95f4fcfe21981f495146f6d7f2fe51afd110
F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95 F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9 F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
F src/pragma.c 9f0ee3d74a7f33eeeff40a4b014fc3abf8182ce2 F src/pragma.c 86c8088ac6a12d3f3be5f7394542651f03fa9a38
F src/prepare.c 78cd7ae8cd0d8de8ef8a8b5352fc5f38693a0852 F src/prepare.c 78cd7ae8cd0d8de8ef8a8b5352fc5f38693a0852
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
@@ -176,15 +176,15 @@ 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 9a5c737a1feb4495d351c56883587d4fda52e81e F src/sqlite.h.in fd75f5bcf479b315b1c717fa1d07f018bd919f79
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 2c3d830ae78b046ebf939c905c023610e43c2796
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 3213f3101e3b85f047d6e389da5a53d76d3d7540 F src/tclsqlite.c 3213f3101e3b85f047d6e389da5a53d76d3d7540
F src/test1.c 3dac8d76be8852d65ff8b9ce4b50ed08b999ed59 F src/test1.c 39378e3e14a8162e29dc90d1e05399d12e8a569e
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
F src/test4.c bf9fa9bece01de08e6f5e02314e4af5c13590dfa F src/test4.c bf9fa9bece01de08e6f5e02314e4af5c13590dfa
@@ -369,7 +369,7 @@ F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47 F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test f3228180c87bbe5d39c9397bf001c0095c3821b9 F test/date.test f3228180c87bbe5d39c9397bf001c0095c3821b9
F test/dbstatus.test 207e5b63fcb7b9c3bb8e1fdf38ebd4654ad0e54b F test/dbstatus.test 207e5b63fcb7b9c3bb8e1fdf38ebd4654ad0e54b
F test/dbstatus2.test bf7396af964b89e39435babbcdf296ae8fc5f10a F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701 F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -403,7 +403,7 @@ F test/eqp.test 46aa946dd55c90635327898275d3e533d23a9845
F test/errmsg.test 050717f1c6a5685de9c79f5f9f6b83d7c592f73a F test/errmsg.test 050717f1c6a5685de9c79f5f9f6b83d7c592f73a
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3 F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test a1b324cb21834a490cd052d409d34789cfef57cb F test/exclusive.test a1b324cb21834a490cd052d409d34789cfef57cb
F test/exclusive2.test 372be98f6de44dd78734e364b7b626ea211761a6 F test/exclusive2.test 881193eccec225cfed9d7f744b65e57f26adee25
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30 F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
@@ -508,7 +508,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
F test/fts4unicode.test 25ccad45896f8e50f6a694cff738a35f798cdb40 F test/fts4unicode.test 25ccad45896f8e50f6a694cff738a35f798cdb40
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test b058483c17952eff7797b837bbb61e27e6b05606 F test/func.test b0fc34fdc36897769651975a2b0a606312753643
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74 F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
@@ -526,7 +526,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617 F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3 F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
F test/incrblob.test 34765fa6fb5d8e0f256fc7d6497c04b205398849 F test/incrblob.test bf210bea512474d4e1d94fbb9b0fcb386cd65dea
F test/incrblob2.test edc3a96e557bd61fb39acc8d2edd43371fbbaa19 F test/incrblob2.test edc3a96e557bd61fb39acc8d2edd43371fbbaa19
F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7 F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7
F test/incrblob4.test 09be37d3dd996a31ea6993bba7837ece549414a8 F test/incrblob4.test 09be37d3dd996a31ea6993bba7837ece549414a8
@@ -652,11 +652,11 @@ F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442 F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401 F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7 F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7
F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0 F test/pageropt.test 290cd59782b1890f02bb33795571facfc5ccac43
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 eb49937dca270b2c3f62d4c91fc7034ca905b7f1 F test/permutations.test 694f4a2667242bab49cce05c54c2adfcc2727d9e
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,7 @@ 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 022fdc986b33701abfd39621072ac3d9f9f7d43e P f8ca5622d99bedca957caa9ad311d798f63b3ce9
R e9d1b00daf0ae79f0e154b8607fa8ad8 R 1add721bf7e9669d3b4d4c28d41bb13b
U dan U dan
Z 82853c015b40f8bb1665068f9eea77d4 Z 3a3766130d03f0bab6c4936a9c26c7a5

View File

@@ -1 +1 @@
f8ca5622d99bedca957caa9ad311d798f63b3ce9 6183f1bd86ceed76d22d9762f3d7eb33262c62d1

View File

@@ -2130,6 +2130,19 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Change the limit on the amount of the database file that may be
** memory mapped.
*/
int sqlite3BtreeSetMmapSize(Btree *p, int nMap){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
sqlite3PagerSetMmapsize(pBt->pPager, nMap);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
/* /*
** Change the way data is synced to disk in order to increase or decrease ** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power ** how well the database resists damage due to OS crashes and power

View File

@@ -63,6 +63,7 @@ int sqlite3BtreeOpen(
int sqlite3BtreeClose(Btree*); int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int); int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetMmapSize(Btree*, int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);

View File

@@ -140,6 +140,9 @@ int sqlite3OsShmMap(
DO_OS_MALLOC_TEST(id); DO_OS_MALLOC_TEST(id);
return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
} }
int sqlite3OsMremap(sqlite3_file *id, i64 iOff, i64 nOld, i64 nNew, void **pp){
return id->pMethods->xMremap(id, iOff, nOld, nNew, pp);
}
/* /*
** The next group of routines are convenience wrappers around the ** The next group of routines are convenience wrappers around the

View File

@@ -259,6 +259,7 @@ int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
int sqlite3OsShmLock(sqlite3_file *id, int, int, int); int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id); void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int); int sqlite3OsShmUnmap(sqlite3_file *id, int);
int sqlite3OsMremap(sqlite3_file *id, i64, i64, i64, void **);
/* /*

View File

@@ -4429,6 +4429,42 @@ static int unixShmUnmap(
# define unixShmUnmap 0 # define unixShmUnmap 0
#endif /* #ifndef SQLITE_OMIT_WAL */ #endif /* #ifndef SQLITE_OMIT_WAL */
/*
** Map, remap or unmap part of the database file.
*/
static int unixMremap(
sqlite3_file *fd, /* Main database file */
sqlite3_int64 iOff, /* Offset to start mapping at */
sqlite3_int64 nOld, /* Size of old mapping, or zero */
sqlite3_int64 nNew, /* Size of new mapping, or zero */
void **ppMap /* IN/OUT: Old/new mappings */
){
unixFile *p = (unixFile *)fd; /* The underlying database file */
int rc = SQLITE_OK; /* Return code */
void *pNew = 0; /* New mapping */
assert( iOff==0 );
if( nOld!=0 ){
void *pOld = *ppMap;
munmap(pOld, nOld);
}
if( nNew>0 ){
int flags = PROT_READ;
if( (p->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
nNew = (nNew+4095) & ~(i64)((1 << 12)-1);
pNew = mmap(0, nNew, flags, MAP_SHARED, p->h, iOff);
if( pNew==MAP_FAILED ){
pNew = 0;
rc = SQLITE_IOERR;
}
}
*ppMap = pNew;
return rc;
}
/* /*
** Here ends the implementation of all sqlite3_file methods. ** Here ends the implementation of all sqlite3_file methods.
** **
@@ -4487,7 +4523,8 @@ static const sqlite3_io_methods METHOD = { \
unixShmMap, /* xShmMap */ \ unixShmMap, /* xShmMap */ \
unixShmLock, /* xShmLock */ \ unixShmLock, /* xShmLock */ \
unixShmBarrier, /* xShmBarrier */ \ unixShmBarrier, /* xShmBarrier */ \
unixShmUnmap /* xShmUnmap */ \ unixShmUnmap, /* xShmUnmap */ \
unixMremap, /* xMremap */ \
}; \ }; \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
@@ -4504,7 +4541,7 @@ static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
IOMETHODS( IOMETHODS(
posixIoFinder, /* Finder function name */ posixIoFinder, /* Finder function name */
posixIoMethods, /* sqlite3_io_methods object name */ posixIoMethods, /* sqlite3_io_methods object name */
2, /* shared memory is enabled */ 3, /* shared memory and mmap are enabled */
unixClose, /* xClose method */ unixClose, /* xClose method */
unixLock, /* xLock method */ unixLock, /* xLock method */
unixUnlock, /* xUnlock method */ unixUnlock, /* xUnlock method */

View File

@@ -659,8 +659,11 @@ struct Pager {
void *pMap; /* Memory mapped prefix of database file */ void *pMap; /* Memory mapped prefix of database file */
i64 nMap; /* Size of mapping at pMap in bytes */ i64 nMap; /* Size of mapping at pMap in bytes */
i64 nMapValid; /* Bytes at pMap known to be valid */ i64 nMapValid; /* Bytes at pMap known to be valid */
i64 nMapLimit; /* Maximum permitted mapping size */
int nMapCfgLimit; /* Configured limit value */
int nMmapOut; /* Number of mmap pages currently outstanding */ int nMmapOut; /* Number of mmap pages currently outstanding */
PgHdr *pFree; /* List of free mmap page headers (pDirty) */ PgHdr *pFree; /* List of free mmap page headers (pDirty) */
int bMapResize; /* Check if the mapping should be resized */
/* /*
** End of the routinely-changing class members ** End of the routinely-changing class members
***************************************************************************/ ***************************************************************************/
@@ -3356,6 +3359,35 @@ void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
} }
/*
** Set Pager.nMapLimit, the maximum permitted mapping size, based on the
** current values of Pager.nMapCfgLimit and Pager.pageSize.
**
** If this connection should not use mmap at all, set nMapLimit to zero.
*/
static void pagerFixMaplimit(Pager *pPager){
if( isOpen(pPager->fd)==0
|| pPager->fd->pMethods->iVersion<3
|| pPager->fd->pMethods->xMremap==0
|| pPager->tempFile
|| pPager->pWal
){
pPager->nMapLimit = 0;
}else if( pPager->nMapCfgLimit<0 ){
pPager->nMapLimit = (i64)pPager->nMapCfgLimit * -1024;
}else{
pPager->nMapLimit = (i64)pPager->nMapCfgLimit * pPager->pageSize;
}
}
/*
** Change the maximum size of any memory mapping made of the database file.
*/
void sqlite3PagerSetMmapsize(Pager *pPager, int nMap){
pPager->nMapCfgLimit = nMap;
pagerFixMaplimit(pPager);
}
/* /*
** Free as much memory as possible from the pager. ** Free as much memory as possible from the pager.
*/ */
@@ -3591,6 +3623,7 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
assert( nReserve>=0 && nReserve<1000 ); assert( nReserve>=0 && nReserve<1000 );
pPager->nReserve = (i16)nReserve; pPager->nReserve = (i16)nReserve;
pagerReportSize(pPager); pagerReportSize(pPager);
pagerFixMaplimit(pPager);
} }
return rc; return rc;
} }
@@ -3816,108 +3849,100 @@ static int pagerSyncHotJournal(Pager *pPager){
return rc; return rc;
} }
#include <sys/mman.h>
/* /*
** Unmap any mapping of the database file. ** Unmap any memory mapping of the database file.
*/ */
static int pagerUnmap(Pager *pPager){ static int pagerUnmap(Pager *pPager){
if( pPager->pMap ){ if( pPager->pMap ){
munmap(pPager->pMap, pPager->nMap); sqlite3OsMremap(pPager->fd, 0, pPager->nMap, 0, &pPager->pMap);
pPager->pMap = 0;
pPager->nMap = 0; pPager->nMap = 0;
pPager->nMapValid = 0; pPager->nMapValid = 0;
} }
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Create, or recreate, the memory mapping of the database file.
*/
static int pagerMap(Pager *pPager){ static int pagerMap(Pager *pPager){
int rc; int rc = SQLITE_OK; /* Return code */
i64 sz = 0; Pgno nPg; /* Size of mapping to request in pages */
i64 sz; /* Size of mapping to request in bytes */
assert( pPager->pMap==0 && pPager->nMap==0 ); assert( pPager->pWal==0 && isOpen(pPager->fd) && pPager->tempFile==0 );
assert( pPager->pMap==0 || pPager->nMap>0 );
assert( pPager->eState>=1 );
assert( pPager->nMmapOut==0 );
assert( pPager->nMapLimit>0 );
rc = sqlite3OsFileSize(pPager->fd, &sz); /* Figure out how large a mapping to request. Set variable sz to this
sz = sz & ~(4096-1); ** value in bytes. */
nPg = (pPager->eState==1) ? pPager->dbSize : pPager->dbFileSize;
sz = (i64)nPg * pPager->pageSize;
if( sz>pPager->nMapLimit ) sz = pPager->nMapLimit;
if( rc==SQLITE_OK && sz>0 ){ if( sz!=pPager->nMapValid ){
int fd; rc = sqlite3OsMremap(pPager->fd, 0, pPager->nMap, sz, &pPager->pMap);
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_GETFD, (void *)&fd);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
void *pMap = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); assert( pPager->pMap!=0 );
if( pMap==MAP_FAILED ){ pPager->nMap = sz;
return SQLITE_IOERR; }else{
} assert( pPager->pMap==0 );
pPager->pMap = pMap; pPager->nMap = 0;
pPager->nMapValid = pPager->nMap = sz;
} }
pPager->nMapValid = pPager->nMap;
} }
pPager->bMapResize = 0;
return rc; return rc;
} }
static int pagerRemap(Pager *pPager, Pgno nPage){ /*
i64 sz = (i64)nPage * pPager->pageSize; ** Obtain a reference to a memory mapped page object for page number pgno.
sz = sz & ~(4096-1); ** The caller must ensure that page pgno lies within the currently mapped
** region. If successful, set *ppPage to point to the new page reference
if( pPager->nMap!=sz ){ ** and return SQLITE_OK. Otherwise, return an SQLite error code and set
void *pMap = mremap(pPager->pMap, pPager->nMap, sz, MREMAP_MAYMOVE); ** *ppPage to zero.
if( pMap==MAP_FAILED ){ **
return SQLITE_IOERR; ** Page references obtained by calling this function should be released
} ** by calling pagerReleaseMapPage().
pPager->pMap = pMap; */
pPager->nMapValid = pPager->nMap = sz;
}
return SQLITE_OK;
}
static int pagerAcquireMapPage(Pager *pPager, Pgno pgno, PgHdr **ppPage){ static int pagerAcquireMapPage(Pager *pPager, Pgno pgno, PgHdr **ppPage){
int rc; PgHdr *p; /* Memory mapped page to return */
*ppPage = 0;
assert( pPager->pWal==0 ); if( pPager->pFree ){
*ppPage = p = pPager->pFree;
if( MEMDB==0 && pPager->tempFile==0 ){ pPager->pFree = p->pDirty;
if( pPager->pMap==0 ){ p->pDirty = 0;
rc = pagerMap(pPager); memset(p->pExtra, 0, pPager->nExtra);
if( rc!=SQLITE_OK ) return rc; }else{
} *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
if( p==0 ){
if( pgno!=1 && pPager->pMap return SQLITE_NOMEM;
&& pPager->nMapValid>=((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;
} }
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++;
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Release a reference to page pPg. pPg must have been returned by an
** earlier call to pagerAcquireMapPage().
*/
static void pagerReleaseMapPage(PgHdr *pPg){ static void pagerReleaseMapPage(PgHdr *pPg){
Pager *pPager = pPg->pPager; Pager *pPager = pPg->pPager;
pPager->nMmapOut--; pPager->nMmapOut--;
@@ -3925,6 +3950,9 @@ static void pagerReleaseMapPage(PgHdr *pPg){
pPager->pFree = pPg; pPager->pFree = pPg;
} }
/*
** Free all PgHdr objects stored in the Pager.pFree list.
*/
static void pagerFreeMapHdrs(Pager *pPager){ static void pagerFreeMapHdrs(Pager *pPager){
PgHdr *p; PgHdr *p;
PgHdr *pNext; PgHdr *pNext;
@@ -5115,7 +5143,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
** possibility by unmapping the db here. */ ** possibility by unmapping the db here. */
pagerUnmap(pPager); pagerUnmap(pPager);
}else if( pPager->pMap ){ }else if( pPager->pMap ){
pagerRemap(pPager, nPage); pPager->bMapResize = 1;
} }
} }
@@ -5226,8 +5254,7 @@ int sqlite3PagerAcquire(
** page 1 if there is no write-transaction open or the ACQUIRE_READONLY ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
** flag was specified by the caller. And so long as the db is not a ** flag was specified by the caller. And so long as the db is not a
** temporary or in-memory database. */ ** temporary or in-memory database. */
const int bMmapOk = ( const int bMmapOk = (pPager->nMapLimit>0 && pgno!=1
(pgno!=1 && pPager->pWal==0 && !pPager->tempFile && !MEMDB)
&& (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY)) && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
); );
@@ -5245,7 +5272,7 @@ int sqlite3PagerAcquire(
}else{ }else{
if( bMmapOk ){ if( bMmapOk ){
if( pPager->pMap==0 ){ if( pPager->pMap==0 || (pPager->bMapResize && pPager->nMmapOut==0) ){
rc = pagerMap(pPager); rc = pagerMap(pPager);
} }
if( rc==SQLITE_OK && pPager->nMap>=((i64)pgno * pPager->pageSize) ){ if( rc==SQLITE_OK && pPager->nMap>=((i64)pgno * pPager->pageSize) ){
@@ -7014,6 +7041,7 @@ static int pagerOpenWal(Pager *pPager){
pPager->journalSizeLimit, &pPager->pWal pPager->journalSizeLimit, &pPager->pWal
); );
} }
pagerFixMaplimit(pPager);
return rc; return rc;
} }
@@ -7104,6 +7132,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0; pPager->pWal = 0;
pagerFixMaplimit(pPager);
} }
} }
return rc; return rc;

View File

@@ -744,6 +744,30 @@ void sqlite3Pragma(
} }
}else }else
/*
** PRAGMA [database.]mmap_size
** PRAGMA [database.]mmap_size=N
**
** Used to set or query the mapping size limit. The mapping size limit is
** used to limit the aggregate size of all memory mapped regions of the
** database file. If this parameter is set to zero, then memory mapping
** is not used at all. If it is set to a positive value, then it is
** interpreted as a maximum size in pages. If set to less than zero, then
** the absolute value is interpreted as a size limit in KB.
**
** The default value is zero (do not use memory mapped IO).
*/
if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
returnSingleInt(pParse, "mmap_size", pDb->pSchema->mmap_size);
}else{
int size = sqlite3Atoi(zRight);
pDb->pSchema->mmap_size = size;
sqlite3BtreeSetMmapSize(pDb->pBt, pDb->pSchema->mmap_size);
}
}else
/* /*
** PRAGMA temp_store ** PRAGMA temp_store
** PRAGMA temp_store = "default"|"memory"|"file" ** PRAGMA temp_store = "default"|"memory"|"file"

View File

@@ -706,6 +706,24 @@ struct sqlite3_file {
** fails to zero-fill short reads might seem to work. However, ** fails to zero-fill short reads might seem to work. However,
** failure to zero-fill short reads will eventually lead to ** failure to zero-fill short reads will eventually lead to
** database corruption. ** database corruption.
**
** Assuming parameter nNew is non-zero, the xMremap method should attempt
** to memory map a region nNew bytes in size starting at offset iOffset
** of the file. If successful, it should set *ppMap to point to the
** mapping and return SQLITE_OK. If the file is opened for read-write
** access, then the mapping should also be read-write.
**
** If nOld is non-zero, then the initial value of *ppMap points to a
** mapping returned by a previous call to xMremap. The existing mapping
** is nOld bytes in size and starts at offset iOffset of the file. In
** this case the xMremap method is expected to unmap the existing mapping
** and overwrite *ppMap with the pointer to the new mapping. If nOld is
** zero, then the initial value of *ppMap is undefined.
**
** If nNew is zero, then no new mapping should be created. Any old
** mapping must still be unmapped if nOld is non-zero. If the nOld
** parameter is non-zero, then the existing mapping is always unmapped -
** even if an error occurs.
*/ */
typedef struct sqlite3_io_methods sqlite3_io_methods; typedef struct sqlite3_io_methods sqlite3_io_methods;
struct sqlite3_io_methods { struct sqlite3_io_methods {
@@ -728,6 +746,9 @@ struct sqlite3_io_methods {
void (*xShmBarrier)(sqlite3_file*); void (*xShmBarrier)(sqlite3_file*);
int (*xShmUnmap)(sqlite3_file*, int deleteFlag); int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
/* Methods above are valid for version 2 */ /* Methods above are valid for version 2 */
int (*xMremap)(sqlite3_file *fd,
sqlite3_int64 iOff, sqlite3_int64 nOld, sqlite3_int64 nNew, void **ppMap);
/* Methods above are valid for version 3 */
/* Additional methods may be added in future releases */ /* Additional methods may be added in future releases */
}; };

View File

@@ -746,6 +746,7 @@ struct Schema {
u8 enc; /* Text encoding used by this database */ u8 enc; /* Text encoding used by this database */
u16 flags; /* Flags associated with this schema */ u16 flags; /* Flags associated with this schema */
int cache_size; /* Number of pages to use in the cache */ int cache_size; /* Number of pages to use in the cache */
int mmap_size; /* Number of pages to memory map */
}; };
/* /*

View File

@@ -5859,9 +5859,9 @@ static int test_getrusage(
getrusage(RUSAGE_SELF, &r); getrusage(RUSAGE_SELF, &r);
sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
r.ru_utime.tv_sec, r.ru_utime.tv_usec, (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
r.ru_stime.tv_sec, r.ru_stime.tv_usec, (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
r.ru_minflt, r.ru_majflt (int)r.ru_minflt, (int)r.ru_majflt
); );
Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
return TCL_OK; return TCL_OK;

View File

@@ -40,6 +40,7 @@ proc db_write {db {reset 0}} {
do_test 1.1 { do_test 1.1 {
db close db close
sqlite3 db test.db sqlite3 db test.db
execsql { PRAGMA mmap_size = 0 }
expr {[file size test.db] / 1024} expr {[file size test.db] / 1024}
} 6 } 6

View File

@@ -25,6 +25,14 @@ ifcapable {!pager_pragmas} {
return return
} }
# Tests in this file verify that locking_mode=exclusive causes SQLite to
# use cached pages even if the database is changed on disk. This doesn't
# work with mmap.
if {[permutation]=="mmap"} {
finish_test
return
}
# This module does not work right if the cache spills at unexpected # This module does not work right if the cache spills at unexpected
# moments. So disable the soft-heap-limit. # moments. So disable the soft-heap-limit.
# #

View File

@@ -1273,11 +1273,13 @@ do_test func-29.3 {
sqlite3_db_status db CACHE_MISS 1 sqlite3_db_status db CACHE_MISS 1
db eval {SELECT typeof(+x) FROM t29 ORDER BY id} db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
} {integer null real blob text} } {integer null real blob text}
do_test func-29.4 { if {[permutation] != "mmap"} {
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1] do_test func-29.4 {
if {$x>100} {set x many} set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
set x if {$x>100} {set x many}
} {many} set x
} {many}
}
do_test func-29.5 { do_test func-29.5 {
db close db close
sqlite3 db test.db sqlite3 db test.db

View File

@@ -123,6 +123,7 @@ foreach AutoVacuumMode [list 0 1] {
forcedelete test.db test.db-journal forcedelete test.db test.db-journal
sqlite3 db test.db sqlite3 db test.db
execsql "PRAGMA mmap_size = 0"
execsql "PRAGMA auto_vacuum = $AutoVacuumMode" execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
do_test incrblob-2.$AutoVacuumMode.1 { do_test incrblob-2.$AutoVacuumMode.1 {
@@ -149,6 +150,7 @@ foreach AutoVacuumMode [list 0 1] {
# Open and close the db to make sure the page cache is empty. # Open and close the db to make sure the page cache is empty.
db close db close
sqlite3 db test.db sqlite3 db test.db
execsql "PRAGMA mmap_size = 0"
# Read the last 20 bytes of the blob via a blob handle. # Read the last 20 bytes of the blob via a blob handle.
set ::blob [db incrblob blobs v 1] set ::blob [db incrblob blobs v 1]
@@ -171,6 +173,7 @@ foreach AutoVacuumMode [list 0 1] {
# Open and close the db to make sure the page cache is empty. # Open and close the db to make sure the page cache is empty.
db close db close
sqlite3 db test.db sqlite3 db test.db
execsql "PRAGMA mmap_size = 0"
# Write the second-to-last 20 bytes of the blob via a blob handle. # Write the second-to-last 20 bytes of the blob via a blob handle.
# #
@@ -200,6 +203,7 @@ foreach AutoVacuumMode [list 0 1] {
# Open and close the db to make sure the page cache is empty. # Open and close the db to make sure the page cache is empty.
db close db close
sqlite3 db test.db sqlite3 db test.db
execsql { PRAGMA mmap_size = 0 }
execsql { SELECT i FROM blobs } execsql { SELECT i FROM blobs }
} {45} } {45}

View File

@@ -92,7 +92,7 @@ do_test pageropt-1.5 {
pagercount_sql { pagercount_sql {
SELECT hex(x) FROM t1 SELECT hex(x) FROM t1
} }
} [list 6 0 0 $blobcontent] } [list [expr {[permutation]=="mmap" ? 1 : 6}] 0 0 $blobcontent]
do_test pageropt-1.6 { do_test pageropt-1.6 {
pagercount_sql { pagercount_sql {
SELECT hex(x) FROM t1 SELECT hex(x) FROM t1

View File

@@ -134,6 +134,14 @@ test_suite "veryquick" -prefix "" -description {
"Very" quick test suite. Runs in less than 5 minutes on a workstation. "Very" quick test suite. Runs in less than 5 minutes on a workstation.
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 [
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
]
test_suite "mmap" -prefix "mm-" -description {
Similar to veryquick. Except with memory mapping enabled.
} -presql {
pragma mmap_size = -65536;
} -files [ } -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* \ test_set $allquicktests -exclude *malloc* *ioerr* *fault* \
multiplex* server1.test shared2.test shared6.test multiplex* server1.test shared2.test shared6.test