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

📄 os_unix.c

📁 sqlite最新源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      int *aNew;      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 */      }else{        pOpen->aPending = aNew;        pOpen->aPending[pOpen->nPending] = pFile->h;        pOpen->nPending++;        pFile->h = -1;      }    }    releaseLockInfo(pFile->pLock);    releaseOpenCnt(pFile->pOpen);    rc = closeUnixFile(id);    unixLeaveMutex();  }  return rc;}/************** End of the posix advisory lock implementation ***********************************************************************************************//************************************************************************************************************ No-op Locking ************************************** Of the various locking implementations available, this is by far the** simplest:  locking is ignored.  No attempt is made to lock the database** file for reading or writing.**** This locking mode is appropriate for use on read-only databases** (ex: databases that are burned into CD-ROM, for example.)  It can** also be used if the application employs some external mechanism to** prevent simultaneous access of the same database by two or more** database connections.  But there is a serious risk of database** corruption if this locking mode is used in situations where multiple** database connections are accessing the same database file at the same** time and one or more of those connections are writing.*/static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){  UNUSED_PARAMETER(NotUsed);  *pResOut = 0;  return SQLITE_OK;}static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){  UNUSED_PARAMETER2(NotUsed, NotUsed2);  return SQLITE_OK;}static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){  UNUSED_PARAMETER2(NotUsed, NotUsed2);  return SQLITE_OK;}/*** Close the file.*/static int nolockClose(sqlite3_file *id) {  return closeUnixFile(id);}/******************* End of the no-op lock implementation ***************************************************************************************************//******************************************************************************************************* Begin dot-file Locking ********************************** The dotfile locking implementation uses the existing of separate lock** files in order to control access to the database.  This works on just** about every filesystem imaginable.  But there are serious downsides:****    (1)  There is zero concurrency.  A single reader blocks all other**         connections from reading or writing the database.****    (2)  An application crash or power loss can leave stale lock files**         sitting around that need to be cleared manually.**** Nevertheless, a dotlock is an appropriate locking mode for use if no** other locking strategy is available.**** Dotfile locking works by creating a file in the same directory as the** database and with the same name but with a ".lock" extension added.** The existance of a lock file implies an EXCLUSIVE lock.  All other lock** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.*//*** The file suffix added to the data base filename in order to create the** lock file.*/#define DOTLOCK_SUFFIX ".lock"/*** This routine checks if there is a RESERVED lock held on the specified** file by this or any other process. If such a lock is held, set *pResOut** to a non-zero value otherwise *pResOut is set to zero.  The return value** is set to SQLITE_OK unless an I/O error occurs during lock checking.**** In dotfile locking, either a lock exists or it does not.  So in this** variation of CheckReservedLock(), *pResOut is set to true if any lock** is held on the file and false if the file is unlocked.*/static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {  int rc = SQLITE_OK;  int reserved = 0;  unixFile *pFile = (unixFile*)id;  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );    assert( pFile );  /* Check if a thread in this process holds such a lock */  if( pFile->locktype>SHARED_LOCK ){    /* Either this connection or some other connection in the same process    ** holds a lock on the file.  No need to check further. */    reserved = 1;  }else{    /* The lock is held if and only if the lockfile exists */    const char *zLockFile = (const char*)pFile->lockingContext;    reserved = access(zLockFile, 0)==0;  }  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);  *pResOut = reserved;  return rc;}/*** Lock the file with the lock specified by parameter locktype - one** of the following:****     (1) SHARED_LOCK**     (2) RESERVED_LOCK**     (3) PENDING_LOCK**     (4) EXCLUSIVE_LOCK**** Sometimes when requesting one lock state, additional lock states** are inserted in between.  The locking might fail on one of the later** transitions leaving the lock state different from what it started but** still short of its goal.  The following chart shows the allowed** transitions and the inserted intermediate states:****    UNLOCKED -> SHARED**    SHARED -> RESERVED**    SHARED -> (PENDING) -> EXCLUSIVE**    RESERVED -> (PENDING) -> EXCLUSIVE**    PENDING -> EXCLUSIVE**** This routine will only increase a lock.  Use the sqlite3OsUnlock()** routine to lower a locking level.**** With dotfile locking, we really only support state (4): EXCLUSIVE.** But we track the other locking levels internally.*/static int dotlockLock(sqlite3_file *id, int locktype) {  unixFile *pFile = (unixFile*)id;  int fd;  char *zLockFile = (char *)pFile->lockingContext;  int rc = SQLITE_OK;  /* If we have any lock, then the lock file already exists.  All we have  ** to do is adjust our internal record of the lock level.  */  if( pFile->locktype > NO_LOCK ){    pFile->locktype = locktype;#if !OS_VXWORKS    /* Always update the timestamp on the old file */    utimes(zLockFile, NULL);#endif    return SQLITE_OK;  }    /* grab an exclusive lock */  fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);  if( fd<0 ){    /* failed to open/create the file, someone else may have stolen the lock */    int tErrno = errno;    if( EEXIST == tErrno ){      rc = SQLITE_BUSY;    } else {      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);      if( IS_LOCK_ERROR(rc) ){        pFile->lastErrno = tErrno;      }    }    return rc;  }   if( close(fd) ){    pFile->lastErrno = errno;    rc = SQLITE_IOERR_CLOSE;  }    /* got it, set the type and return ok */  pFile->locktype = locktype;  return rc;}/*** Lower the locking level on file descriptor pFile to locktype.  locktype** must be either NO_LOCK or SHARED_LOCK.**** If the locking level of the file descriptor is already at or below** the requested locking level, this routine is a no-op.**** When the locking level reaches NO_LOCK, delete the lock file.*/static int dotlockUnlock(sqlite3_file *id, int locktype) {  unixFile *pFile = (unixFile*)id;  char *zLockFile = (char *)pFile->lockingContext;  assert( pFile );  OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,	   pFile->locktype, getpid());  assert( locktype<=SHARED_LOCK );    /* no-op if possible */  if( pFile->locktype==locktype ){    return SQLITE_OK;  }  /* To downgrade to shared, simply update our internal notion of the  ** lock state.  No need to mess with the file on disk.  */  if( locktype==SHARED_LOCK ){    pFile->locktype = SHARED_LOCK;    return SQLITE_OK;  }    /* To fully unlock the database, delete the lock file */  assert( locktype==NO_LOCK );  if( unlink(zLockFile) ){    int rc, tErrno = errno;    if( ENOENT != tErrno ){      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);    }    if( IS_LOCK_ERROR(rc) ){      pFile->lastErrno = tErrno;    }    return rc;   }  pFile->locktype = NO_LOCK;  return SQLITE_OK;}/*** Close a file.  Make sure the lock has been released before closing.*/static int dotlockClose(sqlite3_file *id) {  int rc;  if( id ){    unixFile *pFile = (unixFile*)id;    dotlockUnlock(id, NO_LOCK);    sqlite3_free(pFile->lockingContext);  }  rc = closeUnixFile(id);  return rc;}/****************** End of the dot-file lock implementation *************************************************************************************************//******************************************************************************************************** Begin flock Locking ************************************ Use the flock() system call to do file locking.**** flock() locking is like dot-file locking in that the various** fine-grain locking levels supported by SQLite are collapsed into** a single exclusive lock.  In other words, SHARED, RESERVED, and** PENDING locks are the same thing as an EXCLUSIVE lock.  SQLite** still works when you do this, but concurrency is reduced since** only a single process can be reading the database at a time.**** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if** compiling for VXWORKS.*/#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS/*** This routine checks if there is a RESERVED lock held on the specified** file by this or any other process. If such a lock is held, set *pResOut** to a non-zero value otherwise *pResOut is set to zero.  The return value** is set to SQLITE_OK unless an I/O error occurs during lock checking.*/static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){  int rc = SQLITE_OK;  int reserved = 0;  unixFile *pFile = (unixFile*)id;    SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );    assert( pFile );    /* Check if a thread in this process holds such a lock */  if( pFile->locktype>SHARED_LOCK ){    reserved = 1;  }    /* Otherwise see if some other process holds it. */  if( !reserved ){    /* attempt to get the lock */    int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);    if( !lrc ){      /* got the lock, unlock it */      lrc = flock(pFile->h, LOCK_UN);      if ( lrc ) {        int tErrno = errno;        /* unlock failed with an error */        lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);         if( IS_LOCK_ERROR(lrc) ){          pFile->lastErrno = tErrno;          rc = lrc;        }      }    } else {      int tErrno = errno;      reserved = 1;      /* someone else might have it reserved */      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);       if( IS_LOCK_ERROR(lrc) ){        pFile->lastErrno = tErrno;        rc = lrc;      }    }  }  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){    rc = SQLITE_OK;    reserved=1;  }#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */  *pResOut = reserved;  return rc;}/*** Lock the file with the lock specified by parameter locktype - one** of the following:****     (1) SHARED_LOCK**     (2) RESERVED_LOCK**     (3) PENDING_LOCK**     (4) EXCLUSIVE_LOCK**** Sometimes when requesting one lock state, additional lock states** are inserted in between.  The locking might fail on one of the later** transitions leaving the lock state different from what it started but** still short of its goal.  The following chart shows the allowed** transitions and the inserted intermediate states:****    UNLOCKED -> SHARED**    SHARED -> RESERVED**    SHARED -> (PENDING) -> EXCLUSIVE**    RESERVED -> (PENDING) -> EXCLUSIVE**    PENDING -> EXCLUSIVE**** flock() only really support EXCLUSIVE locks.  We track intermediate** lock states in the sqlite3_file structure, but all locks SHARED or** above are really EXCLUSIVE locks and exclude all other processes from** access the file.**** This routine will only increase a lock.  Use the sqlite3OsUnlock()** routine to lower a locking level.*/static int flockLock(sqlite3_file *id, int locktype) {  int rc = SQLITE_OK;  unixFile *pFile = (unixFile*)id;  assert( pFile );  /* if we already have a lock, it is exclusive.    ** Just adjust level and punt on outta here. */  if (pFile->locktype > NO_LOCK) {    pFile->locktype = locktype;    return SQLITE_OK;  }    /* grab an exclusive lock */    if (flock(pFile->h, LOCK_EX | LOCK_NB)) {    int tErrno = errno;    /* didn't get, must be busy */    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);    if( IS_LOCK_ERROR(rc) ){      pFile->lastErrno = tErrno;    }  } else {    /* got it, set the type and return ok */    pFile->locktype = locktype;  }  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(l

⌨️ 快捷键说明

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