From: drh Date: Fri, 4 Nov 2011 02:24:02 +0000 (+0000) Subject: Use mkdir() and rmdir() rather than open() and unlink() to create the lock X-Git-Tag: mountain-lion~9^2~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9ef6bc427a4c31266a9282b8cc7df894ad933a6e;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 7821e33a9a..619f91a7e0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sshell\sso\sthat\sthe\s".schema"\scommand\sworks\swith\scase\sinsensitive\nLIKE\spatterns\seven\swith\sPRAGMA\scache_sensitive_like=ON. -D 2011-11-04T00:35:56.173 +C Use\smkdir()\sand\srmdir()\srather\sthan\sopen()\sand\sunlink()\sto\screate\sthe\slock\nfiles\swith\sthe\sunix-dotlock\sVFS.\s\sThe\schange\sis\sbackwards\scompatible\sand,\nwe\sare\stold,\sworks\sbetter\son\ssome\snetwork\sfilesystems. +D 2011-11-04T02:24:02.845 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -166,7 +166,7 @@ F src/os.c 5d9b02782ed36345348d6fe21d7762ed3a9cfd2a F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 -F src/os_unix.c ddda0b1c5ae536669634d7bff31b3f8f4d654866 +F src/os_unix.c 32f2ac2adbbba6acb649915a6953524ecf4cf9d5 F src/os_win.c 49d418916428a59d773f39993db0ecde56ab4c37 F src/pager.c ad62daa0c21e27ae332b3ceb4f579a2a97046ddc F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d @@ -699,7 +699,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/superlock.test 7b1167925e9d30a5d1f0701d24812fdda42c3a86 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 -F test/syscall.test 966addf703faee6a5d509abe6d8885e393e552fd +F test/syscall.test 2a922050dbee032f587249b070fb42692f5e1e22 F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 @@ -974,7 +974,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 6f9898db7ff0730cc03f561f9c32ef3dee7e5d81 -R d2ce493b65686d96618972d4df6ad36c +P b06bf3b3605a3c39cdfbb76c9a9f6b5202bb95ec +R 044a4088718b0a84e4c3090a9efafe25 U drh -Z 773ddc7cfde2cddd1397075b47c1fbba +Z 61f6de61b36ef0e121c72533e9e5fa9c diff --git a/manifest.uuid b/manifest.uuid index 943b13cc7b..313b234dee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b06bf3b3605a3c39cdfbb76c9a9f6b5202bb95ec \ No newline at end of file +e2f08426d7a84a2ac6148f485b7af377201a175b \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 0ea6daf27f..5ca3415a53 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -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++){ diff --git a/test/syscall.test b/test/syscall.test index 201bd63647..b67bead7da 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -59,7 +59,7 @@ do_test 2.1.2 { test_syscall exists nosuchcall } 0 foreach s { open close access getcwd stat fstat ftruncate fcntl read pread write pwrite fchmod fallocate - pread64 pwrite64 unlink openDirectory + pread64 pwrite64 unlink openDirectory mkdir rmdir } { if {[test_syscall exists $s]} {lappend syscall_list $s} }