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

📄 os_unix.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
  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;#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  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** 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);#if IS_VXWORKS    rc = findLockInfo(pFile->h, pFile->zRealpath, &pFile->pLock, 0);#else    rc = findLockInfo(pFile->h, &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.**** NB:  If you define USE_PREAD or USE_PREAD64, then it might also** be necessary to define _XOPEN_SOURCE to be 500.  This varies from** one system to another.  Since SQLite does not define USE_PREAD** any any form by default, we will not attempt to define _XOPEN_SOURCE.** See tickets #2741 and #2681.*/static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){  int got;  i64 newOffset;  TIMER_START;#if defined(USE_PREAD)  got = pread(id->h, pBuf, cnt, offset);  SimulateIOError( got = -1 );#elif defined(USE_PREAD64)  got = pread64(id->h, pBuf, cnt, offset);  SimulateIOError( got = -1 );#else  newOffset = lseek(id->h, offset, SEEK_SET);  SimulateIOError( newOffset-- );  if( newOffset!=offset ){    return -1;  }  got = read(id->h, pBuf, cnt);#endif  TIMER_END;  OSTRACE5("READ    %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);  return got;}/*** Read data from a file into a buffer.  Return SQLITE_OK if all** bytes were read successfully and SQLITE_IOERR if anything goes** wrong.*/static int unixRead(  sqlite3_file *id,   void *pBuf,   int amt,  sqlite3_int64 offset){  int got;  assert( id );  got = seekAndRead((unixFile*)id, offset, pBuf, amt);  if( got==amt ){    return SQLITE_OK;  }else if( got<0 ){    return SQLITE_IOERR_READ;  }else{    /* Unread parts of the buffer must be zero-filled */    memset(&((char*)pBuf)[got], 0, amt-got);    return SQLITE_IOERR_SHORT_READ;  }}/*** Seek to the offset in id->offset then read cnt bytes into pBuf.** Return the number of bytes actually read.  Update the offset.*/static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){  int got;  i64 newOffset;  TIMER_START;#if defined(USE_PREAD)  got = pwrite(id->h, pBuf, cnt, offset);#elif defined(USE_PREAD64)  got = pwrite64(id->h, pBuf, cnt, offset);#else  newOffset = lseek(id->h, offset, SEEK_SET);  if( newOffset!=offset ){    return -1;  }  got = write(id->h, pBuf, cnt);#endif  TIMER_END;  OSTRACE5("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);  return got;}/*** Write data from a buffer into a file.  Return SQLITE_OK on success** or some other error code on failure.*/static int unixWrite(  sqlite3_file *id,   const void *pBuf,   int amt,  sqlite3_int64 offset ){  int wrote = 0;  assert( id );  assert( amt>0 );  while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){    amt -= wrote;    offset += wrote;    pBuf = &((char*)pBuf)[wrote];  }  SimulateIOError(( wrote=(-1), amt=1 ));  SimulateDiskfullError(( wrote=0, amt=1 ));  if( amt>0 ){    if( wrote<0 ){      return SQLITE_IOERR_WRITE;    }else{      return SQLITE_FULL;    }  }  return SQLITE_OK;}#ifdef SQLITE_TEST/*** Count the number of fullsyncs and normal syncs.  This is used to test** that syncs and fullsyncs are occuring at the right times.*/int sqlite3_sync_count = 0;int sqlite3_fullsync_count = 0;#endif/*** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined.** Otherwise use fsync() in its place.*/#ifndef HAVE_FDATASYNC# define fdatasync fsync#endif/*** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently** only available on Mac OS X.  But that could change.*/#ifdef F_FULLFSYNC# define HAVE_FULLFSYNC 1#else# define HAVE_FULLFSYNC 0#endif/*** The fsync() system call does not work as advertised on many** unix systems.  The following procedure is an attempt to make** it work better.**** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful** for testing when we want to run through the test suite quickly.** You are strongly advised *not* to deploy with SQLITE_NO_SYNC** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash** or power failure will likely corrupt the database file.*/static int full_fsync(int fd, int fullSync, int dataOnly){  int rc;  /* The following "ifdef/elif/else/" block has the same structure as  ** the one below. It is replicated here solely to avoid cluttering   ** up the real code with the UNUSED_PARAMETER() macros.  */#ifdef SQLITE_NO_SYNC  UNUSED_PARAMETER(fd);  UNUSED_PARAMETER(fullSync);  UNUSED_PARAMETER(dataOnly);#elif HAVE_FULLFSYNC  UNUSED_PARAMETER(dataOnly);#else  UNUSED_PARAMETER(fullSync);#endif  /* Record the number of times that we do a normal fsync() and   ** FULLSYNC.  This is used during testing to verify that this procedure  ** gets called with the correct arguments.  */#ifdef SQLITE_TEST  if( fullSync ) sqlite3_fullsync_count++;  sqlite3_sync_count++;#endif  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a  ** no-op  */#ifdef SQLITE_NO_SYNC  rc = SQLITE_OK;#elif HAVE_FULLFSYNC  if( fullSync ){    rc = fcntl(fd, F_FULLFSYNC, 0);  }else{    rc = 1;  }  /* If the FULLFSYNC failed, fall back to attempting an fsync().   * It shouldn't be possible for fullfsync to fail on the local    * file system (on OSX), so failure indicates that FULLFSYNC   * isn't supported for this file system. So, attempt an fsync    * and (for now) ignore the overhead of a superfluous fcntl call.     * It'd be better to detect fullfsync support once and avoid    * the fcntl call every time sync is called.   */  if( rc ) rc = fsync(fd);#else   if( dataOnly ){    rc = fdatasync(fd);    if( IS_VXWORKS && rc==-1 && errno==ENOTSUP ){      rc = fsync(fd);    }  }else{    rc = fsync(fd);  }#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */  if( IS_VXWORKS && rc!= -1 ){    rc = 0;  }  return rc;}/*** Make sure all writes to a particular file are committed to disk.**** If dataOnly==0 then both the file itself and its metadata (file** size, access time, etc) are synced.  If dataOnly!=0 then only the** file data is synced.**** Under Unix, also make sure that the directory entry for the file** has been created by fsync-ing the directory that contains the file.** If we do not do this and we encounter a power failure, the directory** entry for the journal might not exist after we reboot.  The next** SQLite to access the file will not know that the journal exists (because** the directory entry for the journal was never created) and the transaction** will not roll back - possibly leading to database corruption.*/static int unixSync(sqlite3_file *id, int flags){  int rc;  unixFile *pFile = (unixFile*)id;  int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);  int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */  assert((flags&0x0F)==SQLITE_SYNC_NORMAL      || (flags&0x0F)==SQLITE_SYNC_FULL  );

⌨️ 快捷键说明

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