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

📄 os_unix.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int _AFPFSSetLock(  const char *path,   unixFile *pFile,   unsigned long long offset,   unsigned long long length,   int setLockFlag){  struct ByteRangeLockPB2       pb;  int                     err;    pb.unLockFlag = setLockFlag ? 0 : 1;  pb.startEndFlag = 0;  pb.offset = offset;  pb.length = length;   pb.fd = pFile->h;  OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",     (setLockFlag?"ON":"OFF"), pFile->h, offset, length);  err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);  if ( err==-1 ) {    int rc;    int tErrno = errno;    OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, tErrno, strerror(tErrno));    rc = sqliteErrorFromPosixError(tErrno, setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); /* error */    if( IS_LOCK_ERROR(rc) ){      pFile->lastErrno = tErrno;    }    return rc;  } else {    return SQLITE_OK;  }}/* AFP-style reserved lock checking following the behavior of ** unixCheckReservedLock, see the unixCheckReservedLock function comments */static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){  int rc = SQLITE_OK;  int reserved = 0;  unixFile *pFile = (unixFile*)id;    SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );    assert( pFile );  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;    /* 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 ){    /* lock the RESERVED byte */    int lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);      if( SQLITE_OK==lrc ){      /* if we succeeded in taking the reserved lock, unlock it to restore      ** the original state */      lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1, 0);    } else {      /* if we failed to get the lock then someone else must have it */      reserved = 1;    }    if( IS_LOCK_ERROR(lrc) ){      rc=lrc;    }  }    OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);    *pResOut = reserved;  return rc;}/* AFP-style locking following the behavior of unixLock, see the unixLock ** function comments for details of lock management. */static int afpLock(sqlite3_file *id, int locktype){  int rc = SQLITE_OK;  unixFile *pFile = (unixFile*)id;  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;    assert( pFile );  OSTRACE5("LOCK    %d %s was %s pid=%d\n", pFile->h,         locktypeName(locktype), locktypeName(pFile->locktype), getpid());  /* If there is already a lock of this type or more restrictive on the  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as  ** enterMutex() hasn't been called yet.  */  if( pFile->locktype>=locktype ){    OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,           locktypeName(locktype));    return SQLITE_OK;  }  /* Make sure the locking sequence is correct  */  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );  assert( locktype!=PENDING_LOCK );  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );    /* This mutex is needed because pFile->pLock is shared across threads  */  enterMutex();  /* Make sure the current thread owns the pFile.  */  rc = transferOwnership(pFile);  if( rc!=SQLITE_OK ){    leaveMutex();    return rc;  }      /* A PENDING lock is needed before acquiring a SHARED lock and before  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will  ** be released.  */  if( locktype==SHARED_LOCK       || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)  ){    int failed;    failed = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 1);    if (failed) {      rc = failed;      goto afp_end_lock;    }  }    /* If control gets to this point, then actually go ahead and make  ** operating system calls for the specified lock.  */  if( locktype==SHARED_LOCK ){    int lk, lrc1, lrc2, lrc1Errno;        /* Now get the read-lock SHARED_LOCK */    /* note that the quality of the randomness doesn't matter that much */    lk = random();     context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);    lrc1 = _AFPFSSetLock(context->filePath, pFile,           SHARED_FIRST+context->sharedLockByte, 1, 1);    if( IS_LOCK_ERROR(lrc1) ){      lrc1Errno = pFile->lastErrno;    }    /* Drop the temporary PENDING lock */    lrc2 = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 0);        if( IS_LOCK_ERROR(lrc1) ) {      pFile->lastErrno = lrc1Errno;      rc = lrc1;      goto afp_end_lock;    } else if( IS_LOCK_ERROR(lrc2) ){      rc = lrc2;      goto afp_end_lock;    } else if( lrc1 != SQLITE_OK ) {      rc = lrc1;    } else {      pFile->locktype = SHARED_LOCK;    }  }else{    /* The request was for a RESERVED or EXCLUSIVE lock.  It is    ** assumed that there is a SHARED or greater lock on the file    ** already.    */    int failed = 0;    assert( 0!=pFile->locktype );    if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {        /* Acquire a RESERVED lock */        failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);    }    if (!failed && locktype == EXCLUSIVE_LOCK) {      /* Acquire an EXCLUSIVE lock */              /* Remove the shared lock before trying the range.  we'll need to       ** reestablish the shared lock if we can't get the  afpUnlock      */      if (!(failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST +                         context->sharedLockByte, 1, 0))) {        /* now attemmpt to get the exclusive lock range */        failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,                                SHARED_SIZE, 1);        if (failed && (failed = _AFPFSSetLock(context->filePath, pFile,                        SHARED_FIRST + context->sharedLockByte, 1, 1))) {          rc = failed;        }      } else {        rc = failed;       }    }    if( failed ){      rc = failed;    }  }    if( rc==SQLITE_OK ){    pFile->locktype = locktype;  }else if( locktype==EXCLUSIVE_LOCK ){    pFile->locktype = PENDING_LOCK;  }  afp_end_lock:  leaveMutex();  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype),          rc==SQLITE_OK ? "ok" : "failed");  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.*/static int afpUnlock(sqlite3_file *id, int locktype) {  int rc = SQLITE_OK;  unixFile *pFile = (unixFile*)id;  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;  assert( pFile );  OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,         pFile->locktype, getpid());  assert( locktype<=SHARED_LOCK );  if( pFile->locktype<=locktype ){    return SQLITE_OK;  }  if( CHECK_THREADID(pFile) ){    return SQLITE_MISUSE;  }  enterMutex();  int failed = SQLITE_OK;  if( pFile->locktype>SHARED_LOCK ){    if( locktype==SHARED_LOCK ){      /* unlock the exclusive range - then re-establish the shared lock */      if (pFile->locktype==EXCLUSIVE_LOCK) {        failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,                                  SHARED_SIZE, 0);        if (!failed) {          /* successfully removed the exclusive lock */          if ((failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST+                            context->sharedLockByte, 1, 1))) {            /* failed to re-establish our shared lock */            rc = failed;          }        } else {          rc = failed;        }       }    }    if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {      if ((failed = _AFPFSSetLock(context->filePath, pFile,                                   PENDING_BYTE, 1, 0))){        /* failed to release the pending lock */        rc = failed;       }    }     if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {      if ((failed = _AFPFSSetLock(context->filePath, pFile,                                   RESERVED_BYTE, 1, 0))) {        /* failed to release the reserved lock */        rc = failed;        }    }   }  if( locktype==NO_LOCK ){    int failed = _AFPFSSetLock(context->filePath, pFile,                                SHARED_FIRST + context->sharedLockByte, 1, 0);    if (failed) {      rc = failed;      }  }  if (rc == SQLITE_OK)    pFile->locktype = locktype;  leaveMutex();  return rc;}/*** Close a file & cleanup AFP specific locking context */static int afpClose(sqlite3_file *id) {  if( id ){    unixFile *pFile = (unixFile*)id;    afpUnlock(id, NO_LOCK);    sqlite3_free(pFile->lockingContext);  }  return closeUnixFile(id);}#pragma mark flock() style locking/*** The flockLockingContext is not used*/typedef void flockLockingContext;/* flock-style reserved lock checking following the behavior of  ** unixCheckReservedLock, see the unixCheckReservedLock function comments */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);  *pResOut = reserved;  return rc;}static int flockLock(sqlite3_file *id, int locktype) {  int rc = SQLITE_OK;  int lrc;  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(locktype),            rc==SQLITE_OK ? "ok" : "failed");  return rc;}static int flockUnlock(sqlite3_file *id, int locktype) {  unixFile *pFile = (unixFile*)id;    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;  }    /* shared can just be set because we always have an exclusive */  if (locktype==SHARED_LOCK) {    pFile->locktype = locktype;    return SQLITE_OK;  }    /* no, really, unlock. */  int rc = flock(pFile->h, LOCK_UN);  if (rc) {    int r, tErrno = errno;    r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);    if( IS_LOCK_ERROR(r) ){      pFile->lastErrno = tErrno;    }    return r;  } else {    pFile->locktype = NO_LOCK;    return SQLITE_OK;  }}/*** Close a file.*/static int flockClose(sqlite3_file *id) {  if( id ){    flockUnlock(id, NO_LOCK);  }  

⌨️ 快捷键说明

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