Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -17,11 +17,11 @@ ** The differences are in the way that file locking is done. The default ** implementation uses Posix Advisory Locks. Alternative implementations ** use flock(), dot-files, various proprietary locking schemas, or simply ** skip locking all together. ** -** This source file is group into divisions where the logic for various +** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed ** in the correct division and should be clearly labeled. ** ** The current set of divisions is as follows: @@ -34,15 +34,18 @@ ** + for dot-file locks ** + for flock() locking ** + for named semaphore locks (VxWorks only) ** + for AFP filesystem locks (MacOSX only) ** + for proxy locks (MacOSX only) -** * The routine used to detect an appropriate locking style -** * sqlite3_file methods not associated with locking -** * Implementations of sqlite3_os_init() and sqlite3_os_end() +** * sqlite3_file methods not associated with locking. +** * Definitions of sqlite3_io_methods objects for all locking +** methods plus "finder" functions for each locking method. +** * VFS method implementations. +** * Definitions of sqlite3_vfs objects for all locking methods +** plus implementations of sqlite3_os_init() and sqlite3_os_end(). ** -** $Id: os_unix.c,v 1.223 2008/11/29 00:56:53 drh Exp $ +** $Id: os_unix.c,v 1.224 2008/11/29 02:20:27 drh Exp $ */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ /* @@ -58,13 +61,10 @@ ** ** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE ** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic ** selection of the appropriate locking style based on the filesystem ** where the database is located. -** -** SQLITE_ENABLE_LOCKING_STYLE only works on a Mac. It is turned on by -** default on a Mac and disabled on all other posix platforms. */ #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__DARWIN__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else @@ -94,10 +94,15 @@ ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. +** +** The previous paragraph was written in 2005. (This paragraph is written +** on 2008-11-28.) These days, all Linux kernels support large files, so +** you should probably leave LFS enabled. But some embedded platforms might +** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 @@ -117,14 +122,14 @@ #include #if SQLITE_ENABLE_LOCKING_STYLE # include # if OS_VXWORKS -# define lstat stat # include # include # else +# include # include # include # endif #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -162,12 +167,12 @@ */ #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) /* -** The unixFile structure is subclass of sqlite3_file specific for the unix -** protability layer. +** The unixFile structure is subclass of sqlite3_file specific to the unix +** VFS implementations. */ typedef struct unixFile unixFile; struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ struct unixOpenCnt *pOpen; /* Info about all open fd's on this inode */ @@ -417,22 +422,22 @@ char *zCanonicalName; /* Canonical filename */ }; #if OS_VXWORKS /* -** All unique filesname are held on a linked list headed by this +** All unique filenames are held on a linked list headed by this ** variable: */ static struct vxworksFileId *vxworksFileList = 0; /* ** Simplify a filename into its canonical form ** by making the following changes: ** ** * removing any trailing and duplicate / -** * removing /./ -** * removing /A/../ +** * convert /./ into just / +** * convert /A/../ where A is any simple name into just / ** ** Changes are made in-place. Return the new name length. ** ** The original filename is in z[0..n-1]. Return the number of ** characters in the simplified name. @@ -532,11 +537,11 @@ /****************************************************************************** *************************** Posix Advisory Locking **************************** ** -** POSIX advisory locks broken by design. ANSI STD 1003.1 (1996) +** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996) ** section 6.5.2.2 lines 483 through 490 specify that when a process ** sets or clears a lock, that operation overrides any prior locks set ** by the same process. It does not explicitly say so, but this implies ** that it overrides locks set by the same process using a different ** file descriptor. Consider this test case: @@ -564,10 +569,14 @@ ** st_dev and st_ino fields of the stat structure that fstat() fills in) ** and check for locks already existing on that inode. When locks are ** created or removed, we have to look at our own internal record of the ** locks to see if another thread has previously set a lock on that same ** inode. +** +** (Aside: The use of inode numbers as unique IDs does not work on VxWorks. +** For VxWorks, we have to use the alternative unique ID system based on +** canonical filename and implemented in the previous division.) ** ** The sqlite3_file structure for POSIX is no longer just an integer file ** descriptor. It is now a structure that holds the integer file ** descriptor and a pointer to a structure that describes the internal ** locks on the corresponding inode. There is one locking structure @@ -595,14 +604,14 @@ ** to close() the file descriptor is deferred until all of the locks clear. ** The unixOpenCnt structure keeps a list of file descriptors that need to ** be closed and that list is walked (and cleared) when the last lock ** clears. ** -** Yet another problem with posix locks and threads: +** Yet another problem: LinuxThreads do not play well with posix locks. ** -** Many older versions of linux us the LinuxThreads library which is -** not posix compliant. Under LinuxThreads, a lock created thread +** Many older versions of linux use the LinuxThreads library which is +** not posix compliant. Under LinuxThreads, a lock created by thread ** A cannot be modified or overridden by a different thread B. ** Only thread A can modify the lock. Locking behavior is correct ** if the appliation uses the newer Native Posix Thread Library (NPTL) ** on linux - with NPTL a lock created by thread A can override locks ** in thread B. But there is no way to know at compile-time which @@ -611,11 +620,11 @@ ** We have to do a run-time check to discover the behavior of the ** current process. ** ** On systems where thread A is unable to modify locks created by ** thread B, we have to keep track of which thread created each -** lock. So there is an extra field in the key to the unixLockInfo +** lock. Hence there is an extra field in the key to the unixLockInfo ** structure to record this information. And on those systems it ** is illegal to begin a transaction in one thread and finish it ** in another. For this latter restriction, there is no work-around. ** It is a limitation of LinuxThreads. */ @@ -675,13 +684,12 @@ #endif }; /* ** An instance of the following structure is allocated for each open -** inode on each thread with a different process ID. (Threads have -** different process IDs on some versions of linux, but not on most -** other unixes.) +** inode. Or, on LinuxThreads, there is one of these structures for +** each inode opened by each thread. ** ** A single inode can have multiple file descriptors, so each unixFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of unixFile pointing to it. */ @@ -698,10 +706,15 @@ ** An instance of the following structure is allocated for each open ** inode. This structure keeps track of the number of locks on that ** inode. If a close is attempted against an inode that is holding ** locks, the close is deferred until all locks clear by adding the ** file descriptor to be closed to the pending list. +** +** TODO: Consider changing this so that there is only a single file +** descriptor for each open file, even when it is opened multiple times. +** The close() system call would only occur when the last database +** using the file closes. */ struct unixOpenCnt { struct unixFileId fileId; /* The lookup key */ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ @@ -713,24 +726,24 @@ #endif struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */ }; /* -** List of all unixLockInfo and unixOpenCnt objects. This used to be a hash -** table. But the number of objects is rarely more than a dozen and +** Lists of all unixLockInfo and unixOpenCnt objects. These used to be hash +** tables. But the number of objects is rarely more than a dozen and ** never exceeds a few thousand. And lookup is not on a critical ** path so a simple linked list will suffice. */ static struct unixLockInfo *lockList = 0; static struct unixOpenCnt *openList = 0; /* -** This variable records whether or not threads can override each others +** This variable remembers whether or not threads can override each others ** locks. ** -** 0: No. Threads cannot override each others locks. -** 1: Yes. Threads can override each others locks. +** 0: No. Threads cannot override each others locks. (LinuxThreads) +** 1: Yes. Threads can override each others locks. (Posix & NLPT) ** -1: We don't know yet. ** ** On some systems, we know at compile-time if threads can override each ** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro ** will be set appropriately. On other systems, we have to check at @@ -864,11 +877,10 @@ sqlite3_free(pOpen->aPending); sqlite3_free(pOpen); } } } - /* ** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. @@ -1457,10 +1469,14 @@ /* ** This function performs the parts of the "close file" operation ** common to all locking schemes. It closes the directory and file ** handles, if they are valid, and sets all fields of the unixFile ** structure to 0. +** +** It is *not* necessary to hold the mutex when this routine is called, +** even on VxWorks. A mutex will be acquired on VxWorks by the +** vxworksReleaseFileId() routine. */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; if( pFile ){ if( pFile->dirfd>=0 ){ @@ -1480,11 +1496,11 @@ } } #if OS_VXWORKS if( pFile->pId ){ if( pFile->isDelete ){ - unlink(pFile->pId->zCanonicalName); + unlink(pFile->pId->zCanonicalName); } vxworksReleaseFileId(pFile->pId); pFile->pId = 0; } #endif @@ -1548,40 +1564,29 @@ ** corruption if this locking mode is used in situations where multiple ** database connections are accessing the same database file at the same ** time and one or more of those connections are writing. */ -/* -** The nolockLockingContext is void -*/ -typedef void nolockLockingContext; - static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){ UNUSED_PARAMETER(NotUsed); *pResOut = 0; return SQLITE_OK; } - static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){ UNUSED_PARAMETER2(NotUsed, NotUsed2); return SQLITE_OK; } - static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){ UNUSED_PARAMETER2(NotUsed, NotUsed2); return SQLITE_OK; } /* -** Close a file. +** Close the file. */ static int nolockClose(sqlite3_file *id) { - int rc; - if( OS_VXWORKS ) unixEnterMutex(); - rc = closeUnixFile(id); - if( OS_VXWORKS ) unixLeaveMutex(); - return rc; + return closeUnixFile(id); } /******************* End of the no-op lock implementation ********************* ******************************************************************************/ @@ -1764,22 +1769,20 @@ pFile->locktype = NO_LOCK; return SQLITE_OK; } /* -** Close a file. +** Close a file. Make sure the lock has been released before closing. */ static int dotlockClose(sqlite3_file *id) { int rc; if( id ){ unixFile *pFile = (unixFile*)id; dotlockUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); } - if( OS_VXWORKS ) unixEnterMutex(); rc = closeUnixFile(id); - if( OS_VXWORKS ) unixLeaveMutex(); return rc; } /****************** End of the dot-file lock implementation ******************* ******************************************************************************/ @@ -1790,16 +1793,10 @@ ** ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if ** compiling for VXWORKS. */ #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS -#include - -/* -** The flockLockingContext is not used -*/ -typedef void flockLockingContext; /* flock-style reserved lock checking following the behavior of ** unixCheckReservedLock, see the unixCheckReservedLock function comments */ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.333 2008/11/29 00:56:53 drh Exp $ +** $Id: test1.c,v 1.334 2008/11/29 02:20:27 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include #include @@ -4525,11 +4525,18 @@ Tcl_GetStringFromObj(objv[0], 0), " DB", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; -#if defined(SQLITE_ENABLE_LOCKING_STYLE) && defined(__DARWIN__) +#if !defined(SQLITE_ENABLE_LOCKING_STYLE) +# if defined(__DARWIN__) +# define SQLITE_ENABLE_LOCKING_STYLE 1 +# else +# define SQLITE_ENABLE_LOCKING_STYLE 0 +# endif +#endif +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) { char *proxyPath = "test.proxy"; char *testPath; rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); if( rc ){ Index: src/test_config.c ================================================================== --- src/test_config.c +++ src/test_config.c @@ -14,11 +14,11 @@ ** None of the code in this file goes into a deliverable build. ** ** The focus of this file is providing the TCL testing layer ** access to compile-time constants. ** -** $Id: test_config.c,v 1.44 2008/11/29 00:56:54 drh Exp $ +** $Id: test_config.c,v 1.45 2008/11/29 02:20:27 drh Exp $ */ #include "sqliteLimit.h" #include "sqliteInt.h" @@ -390,11 +390,18 @@ Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); #endif -#if defined(SQLITE_ENABLE_LOCKING_STYLE) && defined(__DARWIN__) +#if !defined(SQLITE_ENABLE_LOCKING_STYLE) +# if defined(__DARWIN__) +# define SQLITE_ENABLE_LOCKING_STYLE 1 +# else +# define SQLITE_ENABLE_LOCKING_STYLE 0 +# endif +#endif +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY); #endif Index: test/lock5.test ================================================================== --- test/lock5.test +++ test/lock5.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: lock5.test,v 1.4 2008/11/21 00:10:35 aswift Exp $ +# $Id: lock5.test,v 1.5 2008/11/29 02:20:27 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # This file is only run if using the unix backend compiled with the @@ -22,10 +22,11 @@ if {[catch {sqlite3 db test.db -vfs unix-none} msg]} { finish_test return } db close +file delete -force test.db.lock ifcapable lock_proxy_pragmas { set ::using_proxy 0 foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { set ::using_proxy $value