1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Change the semantics of xShmGet() such that it will never increase the size

of shared memory.  xShmSize() must be used to grow the size of shared memory.
A shared memory segment size cannot be shrunk (except by dropping it).

FossilOrigin-Name: 72de00731245277b2209103ec0a76e3d4f56530e
This commit is contained in:
drh
2010-05-26 15:06:38 +00:00
parent 51b21b169a
commit 026ac28b28
5 changed files with 69 additions and 80 deletions

View File

@@ -3602,15 +3602,12 @@ static int unixShmClose(
}
/*
** Query and/or changes the size of the underlying storage for
** a shared-memory segment. The reqSize parameter is the new size
** of the underlying storage, or -1 to do just a query. The size
** of the underlying storage (after resizing if resizing occurs) is
** written into pNewSize.
** Changes the size of the underlying storage for a shared-memory segment.
**
** This routine does not (necessarily) change the size of the mapping
** of the underlying storage into memory. Use xShmGet() to change
** the mapping size.
** The reqSize parameter is the new requested size of the shared memory.
** This implementation is free to increase the shared memory size to
** any amount greater than or equal to reqSize. If the shared memory is
** already as big or bigger as reqSize, this routine is a no-op.
**
** The reqSize parameter is the minimum size requested. The implementation
** is free to expand the storage to some larger amount if it chooses.
@@ -3629,23 +3626,15 @@ static int unixShmSize(
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
/* On a query, this loop runs once. When reqSize>=0, the loop potentially
** runs twice, except if the actual size is already greater than or equal
** to the requested size, reqSize is set to -1 on the first iteration and
** the loop only runs once.
*/
while( 1 ){
if( fstat(pShmNode->h, &sStat)==0 ){
*pNewSize = (int)sStat.st_size;
if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
if( reqSize<=(int)sStat.st_size ) break;
}else{
*pNewSize = 0;
rc = SQLITE_IOERR;
break;
}
if( reqSize<0 ) break;
reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
reqSize *= SQLITE_UNIX_SHM_INCR;
rc = ftruncate(pShmNode->h, reqSize);
reqSize = -1;
}
@@ -3654,10 +3643,12 @@ static int unixShmSize(
/*
** 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.
** Map the shared storage into memory.
**
** If reqMapSize is positive, then an attempt is made to make the
** mapping at least reqMapSize bytes in size. However, the mapping
** will never be larger than the size of the underlying shared memory
** as set by prior calls to xShmSize().
**
** *ppBuf is made to point to the memory which is a mapping of the
** underlying storage. A mutex is acquired to prevent other threads
@@ -3674,9 +3665,12 @@ static int unixShmSize(
** To prevent RECOVER from losing its lock while remapping, the
** mutex is not released by unixShmRelease() when in RECOVER.
**
** *pNewMapSize is set to the size of the mapping.
** *pNewMapSize is set to the size of the mapping. Usually *pNewMapSize
** will be reqMapSize or larger, though it could be smaller if the
** underlying shared memory has never been enlarged to reqMapSize bytes
** by prior calls to xShmSize().
**
** *ppBuf and *pNewMapSize might be NULL and zero if no space has
** *ppBuf might be NULL and zero if no space has
** yet been allocated to the underlying storage.
*/
static int unixShmGet(
@@ -3701,17 +3695,21 @@ static int unixShmGet(
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
int actualSize;
if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
&& reqMapSize<actualSize
){
reqMapSize = actualSize;
if( unixShmSize(fd, -1, &actualSize)!=SQLITE_OK ){
actualSize = 0;
}
if( pShmNode->pMMapBuf ){
reqMapSize = actualSize;
if( pShmNode->pMMapBuf || reqMapSize<=0 ){
munmap(pShmNode->pMMapBuf, pShmNode->szMap);
}
pShmNode->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
pShmNode->h, 0);
pShmNode->szMap = pShmNode->pMMapBuf ? reqMapSize : 0;
if( reqMapSize>0 ){
pShmNode->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
pShmNode->h, 0);
pShmNode->szMap = pShmNode->pMMapBuf ? reqMapSize : 0;
}else{
pShmNode->pMMapBuf = 0;
pShmNode->szMap = 0;
}
}
*pNewMapSize = pShmNode->szMap;
*ppBuf = pShmNode->pMMapBuf;