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

📄 os_unix.c

📁 最新的sqlite3.6.2源代码
💻 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_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);    }  }}#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 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.  */    return 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.*/static int detectLockingStyle(  sqlite3_vfs *pVfs,  const char *filePath,   int fd){#ifdef SQLITE_ENABLE_LOCKING_STYLE  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  return LOCKING_STYLE_POSIX;}/*** 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 */  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 ){#ifdef EOVERFLOW    if( errno==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 ){      return SQLITE_IOERR;    }  }  memset(&key1, 0, sizeof(key1));  key1.dev = statbuf.st_dev;  key1.ino = statbuf.st_ino;#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;  key2.ino = statbuf.st_ino;  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;    }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.*/#if SQLITE_THREADSAFEstatic 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/*** Seek to the offset passed as the second argument, then read cnt ** bytes into pBuf. Return the number of bytes actually read.**

⌨️ 快捷键说明

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