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

📄 os.c

📁 sqlite数据库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    if( aNew==0 ){      /* If a malloc fails, just leak the file descriptor */    }else{      pOpen->aPending = aNew;      pOpen->aPending[pOpen->nPending-1] = id->fd;    }  }else{    /* There are no outstanding locks so we can close the file immediately */    close(id->fd);  }  releaseLockInfo(id->pLock);  releaseOpenCnt(id->pOpen);  sqliteOsLeaveMutex();  TRACE2("CLOSE   %-3d\n", id->fd);  OpenCounter(-1);  return SQLITE_OK;#endif#if OS_WIN  CloseHandle(id->h);  OpenCounter(-1);  return SQLITE_OK;#endif#if OS_MAC  if( id->refNumRF!=-1 )    FSClose(id->refNumRF);# ifdef _LARGE_FILE  FSCloseFork(id->refNum);# else  FSClose(id->refNum);# endif  if( id->delOnClose ){    unlink(id->pathToDel);    sqliteFree(id->pathToDel);  }  OpenCounter(-1);  return SQLITE_OK;#endif}/*** Read data from a file into a buffer.  Return SQLITE_OK if all** bytes were read successfully and SQLITE_IOERR if anything goes** wrong.*/int sqliteOsRead(OsFile *id, void *pBuf, int amt){#if OS_UNIX  int got;  SimulateIOError(SQLITE_IOERR);  TIMER_START;  got = read(id->fd, pBuf, amt);  TIMER_END;  TRACE4("READ    %-3d %7d %d\n", id->fd, last_page, elapse);  SEEK(0);  /* if( got<0 ) got = 0; */  if( got==amt ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }#endif#if OS_WIN  DWORD got;  SimulateIOError(SQLITE_IOERR);  TRACE2("READ %d\n", last_page);  if( !ReadFile(id->h, pBuf, amt, &got, 0) ){    got = 0;  }  if( got==(DWORD)amt ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }#endif#if OS_MAC  int got;  SimulateIOError(SQLITE_IOERR);  TRACE2("READ %d\n", last_page);# ifdef _LARGE_FILE  FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);# else  got = amt;  FSRead(id->refNum, &got, pBuf);# endif  if( got==amt ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }#endif}/*** Write data from a buffer into a file.  Return SQLITE_OK on success** or some other error code on failure.*/int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){#if OS_UNIX  int wrote = 0;  SimulateIOError(SQLITE_IOERR);  TIMER_START;  while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  TIMER_END;  TRACE4("WRITE   %-3d %7d %d\n", id->fd, last_page, elapse);  SEEK(0);  if( amt>0 ){    return SQLITE_FULL;  }  return SQLITE_OK;#endif#if OS_WIN  int rc;  DWORD wrote;  SimulateIOError(SQLITE_IOERR);  TRACE2("WRITE %d\n", last_page);  while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  if( !rc || amt>(int)wrote ){    return SQLITE_FULL;  }  return SQLITE_OK;#endif#if OS_MAC  OSErr oserr;  int wrote = 0;  SimulateIOError(SQLITE_IOERR);  TRACE2("WRITE %d\n", last_page);  while( amt>0 ){# ifdef _LARGE_FILE    oserr = FSWriteFork(id->refNum, fsAtMark, 0,                        (ByteCount)amt, pBuf, (ByteCount*)&wrote);# else    wrote = amt;    oserr = FSWrite(id->refNum, &wrote, pBuf);# endif    if( wrote == 0 || oserr != noErr)      break;    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  if( oserr != noErr || amt>wrote ){    return SQLITE_FULL;  }  return SQLITE_OK;#endif}/*** Move the read/write pointer in a file.*/int sqliteOsSeek(OsFile *id, off_t offset){  SEEK(offset/1024 + 1);#if OS_UNIX  lseek(id->fd, offset, SEEK_SET);  return SQLITE_OK;#endif#if OS_WIN  {    LONG upperBits = offset>>32;    LONG lowerBits = offset & 0xffffffff;    DWORD rc;    rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);    /* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */  }  return SQLITE_OK;#endif#if OS_MAC  {    off_t curSize;    if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){      return SQLITE_IOERR;    }    if( offset >= curSize ){      if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){        return SQLITE_IOERR;      }    }# ifdef _LARGE_FILE    if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){# else    if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){# endif      return SQLITE_IOERR;    }else{      return SQLITE_OK;    }  }#endif}/*** Make sure all writes to a particular file are committed to disk.**** 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.*/int sqliteOsSync(OsFile *id){#if OS_UNIX  SimulateIOError(SQLITE_IOERR);  TRACE2("SYNC    %-3d\n", id->fd);  if( fsync(id->fd) ){    return SQLITE_IOERR;  }else{    if( id->dirfd>=0 ){      TRACE2("DIRSYNC %-3d\n", id->dirfd);      fsync(id->dirfd);      close(id->dirfd);  /* Only need to sync once, so close the directory */      id->dirfd = -1;    /* when we are done. */    }    return SQLITE_OK;  }#endif#if OS_WIN  if( FlushFileBuffers(id->h) ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSFlushFork(id->refNum) != noErr ){# else  ParamBlockRec params;  memset(&params, 0, sizeof(ParamBlockRec));  params.ioParam.ioRefNum = id->refNum;  if( PBFlushFileSync(&params) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}/*** Truncate an open file to a specified size*/int sqliteOsTruncate(OsFile *id, off_t nByte){  SimulateIOError(SQLITE_IOERR);#if OS_UNIX  return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;#endif#if OS_WIN  {    LONG upperBits = nByte>>32;    SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);    SetEndOfFile(id->h);  }  return SQLITE_OK;#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){# else  if( SetEOF(id->refNum, nByte) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}/*** Determine the current size of a file in bytes*/int sqliteOsFileSize(OsFile *id, off_t *pSize){#if OS_UNIX  struct stat buf;  SimulateIOError(SQLITE_IOERR);  if( fstat(id->fd, &buf)!=0 ){    return SQLITE_IOERR;  }  *pSize = buf.st_size;  return SQLITE_OK;#endif#if OS_WIN  DWORD upperBits, lowerBits;  SimulateIOError(SQLITE_IOERR);  lowerBits = GetFileSize(id->h, &upperBits);  *pSize = (((off_t)upperBits)<<32) + lowerBits;  return SQLITE_OK;#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSGetForkSize(id->refNum, pSize) != noErr){# else  if( GetEOF(id->refNum, pSize) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}#if OS_WIN/*** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.** Return false (zero) for Win95, Win98, or WinME.**** Here is an interesting observation:  Win95, Win98, and WinME lack** the LockFileEx() API.  But we can still statically link against that** API as long as we don't call it win running Win95/98/ME.  A call to** this routine is used to determine if the host is Win95/98/ME or** WinNT/2K/XP so that we will know whether or not we can safely call** the LockFileEx() API.*/int isNT(void){  static int osType = 0;   /* 0=unknown 1=win95 2=winNT */  if( osType==0 ){    OSVERSIONINFO sInfo;    sInfo.dwOSVersionInfoSize = sizeof(sInfo);    GetVersionEx(&sInfo);    osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;  }  return osType==2;}#endif/*** Windows file locking notes:  [similar issues apply to MacOS]**** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because** those functions are not available.  So we use only LockFile() and** UnlockFile().**** LockFile() prevents not just writing but also reading by other processes.** (This is a design error on the part of Windows, but there is nothing** we can do about that.)  So the region used for locking is at the** end of the file where it is unlikely to ever interfere with an** actual read attempt.**** A database read lock is obtained by locking a single randomly-chosen ** byte out of a specific range of bytes. The lock byte is obtained at ** random so two separate readers can probably access the file at the ** same time, unless they are unlucky and choose the same lock byte.** A database write lock is obtained by locking all bytes in the range.** There can only be one writer.**** A lock is obtained on the first byte of the lock range before acquiring** either a read lock or a write lock.  This prevents two processes from** attempting to get a lock at a same time.  The semantics of ** sqliteOsReadLock() require that if there is already a write lock, that** lock is converted into a read lock atomically.  The lock on the first** byte allows us to drop the old write lock and get the read lock without** another process jumping into the middle and messing us up.  The same** argument applies to sqliteOsWriteLock().**** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,** which means we can use reader/writer locks.  When reader writer locks** are used, the lock is placed on the same range of bytes that is used** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme** will support two or more Win95 readers or two or more WinNT readers.** But a single Win95 reader will lock out all WinNT readers and a single** WinNT reader will lock out all other Win95 readers.**** Note: On MacOS we use the resource fork for locking.**** The following #defines specify the range of bytes used for locking.** N_LOCKBYTE is the number of bytes available for doing the locking.** The first byte used to hold the lock while the lock is changing does** not count toward this number.  FIRST_LOCKBYTE is the address of** the first byte in the range of bytes used for locking.*/#define N_LOCKBYTE       10239#if OS_MAC# define FIRST_LOCKBYTE   (0x000fffff - N_LOCKBYTE)#else# define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)#endif/*** Change the status of the lock on the file "id" to be a readlock.** If the file was write locked, then this reduces the lock to a read.** If the file was read locked, then this acquires a new read lock.**** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this** library was compiled with large file support (LFS) but LFS is not** available on the host, then an SQLITE_NOLFS is returned.*/int sqliteOsReadLock(OsFile *id){#if OS_UNIX  int rc;  sqliteOsEnterMutex();  if( id->pLock->cnt>0 ){    if( !id->locked ){      id->pLock->cnt++;      id->locked = 1;      id->pOpen->nLock++;    }    rc = SQLITE_OK;  }else if( id->locked || id->pLock->cnt==0 ){    struct flock lock;    int s;    lock.l_type = F_RDLCK;    lock.l_whence = SEEK_SET;    lock.l_start = lock.l_len = 0L;    s = fcntl(id->fd, F_SETLK, &lock);    if( s!=0 ){      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;    }else{      rc = SQLITE_OK;      if( !id->locked ){        id->pOpen->nLock++;        id->locked = 1;      }      id->pLock->cnt = 1;    }  }else{    rc = SQLITE_BUSY;  }  sqliteOsLeaveMutex();  return rc;#endif#if OS_WIN  int rc;  if( id->locked>0 ){    rc = SQLITE_OK;  }else{    int lk;    int res;    int cnt = 100;    sqliteRandomness(sizeof(lk), &lk);    lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){      Sleep(1);    }    if( res ){      UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);      if( isNT() ){        OVERLAPPED ovlp;        ovlp.Offset = FIRST_LOCKBYTE+1;        ovlp.OffsetHigh = 0;        ovlp.hEvent = 0;        res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,                           0, N_LOCKBYTE, 0, &ovlp);      }else{        res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);      }      UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);    }    if( res ){      id->locked = lk;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;#endif#if OS_MAC

⌨️ 快捷键说明

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