⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_unix.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
*/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 *//*** The testThreadLockingBehavior() routine launches two separate** threads on this routine.  This routine attempts to lock a file** descriptor then returns.  The success or failure of that attempt** allows the testThreadLockingBehavior() procedure to determine** whether or not threads can override each others locks.*/static void *threadLockingTest(void *pArg){  struct threadTestData *pData = (struct threadTestData*)pArg;  pData->result = fcntl(pData->fd, F_SETLK, &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;  struct threadTestData d[2];  pthread_t t[2];  fd = dup(fd_orig);  if( fd<0 ) return;  memset(d, 0, sizeof(d));  d[0].fd = fd;  d[0].lock.l_type = F_RDLCK;  d[0].lock.l_len = 1;  d[0].lock.l_start = 0;  d[0].lock.l_whence = SEEK_SET;  d[1] = d[0];  d[1].lock.l_type = F_WRLCK;  pthread_create(&t[0], 0, threadLockingTest, &d[0]);  pthread_create(&t[1], 0, threadLockingTest, &d[1]);  pthread_join(t[0], 0);  pthread_join(t[1], 0);  close(fd);  threadsOverrideEachOthersLocks =  d[0].result==0 && d[1].result==0;}#endif /* SQLITE_UNIX_THREADS *//*** Release a lockInfo structure previously allocated by findLockInfo().*/static void releaseLockInfo(struct lockInfo *pLock){  assert( sqlite3OsInMutex(1) );  if (pLock == NULL)    return;  pLock->nRef--;  if( pLock->nRef==0 ){    sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);    sqlite3ThreadSafeFree(pLock);  }}/*** Release a openCnt structure previously allocated by findLockInfo().*/static void releaseOpenCnt(struct openCnt *pOpen){  assert( sqlite3OsInMutex(1) );  if (pOpen == NULL)    return;  pOpen->nRef--;  if( pOpen->nRef==0 ){    sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);    free(pOpen->aPending);    sqlite3ThreadSafeFree(pOpen);  }}#ifdef 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.*/static sqlite3LockingStyle sqlite3TestLockingStyle(const char *filePath,   int fd) {  /* test byte-range lock using fcntl */  struct flock lockInfo;    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 posixLockingStyle;  }     /* testing for flock can give false positives.  So if if the above test  ** fails, then we fall back to using dot-lock style locking.  */    return dotlockLockingStyle;}/* ** Examines the f_fstypename entry in the statfs structure as returned by ** stat() for the file system hosting the database file, assigns the ** appropriate locking style based on it's value.  These values and ** assignments are based on Darwin/OSX behavior and have not been tested on ** other systems.*/static sqlite3LockingStyle sqlite3DetectLockingStyle(const char *filePath,   int fd) {#ifdef SQLITE_FIXED_LOCKING_STYLE  return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE;#else  struct statfs fsInfo;  if (statfs(filePath, &fsInfo) == -1)    return sqlite3TestLockingStyle(filePath, fd);    if (fsInfo.f_flags & MNT_RDONLY)    return noLockingStyle;    if( (!strcmp(fsInfo.f_fstypename, "hfs")) ||    (!strcmp(fsInfo.f_fstypename, "ufs")) )		return posixLockingStyle;    if(!strcmp(fsInfo.f_fstypename, "afpfs"))    return afpLockingStyle;    if(!strcmp(fsInfo.f_fstypename, "nfs"))     return sqlite3TestLockingStyle(filePath, fd);    if(!strcmp(fsInfo.f_fstypename, "smbfs"))    return flockLockingStyle;    if(!strcmp(fsInfo.f_fstypename, "msdos"))    return dotlockLockingStyle;    if(!strcmp(fsInfo.f_fstypename, "webdav"))    return unsupportedLockingStyle;    return sqlite3TestLockingStyle(filePath, fd);  #endif /* SQLITE_FIXED_LOCKING_STYLE */}#endif /* 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 the number of errors.*/static int findLockInfo(  int fd,                      /* The file descriptor used in the key */  struct lockInfo **ppLock,    /* Return the lockInfo structure here */  struct openCnt **ppOpen      /* Return the openCnt structure here */){  int rc;  struct lockKey key1;  struct openKey key2;  struct stat statbuf;  struct lockInfo *pLock;  struct openCnt *pOpen;  rc = fstat(fd, &statbuf);  if( rc!=0 ) return 1;  assert( sqlite3OsInMutex(1) );  memset(&key1, 0, sizeof(key1));  key1.dev = statbuf.st_dev;  key1.ino = statbuf.st_ino;#ifdef SQLITE_UNIX_THREADS  if( threadsOverrideEachOthersLocks<0 ){    testThreadLockingBehavior(fd);  }  key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();#endif  memset(&key2, 0, sizeof(key2));  key2.dev = statbuf.st_dev;  key2.ino = statbuf.st_ino;  pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));  if( pLock==0 ){    struct lockInfo *pOld;    pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) );    if( pLock==0 ){      rc = 1;      goto exit_findlockinfo;    }    pLock->key = key1;    pLock->nRef = 1;    pLock->cnt = 0;    pLock->locktype = 0;    pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);    if( pOld!=0 ){      assert( pOld==pLock );      sqlite3ThreadSafeFree(pLock);      rc = 1;      goto exit_findlockinfo;    }  }else{    pLock->nRef++;  }  *ppLock = pLock;  if( ppOpen!=0 ){    pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));    if( pOpen==0 ){      struct openCnt *pOld;      pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) );      if( pOpen==0 ){        releaseLockInfo(pLock);        rc = 1;        goto exit_findlockinfo;      }      pOpen->key = key2;      pOpen->nRef = 1;      pOpen->nLock = 0;      pOpen->nPending = 0;      pOpen->aPending = 0;      pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);      if( pOld!=0 ){        assert( pOld==pOpen );        sqlite3ThreadSafeFree(pOpen);        releaseLockInfo(pLock);        rc = 1;        goto exit_findlockinfo;      }    }else{      pOpen->nRef++;    }    *ppOpen = pOpen;  }exit_findlockinfo:  return rc;}#ifdef SQLITE_DEBUG/*** Helper function for printing out trace information from debugging** binaries. This returns the string represetation of the supplied** integer lock-type.*/static const char *locktypeName(int locktype){  switch( locktype ){  case NO_LOCK: return "NONE";  case SHARED_LOCK: return "SHARED";  case RESERVED_LOCK: return "RESERVED";  case PENDING_LOCK: return "PENDING";  case EXCLUSIVE_LOCK: return "EXCLUSIVE";  }  return "ERROR";}#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.*/#ifdef SQLITE_UNIX_THREADSstatic 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->h, &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  /* On single-threaded builds, ownership transfer is a no-op */# define transferOwnership(X) SQLITE_OK#endif/*** Delete the named file*/int sqlite3UnixDelete(const char *zFilename){  SimulateIOError(return SQLITE_IOERR_DELETE);  unlink(zFilename);  return SQLITE_OK;}/*** Return TRUE if the named file exists.*/int sqlite3UnixFileExists(const char *zFilename){  return access(zFilename, 0)==0;}/* Forward declaration */static int allocateUnixFile(  int h,                    /* File descriptor of the open file */  OsFile **pId,             /* Write the real file descriptor here */  const char *zFilename,    /* Name of the file being opened */  int delFlag               /* If true, make sure the file deletes on close */);/*** Attempt to open a file for both reading and writing.  If that** fails, try opening it read-only.  If the file does not exist,** try to create it.**** On success, a handle for the open file is written to *id** and *pReadonly is set to 0 if the file was opened for reading and** writing or 1 if the file was opened read-only.  The function returns** SQLITE_OK.**** On failure, the function returns SQLITE_CANTOPEN and leaves** *id and *pReadonly unchanged.*/int sqlite3UnixOpenReadWrite(  const char *zFilename,  OsFile **pId,  int *pReadonly){  int h;    CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly);  assert( 0==*pId );  h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,                        SQLITE_DEFAULT_FILE_PERMISSIONS);  if( h<0 ){#ifdef EISDIR    if( errno==EISDIR ){      return SQLITE_CANTOPEN;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -