/ 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 Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

42
43
44
45
46
47
48


49
50
51
52
53
54
55
....
1111
1112
1113
1114
1115
1116
1117




1118
1119
1120
1121
1122
1123
1124
....
1245
1246
1247
1248
1249
1250
1251







1252
1253
1254
1255
1256
1257
1258
....
2051
2052
2053
2054
2055
2056
2057








2058
2059
2060
2061
2062
2063
2064
....
3870
3871
3872
3873
3874
3875
3876



3877
3878
3879
3880
3881
3882
3883
....
4770
4771
4772
4773
4774
4775
4776



4777
4778
4779
4780
4781
4782
4783
....
4900
4901
4902
4903
4904
4905
4906






















4907
4908
4909
4910
4911
4912
4913
....
5350
5351
5352
5353
5354
5355
5356



5357
5358
5359
5360
5361
5362
5363
**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
**   *  Definitions of sqlite3_vfs objects for all locking methods
**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */



/*
** There are various methods for file locking used for concurrency
** control:
**
**   1. POSIX locking (the default),
**   2. No locking,
**   3. Dot-file locking,
................................................................................
#if SQLITE_ENABLE_LOCKING_STYLE
  unsigned long long sharedByte;  /* for AFP simulated shared lock */
#endif
#if OS_VXWORKS
  sem_t *pSem;                    /* Named POSIX semaphore */
  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
#endif




};

/*
** A lists of all unixInodeInfo objects.
*/
static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
................................................................................
static void releaseInodeInfo(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  assert( unixMutexHeld() );
  if( ALWAYS(pInode) ){
    pInode->nRef--;
    if( pInode->nRef==0 ){
      assert( pInode->pShmNode==0 );







      closePendingFds(pFile);
      if( pInode->pPrev ){
        assert( pInode->pPrev->pNext==pInode );
        pInode->pPrev->pNext = pInode->pNext;
      }else{
        assert( inodeList==pInode );
        inodeList = pInode->pNext;
................................................................................
  return SQLITE_OK;
}

/*
** Close the file.
*/
static int nolockClose(sqlite3_file *id) {








  return closeUnixFile(id);
}

/******************* End of the no-op lock implementation *********************
******************************************************************************/

/******************************************************************************
................................................................................
      if( newLimit>0 && sizeof(size_t)<8 ){
        newLimit = (newLimit & 0x7FFFFFFF);
      }

      *(i64*)pArg = pFile->mmapSizeMax;
      if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
        pFile->mmapSizeMax = newLimit;



        if( pFile->mmapSize>0 ){
          unixUnmapfile(pFile);
          rc = unixMapfile(pFile, -1);
        }
      }
      return rc;
    }
................................................................................

#if SQLITE_MAX_MMAP_SIZE>0
/*
** If it is currently memory mapped, unmap file pFd.
*/
static void unixUnmapfile(unixFile *pFd){
  assert( pFd->nFetchOut==0 );



  if( pFd->pMapRegion ){
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
}
................................................................................
      return SQLITE_IOERR_FSTAT;
    }
    nMap = statbuf.st_size;
  }
  if( nMap>pFd->mmapSizeMax ){
    nMap = pFd->mmapSizeMax;
  }























  assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
  if( nMap!=pFd->mmapSize ){
    unixRemapfile(pFd, nMap);
  }

  return SQLITE_OK;
................................................................................
#endif
  }

  if( pLockingStyle == &posixIoMethods
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
    || pLockingStyle == &nfsIoMethods
#endif



  ){
    unixEnterMutex();
    rc = findInodeInfo(pNew, &pNew->pInode);
    if( rc!=SQLITE_OK ){
      /* If an error occurred in findInodeInfo(), close the file descriptor
      ** immediately, before releasing the mutex. findInodeInfo() may fail
      ** in two scenarios:







>
>







 







>
>
>
>







 







>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>







 







>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
....
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
....
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
....
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
....
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
....
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
....
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
....
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
**   *  Definitions of sqlite3_vfs objects for all locking methods
**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

#define SQLITE_SHARED_MAPPING 1

/*
** There are various methods for file locking used for concurrency
** control:
**
**   1. POSIX locking (the default),
**   2. No locking,
**   3. Dot-file locking,
................................................................................
#if SQLITE_ENABLE_LOCKING_STYLE
  unsigned long long sharedByte;  /* for AFP simulated shared lock */
#endif
#if OS_VXWORKS
  sem_t *pSem;                    /* Named POSIX semaphore */
  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
#endif
#ifdef SQLITE_SHARED_MAPPING
  sqlite3_int64 nSharedMapping;   /* Size of mapped region in bytes */
  void *pSharedMapping;           /* Memory mapped region */
#endif
};

/*
** A lists of all unixInodeInfo objects.
*/
static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
................................................................................
static void releaseInodeInfo(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  assert( unixMutexHeld() );
  if( ALWAYS(pInode) ){
    pInode->nRef--;
    if( pInode->nRef==0 ){
      assert( pInode->pShmNode==0 );
#ifdef SQLITE_SHARED_MAPPING
      if( pInode->pSharedMapping ){
        osMunmap(pInode->pSharedMapping, pInode->nSharedMapping);
        pInode->pSharedMapping = 0;
        pInode->nSharedMapping = 0;
      }
#endif
      closePendingFds(pFile);
      if( pInode->pPrev ){
        assert( pInode->pPrev->pNext==pInode );
        pInode->pPrev->pNext = pInode->pNext;
      }else{
        assert( inodeList==pInode );
        inodeList = pInode->pNext;
................................................................................
  return SQLITE_OK;
}

/*
** Close the file.
*/
static int nolockClose(sqlite3_file *id) {
#ifdef SQLITE_SHARED_MAPPING
  unixFile *pFd = (unixFile*)id;
  if( pFd->pInode ){
    unixEnterMutex();
    releaseInodeInfo(pFd);
    unixLeaveMutex();
  }
#endif
  return closeUnixFile(id);
}

/******************* End of the no-op lock implementation *********************
******************************************************************************/

/******************************************************************************
................................................................................
      if( newLimit>0 && sizeof(size_t)<8 ){
        newLimit = (newLimit & 0x7FFFFFFF);
      }

      *(i64*)pArg = pFile->mmapSizeMax;
      if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
        pFile->mmapSizeMax = newLimit;
#ifdef SQLITE_SHARED_MAPPING
        if( pFile->pInode==0 )
#endif
        if( pFile->mmapSize>0 ){
          unixUnmapfile(pFile);
          rc = unixMapfile(pFile, -1);
        }
      }
      return rc;
    }
................................................................................

#if SQLITE_MAX_MMAP_SIZE>0
/*
** If it is currently memory mapped, unmap file pFd.
*/
static void unixUnmapfile(unixFile *pFd){
  assert( pFd->nFetchOut==0 );
#ifdef SQLITE_SHARED_MAPPING
  if( pFd->pInode ) return;
#endif
  if( pFd->pMapRegion ){
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
}
................................................................................
      return SQLITE_IOERR_FSTAT;
    }
    nMap = statbuf.st_size;
  }
  if( nMap>pFd->mmapSizeMax ){
    nMap = pFd->mmapSizeMax;
  }

#ifdef SQLITE_SHARED_MAPPING
  if( pFd->pInode ){
    unixInodeInfo *pInode = pFd->pInode;
    if( pFd->pMapRegion ) return SQLITE_OK;
    unixEnterMutex();
    if( pInode->pSharedMapping==0 ){
      u8 *pNew = osMmap(0, nMap, PROT_READ, MAP_SHARED, pFd->h, 0);
      if( pNew==MAP_FAILED ){
        unixLogError(SQLITE_OK, "mmap", pFd->zPath);
        pFd->mmapSizeMax = 0;
      }else{
        pInode->pSharedMapping = pNew;
        pInode->nSharedMapping = nMap;
      }
    }
    pFd->pMapRegion = pInode->pSharedMapping;
    pFd->mmapSizeActual = pFd->mmapSize = pInode->nSharedMapping;
    unixLeaveMutex();
    return SQLITE_OK;
  }
#endif

  assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
  if( nMap!=pFd->mmapSize ){
    unixRemapfile(pFd, nMap);
  }

  return SQLITE_OK;
................................................................................
#endif
  }

  if( pLockingStyle == &posixIoMethods
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
    || pLockingStyle == &nfsIoMethods
#endif
#ifdef SQLITE_SHARED_MAPPING
    || pLockingStyle == &nolockIoMethods
#endif
  ){
    unixEnterMutex();
    rc = findInodeInfo(pNew, &pNew->pInode);
    if( rc!=SQLITE_OK ){
      /* If an error occurred in findInodeInfo(), close the file descriptor
      ** immediately, before releasing the mutex. findInodeInfo() may fail
      ** in two scenarios: