/ Check-in [13e7a824]
Login

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

Overview
Comment:Add the new xShmMap (formerly xShmPage) to os_win.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 13e7a8242206bca4b5bf356ef074e66474d39609
User & Date: dan 2010-06-14 16:16:34
Context
2010-06-15
13:56
Changes to the way tcl test scripts work. No changes to production code. Closed-Leaf check-in: 2c5e48a4 user: dan tags: experimental
2010-06-14
17:09
Merge the experimental shared-memory mmap-by-chunk changes into the trunk. check-in: f295e7ed user: drh tags: trunk
16:16
Add the new xShmMap (formerly xShmPage) to os_win.c. check-in: 13e7a824 user: dan tags: experimental
14:07
Remove xShmGet/Size/Release from the sqlite3_vfs structure. Change the name of xShmPage to xShmMap. Remove some code that is now unused from os_unix.c and some of the test VFS implementations. check-in: fc0cabc1 user: dan tags: experimental
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  3569   3569   ** been allocated, it is allocated by this function.
  3570   3570   **
  3571   3571   ** If the shared-memory region has already been allocated or is allocated by
  3572   3572   ** this call as described above, then it is mapped into this processes 
  3573   3573   ** address space (if it is not already), *pp is set to point to the mapped 
  3574   3574   ** memory and SQLITE_OK returned.
  3575   3575   */
  3576         -static int unixShmPage(
         3576  +static int unixShmMap(
  3577   3577     sqlite3_file *fd,               /* Handle open on database file */
  3578   3578     int iRegion,                    /* Region to retrieve */
  3579   3579     int szRegion,                   /* Size of regions */
  3580   3580     int isWrite,                    /* True to extend file if necessary */
  3581   3581     void volatile **pp              /* OUT: Mapped memory */
  3582   3582   ){
  3583   3583     unixFile *pDbFd = (unixFile*)fd;
................................................................................
  3651   3651   }
  3652   3652   
  3653   3653   #else
  3654   3654   # define unixShmOpen    0
  3655   3655   # define unixShmLock    0
  3656   3656   # define unixShmBarrier 0
  3657   3657   # define unixShmClose   0
  3658         -# define unixShmPage    0
         3658  +# define unixShmMap     0
  3659   3659   #endif /* #ifndef SQLITE_OMIT_WAL */
  3660   3660   
  3661   3661   /*
  3662   3662   ** Here ends the implementation of all sqlite3_file methods.
  3663   3663   **
  3664   3664   ********************** End sqlite3_file Methods *******************************
  3665   3665   ******************************************************************************/
................................................................................
  3713   3713      unixFileControl,            /* xFileControl */                            \
  3714   3714      unixSectorSize,             /* xSectorSize */                             \
  3715   3715      unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
  3716   3716      unixShmOpen,                /* xShmOpen */                                \
  3717   3717      unixShmLock,                /* xShmLock */                                \
  3718   3718      unixShmBarrier,             /* xShmBarrier */                             \
  3719   3719      unixShmClose,               /* xShmClose */                               \
  3720         -   unixShmPage                 /* xShmPage */                                \
         3720  +   unixShmMap                  /* xShmMap */                                 \
  3721   3721   };                                                                           \
  3722   3722   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  3723   3723     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  3724   3724     return &METHOD;                                                            \
  3725   3725   }                                                                            \
  3726   3726   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  3727   3727       = FINDER##Impl;

Changes to src/os_win.c.

  1212   1212   ** reverse order that they are acquired.  mutexBuf is always acquired
  1213   1213   ** first and released last.  This invariant is check by asserting
  1214   1214   ** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
  1215   1215   ** released.
  1216   1216   */
  1217   1217   struct winShmNode {
  1218   1218     sqlite3_mutex *mutex;      /* Mutex to access this object */
  1219         -  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
  1220   1219     char *zFilename;           /* Name of the file */
  1221   1220     winFile hFile;             /* File handle from winOpen */
  1222         -  HANDLE hMap;               /* File handle from CreateFileMapping */
         1221  +
         1222  +  int szRegion;              /* Size of shared-memory regions */
         1223  +  int nRegion;               /* Size of array apRegion */
         1224  +  struct ShmRegion {
         1225  +    HANDLE hMap;             /* File handle from CreateFileMapping */
         1226  +    void *pMap;
         1227  +  } *aRegion;
  1223   1228     DWORD lastErrno;           /* The Windows errno from the last I/O error */
  1224         -  int szMap;                 /* Size of the mapping of file into memory */
  1225         -  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
         1229  +
  1226   1230     int nRef;                  /* Number of winShm objects pointing to this */
  1227   1231     winShm *pFirst;            /* All winShm objects pointing to this */
  1228   1232     winShmNode *pNext;         /* Next in list of all winShmNode objects */
  1229   1233   #ifdef SQLITE_DEBUG
  1230   1234     u8 nextShmId;              /* Next available winShm.id value */
  1231   1235   #endif
  1232   1236   };
................................................................................
  1321   1325   static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
  1322   1326     winShmNode **pp;
  1323   1327     winShmNode *p;
  1324   1328     assert( winShmMutexHeld() );
  1325   1329     pp = &winShmNodeList;
  1326   1330     while( (p = *pp)!=0 ){
  1327   1331       if( p->nRef==0 ){
         1332  +      int i;
  1328   1333         if( p->mutex ) sqlite3_mutex_free(p->mutex);
  1329         -      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
  1330         -      if( p->pMMapBuf ){
  1331         -        UnmapViewOfFile(p->pMMapBuf);
  1332         -      }
  1333         -      if( INVALID_HANDLE_VALUE != p->hMap ){
  1334         -        CloseHandle(p->hMap);
         1334  +      for(i=0; i<p->nRegion; i++){
         1335  +        UnmapViewOfFile(p->aRegion[i].pMap);
         1336  +        CloseHandle(p->aRegion[i].hMap);
  1335   1337         }
  1336   1338         if( p->hFile.h != INVALID_HANDLE_VALUE ) {
  1337   1339           winClose((sqlite3_file *)&p->hFile);
  1338   1340         }
  1339   1341         if( deleteFlag ) winDelete(pVfs, p->zFilename, 0);
  1340   1342         *pp = p->pNext;
         1343  +      sqlite3_free(p->aRegion);
  1341   1344         sqlite3_free(p);
  1342   1345       }else{
  1343   1346         pp = &p->pNext;
  1344   1347       }
  1345   1348     }
  1346   1349   }
  1347   1350   
................................................................................
  1400   1403       if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
  1401   1404     }
  1402   1405     if( pShmNode ){
  1403   1406       sqlite3_free(pNew);
  1404   1407     }else{
  1405   1408       pShmNode = pNew;
  1406   1409       pNew = 0;
  1407         -    pShmNode->pMMapBuf = NULL;
  1408         -    pShmNode->hMap = INVALID_HANDLE_VALUE;
  1409   1410       ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
  1410   1411       pShmNode->pNext = winShmNodeList;
  1411   1412       winShmNodeList = pShmNode;
  1412   1413   
  1413   1414       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  1414   1415       if( pShmNode->mutex==0 ){
  1415   1416         rc = SQLITE_NOMEM;
  1416         -      goto shm_open_err;
  1417         -    }
  1418         -    pShmNode->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  1419         -    if( pShmNode->mutexBuf==0 ){
  1420         -      rc = SQLITE_NOMEM;
  1421   1417         goto shm_open_err;
  1422   1418       }
  1423   1419       rc = winOpen(pDbFd->pVfs,
  1424   1420                    pShmNode->zFilename,             /* Name of the file (UTF-8) */
  1425   1421                    (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
  1426   1422                    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
  1427   1423                    0);
................................................................................
  1503   1499     }
  1504   1500     winShmLeaveMutex();
  1505   1501   
  1506   1502     return SQLITE_OK;
  1507   1503   }
  1508   1504   
  1509   1505   /*
  1510         -** Increase the size of the underlying storage for a shared-memory segment.
         1506  +** This function is called to obtain a pointer to region iRegion of the 
         1507  +** shared-memory associated with the database file fd. Shared-memory regions 
         1508  +** are numbered starting from zero. Each shared-memory region is szRegion 
         1509  +** bytes in size.
         1510  +**
         1511  +** If an error occurs, an error code is returned and *pp is set to NULL.
  1511   1512   **
  1512         -** The reqSize parameter is the new requested minimum size of the underlying
  1513         -** shared memory.  This routine may choose to make the shared memory larger
  1514         -** than this value (for example to round the shared memory size up to an
  1515         -** operating-system dependent page size.)
         1513  +** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
         1514  +** region has not been allocated (by any client, including one running in a
         1515  +** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
         1516  +** isWrite is non-zero and the requested shared-memory region has not yet 
         1517  +** been allocated, it is allocated by this function.
  1516   1518   **
  1517         -** This routine will only grow the size of shared memory.  A request for
  1518         -** a smaller size is a no-op.
  1519         -*/
  1520         -static int winShmSize(
  1521         -  sqlite3_file *fd,         /* Database holding the shared memory */
  1522         -  int reqSize,              /* Requested size.  -1 for query only */
  1523         -  int *pNewSize             /* Write new size here */
  1524         -){
  1525         -  winFile *pDbFd = (winFile*)fd;
  1526         -  winShm *p = pDbFd->pShm;
  1527         -  winShmNode *pShmNode = p->pShmNode;
  1528         -  int rc = SQLITE_OK;
  1529         -
  1530         -  *pNewSize = 0;
  1531         -  if( reqSize>=0 ){
  1532         -    sqlite3_int64 sz;
  1533         -    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
  1534         -    if( SQLITE_OK==rc && reqSize>sz ){
  1535         -      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
  1536         -    }
  1537         -  }
  1538         -  if( SQLITE_OK==rc ){
  1539         -    sqlite3_int64 sz;
  1540         -    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
  1541         -    if( SQLITE_OK==rc ){
  1542         -      *pNewSize = (int)sz;
  1543         -    }else{
  1544         -      rc = SQLITE_IOERR;
  1545         -    }
  1546         -  }
  1547         -  return rc;
  1548         -}
  1549         -
  1550         -
  1551         -/*
  1552         -** Map the shared storage into memory.  The minimum size of the
  1553         -** mapping should be reqMapSize if reqMapSize is positive.  If
  1554         -** reqMapSize is zero or negative, the implementation can choose
  1555         -** whatever mapping size is convenient.
  1556         -**
  1557         -** *ppBuf is made to point to the memory which is a mapping of the
  1558         -** underlying storage.  A mutex is acquired to prevent other threads
  1559         -** from running while *ppBuf is in use in order to prevent other threads
  1560         -** remapping *ppBuf out from under this thread.  The winShmRelease()
  1561         -** call will release the mutex.  However, if the lock state is CHECKPOINT,
  1562         -** the mutex is not acquired because CHECKPOINT will never remap the
  1563         -** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
  1564         -** the mutex if and when it promotes to RECOVER.
  1565         -**
  1566         -** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
  1567         -** being remapped also prevents more than one thread from being in
  1568         -** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
  1569         -** To prevent RECOVER from losing its lock while remapping, the
  1570         -** mutex is not released by winShmRelease() when in RECOVER.
  1571         -**
  1572         -** *pNewMapSize is set to the size of the mapping.
  1573         -**
  1574         -** *ppBuf and *pNewMapSize might be NULL and zero if no space has
  1575         -** yet been allocated to the underlying storage.
  1576         -*/
  1577         -static int winShmGet(
  1578         -  sqlite3_file *fd,        /* The database file holding the shared memory */
  1579         -  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  1580         -  int *pNewMapSize,        /* Write new size of mapping here */
  1581         -  void volatile **ppBuf    /* Write mapping buffer origin here */
         1519  +** If the shared-memory region has already been allocated or is allocated by
         1520  +** this call as described above, then it is mapped into this processes 
         1521  +** address space (if it is not already), *pp is set to point to the mapped 
         1522  +** memory and SQLITE_OK returned.
         1523  +*/
         1524  +static int winShmMap(
         1525  +  sqlite3_file *fd,               /* Handle open on database file */
         1526  +  int iRegion,                    /* Region to retrieve */
         1527  +  int szRegion,                   /* Size of regions */
         1528  +  int isWrite,                    /* True to extend file if necessary */
         1529  +  void volatile **pp              /* OUT: Mapped memory */
  1582   1530   ){
  1583   1531     winFile *pDbFd = (winFile*)fd;
  1584   1532     winShm *p = pDbFd->pShm;
  1585   1533     winShmNode *pShmNode = p->pShmNode;
  1586   1534     int rc = SQLITE_OK;
  1587   1535   
  1588         -  if( p->hasMutexBuf==0 ){
  1589         -    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
  1590         -    sqlite3_mutex_enter(pShmNode->mutexBuf);
  1591         -    p->hasMutexBuf = 1;
  1592         -  }
  1593   1536     sqlite3_mutex_enter(pShmNode->mutex);
  1594         -  if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
  1595         -    int actualSize;
  1596         -    if( winShmSize(fd, -1, &actualSize)==SQLITE_OK
  1597         -     && reqMapSize<actualSize
  1598         -    ){
  1599         -      reqMapSize = actualSize;
  1600         -    }
  1601         -    if( pShmNode->pMMapBuf ){
  1602         -      if( !UnmapViewOfFile(pShmNode->pMMapBuf) ){
         1537  +  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
         1538  +
         1539  +  if( pShmNode->nRegion<=iRegion ){
         1540  +    struct ShmRegion *apNew;           /* New aRegion[] array */
         1541  +    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
         1542  +    sqlite3_int64 sz;                  /* Current size of wal-index file */
         1543  +
         1544  +    pShmNode->szRegion = szRegion;
         1545  +
         1546  +    /* The requested region is not mapped into this processes address space.
         1547  +    ** Check to see if it has been allocated (i.e. if the wal-index file is
         1548  +    ** large enough to contain the requested region).
         1549  +    */
         1550  +    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
         1551  +    if( rc!=SQLITE_OK ){
         1552  +      goto shmpage_out;
         1553  +    }
         1554  +
         1555  +    if( sz<nByte ){
         1556  +      /* The requested memory region does not exist. If isWrite is set to
         1557  +      ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
         1558  +      **
         1559  +      ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
         1560  +      ** the requested memory region.
         1561  +      */
         1562  +      if( !isWrite ) goto shmpage_out;
         1563  +      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
         1564  +      if( rc!=SQLITE_OK ){
         1565  +        goto shmpage_out;
         1566  +      }
         1567  +    }
         1568  +
         1569  +    /* Map the requested memory region into this processes address space. */
         1570  +    apNew = (struct ShmRegion *)sqlite3_realloc(
         1571  +        pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
         1572  +    );
         1573  +    if( !apNew ){
         1574  +      rc = SQLITE_IOERR_NOMEM;
         1575  +      goto shmpage_out;
         1576  +    }
         1577  +    pShmNode->aRegion = apNew;
         1578  +
         1579  +    while( pShmNode->nRegion<=iRegion ){
         1580  +      HANDLE hMap;                /* file-mapping handle */
         1581  +      void *pMap = 0;             /* Mapped memory region */
         1582  +     
         1583  +      hMap = CreateFileMapping(pShmNode->hFile.h, 
         1584  +          NULL, PAGE_READWRITE, 0, nByte, NULL
         1585  +      );
         1586  +      if( hMap ){
         1587  +        pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
         1588  +            0, 0, nByte
         1589  +        );
         1590  +      }
         1591  +      if( !pMap ){
  1603   1592           pShmNode->lastErrno = GetLastError();
  1604   1593           rc = SQLITE_IOERR;
         1594  +        if( hMap ) CloseHandle(hMap);
         1595  +        goto shmpage_out;
  1605   1596         }
  1606         -      CloseHandle(pShmNode->hMap);
  1607         -      pShmNode->hMap = INVALID_HANDLE_VALUE;
  1608         -    }
  1609         -    if( SQLITE_OK == rc ){
  1610         -      pShmNode->pMMapBuf = 0;
  1611         -      if( reqMapSize == 0 ){
  1612         -        /* can't create 0 byte file mapping in Windows */
  1613         -        pShmNode->szMap = 0;
  1614         -      }else{
  1615         -        /* create the file mapping object */
  1616         -        if( INVALID_HANDLE_VALUE == pShmNode->hMap ){
  1617         -          /* TBD provide an object name to each file
  1618         -          ** mapping so it can be re-used across processes.
  1619         -          */
  1620         -          pShmNode->hMap = CreateFileMapping(pShmNode->hFile.h,
  1621         -                                          NULL,
  1622         -                                          PAGE_READWRITE,
  1623         -                                          0,
  1624         -                                          reqMapSize,
  1625         -                                          NULL);
  1626         -        }
  1627         -        if( NULL==pShmNode->hMap ){
  1628         -          pShmNode->lastErrno = GetLastError();
  1629         -          rc = SQLITE_IOERR;
  1630         -          pShmNode->szMap = 0;
  1631         -          pShmNode->hMap = INVALID_HANDLE_VALUE;
  1632         -        }else{
  1633         -          pShmNode->pMMapBuf = MapViewOfFile(pShmNode->hMap,
  1634         -                                          FILE_MAP_WRITE | FILE_MAP_READ,
  1635         -                                          0,
  1636         -                                          0,
  1637         -                                          reqMapSize);
  1638         -          if( !pShmNode->pMMapBuf ){
  1639         -            pShmNode->lastErrno = GetLastError();
  1640         -            rc = SQLITE_IOERR;
  1641         -            pShmNode->szMap = 0;
  1642         -          }else{
  1643         -            pShmNode->szMap = reqMapSize;
  1644         -          }
  1645         -        }
  1646         -      }
  1647         -    }
  1648         -  }
  1649         -  *pNewMapSize = pShmNode->szMap;
  1650         -  *ppBuf = pShmNode->pMMapBuf;
         1597  +
         1598  +      pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
         1599  +      pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
         1600  +      pShmNode->nRegion++;
         1601  +    }
         1602  +  }
         1603  +
         1604  +shmpage_out:
         1605  +  if( pShmNode->nRegion>iRegion ){
         1606  +    char *p = (char *)pShmNode->aRegion[iRegion].pMap;
         1607  +    *pp = (void *)&p[iRegion*szRegion];
         1608  +  }else{
         1609  +    *pp = 0;
         1610  +  }
  1651   1611     sqlite3_mutex_leave(pShmNode->mutex);
  1652   1612     return rc;
  1653   1613   }
  1654   1614   
  1655         -/*
  1656         -** Release the lock held on the shared memory segment so that other
  1657         -** threads are free to resize it if necessary.
  1658         -**
  1659         -** If the lock is not currently held, this routine is a harmless no-op.
  1660         -**
  1661         -** If the shared-memory object is in lock state RECOVER, then we do not
  1662         -** really want to release the lock, so in that case too, this routine
  1663         -** is a no-op.
  1664         -*/
  1665         -static int winShmRelease(sqlite3_file *fd){
  1666         -  winFile *pDbFd = (winFile*)fd;
  1667         -  winShm *p = pDbFd->pShm;
  1668         -  if( p->hasMutexBuf ){
  1669         -    winShmNode *pShmNode = p->pShmNode;
  1670         -    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
  1671         -    sqlite3_mutex_leave(pShmNode->mutexBuf);
  1672         -    p->hasMutexBuf = 0;
  1673         -  }
  1674         -  return SQLITE_OK;
  1675         -}
  1676         -
  1677   1615   /*
  1678   1616   ** Change the lock state for a shared-memory segment.
  1679   1617   */
  1680   1618   static int winShmLock(
  1681   1619     sqlite3_file *fd,          /* Database file holding the shared memory */
  1682   1620     int ofst,                  /* First lock to acquire or release */
  1683   1621     int n,                     /* Number of locks to acquire or release */
................................................................................
  1752   1690     winLock,
  1753   1691     winUnlock,
  1754   1692     winCheckReservedLock,
  1755   1693     winFileControl,
  1756   1694     winSectorSize,
  1757   1695     winDeviceCharacteristics,
  1758   1696     winShmOpen,              /* xShmOpen */
  1759         -  winShmSize,              /* xShmSize */
  1760         -  winShmGet,               /* xShmGet */
  1761         -  winShmRelease,           /* xShmRelease */
  1762   1697     winShmLock,              /* xShmLock */
  1763   1698     winShmBarrier,           /* xShmBarrier */
  1764         -  winShmClose              /* xShmClose */
         1699  +  winShmClose,             /* xShmClose */
         1700  +  winShmMap                /* xShmMap */
  1765   1701   };
  1766   1702   
  1767   1703   /***************************************************************************
  1768   1704   ** Here ends the I/O methods that form the sqlite3_io_methods object.
  1769   1705   **
  1770   1706   ** The next block of code implements the VFS methods.
  1771   1707   ****************************************************************************/