/ Check-in [ec37ad6d]
Login

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

Overview
Comment:Hack to have multiple connections to a single file share a single memory mapping of the databse file.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | shared-mapping-hack
Files: files | file ages | folders
SHA3-256: ec37ad6d08362f4c9faad9b629c0fa23f5864ff6ad7f4cbed93a25d5f7b815d8
User & Date: dan 2017-09-12 18:03:12
References
2017-09-22
11:09
Cherrypick [ec37ad6d08] into this branch. With this patch, if SQLITE_SHARED_MAPPING is defined at build-time SQLite will use a single memory mapping for multiple connections to the same database file within a single process. check-in: c7a5880d user: dan tags: begin-concurrent
Context
2017-09-22
11:09
Cherrypick [ec37ad6d08] into this branch. With this patch, if SQLITE_SHARED_MAPPING is defined at build-time SQLite will use a single memory mapping for multiple connections to the same database file within a single process. check-in: c7a5880d user: dan tags: begin-concurrent
2017-09-12
18:11
Merge the mutex-free PRNG change into this branch. check-in: 8b1fc4b9 user: dan tags: shared-mapping-hack
18:03
Hack to have multiple connections to a single file share a single memory mapping of the databse file. check-in: ec37ad6d user: dan tags: shared-mapping-hack
15:05
Fix an error in [b22cdd67] that can cause a negative infinity to be (rarely) reported as a positive infinity. check-in: 9780b23c user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

    42     42   **   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
    43     43   **   *  Definitions of sqlite3_vfs objects for all locking methods
    44     44   **      plus implementations of sqlite3_os_init() and sqlite3_os_end().
    45     45   */
    46     46   #include "sqliteInt.h"
    47     47   #if SQLITE_OS_UNIX              /* This file is used on unix only */
    48     48   
           49  +#define SQLITE_SHARED_MAPPING 1
           50  +
    49     51   /*
    50     52   ** There are various methods for file locking used for concurrency
    51     53   ** control:
    52     54   **
    53     55   **   1. POSIX locking (the default),
    54     56   **   2. No locking,
    55     57   **   3. Dot-file locking,
................................................................................
  1111   1113   #if SQLITE_ENABLE_LOCKING_STYLE
  1112   1114     unsigned long long sharedByte;  /* for AFP simulated shared lock */
  1113   1115   #endif
  1114   1116   #if OS_VXWORKS
  1115   1117     sem_t *pSem;                    /* Named POSIX semaphore */
  1116   1118     char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
  1117   1119   #endif
         1120  +#ifdef SQLITE_SHARED_MAPPING
         1121  +  sqlite3_int64 nSharedMapping;   /* Size of mapped region in bytes */
         1122  +  void *pSharedMapping;           /* Memory mapped region */
         1123  +#endif
  1118   1124   };
  1119   1125   
  1120   1126   /*
  1121   1127   ** A lists of all unixInodeInfo objects.
  1122   1128   */
  1123   1129   static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
  1124   1130   static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
................................................................................
  1245   1251   static void releaseInodeInfo(unixFile *pFile){
  1246   1252     unixInodeInfo *pInode = pFile->pInode;
  1247   1253     assert( unixMutexHeld() );
  1248   1254     if( ALWAYS(pInode) ){
  1249   1255       pInode->nRef--;
  1250   1256       if( pInode->nRef==0 ){
  1251   1257         assert( pInode->pShmNode==0 );
         1258  +#ifdef SQLITE_SHARED_MAPPING
         1259  +      if( pInode->pSharedMapping ){
         1260  +        osMunmap(pInode->pSharedMapping, pInode->nSharedMapping);
         1261  +        pInode->pSharedMapping = 0;
         1262  +        pInode->nSharedMapping = 0;
         1263  +      }
         1264  +#endif
  1252   1265         closePendingFds(pFile);
  1253   1266         if( pInode->pPrev ){
  1254   1267           assert( pInode->pPrev->pNext==pInode );
  1255   1268           pInode->pPrev->pNext = pInode->pNext;
  1256   1269         }else{
  1257   1270           assert( inodeList==pInode );
  1258   1271           inodeList = pInode->pNext;
................................................................................
  2051   2064     return SQLITE_OK;
  2052   2065   }
  2053   2066   
  2054   2067   /*
  2055   2068   ** Close the file.
  2056   2069   */
  2057   2070   static int nolockClose(sqlite3_file *id) {
         2071  +#ifdef SQLITE_SHARED_MAPPING
         2072  +  unixFile *pFd = (unixFile*)id;
         2073  +  if( pFd->pInode ){
         2074  +    unixEnterMutex();
         2075  +    releaseInodeInfo(pFd);
         2076  +    unixLeaveMutex();
         2077  +  }
         2078  +#endif
  2058   2079     return closeUnixFile(id);
  2059   2080   }
  2060   2081   
  2061   2082   /******************* End of the no-op lock implementation *********************
  2062   2083   ******************************************************************************/
  2063   2084   
  2064   2085   /******************************************************************************
................................................................................
  3870   3891         if( newLimit>0 && sizeof(size_t)<8 ){
  3871   3892           newLimit = (newLimit & 0x7FFFFFFF);
  3872   3893         }
  3873   3894   
  3874   3895         *(i64*)pArg = pFile->mmapSizeMax;
  3875   3896         if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
  3876   3897           pFile->mmapSizeMax = newLimit;
         3898  +#ifdef SQLITE_SHARED_MAPPING
         3899  +        if( pFile->pInode==0 )
         3900  +#endif
  3877   3901           if( pFile->mmapSize>0 ){
  3878   3902             unixUnmapfile(pFile);
  3879   3903             rc = unixMapfile(pFile, -1);
  3880   3904           }
  3881   3905         }
  3882   3906         return rc;
  3883   3907       }
................................................................................
  4770   4794   
  4771   4795   #if SQLITE_MAX_MMAP_SIZE>0
  4772   4796   /*
  4773   4797   ** If it is currently memory mapped, unmap file pFd.
  4774   4798   */
  4775   4799   static void unixUnmapfile(unixFile *pFd){
  4776   4800     assert( pFd->nFetchOut==0 );
         4801  +#ifdef SQLITE_SHARED_MAPPING
         4802  +  if( pFd->pInode ) return;
         4803  +#endif
  4777   4804     if( pFd->pMapRegion ){
  4778   4805       osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
  4779   4806       pFd->pMapRegion = 0;
  4780   4807       pFd->mmapSize = 0;
  4781   4808       pFd->mmapSizeActual = 0;
  4782   4809     }
  4783   4810   }
................................................................................
  4900   4927         return SQLITE_IOERR_FSTAT;
  4901   4928       }
  4902   4929       nMap = statbuf.st_size;
  4903   4930     }
  4904   4931     if( nMap>pFd->mmapSizeMax ){
  4905   4932       nMap = pFd->mmapSizeMax;
  4906   4933     }
         4934  +
         4935  +#ifdef SQLITE_SHARED_MAPPING
         4936  +  if( pFd->pInode ){
         4937  +    unixInodeInfo *pInode = pFd->pInode;
         4938  +    if( pFd->pMapRegion ) return SQLITE_OK;
         4939  +    unixEnterMutex();
         4940  +    if( pInode->pSharedMapping==0 ){
         4941  +      u8 *pNew = osMmap(0, nMap, PROT_READ, MAP_SHARED, pFd->h, 0);
         4942  +      if( pNew==MAP_FAILED ){
         4943  +        unixLogError(SQLITE_OK, "mmap", pFd->zPath);
         4944  +        pFd->mmapSizeMax = 0;
         4945  +      }else{
         4946  +        pInode->pSharedMapping = pNew;
         4947  +        pInode->nSharedMapping = nMap;
         4948  +      }
         4949  +    }
         4950  +    pFd->pMapRegion = pInode->pSharedMapping;
         4951  +    pFd->mmapSizeActual = pFd->mmapSize = pInode->nSharedMapping;
         4952  +    unixLeaveMutex();
         4953  +    return SQLITE_OK;
         4954  +  }
         4955  +#endif
  4907   4956   
  4908   4957     assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
  4909   4958     if( nMap!=pFd->mmapSize ){
  4910   4959       unixRemapfile(pFd, nMap);
  4911   4960     }
  4912   4961   
  4913   4962     return SQLITE_OK;
................................................................................
  5350   5399   #endif
  5351   5400     }
  5352   5401   
  5353   5402     if( pLockingStyle == &posixIoMethods
  5354   5403   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  5355   5404       || pLockingStyle == &nfsIoMethods
  5356   5405   #endif
         5406  +#ifdef SQLITE_SHARED_MAPPING
         5407  +    || pLockingStyle == &nolockIoMethods
         5408  +#endif
  5357   5409     ){
  5358   5410       unixEnterMutex();
  5359   5411       rc = findInodeInfo(pNew, &pNew->pInode);
  5360   5412       if( rc!=SQLITE_OK ){
  5361   5413         /* If an error occurred in findInodeInfo(), close the file descriptor
  5362   5414         ** immediately, before releasing the mutex. findInodeInfo() may fail
  5363   5415         ** in two scenarios: