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