/ Check-in [6183f1bd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the sqlite3_io_methods.xMremap() method to the VFS interface. Also "PRAGMA mmap_size".
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental-mmap
Files: files | file ages | folders
SHA1:6183f1bd86ceed76d22d9762f3d7eb33262c62d1
User & Date: dan 2013-03-19 19:28:06
Context
2013-03-20
10:07
Add test file mmap1.test. check-in: aee1f53a user: dan tags: experimental-mmap
2013-03-19
19:28
Add the sqlite3_io_methods.xMremap() method to the VFS interface. Also "PRAGMA mmap_size". check-in: 6183f1bd user: dan tags: experimental-mmap
2013-03-16
20:19
When possible, use memcpy() to and from the mapped region instead of xWrite() and xRead(). check-in: f8ca5622 user: dan tags: experimental-mmap
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  2125   2125     BtShared *pBt = p->pBt;
  2126   2126     assert( sqlite3_mutex_held(p->db->mutex) );
  2127   2127     sqlite3BtreeEnter(p);
  2128   2128     sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  2129   2129     sqlite3BtreeLeave(p);
  2130   2130     return SQLITE_OK;
  2131   2131   }
         2132  +
         2133  +/*
         2134  +** Change the limit on the amount of the database file that may be
         2135  +** memory mapped.
         2136  +*/
         2137  +int sqlite3BtreeSetMmapSize(Btree *p, int nMap){
         2138  +  BtShared *pBt = p->pBt;
         2139  +  assert( sqlite3_mutex_held(p->db->mutex) );
         2140  +  sqlite3BtreeEnter(p);
         2141  +  sqlite3PagerSetMmapsize(pBt->pPager, nMap);
         2142  +  sqlite3BtreeLeave(p);
         2143  +  return SQLITE_OK;
         2144  +}
  2132   2145   
  2133   2146   /*
  2134   2147   ** Change the way data is synced to disk in order to increase or decrease
  2135   2148   ** how well the database resists damage due to OS crashes and power
  2136   2149   ** failures.  Level 1 is the same as asynchronous (no syncs() occur and
  2137   2150   ** there is a high probability of damage)  Level 2 is the default.  There
  2138   2151   ** is a very low but non-zero probability of damage.  Level 3 reduces the

Changes to src/btree.h.

    59     59   #define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
    60     60   #define BTREE_MEMORY        2  /* This is an in-memory DB */
    61     61   #define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
    62     62   #define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */
    63     63   
    64     64   int sqlite3BtreeClose(Btree*);
    65     65   int sqlite3BtreeSetCacheSize(Btree*,int);
           66  +int sqlite3BtreeSetMmapSize(Btree*, int);
    66     67   int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
    67     68   int sqlite3BtreeSyncDisabled(Btree*);
    68     69   int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
    69     70   int sqlite3BtreeGetPageSize(Btree*);
    70     71   int sqlite3BtreeMaxPageCount(Btree*,int);
    71     72   u32 sqlite3BtreeLastPage(Btree*);
    72     73   int sqlite3BtreeSecureDelete(Btree*,int);

Changes to src/os.c.

   135    135     int iPage,
   136    136     int pgsz,
   137    137     int bExtend,                    /* True to extend file if necessary */
   138    138     void volatile **pp              /* OUT: Pointer to mapping */
   139    139   ){
   140    140     DO_OS_MALLOC_TEST(id);
   141    141     return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
          142  +}
          143  +int sqlite3OsMremap(sqlite3_file *id, i64 iOff, i64 nOld, i64 nNew, void **pp){
          144  +  return id->pMethods->xMremap(id, iOff, nOld, nNew, pp);
   142    145   }
   143    146   
   144    147   /*
   145    148   ** The next group of routines are convenience wrappers around the
   146    149   ** VFS methods.
   147    150   */
   148    151   int sqlite3OsOpen(

Changes to src/os.h.

   255    255   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   256    256   int sqlite3OsSectorSize(sqlite3_file *id);
   257    257   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
   258    258   int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
   259    259   int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
   260    260   void sqlite3OsShmBarrier(sqlite3_file *id);
   261    261   int sqlite3OsShmUnmap(sqlite3_file *id, int);
          262  +int sqlite3OsMremap(sqlite3_file *id, i64, i64, i64, void **);
   262    263   
   263    264   
   264    265   /* 
   265    266   ** Functions for accessing sqlite3_vfs methods 
   266    267   */
   267    268   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   268    269   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);

Changes to src/os_unix.c.

  4424   4424   
  4425   4425   #else
  4426   4426   # define unixShmMap     0
  4427   4427   # define unixShmLock    0
  4428   4428   # define unixShmBarrier 0
  4429   4429   # define unixShmUnmap   0
  4430   4430   #endif /* #ifndef SQLITE_OMIT_WAL */
         4431  +
         4432  +/*
         4433  +** Map, remap or unmap part of the database file.
         4434  +*/
         4435  +static int unixMremap(
         4436  +  sqlite3_file *fd,               /* Main database file */
         4437  +  sqlite3_int64 iOff,             /* Offset to start mapping at */
         4438  +  sqlite3_int64 nOld,             /* Size of old mapping, or zero */
         4439  +  sqlite3_int64 nNew,             /* Size of new mapping, or zero */
         4440  +  void **ppMap                    /* IN/OUT: Old/new mappings */
         4441  +){
         4442  +  unixFile *p = (unixFile *)fd;   /* The underlying database file */
         4443  +  int rc = SQLITE_OK;             /* Return code */
         4444  +  void *pNew = 0;                 /* New mapping */
         4445  +
         4446  +  assert( iOff==0 );
         4447  +
         4448  +  if( nOld!=0 ){
         4449  +    void *pOld = *ppMap;
         4450  +    munmap(pOld, nOld);
         4451  +  }
         4452  +
         4453  +  if( nNew>0 ){
         4454  +    int flags = PROT_READ;
         4455  +    if( (p->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
         4456  +    nNew = (nNew+4095) & ~(i64)((1 << 12)-1);
         4457  +    pNew = mmap(0, nNew, flags, MAP_SHARED, p->h, iOff);
         4458  +    if( pNew==MAP_FAILED ){
         4459  +      pNew = 0;
         4460  +      rc = SQLITE_IOERR;
         4461  +    }
         4462  +  }
         4463  +
         4464  +  *ppMap = pNew;
         4465  +  return rc;
         4466  +}
  4431   4467   
  4432   4468   /*
  4433   4469   ** Here ends the implementation of all sqlite3_file methods.
  4434   4470   **
  4435   4471   ********************** End sqlite3_file Methods *******************************
  4436   4472   ******************************************************************************/
  4437   4473   
................................................................................
  4483   4519      CKLOCK,                     /* xCheckReservedLock */                      \
  4484   4520      unixFileControl,            /* xFileControl */                            \
  4485   4521      unixSectorSize,             /* xSectorSize */                             \
  4486   4522      unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
  4487   4523      unixShmMap,                 /* xShmMap */                                 \
  4488   4524      unixShmLock,                /* xShmLock */                                \
  4489   4525      unixShmBarrier,             /* xShmBarrier */                             \
  4490         -   unixShmUnmap                /* xShmUnmap */                               \
         4526  +   unixShmUnmap,               /* xShmUnmap */                               \
         4527  +   unixMremap,                 /* xMremap */                                 \
  4491   4528   };                                                                           \
  4492   4529   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  4493   4530     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  4494   4531     return &METHOD;                                                            \
  4495   4532   }                                                                            \
  4496   4533   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  4497   4534       = FINDER##Impl;
................................................................................
  4500   4537   ** Here are all of the sqlite3_io_methods objects for each of the
  4501   4538   ** locking strategies.  Functions that return pointers to these methods
  4502   4539   ** are also created.
  4503   4540   */
  4504   4541   IOMETHODS(
  4505   4542     posixIoFinder,            /* Finder function name */
  4506   4543     posixIoMethods,           /* sqlite3_io_methods object name */
  4507         -  2,                        /* shared memory is enabled */
         4544  +  3,                        /* shared memory and mmap are enabled */
  4508   4545     unixClose,                /* xClose method */
  4509   4546     unixLock,                 /* xLock method */
  4510   4547     unixUnlock,               /* xUnlock method */
  4511   4548     unixCheckReservedLock     /* xCheckReservedLock method */
  4512   4549   )
  4513   4550   IOMETHODS(
  4514   4551     nolockIoFinder,           /* Finder function name */

Changes to src/pager.c.

   655    655     PagerSavepoint *aSavepoint; /* Array of active savepoints */
   656    656     int nSavepoint;             /* Number of elements in aSavepoint[] */
   657    657     char dbFileVers[16];        /* Changes whenever database file changes */
   658    658   
   659    659     void *pMap;                 /* Memory mapped prefix of database file */
   660    660     i64 nMap;                   /* Size of mapping at pMap in bytes */ 
   661    661     i64 nMapValid;              /* Bytes at pMap known to be valid */
          662  +  i64 nMapLimit;              /* Maximum permitted mapping size */
          663  +  int nMapCfgLimit;           /* Configured limit value */
   662    664     int nMmapOut;               /* Number of mmap pages currently outstanding */
   663    665     PgHdr *pFree;               /* List of free mmap page headers (pDirty) */
          666  +  int bMapResize;             /* Check if the mapping should be resized */
   664    667     /*
   665    668     ** End of the routinely-changing class members
   666    669     ***************************************************************************/
   667    670   
   668    671     u16 nExtra;                 /* Add this many bytes to each in-memory page */
   669    672     i16 nReserve;               /* Number of unused bytes at end of each page */
   670    673     u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
................................................................................
  3351   3354   
  3352   3355   /*
  3353   3356   ** Change the maximum number of in-memory pages that are allowed.
  3354   3357   */
  3355   3358   void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
  3356   3359     sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
  3357   3360   }
         3361  +
         3362  +/*
         3363  +** Set Pager.nMapLimit, the maximum permitted mapping size, based on the
         3364  +** current values of Pager.nMapCfgLimit and Pager.pageSize.
         3365  +**
         3366  +** If this connection should not use mmap at all, set nMapLimit to zero.
         3367  +*/
         3368  +static void pagerFixMaplimit(Pager *pPager){
         3369  +  if( isOpen(pPager->fd)==0 
         3370  +   || pPager->fd->pMethods->iVersion<3 
         3371  +   || pPager->fd->pMethods->xMremap==0 
         3372  +   || pPager->tempFile 
         3373  +   || pPager->pWal 
         3374  +  ){
         3375  +    pPager->nMapLimit = 0;
         3376  +  }else if( pPager->nMapCfgLimit<0 ){
         3377  +    pPager->nMapLimit = (i64)pPager->nMapCfgLimit * -1024;
         3378  +  }else{
         3379  +    pPager->nMapLimit = (i64)pPager->nMapCfgLimit * pPager->pageSize;
         3380  +  }
         3381  +}
         3382  +
         3383  +/*
         3384  +** Change the maximum size of any memory mapping made of the database file.
         3385  +*/
         3386  +void sqlite3PagerSetMmapsize(Pager *pPager, int nMap){
         3387  +  pPager->nMapCfgLimit = nMap;
         3388  +  pagerFixMaplimit(pPager);
         3389  +}
  3358   3390   
  3359   3391   /*
  3360   3392   ** Free as much memory as possible from the pager.
  3361   3393   */
  3362   3394   void sqlite3PagerShrink(Pager *pPager){
  3363   3395     sqlite3PcacheShrink(pPager->pPCache);
  3364   3396   }
................................................................................
  3587   3619   
  3588   3620     *pPageSize = pPager->pageSize;
  3589   3621     if( rc==SQLITE_OK ){
  3590   3622       if( nReserve<0 ) nReserve = pPager->nReserve;
  3591   3623       assert( nReserve>=0 && nReserve<1000 );
  3592   3624       pPager->nReserve = (i16)nReserve;
  3593   3625       pagerReportSize(pPager);
         3626  +    pagerFixMaplimit(pPager);
  3594   3627     }
  3595   3628     return rc;
  3596   3629   }
  3597   3630   
  3598   3631   /*
  3599   3632   ** Return a pointer to the "temporary page" buffer held internally
  3600   3633   ** by the pager.  This is a buffer that is big enough to hold the
................................................................................
  3812   3845     }
  3813   3846     if( rc==SQLITE_OK ){
  3814   3847       rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
  3815   3848     }
  3816   3849     return rc;
  3817   3850   }
  3818   3851   
  3819         -#include <sys/mman.h>
  3820         -
  3821   3852   /*
  3822         -** Unmap any mapping of the database file.
         3853  +** Unmap any memory mapping of the database file.
  3823   3854   */
  3824   3855   static int pagerUnmap(Pager *pPager){
  3825   3856     if( pPager->pMap ){
  3826         -    munmap(pPager->pMap, pPager->nMap);
  3827         -    pPager->pMap = 0;
         3857  +    sqlite3OsMremap(pPager->fd, 0, pPager->nMap, 0, &pPager->pMap);
  3828   3858       pPager->nMap = 0;
  3829   3859       pPager->nMapValid = 0;
  3830   3860     }
  3831   3861     return SQLITE_OK;
  3832   3862   }
  3833   3863   
         3864  +/*
         3865  +** Create, or recreate, the memory mapping of the database file.
         3866  +*/
  3834   3867   static int pagerMap(Pager *pPager){
  3835         -  int rc;
  3836         -  i64 sz = 0;
         3868  +  int rc = SQLITE_OK;             /* Return code */
         3869  +  Pgno nPg;                       /* Size of mapping to request in pages */
         3870  +  i64 sz;                         /* Size of mapping to request in bytes */
  3837   3871   
  3838         -  assert( pPager->pMap==0 && pPager->nMap==0 );
         3872  +  assert( pPager->pWal==0 && isOpen(pPager->fd) && pPager->tempFile==0 );
         3873  +  assert( pPager->pMap==0 || pPager->nMap>0 );
         3874  +  assert( pPager->eState>=1 );
         3875  +  assert( pPager->nMmapOut==0 );
         3876  +  assert( pPager->nMapLimit>0 );
  3839   3877   
  3840         -  rc = sqlite3OsFileSize(pPager->fd, &sz);
  3841         -  sz = sz & ~(4096-1);
         3878  +  /* Figure out how large a mapping to request. Set variable sz to this 
         3879  +  ** value in bytes. */
         3880  +  nPg = (pPager->eState==1) ? pPager->dbSize : pPager->dbFileSize;
         3881  +  sz = (i64)nPg * pPager->pageSize;
         3882  +  if( sz>pPager->nMapLimit ) sz = pPager->nMapLimit;
  3842   3883   
  3843         -  if( rc==SQLITE_OK && sz>0 ){
  3844         -    int fd;
  3845         -    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_GETFD, (void *)&fd);
         3884  +  if( sz!=pPager->nMapValid ){
         3885  +    rc = sqlite3OsMremap(pPager->fd, 0, pPager->nMap, sz, &pPager->pMap);
  3846   3886       if( rc==SQLITE_OK ){
  3847         -      void *pMap = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  3848         -      if( pMap==MAP_FAILED ){
  3849         -        return SQLITE_IOERR;
  3850         -      }
  3851         -      pPager->pMap = pMap;
  3852         -      pPager->nMapValid = pPager->nMap = sz;
  3853         -    }
  3854         -  }
  3855         -
  3856         -  return rc;
  3857         -}
  3858         -
  3859         -static int pagerRemap(Pager *pPager, Pgno nPage){
  3860         -  i64 sz = (i64)nPage * pPager->pageSize;
  3861         -  sz = sz & ~(4096-1);
  3862         -
  3863         -  if( pPager->nMap!=sz ){
  3864         -    void *pMap = mremap(pPager->pMap, pPager->nMap, sz, MREMAP_MAYMOVE);    
  3865         -    if( pMap==MAP_FAILED ){
  3866         -      return SQLITE_IOERR;
  3867         -    }
  3868         -    pPager->pMap = pMap;
  3869         -    pPager->nMapValid = pPager->nMap = sz;
  3870         -  }
         3887  +      assert( pPager->pMap!=0 );
         3888  +      pPager->nMap = sz;
         3889  +    }else{
         3890  +      assert( pPager->pMap==0 );
         3891  +      pPager->nMap = 0;
         3892  +    }
         3893  +    pPager->nMapValid = pPager->nMap;
         3894  +  }
         3895  +  pPager->bMapResize = 0;
         3896  +
         3897  +  return rc;
         3898  +}
         3899  +
         3900  +/*
         3901  +** Obtain a reference to a memory mapped page object for page number pgno. 
         3902  +** The caller must ensure that page pgno lies within the currently mapped 
         3903  +** region. If successful, set *ppPage to point to the new page reference
         3904  +** and return SQLITE_OK. Otherwise, return an SQLite error code and set
         3905  +** *ppPage to zero.
         3906  +**
         3907  +** Page references obtained by calling this function should be released
         3908  +** by calling pagerReleaseMapPage().
         3909  +*/
         3910  +static int pagerAcquireMapPage(Pager *pPager, Pgno pgno, PgHdr **ppPage){
         3911  +  PgHdr *p;                       /* Memory mapped page to return */
         3912  +
         3913  +  if( pPager->pFree ){
         3914  +    *ppPage = p = pPager->pFree;
         3915  +    pPager->pFree = p->pDirty;
         3916  +    p->pDirty = 0;
         3917  +    memset(p->pExtra, 0, pPager->nExtra);
         3918  +  }else{
         3919  +    *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
         3920  +    if( p==0 ){
         3921  +      return SQLITE_NOMEM;
         3922  +    }
         3923  +    p->pExtra = (void *)&p[1];
         3924  +    p->flags = PGHDR_MMAP;
         3925  +    p->nRef = 1;
         3926  +    p->pPager = pPager;
         3927  +  }
         3928  +
         3929  +  assert( p->pExtra==(void *)&p[1] );
         3930  +  assert( p->pPage==0 );
         3931  +  assert( p->flags==PGHDR_MMAP );
         3932  +  assert( p->pPager==pPager );
         3933  +  assert( p->nRef==1 );
         3934  +
         3935  +  p->pData = &((u8 *)pPager->pMap)[(i64)(pgno-1) * pPager->pageSize];
         3936  +  p->pgno = pgno;
         3937  +  pPager->nMmapOut++;
  3871   3938   
  3872   3939     return SQLITE_OK;
  3873   3940   }
  3874   3941   
  3875         -static int pagerAcquireMapPage(Pager *pPager, Pgno pgno, PgHdr **ppPage){
  3876         -  int rc;
  3877         -  *ppPage = 0;
  3878         -
  3879         -  assert( pPager->pWal==0 );
  3880         -
  3881         -  if( MEMDB==0 && pPager->tempFile==0 ){
  3882         -    if( pPager->pMap==0 ){
  3883         -      rc = pagerMap(pPager);
  3884         -      if( rc!=SQLITE_OK ) return rc;
  3885         -    }
  3886         -
  3887         -    if( pgno!=1 && pPager->pMap 
  3888         -     && pPager->nMapValid>=((i64)pgno*pPager->pageSize) 
  3889         -    ){
  3890         -      PgHdr *p;
  3891         -      if( pPager->pFree ){
  3892         -        p = pPager->pFree;
  3893         -        pPager->pFree = p->pDirty;
  3894         -        p->pDirty = 0;
  3895         -        memset(p->pExtra, 0, pPager->nExtra);
  3896         -      }else{
  3897         -        p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
  3898         -        if( p==0 ) return SQLITE_NOMEM;
  3899         -        p->pExtra = (void *)&p[1];
  3900         -        p->flags = PGHDR_MMAP;
  3901         -        p->nRef = 1;
  3902         -        p->pPager = pPager;
  3903         -      }
  3904         -
  3905         -      assert( p->pExtra==(void *)&p[1] );
  3906         -      assert( p->pPage==0 );
  3907         -      assert( p->flags==PGHDR_MMAP );
  3908         -      assert( p->pPager==pPager );
  3909         -      assert( p->nRef==1 );
  3910         -
  3911         -      p->pData = &((u8 *)pPager->pMap)[(i64)(pgno-1) * pPager->pageSize];
  3912         -      p->pgno = pgno;
  3913         -      pPager->nMmapOut++;
  3914         -      *ppPage = p;
  3915         -    }
  3916         -  }
  3917         -
  3918         -  return SQLITE_OK;
  3919         -}
  3920         -
         3942  +/*
         3943  +** Release a reference to page pPg. pPg must have been returned by an 
         3944  +** earlier call to pagerAcquireMapPage().
         3945  +*/
  3921   3946   static void pagerReleaseMapPage(PgHdr *pPg){
  3922   3947     Pager *pPager = pPg->pPager;
  3923   3948     pPager->nMmapOut--;
  3924   3949     pPg->pDirty = pPager->pFree;
  3925   3950     pPager->pFree = pPg;
  3926   3951   }
  3927   3952   
         3953  +/*
         3954  +** Free all PgHdr objects stored in the Pager.pFree list.
         3955  +*/
  3928   3956   static void pagerFreeMapHdrs(Pager *pPager){
  3929   3957     PgHdr *p;
  3930   3958     PgHdr *pNext;
  3931   3959     for(p=pPager->pFree; p; p=pNext){
  3932   3960       pNext = p->pDirty;
  3933   3961       sqlite3_free(p);
  3934   3962     }
................................................................................
  5111   5139           ** may have truncated the database file and then extended it back
  5112   5140           ** to its original size while this process was not holding a lock.
  5113   5141           ** In this case there may exist a Pager.pMap mapping that appears
  5114   5142           ** to be the right size but is not actually valid. Avoid this
  5115   5143           ** possibility by unmapping the db here. */
  5116   5144           pagerUnmap(pPager);
  5117   5145         }else if( pPager->pMap ){
  5118         -        pagerRemap(pPager, nPage);
         5146  +        pPager->bMapResize = 1;
  5119   5147         }
  5120   5148       }
  5121   5149   
  5122   5150       /* If there is a WAL file in the file-system, open this database in WAL
  5123   5151       ** mode. Otherwise, the following function call is a no-op.
  5124   5152       */
  5125   5153       rc = pagerOpenWalIfPresent(pPager);
................................................................................
  5222   5250     PgHdr *pPg = 0;
  5223   5251     const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
  5224   5252   
  5225   5253     /* It is acceptable to use a read-only (mmap) page for any page except
  5226   5254     ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
  5227   5255     ** flag was specified by the caller. And so long as the db is not a 
  5228   5256     ** temporary or in-memory database.  */
  5229         -  const int bMmapOk = (
  5230         -      (pgno!=1 && pPager->pWal==0 && !pPager->tempFile && !MEMDB)
         5257  +  const int bMmapOk = (pPager->nMapLimit>0 && pgno!=1
  5231   5258      && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
  5232   5259     );
  5233   5260   
  5234   5261     assert( pPager->eState>=PAGER_READER );
  5235   5262     assert( assert_pager_state(pPager) );
  5236   5263   
  5237   5264     if( pgno==0 ){
................................................................................
  5241   5268     /* If the pager is in the error state, return an error immediately. 
  5242   5269     ** Otherwise, request the page from the PCache layer. */
  5243   5270     if( pPager->errCode!=SQLITE_OK ){
  5244   5271       rc = pPager->errCode;
  5245   5272     }else{
  5246   5273   
  5247   5274       if( bMmapOk ){
  5248         -      if( pPager->pMap==0 ){
         5275  +      if( pPager->pMap==0 || (pPager->bMapResize && pPager->nMmapOut==0) ){
  5249   5276           rc = pagerMap(pPager);
  5250   5277         }
  5251   5278         if( rc==SQLITE_OK && pPager->nMap>=((i64)pgno * pPager->pageSize) ){
  5252   5279           if( pPager->eState>PAGER_READER ){
  5253   5280             (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
  5254   5281           }
  5255   5282           if( pPg==0 ){
................................................................................
  7010   7037     */
  7011   7038     if( rc==SQLITE_OK ){
  7012   7039       rc = sqlite3WalOpen(pPager->pVfs, 
  7013   7040           pPager->fd, pPager->zWal, pPager->exclusiveMode,
  7014   7041           pPager->journalSizeLimit, &pPager->pWal
  7015   7042       );
  7016   7043     }
         7044  +  pagerFixMaplimit(pPager);
  7017   7045   
  7018   7046     return rc;
  7019   7047   }
  7020   7048   
  7021   7049   
  7022   7050   /*
  7023   7051   ** The caller must be holding a SHARED lock on the database file to call
................................................................................
  7100   7128     */
  7101   7129     if( rc==SQLITE_OK && pPager->pWal ){
  7102   7130       rc = pagerExclusiveLock(pPager);
  7103   7131       if( rc==SQLITE_OK ){
  7104   7132         rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
  7105   7133                              pPager->pageSize, (u8*)pPager->pTmpSpace);
  7106   7134         pPager->pWal = 0;
         7135  +      pagerFixMaplimit(pPager);
  7107   7136       }
  7108   7137     }
  7109   7138     return rc;
  7110   7139   }
  7111   7140   
  7112   7141   #endif /* !SQLITE_OMIT_WAL */
  7113   7142   

Changes to src/pragma.c.

   740    740       }else{
   741    741         int size = sqlite3Atoi(zRight);
   742    742         pDb->pSchema->cache_size = size;
   743    743         sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
   744    744       }
   745    745     }else
   746    746   
          747  +  /*
          748  +  **  PRAGMA [database.]mmap_size
          749  +  **  PRAGMA [database.]mmap_size=N
          750  +  **
          751  +  ** Used to set or query the mapping size limit. The mapping size limit is
          752  +  ** used to limit the aggregate size of all memory mapped regions of the
          753  +  ** database file. If this parameter is set to zero, then memory mapping
          754  +  ** is not used at all. If it is set to a positive value, then it is
          755  +  ** interpreted as a maximum size in pages. If set to less than zero, then
          756  +  ** the absolute value is interpreted as a size limit in KB.
          757  +  **
          758  +  ** The default value is zero (do not use memory mapped IO).
          759  +  */
          760  +  if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
          761  +    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
          762  +    if( !zRight ){
          763  +      returnSingleInt(pParse, "mmap_size", pDb->pSchema->mmap_size);
          764  +    }else{
          765  +      int size = sqlite3Atoi(zRight);
          766  +      pDb->pSchema->mmap_size = size;
          767  +      sqlite3BtreeSetMmapSize(pDb->pBt, pDb->pSchema->mmap_size);
          768  +    }
          769  +  }else
          770  +
   747    771     /*
   748    772     **   PRAGMA temp_store
   749    773     **   PRAGMA temp_store = "default"|"memory"|"file"
   750    774     **
   751    775     ** Return or set the local value of the temp_store flag.  Changing
   752    776     ** the local value does not make changes to the disk file and the default
   753    777     ** value will be restored the next time the database is opened.

Changes to src/sqlite.h.in.

   702    702   ** to xWrite().
   703    703   **
   704    704   ** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
   705    705   ** in the unread portions of the buffer with zeros.  A VFS that
   706    706   ** fails to zero-fill short reads might seem to work.  However,
   707    707   ** failure to zero-fill short reads will eventually lead to
   708    708   ** database corruption.
          709  +**
          710  +** Assuming parameter nNew is non-zero, the xMremap method should attempt
          711  +** to memory map a region nNew bytes in size starting at offset iOffset
          712  +** of the file.  If successful, it should set *ppMap to point to the
          713  +** mapping and return SQLITE_OK. If the file is opened for read-write
          714  +** access, then the mapping should also be read-write.
          715  +**
          716  +** If nOld is non-zero, then the initial value of *ppMap points to a
          717  +** mapping returned by a previous call to xMremap. The existing mapping
          718  +** is nOld bytes in size and starts at offset iOffset of the file. In
          719  +** this case the xMremap method is expected to unmap the existing mapping
          720  +** and overwrite *ppMap with the pointer to the new mapping. If nOld is
          721  +** zero, then the initial value of *ppMap is undefined.
          722  +**
          723  +** If nNew is zero, then no new mapping should be created. Any old
          724  +** mapping must still be unmapped if nOld is non-zero. If the nOld
          725  +** parameter is non-zero, then the existing mapping is always unmapped -
          726  +** even if an error occurs.
   709    727   */
   710    728   typedef struct sqlite3_io_methods sqlite3_io_methods;
   711    729   struct sqlite3_io_methods {
   712    730     int iVersion;
   713    731     int (*xClose)(sqlite3_file*);
   714    732     int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
   715    733     int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
................................................................................
   724    742     int (*xDeviceCharacteristics)(sqlite3_file*);
   725    743     /* Methods above are valid for version 1 */
   726    744     int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
   727    745     int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
   728    746     void (*xShmBarrier)(sqlite3_file*);
   729    747     int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   730    748     /* Methods above are valid for version 2 */
          749  +  int (*xMremap)(sqlite3_file *fd, 
          750  +      sqlite3_int64 iOff, sqlite3_int64 nOld, sqlite3_int64 nNew, void **ppMap);
          751  +  /* Methods above are valid for version 3 */
   731    752     /* Additional methods may be added in future releases */
   732    753   };
   733    754   
   734    755   /*
   735    756   ** CAPI3REF: Standard File Control Opcodes
   736    757   **
   737    758   ** These integer constants are opcodes for the xFileControl method

Changes to src/sqliteInt.h.

   742    742     Hash trigHash;       /* All triggers indexed by name */
   743    743     Hash fkeyHash;       /* All foreign keys by referenced table name */
   744    744     Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
   745    745     u8 file_format;      /* Schema format version for this file */
   746    746     u8 enc;              /* Text encoding used by this database */
   747    747     u16 flags;           /* Flags associated with this schema */
   748    748     int cache_size;      /* Number of pages to use in the cache */
          749  +  int mmap_size;       /* Number of pages to memory map */
   749    750   };
   750    751   
   751    752   /*
   752    753   ** These macros can be used to test, set, or clear bits in the 
   753    754   ** Db.pSchema->flags field.
   754    755   */
   755    756   #define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->flags&(P))==(P))

Changes to src/test1.c.

  5855   5855   ){
  5856   5856     char buf[1024];
  5857   5857     struct rusage r;
  5858   5858     memset(&r, 0, sizeof(r));
  5859   5859     getrusage(RUSAGE_SELF, &r);
  5860   5860   
  5861   5861     sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", 
  5862         -    r.ru_utime.tv_sec, r.ru_utime.tv_usec, 
  5863         -    r.ru_stime.tv_sec, r.ru_stime.tv_usec, 
  5864         -    r.ru_minflt, r.ru_majflt
         5862  +    (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec, 
         5863  +    (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec, 
         5864  +    (int)r.ru_minflt, (int)r.ru_majflt
  5865   5865     );
  5866   5866     Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
  5867   5867     return TCL_OK;
  5868   5868   }
  5869   5869   
  5870   5870   #if SQLITE_OS_WIN
  5871   5871   /*

Changes to test/dbstatus2.test.

    36     36   proc db_write {db {reset 0}} {
    37     37     sqlite3_db_status $db CACHE_WRITE $reset
    38     38   }
    39     39   
    40     40   do_test 1.1 {
    41     41     db close
    42     42     sqlite3 db test.db
           43  +  execsql { PRAGMA mmap_size = 0 }
    43     44     expr {[file size test.db] / 1024}
    44     45   } 6
    45     46   
    46     47   do_test 1.2 {
    47     48     execsql { SELECT b FROM t1 WHERE a=2 }
    48     49     db_hit_miss db
    49     50   } {{0 2 0} {0 4 0}}

Changes to test/exclusive2.test.

    20     20   #
    21     21   do_not_use_codec
    22     22   
    23     23   ifcapable {!pager_pragmas} {
    24     24     finish_test
    25     25     return
    26     26   }
           27  +
           28  +# Tests in this file verify that locking_mode=exclusive causes SQLite to
           29  +# use cached pages even if the database is changed on disk. This doesn't
           30  +# work with mmap.
           31  +if {[permutation]=="mmap"} {
           32  +  finish_test
           33  +  return
           34  +}
    27     35   
    28     36   # This module does not work right if the cache spills at unexpected
    29     37   # moments.  So disable the soft-heap-limit.
    30     38   #
    31     39   sqlite3_soft_heap_limit 0
    32     40   
    33     41   proc pagerChangeCounter {filename new {fd ""}} {

Changes to test/func.test.

  1269   1269   } {1}
  1270   1270   do_test func-29.3 {
  1271   1271     db close
  1272   1272     sqlite3 db test.db
  1273   1273     sqlite3_db_status db CACHE_MISS 1
  1274   1274     db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
  1275   1275   } {integer null real blob text}
  1276         -do_test func-29.4 {
  1277         -  set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
  1278         -  if {$x>100} {set x many}
  1279         -  set x
  1280         -} {many}
         1276  +if {[permutation] != "mmap"} {
         1277  +  do_test func-29.4 {
         1278  +    set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
         1279  +    if {$x>100} {set x many}
         1280  +    set x
         1281  +  } {many}
         1282  +}
  1281   1283   do_test func-29.5 {
  1282   1284     db close
  1283   1285     sqlite3 db test.db
  1284   1286     sqlite3_db_status db CACHE_MISS 1
  1285   1287     db eval {SELECT sum(length(x)) FROM t29}
  1286   1288   } {1000009}
  1287   1289   do_test func-29.6 {

Changes to test/incrblob.test.

   119    119       }
   120    120     }
   121    121   
   122    122     db close
   123    123     forcedelete test.db test.db-journal
   124    124   
   125    125     sqlite3 db test.db
          126  +  execsql "PRAGMA mmap_size = 0"
   126    127     execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
   127    128   
   128    129     do_test incrblob-2.$AutoVacuumMode.1 {
   129    130       set ::str [string repeat abcdefghij 2900]
   130    131       execsql {
   131    132         BEGIN;
   132    133         CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
................................................................................
   145    146       } $AutoVacuumMode
   146    147     }
   147    148   
   148    149     do_test incrblob-2.$AutoVacuumMode.3 {
   149    150       # Open and close the db to make sure the page cache is empty.
   150    151       db close
   151    152       sqlite3 db test.db
          153  +    execsql "PRAGMA mmap_size = 0"
   152    154     
   153    155       # Read the last 20 bytes of the blob via a blob handle.
   154    156       set ::blob [db incrblob blobs v 1]
   155    157       seek $::blob -20 end
   156    158       set ::fragment [read $::blob]
   157    159       close $::blob
   158    160     
................................................................................
   167    169       string range [db one {SELECT v FROM blobs}] end-19 end
   168    170     } $::fragment
   169    171   
   170    172     do_test incrblob-2.$AutoVacuumMode.5 {
   171    173       # Open and close the db to make sure the page cache is empty.
   172    174       db close
   173    175       sqlite3 db test.db
          176  +    execsql "PRAGMA mmap_size = 0"
   174    177     
   175    178       # Write the second-to-last 20 bytes of the blob via a blob handle.
   176    179       #
   177    180       set ::blob [db incrblob blobs v 1]
   178    181       seek $::blob -40 end
   179    182       puts -nonewline $::blob "1234567890abcdefghij"
   180    183       flush $::blob
................................................................................
   196    199       string range [db one {SELECT v FROM blobs}] end-39 end-20
   197    200     } "1234567890abcdefghij"
   198    201   
   199    202     do_test incrblob-2.$AutoVacuumMode.8 {
   200    203       # Open and close the db to make sure the page cache is empty.
   201    204       db close
   202    205       sqlite3 db test.db
          206  +    execsql { PRAGMA mmap_size = 0 }
   203    207   
   204    208       execsql { SELECT i FROM blobs } 
   205    209     } {45}
   206    210   
   207    211     do_test incrblob-2.$AutoVacuumMode.9 {
   208    212       nRead db
   209    213     } [expr $AutoVacuumMode ? 4 : 30]

Changes to test/pageropt.test.

    88     88   # must refill.
    89     89   #
    90     90   do_test pageropt-1.5 {
    91     91     db2 eval {CREATE TABLE t2(y)}
    92     92     pagercount_sql {
    93     93       SELECT hex(x) FROM t1
    94     94     }
    95         -} [list 6 0 0 $blobcontent]
           95  +} [list [expr {[permutation]=="mmap" ? 1 : 6}] 0 0 $blobcontent]
    96     96   do_test pageropt-1.6 {
    97     97     pagercount_sql {
    98     98       SELECT hex(x) FROM t1
    99     99     }
   100    100   } [list 0 0 0 $blobcontent]
   101    101   
   102    102   # Verify that the last page of an overflow chain is not read from

Changes to test/permutations.test.

   130    130   #
   131    131   lappend ::testsuitelist xxx
   132    132   
   133    133   test_suite "veryquick" -prefix "" -description {
   134    134     "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
   135    135     This test suite is the same as the "quick" tests, except that some files
   136    136     that test malloc and IO errors are omitted.
          137  +} -files [
          138  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
          139  +]
          140  +
          141  +test_suite "mmap" -prefix "mm-" -description {
          142  +  Similar to veryquick. Except with memory mapping enabled.
          143  +} -presql {
          144  +  pragma mmap_size = -65536;
   137    145   } -files [
   138    146     test_set $allquicktests -exclude *malloc* *ioerr* *fault* \
   139    147     multiplex* server1.test shared2.test shared6.test
   140    148   ]
   141    149   
   142    150   test_suite "valgrind" -prefix "" -description {
   143    151     Run the "veryquick" test suite with a couple of multi-process tests (that