📄 os_unix.c
字号:
#define LOCKING_STYLE_AFP 5#define LOCKING_STYLE_NAMEDSEM 6/*** 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 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.**** 0: No. Threads cannot override each others locks.** 1: Yes. Threads can override each others locks.** -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** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is** undefined.**** This variable normally has file scope only. But during testing, we make** it a global so that the test code can change its value in order to verify** that the right stuff happens in either case.*/#ifndef SQLITE_THREAD_OVERRIDE_LOCK# define SQLITE_THREAD_OVERRIDE_LOCK -1#endif#ifdef SQLITE_TESTint threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;#elsestatic int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;#endif/*** This structure holds information passed into individual test** threads by the testThreadLockingBehavior() routine.*/struct threadTestData { int fd; /* File to be locked */ struct flock lock; /* The locking operation */ 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__/*** This function is used as the main routine for a thread launched by** testThreadLockingBehavior(). It tests whether the shared-lock obtained** by the main thread in testThreadLockingBehavior() conflicts with a** hypothetical write-lock obtained by this thread on the same file.**** The write-lock is not actually acquired, as this is not possible if ** the file is open in read-only mode (see ticket #3472).*/ static void *threadLockingTest(void *pArg){ struct threadTestData *pData = (struct threadTestData*)pArg; pData->result = fcntl(pData->fd, F_GETLK, &pData->lock); return pArg;}/*** This procedure attempts to determine whether or not threads** can override each others locks then sets the ** threadsOverrideEachOthersLocks variable appropriately.*/static void testThreadLockingBehavior(int fd_orig){ int fd; int rc; struct threadTestData d; struct flock l; pthread_t t; fd = dup(fd_orig); if( fd<0 ) return; memset(&l, 0, sizeof(l)); l.l_type = F_RDLCK; l.l_len = 1; l.l_start = 0; l.l_whence = SEEK_SET; rc = fcntl(fd_orig, F_SETLK, &l); if( rc!=0 ) return; memset(&d, 0, sizeof(d)); d.fd = fd; d.lock = l; d.lock.l_type = F_WRLCK; pthread_create(&t, 0, threadLockingTest, &d); pthread_join(t, 0); close(fd); if( d.result!=0 ) return; threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);}#else/*** On anything other than linux, assume threads override each others locks.*/static void testThreadLockingBehavior(int fd_orig){ threadsOverrideEachOthersLocks = 1;}#endif /* __linux__ */#endif /* SQLITE_THREADSAFE *//*** Release a lockInfo structure previously allocated by findLockInfo().*/static void releaseLockInfo(struct lockInfo *pLock){ if( pLock ){ pLock->nRef--; if( pLock->nRef==0 ){ if( pLock->pPrev ){ assert( pLock->pPrev->pNext==pLock ); pLock->pPrev->pNext = pLock->pNext; }else{ assert( lockList==pLock ); lockList = pLock->pNext; } if( pLock->pNext ){ assert( pLock->pNext->pPrev==pLock ); pLock->pNext->pPrev = pLock->pPrev; } sqlite3_free(pLock); } }}/*** Release a openCnt structure previously allocated by findLockInfo().*/static void releaseOpenCnt(struct openCnt *pOpen){ if( pOpen ){ pOpen->nRef--; if( pOpen->nRef==0 ){ if( pOpen->pPrev ){ assert( pOpen->pPrev->pNext==pOpen ); pOpen->pPrev->pNext = pOpen->pNext; }else{ assert( openList==pOpen ); openList = pOpen->pNext; } if( pOpen->pNext ){ assert( pOpen->pNext->pPrev==pOpen ); pOpen->pNext->pPrev = pOpen->pPrev; } sqlite3_free(pOpen->aPending); sqlite3_free(pOpen); } }}#if IS_VXWORKS/*** Implementation of a realpath() like function for vxWorks** to determine canonical path name from given name. It does** not support symlinks. Neither does it handle volume prefixes.*/char *vxrealpath(const char *pathname, int dostat){ struct stat sbuf; int len; char *where, *ptr, *last; char *result, *curpath, *workpath, *namebuf; len = pathconf(pathname, _PC_PATH_MAX); if( len<0 ){ len = PATH_MAX; } result = sqlite3_malloc(len * 4); if( !result ){ return 0; } curpath = result + len; workpath = curpath + len; namebuf = workpath + len; strcpy(curpath, pathname); if( *pathname!='/' ){ if( !getcwd(workpath, len) ){ sqlite3_free(result); return 0; } }else{ *workpath = '\0'; } where = curpath; while( *where ){ if( !strcmp(where, ".") ){ where++; continue; } if( !strncmp(where, "./", 2) ){ where += 2; continue; } if( !strncmp(where, "../", 3) ){ where += 3; ptr = last = workpath; while( *ptr ){ if( *ptr=='/' ){ last = ptr; } ptr++; } *last = '\0'; continue; } ptr = strchr(where, '/'); if( !ptr ){ ptr = where + strlen(where) - 1; }else{ *ptr = '\0'; } strcpy(namebuf, workpath); for( last = namebuf; *last; last++ ){ continue; } if( *--last!='/' ){ strcat(namebuf, "/"); } strcat(namebuf, where); where = ++ptr; if( dostat ){ if( stat(namebuf, &sbuf)==-1 ){ sqlite3_free(result); return 0; } if( (sbuf.st_mode & S_IFDIR)==S_IFDIR ){ strcpy(workpath, namebuf); continue; } if( *where ){ sqlite3_free(result); return 0; } } strcpy(workpath, namebuf); } strcpy(result, workpath); return result;}#endif#if SQLITE_ENABLE_LOCKING_STYLE/*** Tests a byte-range locking query to see if byte range locks are ** supported, if not we fall back to dotlockLockingStyle.** On vxWorks we fall back to namedsemLockingStyle.*/static int testLockingStyle(int fd){ struct flock lockInfo; /* Test byte-range lock using fcntl(). If the call succeeds, ** assume that the file-system supports POSIX style locks. */ lockInfo.l_len = 1; lockInfo.l_start = 0; lockInfo.l_whence = SEEK_SET; lockInfo.l_type = F_RDLCK; if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) { return LOCKING_STYLE_POSIX; } /* Testing for flock() can give false positives. So if if the above ** 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);}#endif/* ** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the ** f_fstypename entry in the statfs structure as returned by stat() for ** the file system hosting the database file and selects the appropriate** locking style based on its value. These values and assignments are ** based on Darwin/OSX behavior and have not been thoroughly tested on ** other systems.**** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always** returns LOCKING_STYLE_POSIX.*/#if SQLITE_ENABLE_LOCKING_STYLEstatic int detectLockingStyle( sqlite3_vfs *pVfs, const char *filePath, int fd){#if IS_VXWORKS if( !filePath ){ return LOCKING_STYLE_NONE; } if( pVfs->pAppData ){ return SQLITE_PTR_TO_INT(pVfs->pAppData); } if (access(filePath, 0) != -1){ return testLockingStyle(fd); }#else struct Mapping { const char *zFilesystem; int eLockingStyle; } aMap[] = { { "hfs", LOCKING_STYLE_POSIX }, { "ufs", LOCKING_STYLE_POSIX }, { "afpfs", LOCKING_STYLE_AFP },#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB { "smbfs", LOCKING_STYLE_AFP },#else { "smbfs", LOCKING_STYLE_FLOCK },#endif { "msdos", LOCKING_STYLE_DOTFILE }, { "webdav", LOCKING_STYLE_NONE }, { 0, 0 } }; int i; struct statfs fsInfo; if( !filePath ){ return LOCKING_STYLE_NONE; } if( pVfs->pAppData ){ return SQLITE_PTR_TO_INT(pVfs->pAppData); } if( statfs(filePath, &fsInfo) != -1 ){ if( fsInfo.f_flags & MNT_RDONLY ){ return LOCKING_STYLE_NONE; } for(i=0; aMap[i].zFilesystem; i++){ if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){ return aMap[i].eLockingStyle; } } } /* Default case. Handles, amongst others, "nfs". */ return testLockingStyle(fd); #endif /* if IS_VXWORKS */ return LOCKING_STYLE_POSIX;}#else #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX#endif /* ifdef 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( int fd, /* The file descriptor used in the key */#if IS_VXWORKS void *rnam, /* vxWorks realname */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -