diff options
Diffstat (limited to 'src/os_unix.c')
-rw-r--r-- | src/os_unix.c | 1010 |
1 files changed, 508 insertions, 502 deletions
diff --git a/src/os_unix.c b/src/os_unix.c index 3333f0a8b..e894dd368 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -12,7 +12,7 @@ ** ** This file contains code that is specific to Unix systems. ** -** $Id: os_unix.c,v 1.218 2008/11/21 00:24:42 drh Exp $ +** $Id: os_unix.c,v 1.219 2008/11/21 20:32:34 drh Exp $ */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ @@ -41,13 +41,15 @@ #endif /* -** Define the IS_VXWORKS pre-processor macro to 1 if building on +** Define the OS_VXWORKS pre-processor macro to 1 if building on ** vxworks, or 0 otherwise. */ -#if defined(__RTP__) || defined(_WRS_KERNEL) -# define IS_VXWORKS 1 -#else -# define IS_VXWORKS 0 +#ifndef OS_VXWORKS +# if defined(__RTP__) || defined(_WRS_KERNEL) +# define OS_VXWORKS 1 +# else +# define OS_VXWORKS 0 +# endif #endif /* @@ -84,7 +86,7 @@ #if SQLITE_ENABLE_LOCKING_STYLE # include <sys/ioctl.h> -# if IS_VXWORKS +# if OS_VXWORKS # define lstat stat # include <semaphore.h> # include <limits.h> @@ -130,30 +132,28 @@ typedef struct unixFile unixFile; struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ -#ifdef SQLITE_TEST - /* In test mode, increase the size of this structure a bit so that - ** it is larger than the struct CrashFile defined in test6.c. - */ - char aPadding[32]; -#endif - struct openCnt *pOpen; /* Info about all open fd's on this inode */ - struct lockInfo *pLock; /* Info about locks on this inode */ + struct unixOpenCnt *pOpen; /* Info about all open fd's on this inode */ + struct unixLockInfo *pLock; /* Info about locks on this inode */ + int h; /* The file descriptor */ + int dirfd; /* File descriptor for the directory */ + unsigned char locktype; /* The type of lock held on this fd */ + int lastErrno; /* The unix errno from the last I/O error */ #if SQLITE_ENABLE_LOCKING_STYLE - void *lockingContext; /* Locking style specific state */ + void *lockingContext; /* Locking style specific state */ + int oflags; /* The flags specified at open */ #endif - int h; /* The file descriptor */ - unsigned char locktype; /* The type of lock held on this fd */ - int dirfd; /* File descriptor for the directory */ #if SQLITE_THREADSAFE - pthread_t tid; /* The thread that "owns" this unixFile */ + pthread_t tid; /* The thread that "owns" this unixFile */ #endif - int lastErrno; /* The unix errno from the last I/O error */ -#if IS_VXWORKS - int isDelete; /* Delete on close if true */ - char *zRealpath; +#if OS_VXWORKS + int isDelete; /* Delete on close if true */ + char *zVxworksPath; /* Canonical pathname of the file */ #endif -#if SQLITE_ENABLE_LOCKING_STYLE - int oflags; /* The flags specified at open */ +#ifdef SQLITE_TEST + /* In test mode, increase the size of this structure a bit so that + ** it is larger than the struct CrashFile defined in test6.c. + */ + char aPadding[32]; #endif }; @@ -199,38 +199,19 @@ struct unixFile { #define threadid 0 #endif -/* -** Set or check the unixFile.tid field. This field is set when an unixFile -** is first opened. All subsequent uses of the unixFile verify that the -** same thread is operating on the unixFile. Some operating systems do -** not allow locks to be overridden by other threads and that restriction -** means that sqlite3* database handles cannot be moved from one thread -** to another. This logic makes sure a user does not try to do that -** by mistake. -** -** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to -** another as long as we are running on a system that supports threads -** overriding each others locks (which now the most common behavior) -** or if no locks are held. But the unixFile.pLock field needs to be -** recomputed because its key includes the thread-id. See the -** transferOwnership() function below for additional information -*/ -#if SQLITE_THREADSAFE -# define SET_THREADID(X) (X)->tid = pthread_self() -# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ - !pthread_equal((X)->tid, pthread_self())) -#else -# define SET_THREADID(X) -# define CHECK_THREADID(X) 0 -#endif -/* +/************************************************************************ +*********** Posix Advisory Locking And Thread Interaction *************** +************************************************************************* +** ** Here is the dirt on POSIX advisory locks: 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: +** +** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); ** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); ** ** Suppose ./file1 and ./file2 are really the same file (because @@ -281,12 +262,12 @@ struct unixFile { ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each unixFile structure contains -** a pointer to an openCnt structure. There is one openCnt structure +** a pointer to an unixOpenCnt structure. There is one unixOpenCnt structure ** per open inode, which means that multiple unixFile can point to a single -** openCnt. When an attempt is made to close an unixFile, if there are +** unixOpenCnt. When an attempt is made to close an unixFile, if there are ** other unixFile open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. -** The openCnt structure keeps a list of file descriptors that need to +** 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. ** @@ -298,13 +279,13 @@ struct unixFile { ** on other threads and even though the other threads have different ** process IDs. Linux threads is inconsistent in this respect. ** (I'm beginning to think that linux threads is an abomination too.) -** The consequence of this all is that the hash table for the lockInfo +** The consequence of this all is that the hash table for the unixLockInfo ** structure has to include the process id as part of its key because ** locks in different threads are treated as distinct. But the -** openCnt structure should not include the process id in its +** unixOpenCnt structure should not include the process id in its ** key because close() clears lock on all threads, not just the current ** thread. Were it not for this goofiness in linux threads, we could -** combine the lockInfo and openCnt structures into a single structure. +** combine the unixLockInfo and unixOpenCnt structures into a single structure. ** ** 2004-Jun-28: ** On some versions of linux, threads can override each others locks. @@ -323,23 +304,57 @@ struct unixFile { */ /* +** Set or check the unixFile.tid field. This field is set when an unixFile +** is first opened. All subsequent uses of the unixFile verify that the +** same thread is operating on the unixFile. Some operating systems do +** not allow locks to be overridden by other threads and that restriction +** means that sqlite3* database handles cannot be moved from one thread +** to another. This logic makes sure a user does not try to do that +** by mistake. +** +** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the unixFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information +*/ +#if SQLITE_THREADSAFE +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) +#else +# define SET_THREADID(X) +# define CHECK_THREADID(X) 0 +#endif + +/* ** An instance of the following structure serves as the key used -** to locate a particular lockInfo structure given its inode. +** to locate a particular unixOpenCnt structure given its inode. This +** is the same as the unixLockKey except that the thread ID is omitted. +*/ +struct unixFileId { + dev_t dev; /* Device number */ +#if OS_VXWORKS + void *pNameId; /* Key of canonical filename entry in vxworksFilenameHash */ +#else + ino_t ino; /* Inode number */ +#endif +}; + +/* +** An instance of the following structure serves as the key used +** to locate a particular unixLockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the -** lockKey.tid field to the thread ID. If threads can override +** unixLockKey.tid field to the thread ID. If threads can override ** each others locks then tid is always set to zero. tid is omitted ** if we compile without threading support. */ -struct lockKey { - dev_t dev; /* Device number */ -#if IS_VXWORKS - void *rnam; /* Realname since inode unusable */ -#else - ino_t ino; /* Inode number */ -#endif +struct unixLockKey { + struct unixFileId fid; /* Unique identifier for the file */ #if SQLITE_THREADSAFE - pthread_t tid; /* Thread ID or zero if threads can override each other */ + pthread_t tid; /* Thread ID or zero if threads can override each other */ #endif }; @@ -352,26 +367,13 @@ struct lockKey { ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of unixFile pointing to it. */ -struct lockInfo { - struct lockKey key; /* The lookup key */ - int cnt; /* Number of SHARED locks held */ - int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ - int nRef; /* Number of pointers to this structure */ - struct lockInfo *pNext, *pPrev; /* List of all lockInfo objects */ -}; - -/* -** An instance of the following structure serves as the key used -** to locate a particular openCnt structure given its inode. This -** is the same as the lockKey except that the thread ID is omitted. -*/ -struct openKey { - dev_t dev; /* Device number */ -#if IS_VXWORKS - void *rnam; /* Realname since inode unusable */ -#else - ino_t ino; /* Inode number */ -#endif +struct unixLockInfo { + struct unixLockKey lockKey; /* The lookup key */ + int cnt; /* Number of SHARED locks held */ + int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + int nRef; /* Number of pointers to this structure */ + struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ + struct unixLockInfo *pPrev; /* .... doubly linked */ }; /* @@ -381,91 +383,29 @@ struct openKey { ** locks, the close is deferred until all locks clear by adding the ** file descriptor to be closed to the pending list. */ -struct openCnt { - struct openKey key; /* The lookup key */ - int nRef; /* Number of pointers to this structure */ - int nLock; /* Number of outstanding locks */ - int nPending; /* Number of pending close() operations */ - int *aPending; /* Malloced space holding fd's awaiting a close() */ -#if IS_VXWORKS - sem_t *pSem; /* Named POSIX semaphore */ +struct unixOpenCnt { + struct unixFileId fileId; /* The lookup key */ + int nRef; /* Number of pointers to this structure */ + int nLock; /* Number of outstanding locks */ + int nPending; /* Number of pending close() operations */ + int *aPending; /* Malloced space holding fd's awaiting a close() */ +#if OS_VXWORKS + sem_t *pSem; /* Named POSIX semaphore */ char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */ #endif - struct openCnt *pNext, *pPrev; /* List of all openCnt objects */ + struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */ }; /* -** List of all lockInfo and openCnt objects. This used to be a hash +** 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 ** never exceeds a few thousand. And lookup is not on a critical -** path oo a simple linked list will suffice. -*/ -static struct lockInfo *lockList = 0; -static struct openCnt *openList = 0; - -#ifdef SQLITE_TEST -/* simulate multiple hosts by creating unique hostid file paths */ -int sqlite3_hostid_num = 0; -#endif - - -#if IS_VXWORKS -/* -** This hash table is used to bind the canonical file name to a -** unixFile structure and use the hash key (= canonical name) -** instead of the Inode number of the file to find the matching -** lockInfo and openCnt structures. It also helps to make the -** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used -** for the file. -*/ -static Hash nameHash; -#endif - -/* -** The locking styles are associated with the different file locking -** capabilities supported by different file systems. -** -** POSIX locking style fully supports shared and exclusive byte-range locks -** AFP locking only supports exclusive byte-range locks -** FLOCK only supports a single file-global exclusive lock -** DOTLOCK isn't a true locking style, it refers to the use of a special -** file named the same as the database file with a '.lock' extension, this -** can be used on file systems that do not offer any reliable file locking -** NONE locking means that no locking will be attempted, this is only used for -** read-only file systems currently -** NAMEDSEM is similar to DOTLOCK but uses a named semaphore instead of an -** indicator file. -** PROXY uses a second file to represent the lock state of the database file -** which is never actually locked, a third file controls access to the proxy -** UNSUPPORTED means that no locking will be attempted, this is only used for -** file systems that are known to be unsupported -*/ -#define LOCKING_STYLE_POSIX 1 -#define LOCKING_STYLE_NONE 2 -#define LOCKING_STYLE_DOTFILE 3 -#define LOCKING_STYLE_FLOCK 4 -#define LOCKING_STYLE_AFP 5 -#define LOCKING_STYLE_NAMEDSEM 6 -#define LOCKING_STYLE_PROXY 7 - -/* -** Only set the lastErrno if the error code is a real error and not -** a normal expected return code of SQLITE_BUSY or SQLITE_OK +** path so a simple linked list will suffice. */ -#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) +static struct unixLockInfo *lockList = 0; +static struct unixOpenCnt *openList = 0; /* -** Helper functions to obtain and relinquish the global mutex. -*/ -static void enterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} -static void leaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} - -#if SQLITE_THREADSAFE -/* ** This variable records whether or not threads can override each others ** locks. ** @@ -502,66 +442,7 @@ struct threadTestData { int result; /* Result of the locking operation */ }; -#ifdef SQLITE_LOCK_TRACE -/* -** Print out information about all locking operations. -** -** This routine is used for troubleshooting locks on multithreaded -** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE -** command-line option on the compiler. This code is normally -** turned off. -*/ -static int lockTrace(int fd, int op, struct flock *p){ - char *zOpName, *zType; - int s; - int savedErrno; - if( op==F_GETLK ){ - zOpName = "GETLK"; - }else if( op==F_SETLK ){ - zOpName = "SETLK"; - }else{ - s = fcntl(fd, op, p); - sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); - return s; - } - if( p->l_type==F_RDLCK ){ - zType = "RDLCK"; - }else if( p->l_type==F_WRLCK ){ - zType = "WRLCK"; - }else if( p->l_type==F_UNLCK ){ - zType = "UNLCK"; - }else{ - assert( 0 ); - } - assert( p->l_whence==SEEK_SET ); - s = fcntl(fd, op, p); - savedErrno = errno; - sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", - threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, - (int)p->l_pid, s); - if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ - struct flock l2; - l2 = *p; - fcntl(fd, F_GETLK, &l2); - if( l2.l_type==F_RDLCK ){ - zType = "RDLCK"; - }else if( l2.l_type==F_WRLCK ){ - zType = "WRLCK"; - }else if( l2.l_type==F_UNLCK ){ - zType = "UNLCK"; - }else{ - assert( 0 ); - } - sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", - zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); - } - errno = savedErrno; - return s; -} -#define fcntl lockTrace -#endif /* SQLITE_LOCK_TRACE */ - -#ifdef __linux__ +#if SQLITE_THREADSAFE && defined(__linux__) /* ** This function is used as the main routine for a thread launched by ** testThreadLockingBehavior(). It tests whether the shared-lock obtained @@ -576,7 +457,10 @@ static void *threadLockingTest(void *pArg){ pData->result = fcntl(pData->fd, F_GETLK, &pData->lock); return pArg; } +#endif /* SQLITE_THREADSAFE && defined(__linux__) */ + +#if SQLITE_THREADSAFE && defined(__linux__) /* ** This procedure attempts to determine whether or not threads ** can override each others locks then sets the @@ -608,21 +492,71 @@ static void testThreadLockingBehavior(int fd_orig){ if( d.result!=0 ) return; threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK); } -#else +#else /* if !SQLITE_THREADSAFE || !defined(__linux__) */ /* ** On anything other than linux, assume threads override each others locks. */ static void testThreadLockingBehavior(int fd_orig){ + UNUSED_PARAMETER(fd_orig); threadsOverrideEachOthersLocks = 1; } -#endif /* __linux__ */ +#endif /* SQLITE_THERADSAFE && defined(__linux__) */ +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#if SQLITE_THREADSAFE +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + OSTRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + OSTRACE4("Transfer ownership of %d from %d to %d\n", + pFile->h, pFile->tid, hSelf); + pFile->tid = hSelf; + if (pFile->pLock != NULL) { + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile, &pFile->pLock, 0); + OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; + } else { + return SQLITE_OK; + } +} +#else /* if not SQLITE_THREADSAFE */ + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK #endif /* SQLITE_THREADSAFE */ + /* -** Release a lockInfo structure previously allocated by findLockInfo(). +** Release a unixLockInfo structure previously allocated by findLockInfo(). */ -static void releaseLockInfo(struct lockInfo *pLock){ +static void releaseLockInfo(struct unixLockInfo *pLock){ if( pLock ){ pLock->nRef--; if( pLock->nRef==0 ){ @@ -643,9 +577,9 @@ static void releaseLockInfo(struct lockInfo *pLock){ } /* -** Release a openCnt structure previously allocated by findLockInfo(). +** Release a unixOpenCnt structure previously allocated by findLockInfo(). */ -static void releaseOpenCnt(struct openCnt *pOpen){ +static void releaseOpenCnt(struct unixOpenCnt *pOpen){ if( pOpen ){ pOpen->nRef--; if( pOpen->nRef==0 ){ @@ -666,7 +600,151 @@ static void releaseOpenCnt(struct openCnt *pOpen){ } } -#if IS_VXWORKS + +/* +** 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. +** +** Return an appropriate error code. +*/ +static int findLockInfo( + unixFile *pFile, /* Unix file with file desc used in the key */ + struct unixLockInfo **ppLock, /* Return the unixLockInfo structure here */ + struct unixOpenCnt **ppOpen /* Return the unixOpenCnt structure here */ +){ + int rc; /* System call return code */ + int fd; /* The file descriptor for pFile */ + struct unixLockKey lockKey; /* Lookup key for the unixLockInfo structure */ + struct unixFileId fileId; /* Lookup key for the unixOpenCnt struct */ + struct stat statbuf; /* Low-level file information */ + struct unixLockInfo *pLock; /* Candidate unixLockInfo object */ + struct unixOpenCnt *pOpen; /* Candidate unixOpenCnt object */ + + /* Get low-level information about the file that we can used to + ** create a unique name for the file. + */ + fd = pFile->h; + rc = fstat(fd, &statbuf); + if( rc!=0 ){ + pFile->lastErrno = errno; +#ifdef EOVERFLOW + if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; +#endif + return SQLITE_IOERR; + } + + /* On OS X on an msdos filesystem, the inode number is reported + ** incorrectly for zero-size files. See ticket #3260. To work + ** around this problem (we consider it a bug in OS X, not SQLite) + ** we always increase the file size to 1 by writing a single byte + ** prior to accessing the inode number. The one byte written is + ** an ASCII 'S' character which also happens to be the first byte + ** in the header of every SQLite database. In this way, if there + ** is a race condition such that another thread has already populated + ** the first page of the database, no damage is done. + */ + if( statbuf.st_size==0 ){ + write(fd, "S", 1); + rc = fstat(fd, &statbuf); + if( rc!=0 ){ + pFile->lastErrno = errno; + return SQLITE_IOERR; + } + } + + memset(&lockKey, 0, sizeof(lockKey)); + lockKey.fid.dev = statbuf.st_dev; +#if OS_VXWORKS + /* The pFile->zVxworksPath name has been hashed into the vxworksFilenameHash + ** hash table at this point, so safe to using pointer comparison + ** to compare the names. */ + lockKey.fid.pNameId = pFile->zVxworksPath; +#else + lockKey.fid.ino = statbuf.st_ino; +#endif +#if SQLITE_THREADSAFE + if( threadsOverrideEachOthersLocks<0 ){ + testThreadLockingBehavior(fd); + } + lockKey.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); +#endif + fileId = lockKey.fid; + if( ppLock!=0 ){ + pLock = lockList; + while( pLock && memcmp(&lockKey, &pLock->lockKey, sizeof(lockKey)) ){ + pLock = pLock->pNext; + } + if( pLock==0 ){ + pLock = sqlite3_malloc( sizeof(*pLock) ); + if( pLock==0 ){ + rc = SQLITE_NOMEM; + goto exit_findlockinfo; + } + pLock->lockKey = lockKey; + pLock->nRef = 1; + pLock->cnt = 0; + pLock->locktype = 0; + pLock->pNext = lockList; + pLock->pPrev = 0; + if( lockList ) lockList->pPrev = pLock; + lockList = pLock; + }else{ + pLock->nRef++; + } + *ppLock = pLock; + } + if( ppOpen!=0 ){ + pOpen = openList; + while( pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)) ){ + pOpen = pOpen->pNext; + } + if( pOpen==0 ){ + pOpen = sqlite3_malloc( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = SQLITE_NOMEM; + goto exit_findlockinfo; + } + pOpen->fileId = fileId; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOpen->pNext = openList; + pOpen->pPrev = 0; + if( openList ) openList->pPrev = pOpen; + openList = pOpen; +#if OS_VXWORKS + pOpen->pSem = NULL; + pOpen->aSemName[0] = '\0'; +#endif + }else{ + pOpen->nRef++; + } + *ppOpen = pOpen; + } + +exit_findlockinfo: + return rc; +} +/************************************************************************** +******************** End of the posix lock work-around ******************** +**************************************************************************/ + +#if OS_VXWORKS +/* +** This hash table is used to bind the canonical file name to a +** unixFile structure and use the hash key (= canonical name) +** instead of the Inode number of the file to find the matching +** unixLockInfo and unixOpenCnt structures. It also helps to make the +** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used +** for the file. +*/ +static Hash vxworksFilenameHash; +#endif + +#if OS_VXWORKS /* ** Implementation of a realpath() like function for vxWorks ** to determine canonical path name from given name. It does @@ -758,6 +836,122 @@ vxrealpath(const char *pathname, int dostat) } #endif + + +#ifdef SQLITE_TEST +/* simulate multiple hosts by creating unique hostid file paths */ +int sqlite3_hostid_num = 0; +#endif + +/* +** The locking styles are associated with the different file locking +** capabilities supported by different file systems. +** +** POSIX support for shared and exclusive byte-range locks +** +** AFP support exclusive byte-range locks +** +** FLOCK only a single file-global exclusive lock +** +** DOTLOCK isn't a true locking style, it refers to the use of a special +** file named the same as the database file with a '.lock' +** extension, this can be used on file systems that do not +** offer any reliable file locking +** +** NONE no locking will be attempted, this is only used for +** read-only file systems currently +** +** NAMEDSEM similar to DOTLOCK but uses a named semaphore instead of an +** indicator file. +** +** PROXY uses a second file to represent the lock state of the database +** file which is never actually locked, a third file controls +** access to the proxy +*/ +#define LOCKING_STYLE_POSIX 1 +#define LOCKING_STYLE_NONE 2 +#define LOCKING_STYLE_DOTFILE 3 +#define LOCKING_STYLE_FLOCK 4 +#define LOCKING_STYLE_AFP 5 +#define LOCKING_STYLE_NAMEDSEM 6 +#define LOCKING_STYLE_PROXY 7 + +/* +** Only set the lastErrno if the error code is a real error and not +** a normal expected return code of SQLITE_BUSY or SQLITE_OK +*/ +#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) + +/* +** Helper functions to obtain and relinquish the global mutex. +*/ +static void unixEnterMutex(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} +static void unixLeaveMutex(void){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} + +#ifdef SQLITE_LOCK_TRACE +/* +** Print out information about all locking operations. +** +** This routine is used for troubleshooting locks on multithreaded +** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE +** command-line option on the compiler. This code is normally +** turned off. +*/ +static int lockTrace(int fd, int op, struct flock *p){ + char *zOpName, *zType; + int s; + int savedErrno; + if( op==F_GETLK ){ + zOpName = "GETLK"; + }else if( op==F_SETLK ){ + zOpName = "SETLK"; + }else{ + s = fcntl(fd, op, p); + sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); + return s; + } + if( p->l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( p->l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( p->l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + assert( p->l_whence==SEEK_SET ); + s = fcntl(fd, op, p); + savedErrno = errno; + sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", + threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, + (int)p->l_pid, s); + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + struct flock l2; + l2 = *p; + fcntl(fd, F_GETLK, &l2); + if( l2.l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( l2.l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( l2.l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", + zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); + } + errno = savedErrno; + return s; +} +#define fcntl lockTrace +#endif /* SQLITE_LOCK_TRACE */ + + #if SQLITE_ENABLE_LOCKING_STYLE /* ** The proxyLockingContext has the path and file structures for the remote @@ -807,7 +1001,7 @@ static int testLockingStyle(int fd){ ** test fails, then we fall back to using dot-file style locking (or ** named-semaphore locking on vxworks). */ - return (IS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE); + return (OS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE); } #endif @@ -828,7 +1022,7 @@ static int detectLockingStyle( const char *filePath, int fd ){ -#if IS_VXWORKS +#if OS_VXWORKS if( !filePath ){ return LOCKING_STYLE_NONE; } @@ -877,143 +1071,13 @@ static int detectLockingStyle( /* Default case. Handles, amongst others, "nfs". */ return testLockingStyle(fd); -#endif /* if IS_VXWORKS */ +#endif /* if OS_VXWORKS */ return LOCKING_STYLE_POSIX; } #else #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX #endif /* if SQLITE_ENABLE_LOCKING_STYLE */ -/* -** Given a file descriptor, locate lockInfo and openCnt structures that -** describes that file descriptor. Create new ones if necessary. The -** return values might be uninitialized if an error occurs. -** -** Return an appropriate error code. -*/ -static int findLockInfo( - unixFile *pFile, /* Unix file with file desc used in the key */ -#if IS_VXWORKS - void *rnam, /* vxWorks realname */ -#endif - struct lockInfo **ppLock, /* Return the lockInfo structure here */ - struct openCnt **ppOpen /* Return the openCnt structure here */ -){ - int rc; - int fd; - struct lockKey key1; - struct openKey key2; - struct stat statbuf; - struct lockInfo *pLock; - struct openCnt *pOpen; - fd = pFile->h; - rc = fstat(fd, &statbuf); - if( rc!=0 ){ - pFile->lastErrno = errno; -#ifdef EOVERFLOW - if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; -#endif - return SQLITE_IOERR; - } - - /* On OS X on an msdos filesystem, the inode number is reported - ** incorrectly for zero-size files. See ticket #3260. To work - ** around this problem (we consider it a bug in OS X, not SQLite) - ** we always increase the file size to 1 by writing a single byte - ** prior to accessing the inode number. The one byte written is - ** an ASCII 'S' character which also happens to be the first byte - ** in the header of every SQLite database. In this way, if there - ** is a race condition such that another thread has already populated - ** the first page of the database, no damage is done. - */ - if( statbuf.st_size==0 ){ - write(fd, "S", 1); - rc = fstat(fd, &statbuf); - if( rc!=0 ){ - pFile->lastErrno = errno; - return SQLITE_IOERR; - } - } - - memset(&key1, 0, sizeof(key1)); - key1.dev = statbuf.st_dev; -#if IS_VXWORKS - key1.rnam = rnam; -#else - key1.ino = statbuf.st_ino; -#endif -#if SQLITE_THREADSAFE - if( threadsOverrideEachOthersLocks<0 ){ - testThreadLockingBehavior(fd); - } - key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); -#endif - memset(&key2, 0, sizeof(key2)); - key2.dev = statbuf.st_dev; -#if IS_VXWORKS - key2.rnam = rnam; -#else - key2.ino = statbuf.st_ino; -#endif - if( ppLock!=0 ){ - pLock = lockList; - while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){ - pLock = pLock->pNext; - } - if( pLock==0 ){ - pLock = sqlite3_malloc( sizeof(*pLock) ); - if( pLock==0 ){ - rc = SQLITE_NOMEM; - goto exit_findlockinfo; - } - pLock->key = key1; - pLock->nRef = 1; - pLock->cnt = 0; - pLock->locktype = 0; - pLock->pNext = lockList; - pLock->pPrev = 0; - if( lockList ) lockList->pPrev = pLock; - lockList = pLock; - }else{ - pLock->nRef++; - } - *ppLock = pLock; - } - if( ppOpen!=0 ){ - pOpen = openList; - while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){ - pOpen = pOpen->pNext; - } - if( pOpen==0 ){ - pOpen = sqlite3_malloc( sizeof(*pOpen) ); - if( pOpen==0 ){ - releaseLockInfo(pLock); - rc = SQLITE_NOMEM; - goto exit_findlockinfo; - } - pOpen->key = key2; - pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOpen->pNext = openList; - pOpen->pPrev = 0; - if( openList ) openList->pPrev = pOpen; - openList = pOpen; -#if IS_VXWORKS - pOpen->pSem = NULL; - pOpen->aSemName[0] = '\0'; -#endif - }else{ - pOpen->nRef++; - } - *ppOpen = pOpen; - } - -exit_findlockinfo: - return rc; -} - #ifdef SQLITE_DEBUG /* ** Helper function for printing out trace information from debugging @@ -1033,60 +1097,6 @@ static const char *locktypeName(int locktype){ #endif /* -** If we are currently in a different thread than the thread that the -** unixFile argument belongs to, then transfer ownership of the unixFile -** over to the current thread. -** -** A unixFile is only owned by a thread on systems where one thread is -** unable to override locks created by a different thread. RedHat9 is -** an example of such a system. -** -** Ownership transfer is only allowed if the unixFile is currently unlocked. -** If the unixFile is locked and an ownership is wrong, then return -** SQLITE_MISUSE. SQLITE_OK is returned if everything works. -*/ -#if SQLITE_THREADSAFE -static int transferOwnership(unixFile *pFile){ - int rc; - pthread_t hSelf; - if( threadsOverrideEachOthersLocks ){ - /* Ownership transfers not needed on this system */ - return SQLITE_OK; - } - hSelf = pthread_self(); - if( pthread_equal(pFile->tid, hSelf) ){ - /* We are still in the same thread */ - OSTRACE1("No-transfer, same thread\n"); - return SQLITE_OK; - } - if( pFile->locktype!=NO_LOCK ){ - /* We cannot change ownership while we are holding a lock! */ - return SQLITE_MISUSE; - } - OSTRACE4("Transfer ownership of %d from %d to %d\n", - pFile->h, pFile->tid, hSelf); - pFile->tid = hSelf; - if (pFile->pLock != NULL) { - releaseLockInfo(pFile->pLock); -#if IS_VXWORKS - rc = findLockInfo(pFile, pFile->zRealpath, &pFile->pLock, 0); -#else - rc = findLockInfo(pFile, &pFile->pLock, 0); -#endif - OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, - locktypeName(pFile->locktype), - locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); - return rc; - } else { - return SQLITE_OK; - } -} -#else - /* On single-threaded builds, ownership transfer is a no-op */ -# define transferOwnership(X) SQLITE_OK -#endif - -/* ** Seek to the offset passed as the second argument, then read cnt ** bytes into pBuf. Return the number of bytes actually read. ** @@ -1316,7 +1326,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ #else if( dataOnly ){ rc = fdatasync(fd); - if( IS_VXWORKS && rc==-1 && errno==ENOTSUP ){ + if( OS_VXWORKS && rc==-1 && errno==ENOTSUP ){ rc = fsync(fd); } }else{ @@ -1324,7 +1334,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ } #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ - if( IS_VXWORKS && rc!= -1 ){ + if( OS_VXWORKS && rc!= -1 ){ rc = 0; } return rc; @@ -1523,7 +1533,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); - enterMutex(); /* Because pFile->pLock is shared across threads */ + unixEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ @@ -1547,7 +1557,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ } } - leaveMutex(); + unixLeaveMutex(); OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); *pResOut = reserved; @@ -1619,7 +1629,7 @@ static int unixLock(sqlite3_file *id, int locktype){ */ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; - struct lockInfo *pLock = pFile->pLock; + struct unixLockInfo *pLock = pFile->pLock; struct flock lock; int s; @@ -1630,7 +1640,7 @@ static int unixLock(sqlite3_file *id, int locktype){ /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the end_lock: exit path, as - ** enterMutex() hasn't been called yet. + ** unixEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -1646,13 +1656,13 @@ static int unixLock(sqlite3_file *id, int locktype){ /* This mutex is needed because pFile->pLock is shared across threads */ - enterMutex(); + unixEnterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - leaveMutex(); + unixLeaveMutex(); return rc; } pLock = pFile->pLock; @@ -1787,7 +1797,7 @@ static int unixLock(sqlite3_file *id, int locktype){ } end_lock: - leaveMutex(); + unixLeaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -1801,7 +1811,7 @@ end_lock: ** the requested locking level, this routine is a no-op. */ static int unixUnlock(sqlite3_file *id, int locktype){ - struct lockInfo *pLock; + struct unixLockInfo *pLock; struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; @@ -1818,7 +1828,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - enterMutex(); + unixEnterMutex(); h = pFile->h; pLock = pFile->pLock; assert( pLock->cnt!=0 ); @@ -1857,7 +1867,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ } } if( locktype==NO_LOCK ){ - struct openCnt *pOpen; + struct unixOpenCnt *pOpen; /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released @@ -1916,7 +1926,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ } end_unlock: - leaveMutex(); + unixLeaveMutex(); if( rc==SQLITE_OK ) pFile->locktype = locktype; return rc; } @@ -1946,19 +1956,19 @@ static int closeUnixFile(sqlite3_file *id){ return SQLITE_IOERR_CLOSE; } } -#if IS_VXWORKS - if( pFile->isDelete && pFile->zRealpath ){ - unlink(pFile->zRealpath); +#if OS_VXWORKS + if( pFile->isDelete && pFile->zVxworksPath ){ + unlink(pFile->zVxworksPath); } - if( pFile->zRealpath ){ + if( pFile->zVxworksPath ){ HashElem *pElem; - int n = strlen(pFile->zRealpath) + 1; - pElem = sqlite3HashFindElem(&nameHash, pFile->zRealpath, n); + int n = strlen(pFile->zVxworksPath) + 1; + pElem = sqlite3HashFindElem(&vxworksFilenameHash, pFile->zVxworksPath, n); if( pElem ){ long cnt = (long)pElem->data; cnt--; if( cnt==0 ){ - sqlite3HashInsert(&nameHash, pFile->zRealpath, n, 0); + sqlite3HashInsert(&vxworksFilenameHash, pFile->zVxworksPath, n, 0); }else{ pElem->data = (void*)cnt; } @@ -1980,7 +1990,7 @@ static int unixClose(sqlite3_file *id){ if( id ){ unixFile *pFile = (unixFile *)id; unixUnlock(id, NO_LOCK); - enterMutex(); + unixEnterMutex(); if( pFile->pOpen && pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file @@ -1988,7 +1998,7 @@ static int unixClose(sqlite3_file *id){ ** the last lock is cleared. */ int *aNew; - struct openCnt *pOpen = pFile->pOpen; + struct unixOpenCnt *pOpen = pFile->pOpen; aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ @@ -2002,14 +2012,14 @@ static int unixClose(sqlite3_file *id){ releaseLockInfo(pFile->pLock); releaseOpenCnt(pFile->pOpen); rc = closeUnixFile(id); - leaveMutex(); + unixLeaveMutex(); } return rc; } #if SQLITE_ENABLE_LOCKING_STYLE -#if !IS_VXWORKS +#if !OS_VXWORKS #pragma mark AFP support /* @@ -2130,7 +2140,7 @@ static int afpLock(sqlite3_file *id, int locktype){ /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as - ** enterMutex() hasn't been called yet. + ** unixEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -2146,13 +2156,13 @@ static int afpLock(sqlite3_file *id, int locktype){ /* This mutex is needed because pFile->pLock is shared across threads */ - enterMutex(); + unixEnterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - leaveMutex(); + unixLeaveMutex(); return rc; } @@ -2250,7 +2260,7 @@ static int afpLock(sqlite3_file *id, int locktype){ } afp_end_lock: - leaveMutex(); + unixLeaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -2279,7 +2289,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) { if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - enterMutex(); + unixEnterMutex(); if( pFile->locktype>SHARED_LOCK ){ if( pFile->locktype==EXCLUSIVE_LOCK ){ @@ -2304,7 +2314,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) { if( rc==SQLITE_OK ){ if( locktype==NO_LOCK ){ - struct openCnt *pOpen = pFile->pOpen; + struct unixOpenCnt *pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ @@ -2327,7 +2337,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) { } } end_afpunlock: - leaveMutex(); + unixLeaveMutex(); if( rc==SQLITE_OK ) pFile->locktype = locktype; return rc; } @@ -2339,7 +2349,7 @@ static int afpClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; afpUnlock(id, NO_LOCK); - enterMutex(); + unixEnterMutex(); if( pFile->pOpen && pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file @@ -2347,7 +2357,7 @@ static int afpClose(sqlite3_file *id) { ** the last lock is cleared. */ int *aNew; - struct openCnt *pOpen = pFile->pOpen; + struct unixOpenCnt *pOpen = pFile->pOpen; aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ @@ -2361,7 +2371,7 @@ static int afpClose(sqlite3_file *id) { releaseOpenCnt(pFile->pOpen); sqlite3_free(pFile->lockingContext); closeUnixFile(id); - leaveMutex(); + unixLeaveMutex(); } return SQLITE_OK; } @@ -2516,7 +2526,7 @@ static int flockClose(sqlite3_file *id) { return closeUnixFile(id); } -#endif /* !IS_VXWORKS */ +#endif /* !OS_VXWORKS */ #pragma mark Old-School .lock file based locking #define DOTLOCK_SUFFIX ".lock" @@ -2570,7 +2580,7 @@ static int dotlockLock(sqlite3_file *id, int locktype) { ** Just adjust level and punt on outta here. */ if (pFile->locktype > NO_LOCK) { pFile->locktype = locktype; -#if !IS_VXWORKS +#if !OS_VXWORKS /* Always update the timestamp on the old file */ utimes(zLockFile, NULL); #endif @@ -2657,13 +2667,13 @@ static int dotlockClose(sqlite3_file *id) { dotlockUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); } - if( IS_VXWORKS ) enterMutex(); + if( OS_VXWORKS ) unixEnterMutex(); rc = closeUnixFile(id); - if( IS_VXWORKS ) leaveMutex(); + if( OS_VXWORKS ) unixLeaveMutex(); return rc; } -#if IS_VXWORKS +#if OS_VXWORKS #pragma mark POSIX/vxWorks named semaphore based locking @@ -2777,16 +2787,16 @@ static int namedsemClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; namedsemUnlock(id, NO_LOCK); assert( pFile ); - enterMutex(); + unixEnterMutex(); releaseLockInfo(pFile->pLock); releaseOpenCnt(pFile->pOpen); closeUnixFile(id); - leaveMutex(); + unixLeaveMutex(); } return SQLITE_OK; } -#endif /* IS_VXWORKS */ +#endif /* OS_VXWORKS */ #pragma mark Proxy locking support @@ -3382,9 +3392,9 @@ static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){ */ static int nolockClose(sqlite3_file *id) { int rc; - if( IS_VXWORKS ) enterMutex(); + if( OS_VXWORKS ) unixEnterMutex(); rc = closeUnixFile(id); - if( IS_VXWORKS ) leaveMutex(); + if( OS_VXWORKS ) unixLeaveMutex(); return rc; } @@ -3502,7 +3512,7 @@ IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) #if SQLITE_ENABLE_LOCKING_STYLE ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock) -#if IS_VXWORKS +#if OS_VXWORKS ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock) @@ -3547,46 +3557,46 @@ static int fillInUnixFile( ** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly ** here to prevent compiler warnings about unused parameters. */ - if( !IS_VXWORKS ) UNUSED_PARAMETER(isDelete); + if( !OS_VXWORKS ) UNUSED_PARAMETER(isDelete); if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs); - if( !IS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename); + if( !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename); OSTRACE3("OPEN %-3d %s\n", h, zFilename); pNew->h = h; pNew->dirfd = dirfd; SET_THREADID(pNew); -#if IS_VXWORKS +#if OS_VXWORKS { HashElem *pElem; char *zRealname = vxrealpath(zFilename, 1); int n; - pNew->zRealpath = 0; + pNew->zVxworksPath = 0; if( !zRealname ){ rc = SQLITE_NOMEM; eLockingStyle = LOCKING_STYLE_NONE; }else{ n = strlen(zRealname) + 1; - enterMutex(); - pElem = sqlite3HashFindElem(&nameHash, zRealname, n); + unixEnterMutex(); + pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n); if( pElem ){ long cnt = (long)pElem->data; cnt++; - pNew->zRealpath = pElem->pKey; + pNew->zVxworksPath = pElem->pKey; pElem->data = (void*)cnt; }else{ - if( sqlite3HashInsert(&nameHash, zRealname, n, (void*)1)==0 ){ - pElem = sqlite3HashFindElem(&nameHash, zRealname, n); + if( sqlite3HashInsert(&vxworksFilenameHash, zRealname, n,(void*)1)==0 ){ + pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n); if( pElem ){ - pNew->zRealpath = pElem->pKey; + pNew->zVxworksPath = pElem->pKey; }else{ - sqlite3HashInsert(&nameHash, zRealname, n, 0); + sqlite3HashInsert(&vxworksFilenameHash, zRealname, n, 0); rc = SQLITE_NOMEM; eLockingStyle = LOCKING_STYLE_NONE; } } } - leaveMutex(); + unixLeaveMutex(); sqlite3_free(zRealname); } } @@ -3620,19 +3630,15 @@ static int fillInUnixFile( switch( eLockingStyle ){ case LOCKING_STYLE_POSIX: { - enterMutex(); -#if IS_VXWORKS - rc = findLockInfo(pNew, pNew->zRealpath, &pNew->pLock, &pNew->pOpen); -#else + unixEnterMutex(); rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); -#endif - leaveMutex(); + unixLeaveMutex(); break; } #if SQLITE_ENABLE_LOCKING_STYLE -#if !IS_VXWORKS +#if !OS_VXWORKS case LOCKING_STYLE_AFP: { /* AFP locking uses the file path so it needs to be included in ** the afpLockingContext. @@ -3647,9 +3653,9 @@ static int fillInUnixFile( ** copy of the filename. */ pCtx->dbPath = zFilename; srandomdev(); - enterMutex(); + unixEnterMutex(); rc = findLockInfo(pNew, NULL, &pNew->pOpen); - leaveMutex(); + unixLeaveMutex(); } break; } @@ -3672,17 +3678,17 @@ static int fillInUnixFile( break; } -#if IS_VXWORKS +#if OS_VXWORKS case LOCKING_STYLE_NAMEDSEM: { /* Named semaphore locking uses the file path so it needs to be ** included in the namedsemLockingContext */ - enterMutex(); - rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen); + unixEnterMutex(); + rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){ char *zSemName = pNew->pOpen->aSemName; int n; - sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zRealpath); + sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zVxworksPath); for( n=0; zSemName[n]; n++ ) if( zSemName[n]=='/' ) zSemName[n] = '_'; pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1); @@ -3691,7 +3697,7 @@ static int fillInUnixFile( pNew->pOpen->aSemName[0] = '\0'; } } - leaveMutex(); + unixLeaveMutex(); break; } #endif @@ -3703,7 +3709,7 @@ static int fillInUnixFile( } pNew->lastErrno = 0; -#if IS_VXWORKS +#if OS_VXWORKS if( rc!=SQLITE_OK ){ unlink(zFilename); isDelete = 0; @@ -3947,7 +3953,7 @@ static int unixOpen( return SQLITE_CANTOPEN; } if( isDelete ){ -#if IS_VXWORKS +#if OS_VXWORKS zPath = zName; #else unlink(zName); @@ -4025,7 +4031,7 @@ static int unixDelete(sqlite3_vfs *NotUsed, const char *zPath, int dirSync){ int fd; rc = openDirectory(zPath, &fd); if( rc==SQLITE_OK ){ -#if IS_VXWORKS +#if OS_VXWORKS if( fsync(fd)==-1 ) #else if( fsync(fd) ) @@ -4106,7 +4112,7 @@ static int unixFullPathname( assert( pVfs->mxPathname==MAX_PATHNAME ); UNUSED_PARAMETER(pVfs); -#if IS_VXWORKS +#if OS_VXWORKS { char *zRealname = vxrealpath(zPath, 0); zOut[0] = '\0'; @@ -4156,7 +4162,7 @@ static int unixFullPathname( zFull[j] = 0; } #endif -#endif /* #if IS_VXWORKS */ +#endif /* #if OS_VXWORKS */ } @@ -4181,12 +4187,12 @@ static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){ static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){ char *zErr; UNUSED_PARAMETER(NotUsed); - enterMutex(); + unixEnterMutex(); zErr = dlerror(); if( zErr ){ sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); } - leaveMutex(); + unixLeaveMutex(); } static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){ UNUSED_PARAMETER(NotUsed); @@ -4254,7 +4260,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** than the argument. */ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if IS_VXWORKS +#if OS_VXWORKS struct timespec sp; sp.tv_sec = microseconds / 1000000; @@ -4286,14 +4292,14 @@ int sqlite3_current_time = 0; ** return 0. Return 1 if the time and date cannot be found. */ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ -#if IS_VXWORKS - struct timespec sNow; - clock_gettime(CLOCK_REALTIME, &sNow); - *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0; -#elif defined(NO_GETTOD) +#if defined(NO_GETTOD) time_t t; time(&t); *prNow = t/86400.0 + 2440587.5; +#elif OS_VXWORKS + struct timespec sNow; + clock_gettime(CLOCK_REALTIME, &sNow); + *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0; #else struct timeval sNow; gettimeofday(&sNow, 0); @@ -4362,8 +4368,8 @@ int sqlite3_os_init(void){ sqlite3_vfs_register(&aVfs[i], 0); } #endif -#if IS_VXWORKS - sqlite3HashInit(&nameHash, 1); +#if OS_VXWORKS + sqlite3HashInit(&vxworksFilenameHash, 1); #endif sqlite3_vfs_register(&unixVfs, 1); return SQLITE_OK; |