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

Use mkdir() and rmdir() rather than open() and unlink() to create the lock

files with the unix-dotlock VFS.  The change is backwards compatible and,
we are told, works better on some network filesystems.

FossilOrigin-Name: e2f08426d7a84a2ac6148f485b7af377201a175b
This commit is contained in:
drh
2011-11-04 02:24:02 +00:00
parent 6ac7a58b14
commit 9ef6bc427a
4 changed files with 31 additions and 24 deletions

View File

@@ -407,6 +407,12 @@ static struct unix_syscall {
{ "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
{ "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
}; /* End of the overrideable system calls */
/*
@@ -1845,8 +1851,8 @@ static int nolockClose(sqlite3_file *id) {
************************* Begin dot-file Locking ******************************
**
** The dotfile locking implementation uses the existance of separate lock
** files in order to control access to the database. This works on just
** about every filesystem imaginable. But there are serious downsides:
** files (really a directory) to control access to the database. This works
** on just about every filesystem imaginable. But there are serious downsides:
**
** (1) There is zero concurrency. A single reader blocks all other
** connections from reading or writing the database.
@@ -1857,15 +1863,15 @@ static int nolockClose(sqlite3_file *id) {
** Nevertheless, a dotlock is an appropriate locking mode for use if no
** other locking strategy is available.
**
** Dotfile locking works by creating a file in the same directory as the
** database and with the same name but with a ".lock" extension added.
** The existance of a lock file implies an EXCLUSIVE lock. All other lock
** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
** Dotfile locking works by creating a subdirectory in the same directory as
** the database and with the same name but with a ".lock" extension added.
** The existance of a lock directory implies an EXCLUSIVE lock. All other
** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
*/
/*
** The file suffix added to the data base filename in order to create the
** lock file.
** lock directory.
*/
#define DOTLOCK_SUFFIX ".lock"
@@ -1932,7 +1938,6 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
*/
static int dotlockLock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
int rc = SQLITE_OK;
@@ -1952,9 +1957,9 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
}
/* grab an exclusive lock */
fd = robust_open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
if( fd<0 ){
/* failed to open/create the file, someone else may have stolen the lock */
rc = osMkdir(zLockFile, 0777);
if( rc<0 ){
/* failed to open/create the lock directory */
int tErrno = errno;
if( EEXIST == tErrno ){
rc = SQLITE_BUSY;
@@ -1966,7 +1971,6 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
}
return rc;
}
robust_close(pFile, fd, __LINE__);
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
@@ -1985,6 +1989,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
int rc;
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
@@ -2006,7 +2011,9 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
/* To fully unlock the database, delete the lock file */
assert( eFileLock==NO_LOCK );
if( osUnlink(zLockFile) ){
rc = osRmdir(zLockFile);
if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
if( rc<0 ){
int rc = 0;
int tErrno = errno;
if( ENOENT != tErrno ){
@@ -5715,7 +5722,7 @@ static int proxyCreateLockPath(const char *lockPath){
if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
|| (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
buf[i]='\0';
if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
int err=errno;
if( err!=EEXIST ) {
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
@@ -6751,7 +6758,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==18 );
assert( ArraySize(aSyscall)==20 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){