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

Changes so that the xShmOpen VFS method is no longer required. Its job can be done by the first call to xShmMap. Rename xShmClose to xShmUnmap.

FossilOrigin-Name: f4780bde62c6c19146d2723c101540b8db898d38
This commit is contained in:
dan
2010-07-13 18:44:03 +00:00
parent 2103245e75
commit da9fe0c327
14 changed files with 241 additions and 286 deletions

View File

@@ -3275,7 +3275,7 @@ static void unixShmPurge(unixFile *pFd){
}
/*
** Open a shared-memory area associated with open database file fd.
** Open a shared-memory area associated with open database file pDbFd.
** This particular implementation uses mmapped files.
**
** The file used to implement shared-memory is in the same directory
@@ -3294,27 +3294,22 @@ static void unixShmPurge(unixFile *pFd){
** file are currently open, in this process or in other processes, then
** the file must be truncated to zero length or have its header cleared.
*/
static int unixShmOpen(
sqlite3_file *fd /* The file descriptor of the associated database */
){
struct unixShm *p = 0; /* The connection to be opened */
struct unixShmNode *pShmNode = 0; /* The underlying mmapped file */
int rc; /* Result code */
struct unixFile *pDbFd; /* Underlying database file */
unixInodeInfo *pInode; /* The inode of fd */
char *zShmFilename; /* Name of the file used for SHM */
int nShmFilename; /* Size of the SHM filename in bytes */
static int unixOpenSharedMemory(unixFile *pDbFd){
struct unixShm *p = 0; /* The connection to be opened */
struct unixShmNode *pShmNode; /* The underlying mmapped file */
int rc; /* Result code */
unixInodeInfo *pInode; /* The inode of fd */
char *zShmFilename; /* Name of the file used for SHM */
int nShmFilename; /* Size of the SHM filename in bytes */
/* Allocate space for the new sqlite3_shm object.
*/
/* Allocate space for the new unixShm object. */
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
pDbFd = (struct unixFile*)fd;
assert( pDbFd->pShm==0 );
/* Check to see if a unixShmNode object already exists. Reuse an existing
** one if present. Create a new one if necessary.
/* Check to see if a unixShmNode object already exists. Reuse an existing
** one if present. Create a new one if necessary.
*/
unixEnterMutex();
pInode = pDbFd->pInode;
@@ -3380,49 +3375,107 @@ shm_open_err:
}
/*
** Close a connection to shared-memory. Delete the underlying
** storage if deleteFlag is true.
** This function is called to obtain a pointer to region iRegion of the
** 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.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
** bExtend is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
** this call as described above, then it is mapped into this processes
** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
*/
static int unixShmClose(
sqlite3_file *fd, /* The underlying database file */
int deleteFlag /* Delete shared-memory if true */
static int unixShmMap(
sqlite3_file *fd, /* Handle open on database file */
int iRegion, /* Region to retrieve */
int szRegion, /* Size of regions */
int bExtend, /* True to extend file if necessary */
void volatile **pp /* OUT: Mapped memory */
){
unixShm *p; /* The connection to be closed */
unixShmNode *pShmNode; /* The underlying shared-memory file */
unixShm **pp; /* For looping over sibling connections */
unixFile *pDbFd; /* The underlying database file */
unixFile *pDbFd = (unixFile*)fd;
unixShm *p;
unixShmNode *pShmNode;
int rc = SQLITE_OK;
pDbFd = (unixFile*)fd;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_OK;
pShmNode = p->pShmNode;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
/* Remove connection p from the set of connections associated
** with pShmNode */
sqlite3_mutex_enter(pShmNode->mutex);
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
*pp = p->pNext;
/* Free the connection p */
sqlite3_free(p);
pDbFd->pShm = 0;
sqlite3_mutex_leave(pShmNode->mutex);
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
unixEnterMutex();
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
if( deleteFlag ) unlink(pShmNode->zFilename);
unixShmPurge(pDbFd);
/* If the shared-memory file has not yet been opened, open it now. */
if( pDbFd->pShm==0 ){
rc = unixOpenSharedMemory(pDbFd);
if( rc!=SQLITE_OK ) return rc;
}
unixLeaveMutex();
return SQLITE_OK;
p = pDbFd->pShm;
pShmNode = p->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
char **apNew; /* New apRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
struct stat sStat; /* Used by fstat() */
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).
*/
if( fstat(pShmNode->h, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
if( sStat.st_size<nByte ){
/* The requested memory region does not exist. If bExtend is set to
** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
**
** Alternatively, if bExtend is true, use ftruncate() to allocate
** the requested memory region.
*/
if( !bExtend ) goto shmpage_out;
if( ftruncate(pShmNode->h, nByte) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
apNew = (char **)sqlite3_realloc(
pShmNode->apRegion, (iRegion+1)*sizeof(char *)
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM;
goto shmpage_out;
}
pShmNode->apRegion = apNew;
while(pShmNode->nRegion<=iRegion){
void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, iRegion*szRegion
);
if( pMem==MAP_FAILED ){
rc = SQLITE_IOERR;
goto shmpage_out;
}
pShmNode->apRegion[pShmNode->nRegion] = pMem;
pShmNode->nRegion++;
}
}
shmpage_out:
if( pShmNode->nRegion>iRegion ){
*pp = pShmNode->apRegion[iRegion];
}else{
*pp = 0;
}
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
/*
@@ -3552,107 +3605,57 @@ static void unixShmBarrier(
}
/*
** This function is called to obtain a pointer to region iRegion of the
** 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.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
** isWrite is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
** this call as described above, then it is mapped into this processes
** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
** Close a connection to shared-memory. Delete the underlying
** storage if deleteFlag is true.
*/
static int unixShmMap(
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 */
static int unixShmUnmap(
sqlite3_file *fd, /* The underlying database file */
int deleteFlag /* Delete shared-memory if true */
){
unixFile *pDbFd = (unixFile*)fd;
unixShm *p = pDbFd->pShm;
unixShmNode *pShmNode = p->pShmNode;
int rc = SQLITE_OK;
unixShm *p; /* The connection to be closed */
unixShmNode *pShmNode; /* The underlying shared-memory file */
unixShm **pp; /* For looping over sibling connections */
unixFile *pDbFd; /* The underlying database file */
pDbFd = (unixFile*)fd;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_OK;
pShmNode = p->pShmNode;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
/* Remove connection p from the set of connections associated
** with pShmNode */
sqlite3_mutex_enter(pShmNode->mutex);
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
*pp = p->pNext;
if( pShmNode->nRegion<=iRegion ){
char **apNew; /* New apRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
struct stat sStat; /* Used by fstat() */
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).
*/
if( fstat(pShmNode->h, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
if( sStat.st_size<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;
if( ftruncate(pShmNode->h, nByte) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
apNew = (char **)sqlite3_realloc(
pShmNode->apRegion, (iRegion+1)*sizeof(char *)
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM;
goto shmpage_out;
}
pShmNode->apRegion = apNew;
while(pShmNode->nRegion<=iRegion){
void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, iRegion*szRegion
);
if( pMem==MAP_FAILED ){
rc = SQLITE_IOERR;
goto shmpage_out;
}
pShmNode->apRegion[pShmNode->nRegion] = pMem;
pShmNode->nRegion++;
}
}
shmpage_out:
if( pShmNode->nRegion>iRegion ){
*pp = pShmNode->apRegion[iRegion];
}else{
*pp = 0;
}
/* Free the connection p */
sqlite3_free(p);
pDbFd->pShm = 0;
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
unixEnterMutex();
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
if( deleteFlag ) unlink(pShmNode->zFilename);
unixShmPurge(pDbFd);
}
unixLeaveMutex();
return SQLITE_OK;
}
#else
# define unixShmOpen 0
# define unixShmLock 0
# define unixShmMap 0
# define unixShmLock 0
# define unixShmBarrier 0
# define unixShmClose 0
# define unixShmUnmap 0
#endif /* #ifndef SQLITE_OMIT_WAL */
/*
@@ -3710,11 +3713,10 @@ static const sqlite3_io_methods METHOD = { \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics, /* xDeviceCapabilities */ \
unixShmOpen, /* xShmOpen */ \
unixShmLock, /* xShmLock */ \
unixShmMap, /* xShmMap */ \
unixShmLock, /* xShmLock */ \
unixShmBarrier, /* xShmBarrier */ \
unixShmClose /* xShmClose */ \
unixShmUnmap /* xShmUnmap */ \
}; \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \