1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Add the new optional "unix-excl" VFS. This VFS grabs an exclusive lock on

the database preventing other processes from accessing it, but continues to
allow other database connections from the same process.

FossilOrigin-Name: 00051c3296e11211b2bb5ae28f016b17dca857d7
This commit is contained in:
drh
2011-03-12 17:02:57 +00:00
parent 11c58f7d8e
commit a7e61d8b24
4 changed files with 98 additions and 24 deletions

View File

@@ -1,5 +1,8 @@
C More\stests\sfor\sSQLITE_OMIT_UNIQUE_ENFORCEMENT\sand\sminor\schange\sto\simplementation. -----BEGIN PGP SIGNED MESSAGE-----
D 2011-03-12T04:58:55.547 Hash: SHA1
C Add\sthe\snew\soptional\s"unix-excl"\sVFS.\s\sThis\sVFS\sgrabs\san\sexclusive\slock\son\nthe\sdatabase\spreventing\sother\sprocesses\sfrom\saccessing\sit,\sbut\scontinues\sto\nallow\sother\sdatabase\sconnections\sfrom\sthe\ssame\sprocess.
D 2011-03-12T17:02:57.101
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -162,7 +165,7 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf
F src/os_unix.c c4d50608133e16185dd2e120d2713c096f390260 F src/os_unix.c 557837beff775c448bb072ae21edeff912d1f0df
F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845 F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845
F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1 F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1 F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
@@ -177,7 +180,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944
F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b F src/shell.c 54f8fe0afab6839444882c4d18a0032668392c9a
F src/sqlite.h.in 369c767e6b9f101d63d8e4c5e40279f975ccec08 F src/sqlite.h.in 369c767e6b9f101d63d8e4c5e40279f975ccec08
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h 2cea3e47997e3f4d9b4f1ce62f99c35be1b5a586 F src/sqliteInt.h 2cea3e47997e3f4d9b4f1ce62f99c35be1b5a586
@@ -913,7 +916,18 @@ 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 f957f23a8a392bb1720720960bda2c7b24de9663 P b86999436ec2414c990ba720441fe316f647eef6
R 9809ca6e3f2473669b6771844893033b R b4018b4a3ca8304164ff6618b813c5a9
U shaneh T *bgcolor * #aaa8d3
Z 165de3d9f760ec4796ef397e07022985 T *branch * unix-excl
T *sym-unix-excl *
T -sym-trunk *
U drh
Z ca346ade739e93ef182345e803581a80
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFNe6dEoxKgR168RlERAkgMAJ47rTo3YzDvLp8S+pIflXBmm5FOSwCggCkn
s82X2XcH9cqBqUU6lQenClw=
=LUbU
-----END PGP SIGNATURE-----

View File

@@ -1 +1 @@
b86999436ec2414c990ba720441fe316f647eef6 00051c3296e11211b2bb5ae28f016b17dca857d7

View File

@@ -206,6 +206,7 @@ struct unixFile {
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 */
unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
int lastErrno; /* The unix errno from last I/O error */ int lastErrno; /* The unix errno from last I/O error */
void *lockingContext; /* Locking style specific state */ void *lockingContext; /* Locking style specific state */
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
@@ -242,6 +243,11 @@ struct unixFile {
#endif #endif
}; };
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
/* /*
** Include code that is common to all os_*.c files ** Include code that is common to all os_*.c files
*/ */
@@ -887,7 +893,8 @@ struct unixFileId {
struct unixInodeInfo { struct unixInodeInfo {
struct unixFileId fileId; /* The lookup key */ struct unixFileId fileId; /* The lookup key */
int nShared; /* Number of SHARED locks held */ int nShared; /* Number of SHARED locks held */
int eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
unsigned char bProcessLock; /* An exclusive process lock is held */
int nRef; /* Number of pointers to this structure */ int nRef; /* Number of pointers to this structure */
unixShmNode *pShmNode; /* Shared memory associated with this inode */ unixShmNode *pShmNode; /* Shared memory associated with this inode */
int nLock; /* Number of outstanding file locks */ int nLock; /* Number of outstanding file locks */
@@ -1158,7 +1165,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
/* Otherwise see if some other process holds it. /* Otherwise see if some other process holds it.
*/ */
#ifndef __DJGPP__ #ifndef __DJGPP__
if( !reserved ){ if( !reserved && !pFile->pInode->bProcessLock ){
struct flock lock; struct flock lock;
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = RESERVED_BYTE; lock.l_start = RESERVED_BYTE;
@@ -1181,6 +1188,40 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc; return rc;
} }
/*
** Attempt to set a system-lock on the file pFile. The lock is
** described by pLock.
**
** If the pFile was opened from unix-excl, then the only lock ever
** obtained is an exclusive lock, and it is obtained exactly once
** the first time any lock is attempted. All subsequent system locking
** operations become no-ops. Locking operations still happen internally,
** in order to coordinate access between separate database connections
** within this process, but all of that is handled in memory and the
** operating system does not participate.
*/
static int unixFileLock(unixFile *pFile, struct flock *pLock){
int rc;
assert( unixMutexHeld() );
if( (pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pFile->pInode->bProcessLock ){
if( pFile->pInode->bProcessLock==0 ){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
lock.l_type = F_WRLCK;
rc = osFcntl(pFile->h, F_SETLK, &lock);
if( rc<0 ) return rc;
pFile->pInode->bProcessLock = 1;
}else{
rc = 0;
}
}else{
rc = osFcntl(pFile->h, F_SETLK, pLock);
}
return rc;
}
/* /*
** Lock the file with the lock specified by parameter eFileLock - one ** Lock the file with the lock specified by parameter eFileLock - one
** of the following: ** of the following:
@@ -1317,7 +1358,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
){ ){
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE; lock.l_start = PENDING_BYTE;
s = osFcntl(pFile->h, F_SETLK, &lock); s = unixFileLock(pFile, &lock);
if( s==(-1) ){ if( s==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
@@ -1339,14 +1380,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* Now get the read-lock */ /* Now get the read-lock */
lock.l_start = SHARED_FIRST; lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE; lock.l_len = SHARED_SIZE;
if( (s = osFcntl(pFile->h, F_SETLK, &lock))==(-1) ){ if( (s = unixFileLock(pFile, &lock))==(-1) ){
tErrno = errno; tErrno = errno;
} }
/* Drop the temporary PENDING lock */ /* Drop the temporary PENDING lock */
lock.l_start = PENDING_BYTE; lock.l_start = PENDING_BYTE;
lock.l_len = 1L; lock.l_len = 1L;
lock.l_type = F_UNLCK; lock.l_type = F_UNLCK;
if( osFcntl(pFile->h, F_SETLK, &lock)!=0 ){ if( unixFileLock(pFile, &lock)!=0 ){
if( s != -1 ){ if( s != -1 ){
/* This could happen with a network mount */ /* This could happen with a network mount */
tErrno = errno; tErrno = errno;
@@ -1389,7 +1430,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
default: default:
assert(0); assert(0);
} }
s = osFcntl(pFile->h, F_SETLK, &lock); s = unixFileLock(pFile, &lock);
if( s==(-1) ){ if( s==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
@@ -1458,7 +1499,7 @@ static void setPendingFd(unixFile *pFile){
** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to ** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
** remove the write lock on a region when a read lock is set. ** remove the write lock on a region when a read lock is set.
*/ */
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;
unixInodeInfo *pInode; unixInodeInfo *pInode;
struct flock lock; struct flock lock;
@@ -1525,7 +1566,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST; lock.l_start = SHARED_FIRST;
lock.l_len = divSize; lock.l_len = divSize;
if( osFcntl(h, F_SETLK, &lock)==(-1) ){ if( unixFileLock(pFile,, &lock)==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){ if( IS_LOCK_ERROR(rc) ){
@@ -1537,7 +1578,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST; lock.l_start = SHARED_FIRST;
lock.l_len = divSize; lock.l_len = divSize;
if( osFcntl(h, F_SETLK, &lock)==(-1) ){ if( unixFileLock(pFile, &lock)==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
if( IS_LOCK_ERROR(rc) ){ if( IS_LOCK_ERROR(rc) ){
@@ -1549,7 +1590,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST+divSize; lock.l_start = SHARED_FIRST+divSize;
lock.l_len = SHARED_SIZE-divSize; lock.l_len = SHARED_SIZE-divSize;
if( osFcntl(h, F_SETLK, &lock)==(-1) ){ if( unixFileLock(pFile, &lock)==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){ if( IS_LOCK_ERROR(rc) ){
@@ -1564,7 +1605,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST; lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE; lock.l_len = SHARED_SIZE;
if( osFcntl(h, F_SETLK, &lock)==(-1) ){ if( unixFileLock(pFile, &lock)==(-1) ){
tErrno = errno; tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
if( IS_LOCK_ERROR(rc) ){ if( IS_LOCK_ERROR(rc) ){
@@ -1578,7 +1619,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE; lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
if( osFcntl(h, F_SETLK, &lock)!=(-1) ){ if( unixFileLock(pFile, &lock)!=(-1) ){
pInode->eFileLock = SHARED_LOCK; pInode->eFileLock = SHARED_LOCK;
}else{ }else{
tErrno = errno; tErrno = errno;
@@ -1602,7 +1643,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
SimulateIOErrorBenign(1); SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) ) SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0); SimulateIOErrorBenign(0);
if( osFcntl(h, F_SETLK, &lock)!=(-1) ){ if( unixFileLock(pFile, &lock)!=(-1) ){
pInode->eFileLock = NO_LOCK; pInode->eFileLock = NO_LOCK;
}else{ }else{
tErrno = errno; tErrno = errno;
@@ -1640,7 +1681,7 @@ end_unlock:
** the requested locking level, this routine is a no-op. ** the requested locking level, this routine is a no-op.
*/ */
static int unixUnlock(sqlite3_file *id, int eFileLock){ static int unixUnlock(sqlite3_file *id, int eFileLock){
return _posixUnlock(id, eFileLock, 0); return posixUnlock(id, eFileLock, 0);
} }
/* /*
@@ -2821,7 +2862,7 @@ static int afpClose(sqlite3_file *id) {
** the requested locking level, this routine is a no-op. ** the requested locking level, this routine is a no-op.
*/ */
static int nfsUnlock(sqlite3_file *id, int eFileLock){ static int nfsUnlock(sqlite3_file *id, int eFileLock){
return _posixUnlock(id, eFileLock, 1); return posixUnlock(id, eFileLock, 1);
} }
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
@@ -4351,6 +4392,11 @@ static int fillInUnixFile(
pNew->h = h; pNew->h = h;
pNew->dirfd = dirfd; pNew->dirfd = dirfd;
pNew->zPath = zFilename; pNew->zPath = zFilename;
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
pNew->ctrlFlags = UNIXFILE_EXCL;
}else{
pNew->ctrlFlags = 0;
}
#if OS_VXWORKS #if OS_VXWORKS
pNew->pId = vxworksFindFileId(zFilename); pNew->pId = vxworksFindFileId(zFilename);
@@ -6550,6 +6596,7 @@ int sqlite3_os_init(void){
#endif #endif
UNIXVFS("unix-none", nolockIoFinder ), UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ), UNIXVFS("unix-dotfile", dotlockIoFinder ),
UNIXVFS("unix-excl", posixIoFinder ),
#if OS_VXWORKS #if OS_VXWORKS
UNIXVFS("unix-namedsem", semIoFinder ), UNIXVFS("unix-namedsem", semIoFinder ),
#endif #endif

View File

@@ -419,6 +419,7 @@ struct callback_data {
** .explain ON */ ** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */ char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */ const char *zDbFilename; /* name of the database file */
const char *zVfs; /* Name of VFS to use */
sqlite3_stmt *pStmt; /* Current statement if any. */ sqlite3_stmt *pStmt; /* Current statement if any. */
FILE *pLog; /* Write log output here */ FILE *pLog; /* Write log output here */
}; };
@@ -2600,6 +2601,7 @@ static const char zOptions[] =
" -stats print memory stats before each finalize\n" " -stats print memory stats before each finalize\n"
" -nullvalue 'text' set text string for NULL values\n" " -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n" " -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
; ;
static void usage(int showDetail){ static void usage(int showDetail){
fprintf(stderr, fprintf(stderr,
@@ -2684,6 +2686,15 @@ int main(int argc, char **argv){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif #endif
}else if( strcmp(argv[i],"-vfs")==0 ){
i++;
sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[i]);
if( pVfs ){
sqlite3_vfs_register(pVfs, 1);
}else{
fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
exit(1);
}
} }
} }
if( i<argc ){ if( i<argc ){
@@ -2792,6 +2803,8 @@ int main(int argc, char **argv){
stdin_is_interactive = 0; stdin_is_interactive = 0;
}else if( strcmp(z,"-heap")==0 ){ }else if( strcmp(z,"-heap")==0 ){
i++; i++;
}else if( strcmp(z,"-vfs")==0 ){
i++;
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){ }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
usage(1); usage(1);
}else{ }else{