mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Simplifications to the SHM implementation in os_unix.c, taking advantage
of the removal of the LinuxThreads mess. FossilOrigin-Name: d1debe5def82a6bc72f11b8787176ac60259630f
This commit is contained in:
18
manifest
18
manifest
@@ -1,8 +1,8 @@
|
|||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
Hash: SHA1
|
Hash: SHA1
|
||||||
|
|
||||||
C Simplify\sos_unix.c\sby\sremoving\ssupport\sfor\sLinuxThreads.\s\sLinux\ssystems\smust\neither\suse\sNPTL\sor\selse\snot\sshare\sdatabase\sconnections\sacross\sthreads.
|
C Simplifications\sto\sthe\sSHM\simplementation\sin\sos_unix.c,\staking\sadvantage\nof\sthe\sremoval\sof\sthe\sLinuxThreads\smess.
|
||||||
D 2010-05-14T12:43:02
|
D 2010-05-14T14:52:25
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -155,7 +155,7 @@ F src/os.c c0a5dfce2a214dacb679425632d04f8a2021f364
|
|||||||
F src/os.h 8a7e2456237ecf3a2e55b02f9fe6091f1ad36902
|
F src/os.h 8a7e2456237ecf3a2e55b02f9fe6091f1ad36902
|
||||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||||
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
||||||
F src/os_unix.c a725e2dc6f3d72b1776a04898fe088e3bb7d3a04
|
F src/os_unix.c 025da44ba18d91c2d0205e667bae4dd47be13639
|
||||||
F src/os_win.c 70c4a3327716213b59adf3a8adf2d5318b044a19
|
F src/os_win.c 70c4a3327716213b59adf3a8adf2d5318b044a19
|
||||||
F src/pager.c 1e163a82ae8405433dca559831caa06aafbba3b0
|
F src/pager.c 1e163a82ae8405433dca559831caa06aafbba3b0
|
||||||
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
||||||
@@ -816,14 +816,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 5fe529f239cddbf4b7ea57abb02d95cc0d94f5f5
|
P e294b696ba91512b1ca5547774c51ea07b4cb5bc
|
||||||
R 5512a2ec91f48237ba41c44554f0cdb3
|
R 21f94067ad533c60202276014029d639
|
||||||
U drh
|
U drh
|
||||||
Z 7e4d9cef7a6cf6a0301b86729a795d9b
|
Z 433a8524a713de9ce43e3d2748510f46
|
||||||
-----BEGIN PGP SIGNATURE-----
|
-----BEGIN PGP SIGNATURE-----
|
||||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||||
|
|
||||||
iD8DBQFL7UVZoxKgR168RlERAg5mAJ4wza7P9iBLqUhXxXQynpkN9aVQ/gCeJx3P
|
iD8DBQFL7WOsoxKgR168RlERAjJgAJ9zjWsl8oBYzeTvVFGM58MGDrdXDwCfV8pN
|
||||||
v/M7Sm67jKczR1nujm0jbQs=
|
CnLKIoKp0Sl7DOCRB0tGSS8=
|
||||||
=9Mna
|
=V8Bz
|
||||||
-----END PGP SIGNATURE-----
|
-----END PGP SIGNATURE-----
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e294b696ba91512b1ca5547774c51ea07b4cb5bc
|
d1debe5def82a6bc72f11b8787176ac60259630f
|
||||||
369
src/os_unix.c
369
src/os_unix.c
@@ -175,9 +175,11 @@
|
|||||||
*/
|
*/
|
||||||
#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
|
#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
|
||||||
|
|
||||||
/* Forward reference */
|
/* Forward references */
|
||||||
typedef struct unixShm unixShm;
|
typedef struct unixShm unixShm; /* Connection shared memory */
|
||||||
typedef struct unixShmFile unixShmFile;
|
typedef struct unixShmNode unixShmNode; /* Shared memory instance */
|
||||||
|
typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
|
||||||
|
typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Sometimes, after a file handle is closed by SQLite, the file descriptor
|
** Sometimes, after a file handle is closed by SQLite, the file descriptor
|
||||||
@@ -185,7 +187,6 @@ typedef struct unixShmFile unixShmFile;
|
|||||||
** structure are used to store the file descriptor while waiting for an
|
** structure are used to store the file descriptor while waiting for an
|
||||||
** opportunity to either close or reuse it.
|
** opportunity to either close or reuse it.
|
||||||
*/
|
*/
|
||||||
typedef struct UnixUnusedFd UnixUnusedFd;
|
|
||||||
struct UnixUnusedFd {
|
struct UnixUnusedFd {
|
||||||
int fd; /* File descriptor to close */
|
int fd; /* File descriptor to close */
|
||||||
int flags; /* Flags this file descriptor was opened with */
|
int flags; /* Flags this file descriptor was opened with */
|
||||||
@@ -199,7 +200,7 @@ struct UnixUnusedFd {
|
|||||||
typedef struct unixFile unixFile;
|
typedef struct unixFile unixFile;
|
||||||
struct unixFile {
|
struct unixFile {
|
||||||
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
||||||
struct unixInodeInfo *pInode; /* Info about locks on this inode */
|
unixInodeInfo *pInode; /* Info about locks on this inode */
|
||||||
int h; /* The file descriptor */
|
int h; /* The file descriptor */
|
||||||
int dirfd; /* File descriptor for the directory */
|
int dirfd; /* File descriptor for the directory */
|
||||||
unsigned char eFileLock; /* The type of lock held on this fd */
|
unsigned char eFileLock; /* The type of lock held on this fd */
|
||||||
@@ -715,23 +716,24 @@ struct unixInodeInfo {
|
|||||||
int nShared; /* Number of SHARED locks held */
|
int nShared; /* Number of SHARED locks held */
|
||||||
int eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
int eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
||||||
int nRef; /* Number of pointers to this structure */
|
int nRef; /* Number of pointers to this structure */
|
||||||
|
unixShmNode *pShmNode; /* Shared memory associated with this inode */
|
||||||
|
int nLock; /* Number of outstanding file locks */
|
||||||
|
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
||||||
|
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
||||||
|
unixInodeInfo *pPrev; /* .... doubly linked */
|
||||||
#if defined(SQLITE_ENABLE_LOCKING_STYLE)
|
#if defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||||
unsigned long long sharedByte; /* for AFP simulated shared lock */
|
unsigned long long sharedByte; /* for AFP simulated shared lock */
|
||||||
#endif
|
#endif
|
||||||
int nLock; /* Number of outstanding file locks */
|
|
||||||
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
|
||||||
#if OS_VXWORKS
|
#if OS_VXWORKS
|
||||||
sem_t *pSem; /* Named POSIX semaphore */
|
sem_t *pSem; /* Named POSIX semaphore */
|
||||||
char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
|
char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
|
||||||
#endif
|
#endif
|
||||||
struct unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
|
||||||
struct unixInodeInfo *pPrev; /* .... doubly linked */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A lists of all unixInodeInfo objects.
|
** A lists of all unixInodeInfo objects.
|
||||||
*/
|
*/
|
||||||
static struct unixInodeInfo *inodeList = 0;
|
static unixInodeInfo *inodeList = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
|
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
|
||||||
@@ -739,11 +741,12 @@ static struct unixInodeInfo *inodeList = 0;
|
|||||||
** The mutex entered using the unixEnterMutex() function must be held
|
** The mutex entered using the unixEnterMutex() function must be held
|
||||||
** when this function is called.
|
** when this function is called.
|
||||||
*/
|
*/
|
||||||
static void releaseInodeInfo(struct unixInodeInfo *pInode){
|
static void releaseInodeInfo(unixInodeInfo *pInode){
|
||||||
assert( unixMutexHeld() );
|
assert( unixMutexHeld() );
|
||||||
if( pInode ){
|
if( pInode ){
|
||||||
pInode->nRef--;
|
pInode->nRef--;
|
||||||
if( pInode->nRef==0 ){
|
if( pInode->nRef==0 ){
|
||||||
|
assert( pInode->pShmNode==0 );
|
||||||
if( pInode->pPrev ){
|
if( pInode->pPrev ){
|
||||||
assert( pInode->pPrev->pNext==pInode );
|
assert( pInode->pPrev->pNext==pInode );
|
||||||
pInode->pPrev->pNext = pInode->pNext;
|
pInode->pPrev->pNext = pInode->pNext;
|
||||||
@@ -772,13 +775,13 @@ static void releaseInodeInfo(struct unixInodeInfo *pInode){
|
|||||||
*/
|
*/
|
||||||
static int findInodeInfo(
|
static int findInodeInfo(
|
||||||
unixFile *pFile, /* Unix file with file desc used in the key */
|
unixFile *pFile, /* Unix file with file desc used in the key */
|
||||||
struct unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
|
unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
|
||||||
){
|
){
|
||||||
int rc; /* System call return code */
|
int rc; /* System call return code */
|
||||||
int fd; /* The file descriptor for pFile */
|
int fd; /* The file descriptor for pFile */
|
||||||
struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
|
struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
|
||||||
struct stat statbuf; /* Low-level file information */
|
struct stat statbuf; /* Low-level file information */
|
||||||
struct unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
|
unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
|
||||||
|
|
||||||
assert( unixMutexHeld() );
|
assert( unixMutexHeld() );
|
||||||
|
|
||||||
@@ -963,7 +966,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||||||
*/
|
*/
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
struct unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
int tErrno = 0;
|
int tErrno = 0;
|
||||||
@@ -1160,7 +1163,7 @@ end_lock:
|
|||||||
*/
|
*/
|
||||||
static int closePendingFds(unixFile *pFile){
|
static int closePendingFds(unixFile *pFile){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
struct unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
UnixUnusedFd *pError = 0;
|
UnixUnusedFd *pError = 0;
|
||||||
UnixUnusedFd *p;
|
UnixUnusedFd *p;
|
||||||
UnixUnusedFd *pNext;
|
UnixUnusedFd *pNext;
|
||||||
@@ -1184,7 +1187,7 @@ static int closePendingFds(unixFile *pFile){
|
|||||||
** pUnused list.
|
** pUnused list.
|
||||||
*/
|
*/
|
||||||
static void setPendingFd(unixFile *pFile){
|
static void setPendingFd(unixFile *pFile){
|
||||||
struct unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
UnixUnusedFd *p = pFile->pUnused;
|
UnixUnusedFd *p = pFile->pUnused;
|
||||||
p->pNext = pInode->pUnused;
|
p->pNext = pInode->pUnused;
|
||||||
pInode->pUnused = p;
|
pInode->pUnused = p;
|
||||||
@@ -1207,7 +1210,7 @@ static void setPendingFd(unixFile *pFile){
|
|||||||
*/
|
*/
|
||||||
static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
struct unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
int h;
|
int h;
|
||||||
@@ -2234,7 +2237,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||||||
static int afpLock(sqlite3_file *id, int eFileLock){
|
static int afpLock(sqlite3_file *id, int eFileLock){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
struct unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
||||||
|
|
||||||
assert( pFile );
|
assert( pFile );
|
||||||
@@ -2416,7 +2419,7 @@ afp_end_lock:
|
|||||||
static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
struct unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
||||||
int skipShared = 0;
|
int skipShared = 0;
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
@@ -3090,24 +3093,31 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Object used to represent a single file opened and mmapped to provide
|
** Object used to represent an shared memory buffer.
|
||||||
** shared memory. When multiple threads all reference the same
|
**
|
||||||
** log-summary, each thread has its own unixFile object, but they all
|
** When multiple threads all reference the same wal-index, each thread
|
||||||
** point to a single instance of this object. In other words, each
|
** has its own unixShm object, but they all point to a single instance
|
||||||
** log-summary is opened only once per process.
|
** of this unixShmNode object. In other words, each wal-index is opened
|
||||||
|
** only once per process.
|
||||||
|
**
|
||||||
|
** Each unixShmNode object is connected to a single unixInodeInfo object.
|
||||||
|
** We could coalesce this object into unixInodeInfo, but that would mean
|
||||||
|
** every open file that does not use shared memory (in other words, most
|
||||||
|
** open files) would have to carry around this extra information. So
|
||||||
|
** the unixInodeInfo object contains a pointer to this unixShmNode object
|
||||||
|
** and the unixShmNode object is created only when needed.
|
||||||
**
|
**
|
||||||
** unixMutexHeld() must be true when creating or destroying
|
** unixMutexHeld() must be true when creating or destroying
|
||||||
** this object or while reading or writing the following fields:
|
** this object or while reading or writing the following fields:
|
||||||
**
|
**
|
||||||
** nRef
|
** nRef
|
||||||
** pNext
|
|
||||||
**
|
**
|
||||||
** The following fields are read-only after the object is created:
|
** The following fields are read-only after the object is created:
|
||||||
**
|
**
|
||||||
** fid
|
** fid
|
||||||
** zFilename
|
** zFilename
|
||||||
**
|
**
|
||||||
** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and
|
** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
|
||||||
** unixMutexHeld() is true when reading or writing any other field
|
** unixMutexHeld() is true when reading or writing any other field
|
||||||
** in this structure.
|
** in this structure.
|
||||||
**
|
**
|
||||||
@@ -3117,17 +3127,16 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
|
|||||||
** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
|
** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
|
||||||
** released.
|
** released.
|
||||||
*/
|
*/
|
||||||
struct unixShmFile {
|
struct unixShmNode {
|
||||||
struct unixFileId fid; /* Unique file identifier */
|
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
|
||||||
sqlite3_mutex *mutex; /* Mutex to access this object */
|
sqlite3_mutex *mutex; /* Mutex to access this object */
|
||||||
sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */
|
sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */
|
||||||
char *zFilename; /* Name of the mmapped file */
|
char *zFilename; /* Name of the mmapped file */
|
||||||
int h; /* Open file descriptor */
|
int h; /* Open file descriptor */
|
||||||
int szMap; /* Size of the mapping of file into memory */
|
int szMap; /* Size of the mapping into memory */
|
||||||
char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */
|
char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */
|
||||||
int nRef; /* Number of unixShm objects pointing to this */
|
int nRef; /* Number of unixShm objects pointing to this */
|
||||||
unixShm *pFirst; /* All unixShm objects pointing to this */
|
unixShm *pFirst; /* All unixShm objects pointing to this */
|
||||||
unixShmFile *pNext; /* Next in list of all unixShmFile objects */
|
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
u8 exclMask; /* Mask of exclusive locks held */
|
u8 exclMask; /* Mask of exclusive locks held */
|
||||||
u8 sharedMask; /* Mask of shared locks held */
|
u8 sharedMask; /* Mask of shared locks held */
|
||||||
@@ -3135,33 +3144,29 @@ struct unixShmFile {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
** A global array of all unixShmFile objects.
|
|
||||||
**
|
|
||||||
** The unixMutexHeld() must be true while reading or writing this list.
|
|
||||||
*/
|
|
||||||
static unixShmFile *unixShmFileList = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Structure used internally by this VFS to record the state of an
|
** Structure used internally by this VFS to record the state of an
|
||||||
** open shared memory connection.
|
** open shared memory connection.
|
||||||
**
|
**
|
||||||
** unixShm.pFile->mutex must be held while reading or writing the
|
** The following fields are initialized when this object is created and
|
||||||
** unixShm.pNext and unixShm.locks[] elements.
|
** are read-only thereafter:
|
||||||
**
|
**
|
||||||
** The unixShm.pFile element is initialized when the object is created
|
** unixShm.pFile
|
||||||
** and is read-only thereafter.
|
** unixShm.id
|
||||||
|
**
|
||||||
|
** All other fields are read/write. The unixShm.pFile->mutex must be held
|
||||||
|
** while accessing any read/write fields.
|
||||||
*/
|
*/
|
||||||
struct unixShm {
|
struct unixShm {
|
||||||
unixShmFile *pFile; /* The underlying unixShmFile object */
|
unixShmNode *pShmNode; /* The underlying unixShmNode object */
|
||||||
unixShm *pNext; /* Next unixShm with the same unixShmFile */
|
unixShm *pNext; /* Next unixShm with the same unixShmNode */
|
||||||
u8 lockState; /* Current lock state */
|
u8 lockState; /* Current lock state */
|
||||||
u8 hasMutex; /* True if holding the unixShmFile mutex */
|
u8 hasMutex; /* True if holding the unixShmNode mutex */
|
||||||
u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
|
u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
|
||||||
u8 sharedMask; /* Mask of shared locks held */
|
u8 sharedMask; /* Mask of shared locks held */
|
||||||
u8 exclMask; /* Mask of exclusive locks held */
|
u8 exclMask; /* Mask of exclusive locks held */
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
u8 id; /* Id of this connection with its unixShmFile */
|
u8 id; /* Id of this connection within its unixShmNode */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3221,7 +3226,7 @@ static const char *unixShmLockString(u8 mask){
|
|||||||
** otherwise.
|
** otherwise.
|
||||||
*/
|
*/
|
||||||
static int unixShmSystemLock(
|
static int unixShmSystemLock(
|
||||||
unixShmFile *pFile, /* Apply locks to this open shared-memory segment */
|
unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
|
||||||
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
|
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
|
||||||
u8 lockMask /* Which bytes to lock or unlock */
|
u8 lockMask /* Which bytes to lock or unlock */
|
||||||
){
|
){
|
||||||
@@ -3231,8 +3236,8 @@ static int unixShmSystemLock(
|
|||||||
int rc; /* Result code form fcntl() */
|
int rc; /* Result code form fcntl() */
|
||||||
u8 mask; /* Mask of bits in lockMask */
|
u8 mask; /* Mask of bits in lockMask */
|
||||||
|
|
||||||
/* Access to the unixShmFile object is serialized by the caller */
|
/* Access to the unixShmNode object is serialized by the caller */
|
||||||
assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
|
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
|
||||||
|
|
||||||
/* Initialize the locking parameters */
|
/* Initialize the locking parameters */
|
||||||
memset(&f, 0, sizeof(f));
|
memset(&f, 0, sizeof(f));
|
||||||
@@ -3262,7 +3267,7 @@ static int unixShmSystemLock(
|
|||||||
assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
|
assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
|
||||||
|
|
||||||
/* Acquire the system-level lock */
|
/* Acquire the system-level lock */
|
||||||
rc = fcntl(pFile->h, lockOp, &f);
|
rc = fcntl(pShmNode->h, lockOp, &f);
|
||||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||||
|
|
||||||
/* Update the global lock state and do debug tracing */
|
/* Update the global lock state and do debug tracing */
|
||||||
@@ -3271,17 +3276,17 @@ static int unixShmSystemLock(
|
|||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( lockType==F_UNLCK ){
|
if( lockType==F_UNLCK ){
|
||||||
OSTRACE(("unlock ok"));
|
OSTRACE(("unlock ok"));
|
||||||
pFile->exclMask &= ~lockMask;
|
pShmNode->exclMask &= ~lockMask;
|
||||||
pFile->sharedMask &= ~lockMask;
|
pShmNode->sharedMask &= ~lockMask;
|
||||||
}else if( lockType==F_RDLCK ){
|
}else if( lockType==F_RDLCK ){
|
||||||
OSTRACE(("read-lock ok"));
|
OSTRACE(("read-lock ok"));
|
||||||
pFile->exclMask &= ~lockMask;
|
pShmNode->exclMask &= ~lockMask;
|
||||||
pFile->sharedMask |= lockMask;
|
pShmNode->sharedMask |= lockMask;
|
||||||
}else{
|
}else{
|
||||||
assert( lockType==F_WRLCK );
|
assert( lockType==F_WRLCK );
|
||||||
OSTRACE(("write-lock ok"));
|
OSTRACE(("write-lock ok"));
|
||||||
pFile->exclMask |= lockMask;
|
pShmNode->exclMask |= lockMask;
|
||||||
pFile->sharedMask &= ~lockMask;
|
pShmNode->sharedMask &= ~lockMask;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if( lockType==F_UNLCK ){
|
if( lockType==F_UNLCK ){
|
||||||
@@ -3295,8 +3300,8 @@ static int unixShmSystemLock(
|
|||||||
}
|
}
|
||||||
OSTRACE((" - change requested %s - afterwards %s:%s\n",
|
OSTRACE((" - change requested %s - afterwards %s:%s\n",
|
||||||
unixShmLockString(lockMask),
|
unixShmLockString(lockMask),
|
||||||
unixShmLockString(pFile->sharedMask),
|
unixShmLockString(pShmNode->sharedMask),
|
||||||
unixShmLockString(pFile->exclMask)));
|
unixShmLockString(pShmNode->exclMask)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3307,7 +3312,7 @@ static int unixShmSystemLock(
|
|||||||
** parameter.
|
** parameter.
|
||||||
*/
|
*/
|
||||||
static int unixShmUnlock(
|
static int unixShmUnlock(
|
||||||
unixShmFile *pFile, /* The underlying shared-memory file */
|
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||||
unixShm *p, /* The connection to be unlocked */
|
unixShm *p, /* The connection to be unlocked */
|
||||||
u8 unlockMask /* Mask of locks to be unlocked */
|
u8 unlockMask /* Mask of locks to be unlocked */
|
||||||
){
|
){
|
||||||
@@ -3315,12 +3320,12 @@ static int unixShmUnlock(
|
|||||||
unixShm *pX; /* For looping over all sibling connections */
|
unixShm *pX; /* For looping over all sibling connections */
|
||||||
u8 allMask; /* Union of locks held by connections other than "p" */
|
u8 allMask; /* Union of locks held by connections other than "p" */
|
||||||
|
|
||||||
/* Access to the unixShmFile object is serialized by the caller */
|
/* Access to the unixShmNode object is serialized by the caller */
|
||||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
assert( sqlite3_mutex_held(pShmNode->mutex) );
|
||||||
|
|
||||||
/* Compute locks held by sibling connections */
|
/* Compute locks held by sibling connections */
|
||||||
allMask = 0;
|
allMask = 0;
|
||||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
if( pX==p ) continue;
|
if( pX==p ) continue;
|
||||||
assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
|
assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
|
||||||
allMask |= pX->sharedMask;
|
allMask |= pX->sharedMask;
|
||||||
@@ -3328,7 +3333,7 @@ static int unixShmUnlock(
|
|||||||
|
|
||||||
/* Unlock the system-level locks */
|
/* Unlock the system-level locks */
|
||||||
if( (unlockMask & allMask)!=unlockMask ){
|
if( (unlockMask & allMask)!=unlockMask ){
|
||||||
rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask);
|
rc = unixShmSystemLock(pShmNode, F_UNLCK, unlockMask & ~allMask);
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -3345,7 +3350,7 @@ static int unixShmUnlock(
|
|||||||
** Get reader locks for connection p on all locks in the readMask parameter.
|
** Get reader locks for connection p on all locks in the readMask parameter.
|
||||||
*/
|
*/
|
||||||
static int unixShmSharedLock(
|
static int unixShmSharedLock(
|
||||||
unixShmFile *pFile, /* The underlying shared-memory file */
|
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||||
unixShm *p, /* The connection to get the shared locks */
|
unixShm *p, /* The connection to get the shared locks */
|
||||||
u8 readMask /* Mask of shared locks to be acquired */
|
u8 readMask /* Mask of shared locks to be acquired */
|
||||||
){
|
){
|
||||||
@@ -3353,15 +3358,15 @@ static int unixShmSharedLock(
|
|||||||
unixShm *pX; /* For looping over all sibling connections */
|
unixShm *pX; /* For looping over all sibling connections */
|
||||||
u8 allShared; /* Union of locks held by connections other than "p" */
|
u8 allShared; /* Union of locks held by connections other than "p" */
|
||||||
|
|
||||||
/* Access to the unixShmFile object is serialized by the caller */
|
/* Access to the unixShmNode object is serialized by the caller */
|
||||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
assert( sqlite3_mutex_held(pShmNode->mutex) );
|
||||||
|
|
||||||
/* Find out which shared locks are already held by sibling connections.
|
/* Find out which shared locks are already held by sibling connections.
|
||||||
** If any sibling already holds an exclusive lock, go ahead and return
|
** If any sibling already holds an exclusive lock, go ahead and return
|
||||||
** SQLITE_BUSY.
|
** SQLITE_BUSY.
|
||||||
*/
|
*/
|
||||||
allShared = 0;
|
allShared = 0;
|
||||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
if( pX==p ) continue;
|
if( pX==p ) continue;
|
||||||
if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
|
if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
|
||||||
allShared |= pX->sharedMask;
|
allShared |= pX->sharedMask;
|
||||||
@@ -3369,7 +3374,7 @@ static int unixShmSharedLock(
|
|||||||
|
|
||||||
/* Get shared locks at the system level, if necessary */
|
/* Get shared locks at the system level, if necessary */
|
||||||
if( (~allShared) & readMask ){
|
if( (~allShared) & readMask ){
|
||||||
rc = unixShmSystemLock(pFile, F_RDLCK, readMask);
|
rc = unixShmSystemLock(pShmNode, F_RDLCK, readMask);
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -3386,20 +3391,20 @@ static int unixShmSharedLock(
|
|||||||
** the writeMask parameter.
|
** the writeMask parameter.
|
||||||
*/
|
*/
|
||||||
static int unixShmExclusiveLock(
|
static int unixShmExclusiveLock(
|
||||||
unixShmFile *pFile, /* The underlying shared-memory file */
|
unixShmNode *pShmNode, /* The underlying shared-memory file */
|
||||||
unixShm *p, /* The connection to get the exclusive locks */
|
unixShm *p, /* The connection to get the exclusive locks */
|
||||||
u8 writeMask /* Mask of exclusive locks to be acquired */
|
u8 writeMask /* Mask of exclusive locks to be acquired */
|
||||||
){
|
){
|
||||||
int rc; /* Result code */
|
int rc; /* Result code */
|
||||||
unixShm *pX; /* For looping over all sibling connections */
|
unixShm *pX; /* For looping over all sibling connections */
|
||||||
|
|
||||||
/* Access to the unixShmFile object is serialized by the caller */
|
/* Access to the unixShmNode object is serialized by the caller */
|
||||||
assert( sqlite3_mutex_held(pFile->mutex) );
|
assert( sqlite3_mutex_held(pShmNode->mutex) );
|
||||||
|
|
||||||
/* Make sure no sibling connections hold locks that will block this
|
/* Make sure no sibling connections hold locks that will block this
|
||||||
** lock. If any do, return SQLITE_BUSY right away.
|
** lock. If any do, return SQLITE_BUSY right away.
|
||||||
*/
|
*/
|
||||||
for(pX=pFile->pFirst; pX; pX=pX->pNext){
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
if( pX==p ) continue;
|
if( pX==p ) continue;
|
||||||
if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
|
if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
|
||||||
if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
|
if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
|
||||||
@@ -3408,7 +3413,7 @@ static int unixShmExclusiveLock(
|
|||||||
/* Get the exclusive locks at the system level. Then if successful
|
/* Get the exclusive locks at the system level. Then if successful
|
||||||
** also mark the local connection as being locked.
|
** also mark the local connection as being locked.
|
||||||
*/
|
*/
|
||||||
rc = unixShmSystemLock(pFile, F_WRLCK, writeMask);
|
rc = unixShmSystemLock(pShmNode, F_WRLCK, writeMask);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->sharedMask &= ~writeMask;
|
p->sharedMask &= ~writeMask;
|
||||||
p->exclMask |= writeMask;
|
p->exclMask |= writeMask;
|
||||||
@@ -3417,26 +3422,21 @@ static int unixShmExclusiveLock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0.
|
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
|
||||||
**
|
**
|
||||||
** This is not a VFS shared-memory method; it is a utility function called
|
** This is not a VFS shared-memory method; it is a utility function called
|
||||||
** by VFS shared-memory methods.
|
** by VFS shared-memory methods.
|
||||||
*/
|
*/
|
||||||
static void unixShmPurge(void){
|
static void unixShmPurge(unixFile *pFd){
|
||||||
unixShmFile **pp;
|
unixShmNode *p = pFd->pInode->pShmNode;
|
||||||
unixShmFile *p;
|
|
||||||
assert( unixMutexHeld() );
|
assert( unixMutexHeld() );
|
||||||
pp = &unixShmFileList;
|
if( p && p->nRef==0 ){
|
||||||
while( (p = *pp)!=0 ){
|
assert( p->pInode==pFd->pInode );
|
||||||
if( p->nRef==0 ){
|
|
||||||
if( p->mutex ) sqlite3_mutex_free(p->mutex);
|
if( p->mutex ) sqlite3_mutex_free(p->mutex);
|
||||||
if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
|
if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
|
||||||
if( p->h>=0 ) close(p->h);
|
if( p->h>=0 ) close(p->h);
|
||||||
*pp = p->pNext;
|
p->pInode->pShmNode = 0;
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
}else{
|
|
||||||
pp = &p->pNext;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3459,110 +3459,86 @@ static int unixShmOpen(
|
|||||||
sqlite3_file *fd /* The file descriptor of the associated database */
|
sqlite3_file *fd /* The file descriptor of the associated database */
|
||||||
){
|
){
|
||||||
struct unixShm *p = 0; /* The connection to be opened */
|
struct unixShm *p = 0; /* The connection to be opened */
|
||||||
struct unixShmFile *pFile = 0; /* The underlying mmapped file */
|
struct unixShmNode *pShmNode = 0; /* The underlying mmapped file */
|
||||||
int rc; /* Result code */
|
int rc; /* Result code */
|
||||||
struct unixFileId fid; /* Unix file identifier */
|
|
||||||
struct unixShmFile *pNew; /* Newly allocated pFile */
|
|
||||||
struct stat sStat; /* Result from stat() an fstat() */
|
|
||||||
struct unixFile *pDbFd; /* Underlying database file */
|
struct unixFile *pDbFd; /* Underlying database file */
|
||||||
int nPath; /* Size of pDbFd->zPath in bytes */
|
int nPath; /* Size of pDbFd->zPath in bytes */
|
||||||
|
|
||||||
/* Allocate space for the new sqlite3_shm object. Also speculatively
|
/* Allocate space for the new sqlite3_shm object.
|
||||||
** allocate space for a new unixShmFile and filename.
|
|
||||||
*/
|
*/
|
||||||
p = sqlite3_malloc( sizeof(*p) );
|
p = sqlite3_malloc( sizeof(*p) );
|
||||||
if( p==0 ) return SQLITE_NOMEM;
|
if( p==0 ) return SQLITE_NOMEM;
|
||||||
memset(p, 0, sizeof(*p));
|
memset(p, 0, sizeof(*p));
|
||||||
pDbFd = (struct unixFile*)fd;
|
pDbFd = (struct unixFile*)fd;
|
||||||
assert( pDbFd->pShm==0 );
|
assert( pDbFd->pShm==0 );
|
||||||
nPath = strlen(pDbFd->zPath);
|
|
||||||
pNew = sqlite3_malloc( sizeof(*pFile) + nPath + 15 );
|
|
||||||
if( pNew==0 ){
|
|
||||||
sqlite3_free(p);
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
memset(pNew, 0, sizeof(*pNew));
|
|
||||||
pNew->zFilename = (char*)&pNew[1];
|
|
||||||
sqlite3_snprintf(nPath+15, pNew->zFilename, "%s-wal-index", pDbFd->zPath);
|
|
||||||
|
|
||||||
/* Look to see if there is an existing unixShmFile that can be used.
|
/* Check to see if a unixShmNode object already exists. Reuse an existing
|
||||||
** If no matching unixShmFile currently exists, create a new one.
|
** one if present. Create a new one if necessary.
|
||||||
*/
|
*/
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
rc = stat(pNew->zFilename, &sStat);
|
pShmNode = pDbFd->pInode->pShmNode;
|
||||||
if( rc==0 ){
|
if( pShmNode==0 ){
|
||||||
memset(&fid, 0, sizeof(fid));
|
nPath = strlen(pDbFd->zPath);
|
||||||
fid.dev = sStat.st_dev;
|
pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nPath + 15 );
|
||||||
fid.ino = sStat.st_ino;
|
if( pShmNode==0 ){
|
||||||
for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){
|
|
||||||
if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( pFile ){
|
|
||||||
sqlite3_free(pNew);
|
|
||||||
}else{
|
|
||||||
pFile = pNew;
|
|
||||||
pNew = 0;
|
|
||||||
pFile->h = -1;
|
|
||||||
pFile->pNext = unixShmFileList;
|
|
||||||
unixShmFileList = pFile;
|
|
||||||
|
|
||||||
pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
||||||
if( pFile->mutex==0 ){
|
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
goto shm_open_err;
|
goto shm_open_err;
|
||||||
}
|
}
|
||||||
pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
memset(pShmNode, 0, sizeof(*pShmNode));
|
||||||
if( pFile->mutexBuf==0 ){
|
pShmNode->zFilename = (char*)&pShmNode[1];
|
||||||
|
sqlite3_snprintf(nPath+15, pShmNode->zFilename,
|
||||||
|
"%s-wal-index", pDbFd->zPath);
|
||||||
|
pShmNode->h = -1;
|
||||||
|
pDbFd->pInode->pShmNode = pShmNode;
|
||||||
|
pShmNode->pInode = pDbFd->pInode;
|
||||||
|
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;
|
rc = SQLITE_NOMEM;
|
||||||
goto shm_open_err;
|
goto shm_open_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664);
|
pShmNode->h = open(pShmNode->zFilename, O_RDWR|O_CREAT, 0664);
|
||||||
if( pFile->h<0 ){
|
if( pShmNode->h<0 ){
|
||||||
rc = SQLITE_CANTOPEN_BKPT;
|
rc = SQLITE_CANTOPEN_BKPT;
|
||||||
goto shm_open_err;
|
goto shm_open_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fstat(pFile->h, &sStat);
|
|
||||||
if( rc ){
|
|
||||||
rc = SQLITE_CANTOPEN_BKPT;
|
|
||||||
goto shm_open_err;
|
|
||||||
}
|
|
||||||
pFile->fid.dev = sStat.st_dev;
|
|
||||||
pFile->fid.ino = sStat.st_ino;
|
|
||||||
|
|
||||||
/* Check to see if another process is holding the dead-man switch.
|
/* Check to see if another process is holding the dead-man switch.
|
||||||
** If not, truncate the file to zero length.
|
** If not, truncate the file to zero length.
|
||||||
*/
|
*/
|
||||||
if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
|
rc = SQLITE_OK;
|
||||||
if( ftruncate(pFile->h, 0) ){
|
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
|
||||||
|
if( ftruncate(pShmNode->h, 0) ){
|
||||||
rc = SQLITE_IOERR;
|
rc = SQLITE_IOERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS);
|
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS);
|
||||||
}
|
}
|
||||||
if( rc ) goto shm_open_err;
|
if( rc ) goto shm_open_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the new connection a child of the unixShmFile */
|
/* Make the new connection a child of the unixShmNode */
|
||||||
p->pFile = pFile;
|
p->pShmNode = pShmNode;
|
||||||
p->pNext = pFile->pFirst;
|
p->pNext = pShmNode->pFirst;
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
p->id = pFile->nextShmId++;
|
p->id = pShmNode->nextShmId++;
|
||||||
#endif
|
#endif
|
||||||
pFile->pFirst = p;
|
pShmNode->pFirst = p;
|
||||||
pFile->nRef++;
|
pShmNode->nRef++;
|
||||||
pDbFd->pShm = p;
|
pDbFd->pShm = p;
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
|
|
||||||
/* Jump here on any error */
|
/* Jump here on any error */
|
||||||
shm_open_err:
|
shm_open_err:
|
||||||
unixShmPurge(); /* This call frees pFile if required */
|
unixShmPurge(pDbFd); /* This call frees pShmNode if required */
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
sqlite3_free(pNew);
|
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -3576,37 +3552,41 @@ static int unixShmClose(
|
|||||||
int deleteFlag /* Delete shared-memory if true */
|
int deleteFlag /* Delete shared-memory if true */
|
||||||
){
|
){
|
||||||
unixShm *p; /* The connection to be closed */
|
unixShm *p; /* The connection to be closed */
|
||||||
unixShmFile *pFile; /* The underlying shared-memory file */
|
unixShmNode *pShmNode; /* The underlying shared-memory file */
|
||||||
unixShm **pp; /* For looping over sibling connections */
|
unixShm **pp; /* For looping over sibling connections */
|
||||||
unixFile *pDbFd; /* The underlying database file */
|
unixFile *pDbFd; /* The underlying database file */
|
||||||
|
|
||||||
pDbFd = (unixFile*)fd;
|
pDbFd = (unixFile*)fd;
|
||||||
p = pDbFd->pShm;
|
p = pDbFd->pShm;
|
||||||
if( p==0 ) return SQLITE_OK;
|
if( p==0 ) return SQLITE_OK;
|
||||||
pFile = p->pFile;
|
pShmNode = p->pShmNode;
|
||||||
|
|
||||||
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||||
|
assert( pShmNode->pInode==pDbFd->pInode );
|
||||||
|
|
||||||
/* Verify that the connection being closed holds no locks */
|
/* Verify that the connection being closed holds no locks */
|
||||||
assert( p->exclMask==0 );
|
assert( p->exclMask==0 );
|
||||||
assert( p->sharedMask==0 );
|
assert( p->sharedMask==0 );
|
||||||
|
|
||||||
/* Remove connection p from the set of connections associated with pFile */
|
/* Remove connection p from the set of connections associated
|
||||||
sqlite3_mutex_enter(pFile->mutex);
|
** with pShmNode */
|
||||||
for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
|
sqlite3_mutex_enter(pShmNode->mutex);
|
||||||
|
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
|
||||||
*pp = p->pNext;
|
*pp = p->pNext;
|
||||||
|
|
||||||
/* Free the connection p */
|
/* Free the connection p */
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
pDbFd->pShm = 0;
|
pDbFd->pShm = 0;
|
||||||
sqlite3_mutex_leave(pFile->mutex);
|
sqlite3_mutex_leave(pShmNode->mutex);
|
||||||
|
|
||||||
/* If pFile->nRef has reached 0, then close the underlying
|
/* If pShmNode->nRef has reached 0, then close the underlying
|
||||||
** shared-memory file, too */
|
** shared-memory file, too */
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
assert( pFile->nRef>0 );
|
assert( pShmNode->nRef>0 );
|
||||||
pFile->nRef--;
|
pShmNode->nRef--;
|
||||||
if( pFile->nRef==0 ){
|
if( pShmNode->nRef==0 ){
|
||||||
if( deleteFlag ) unlink(pFile->zFilename);
|
if( deleteFlag ) unlink(pShmNode->zFilename);
|
||||||
unixShmPurge();
|
unixShmPurge(pDbFd);
|
||||||
}
|
}
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
|
|
||||||
@@ -3634,17 +3614,20 @@ static int unixShmSize(
|
|||||||
){
|
){
|
||||||
unixFile *pDbFd = (unixFile*)fd;
|
unixFile *pDbFd = (unixFile*)fd;
|
||||||
unixShm *p = pDbFd->pShm;
|
unixShm *p = pDbFd->pShm;
|
||||||
unixShmFile *pFile = p->pFile;
|
unixShmNode *pShmNode = p->pShmNode;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
struct stat sStat;
|
struct stat sStat;
|
||||||
|
|
||||||
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||||
|
assert( pShmNode->pInode==pDbFd->pInode );
|
||||||
|
|
||||||
/* On a query, this loop runs once. When reqSize>=0, the loop potentially
|
/* 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
|
** 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
|
** to the requested size, reqSize is set to -1 on the first iteration and
|
||||||
** the loop only runs once.
|
** the loop only runs once.
|
||||||
*/
|
*/
|
||||||
while( 1 ){
|
while( 1 ){
|
||||||
if( fstat(pFile->h, &sStat)==0 ){
|
if( fstat(pShmNode->h, &sStat)==0 ){
|
||||||
*pNewSize = (int)sStat.st_size;
|
*pNewSize = (int)sStat.st_size;
|
||||||
if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
|
if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
|
||||||
}else{
|
}else{
|
||||||
@@ -3655,7 +3638,7 @@ static int unixShmSize(
|
|||||||
if( reqSize<0 ) break;
|
if( reqSize<0 ) break;
|
||||||
reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
|
reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
|
||||||
reqSize *= SQLITE_UNIX_SHM_INCR;
|
reqSize *= SQLITE_UNIX_SHM_INCR;
|
||||||
rc = ftruncate(pFile->h, reqSize);
|
rc = ftruncate(pShmNode->h, reqSize);
|
||||||
reqSize = -1;
|
reqSize = -1;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3696,32 +3679,35 @@ static int unixShmGet(
|
|||||||
){
|
){
|
||||||
unixFile *pDbFd = (unixFile*)fd;
|
unixFile *pDbFd = (unixFile*)fd;
|
||||||
unixShm *p = pDbFd->pShm;
|
unixShm *p = pDbFd->pShm;
|
||||||
unixShmFile *pFile = p->pFile;
|
unixShmNode *pShmNode = p->pShmNode;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||||
|
assert( pShmNode->pInode==pDbFd->pInode );
|
||||||
|
|
||||||
if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
|
if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
|
||||||
assert( sqlite3_mutex_notheld(pFile->mutex) );
|
assert( sqlite3_mutex_notheld(pShmNode->mutex) );
|
||||||
sqlite3_mutex_enter(pFile->mutexBuf);
|
sqlite3_mutex_enter(pShmNode->mutexBuf);
|
||||||
p->hasMutexBuf = 1;
|
p->hasMutexBuf = 1;
|
||||||
}
|
}
|
||||||
sqlite3_mutex_enter(pFile->mutex);
|
sqlite3_mutex_enter(pShmNode->mutex);
|
||||||
if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
|
if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
|
||||||
int actualSize;
|
int actualSize;
|
||||||
if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
|
if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
|
||||||
&& reqMapSize<actualSize
|
&& reqMapSize<actualSize
|
||||||
){
|
){
|
||||||
reqMapSize = actualSize;
|
reqMapSize = actualSize;
|
||||||
}
|
}
|
||||||
if( pFile->pMMapBuf ){
|
if( pShmNode->pMMapBuf ){
|
||||||
munmap(pFile->pMMapBuf, pFile->szMap);
|
munmap(pShmNode->pMMapBuf, pShmNode->szMap);
|
||||||
}
|
}
|
||||||
pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
|
pShmNode->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||||
pFile->h, 0);
|
pShmNode->h, 0);
|
||||||
pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0;
|
pShmNode->szMap = pShmNode->pMMapBuf ? reqMapSize : 0;
|
||||||
}
|
}
|
||||||
*pNewMapSize = pFile->szMap;
|
*pNewMapSize = pShmNode->szMap;
|
||||||
*ppBuf = pFile->pMMapBuf;
|
*ppBuf = pShmNode->pMMapBuf;
|
||||||
sqlite3_mutex_leave(pFile->mutex);
|
sqlite3_mutex_leave(pShmNode->mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3740,8 +3726,8 @@ static int unixShmRelease(sqlite3_file *fd){
|
|||||||
unixShm *p = pDbFd->pShm;
|
unixShm *p = pDbFd->pShm;
|
||||||
|
|
||||||
if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
|
if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
|
||||||
assert( sqlite3_mutex_notheld(p->pFile->mutex) );
|
assert( sqlite3_mutex_notheld(p->pShmNode->mutex) );
|
||||||
sqlite3_mutex_leave(p->pFile->mutexBuf);
|
sqlite3_mutex_leave(p->pShmNode->mutexBuf);
|
||||||
p->hasMutexBuf = 0;
|
p->hasMutexBuf = 0;
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@@ -3773,9 +3759,12 @@ static int unixShmLock(
|
|||||||
){
|
){
|
||||||
unixFile *pDbFd = (unixFile*)fd;
|
unixFile *pDbFd = (unixFile*)fd;
|
||||||
unixShm *p = pDbFd->pShm;
|
unixShm *p = pDbFd->pShm;
|
||||||
unixShmFile *pFile = p->pFile;
|
unixShmNode *pShmNode = p->pShmNode;
|
||||||
int rc = SQLITE_PROTOCOL;
|
int rc = SQLITE_PROTOCOL;
|
||||||
|
|
||||||
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||||
|
assert( pShmNode->pInode==pDbFd->pInode );
|
||||||
|
|
||||||
/* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
|
/* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
|
||||||
** directly requested; they are side effects from requesting
|
** directly requested; they are side effects from requesting
|
||||||
** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
|
** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
|
||||||
@@ -3802,15 +3791,15 @@ static int unixShmLock(
|
|||||||
p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
|
p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
|
||||||
|
|
||||||
if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
|
if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
|
||||||
assert( sqlite3_mutex_notheld(pFile->mutex) );
|
assert( sqlite3_mutex_notheld(pShmNode->mutex) );
|
||||||
sqlite3_mutex_enter(pFile->mutexBuf);
|
sqlite3_mutex_enter(pShmNode->mutexBuf);
|
||||||
p->hasMutexBuf = 1;
|
p->hasMutexBuf = 1;
|
||||||
}
|
}
|
||||||
sqlite3_mutex_enter(pFile->mutex);
|
sqlite3_mutex_enter(pShmNode->mutex);
|
||||||
switch( desiredLock ){
|
switch( desiredLock ){
|
||||||
case SQLITE_SHM_UNLOCK: {
|
case SQLITE_SHM_UNLOCK: {
|
||||||
assert( p->lockState!=SQLITE_SHM_RECOVER );
|
assert( p->lockState!=SQLITE_SHM_RECOVER );
|
||||||
unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
|
unixShmUnlock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
p->lockState = SQLITE_SHM_UNLOCK;
|
p->lockState = SQLITE_SHM_UNLOCK;
|
||||||
break;
|
break;
|
||||||
@@ -3821,22 +3810,22 @@ static int unixShmLock(
|
|||||||
rc = SQLITE_BUSY;
|
rc = SQLITE_BUSY;
|
||||||
assert( p->lockState==SQLITE_SHM_UNLOCK );
|
assert( p->lockState==SQLITE_SHM_UNLOCK );
|
||||||
for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
|
for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
|
||||||
rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B);
|
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B);
|
||||||
if( rc==SQLITE_BUSY ){
|
if( rc==SQLITE_BUSY ){
|
||||||
rc = unixShmSharedLock(pFile, p, UNIX_SHM_D);
|
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_D);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->lockState = SQLITE_SHM_READ_FULL;
|
p->lockState = SQLITE_SHM_READ_FULL;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
unixShmUnlock(pFile, p, UNIX_SHM_B);
|
unixShmUnlock(pShmNode, p, UNIX_SHM_B);
|
||||||
p->lockState = SQLITE_SHM_READ;
|
p->lockState = SQLITE_SHM_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
assert( p->lockState==SQLITE_SHM_WRITE
|
assert( p->lockState==SQLITE_SHM_WRITE
|
||||||
|| p->lockState==SQLITE_SHM_RECOVER );
|
|| p->lockState==SQLITE_SHM_RECOVER );
|
||||||
rc = unixShmSharedLock(pFile, p, UNIX_SHM_A);
|
rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A);
|
||||||
unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
|
unixShmUnlock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
|
||||||
p->lockState = SQLITE_SHM_READ;
|
p->lockState = SQLITE_SHM_READ;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3844,7 +3833,7 @@ static int unixShmLock(
|
|||||||
case SQLITE_SHM_WRITE: {
|
case SQLITE_SHM_WRITE: {
|
||||||
assert( p->lockState==SQLITE_SHM_READ
|
assert( p->lockState==SQLITE_SHM_READ
|
||||||
|| p->lockState==SQLITE_SHM_READ_FULL );
|
|| p->lockState==SQLITE_SHM_READ_FULL );
|
||||||
rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
|
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->lockState = SQLITE_SHM_WRITE;
|
p->lockState = SQLITE_SHM_WRITE;
|
||||||
}
|
}
|
||||||
@@ -3855,13 +3844,13 @@ static int unixShmLock(
|
|||||||
|| p->lockState==SQLITE_SHM_PENDING
|
|| p->lockState==SQLITE_SHM_PENDING
|
||||||
);
|
);
|
||||||
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
if( p->lockState==SQLITE_SHM_UNLOCK ){
|
||||||
rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C);
|
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_B|UNIX_SHM_C);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->lockState = SQLITE_SHM_PENDING;
|
p->lockState = SQLITE_SHM_PENDING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( p->lockState==SQLITE_SHM_PENDING ){
|
if( p->lockState==SQLITE_SHM_PENDING ){
|
||||||
rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A);
|
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_A);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->lockState = SQLITE_SHM_CHECKPOINT;
|
p->lockState = SQLITE_SHM_CHECKPOINT;
|
||||||
}
|
}
|
||||||
@@ -3873,15 +3862,15 @@ static int unixShmLock(
|
|||||||
assert( p->lockState==SQLITE_SHM_READ
|
assert( p->lockState==SQLITE_SHM_READ
|
||||||
|| p->lockState==SQLITE_SHM_READ_FULL
|
|| p->lockState==SQLITE_SHM_READ_FULL
|
||||||
);
|
);
|
||||||
assert( sqlite3_mutex_held(pFile->mutexBuf) );
|
assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
|
||||||
rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C);
|
rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
p->lockState = SQLITE_SHM_RECOVER;
|
p->lockState = SQLITE_SHM_RECOVER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_mutex_leave(pFile->mutex);
|
sqlite3_mutex_leave(pShmNode->mutex);
|
||||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
|
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
|
||||||
p->id, getpid(), azLkName[p->lockState]));
|
p->id, getpid(), azLkName[p->lockState]));
|
||||||
if( pGotLock ) *pGotLock = p->lockState;
|
if( pGotLock ) *pGotLock = p->lockState;
|
||||||
@@ -4497,7 +4486,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
|||||||
** Even if a subsequent open() call does succeed, the consequences of
|
** Even if a subsequent open() call does succeed, the consequences of
|
||||||
** not searching for a resusable file descriptor are not dire. */
|
** not searching for a resusable file descriptor are not dire. */
|
||||||
if( 0==stat(zPath, &sStat) ){
|
if( 0==stat(zPath, &sStat) ){
|
||||||
struct unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
|
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
pInode = inodeList;
|
pInode = inodeList;
|
||||||
|
|||||||
Reference in New Issue
Block a user