sqlite源码之os.c

/*
2005 November 29

The author disclaims copyright to this source code. In place of
a legal notice, here is a blessing:

May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.


This file contains OS interface code that is common to all
architectures.
这个文件中包含对于所有架构一致的操作系统接口代码
*/

#include "sqliteInt.h"

/*
If we compile with the SQLITE_TEST macro set, then the following block
of code will give us the ability to simulate a disk I/O error.  This
is used for testing the I/O recovery logic.
如果我们使用SQLIET_TEST宏进行编译,那么接下来的代码将给我们带来模拟磁盘IO错误的能力。
这可以用来测试IO恢复逻辑。
*/
#if defined(SQLITE_TEST)
int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
int sqlite3_io_error_benign = 0;         /* True if errors are benign */
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#endif /* defined(SQLITE_TEST) */

/*
When testing, also keep a count of the number of open files.
当测试的时候,还要保留打开文件数量的计数
*/
#if defined(SQLITE_TEST)
int sqlite3_open_file_count = 0;
#endif /* defined(SQLITE_TEST) */

/*
The default SQLite sqlite3_vfs implementations do not allocate
memory (actually, os_unix.c allocates a small amount of memory
from within OsOpen()), but some third-party implementations may.
So we test the effects of a malloc() failing and the sqlite3OsXXX()
function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
SQLite在默认情况下,sqlite3_vfs的实现不会分配内存。(实际上,os_unix.c从OsOpen中分配少量的内存),
但是一些第三方的实现可能会分配内存。所以我们测试分配内存失败的影响,
方法sqliet3OsXXX()使用DO_OS_MALLOC_TEST宏返回SQLITE_IOERR_NOMEN。
The following functions are instrumented for malloc() failure
testing:
接下来的方法用来指示分配失败的错误
sqlite3OsRead()
sqlite3OsWrite()
sqlite3OsSync()
sqlite3OsFileSize()
sqlite3OsLock()
sqlite3OsCheckReservedLock()
sqlite3OsFileControl()
sqlite3OsShmMap()
sqlite3OsOpen()
sqlite3OsDelete()
sqlite3OsAccess()
sqlite3OsFullPathname()

*/

#if defined(SQLITE_TEST)
int sqlite3_memdebug_vfs_oom_test = 1;//OutOfMemory测试
  #define DO_OS_MALLOC_TEST(x)                                       \
  if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \
    void *pTstAlloc = sqlite3Malloc(10);                             \
    if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT;                  \
    sqlite3_free(pTstAlloc);                                         \
  }
#else
  #define DO_OS_MALLOC_TEST(x)
#endif

/*
The following routines are convenience wrappers around methods
of the sqlite3_file object. This is mostly just syntactic sugar. All
of this would be completely automatic if SQLite were coded using
C++ instead of plain old C.
接下来的例程围绕sqlite3_file对象方法的便携包装器。这主要是语法糖。
如果使用C++而不是C来编码SQLite,那么所有的这些将会是完全自动的。
*/

void sqlite3OsClose(sqlite3_file *pId){//关闭一个文件描述符
  if( pId->pMethods ){//如果成员变量存在
    pId->pMethods->xClose(pId);//调用文件描述符的xClose方法来关闭这个文件描述符
    pId->pMethods = 0;//把这个成员变量赋为空
  }
}
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xRead(id, pBuf, amt, offset);
}
int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xWrite(id, pBuf, amt, offset);
}
int sqlite3OsTruncate(sqlite3_file *id, i64 size){
  return id->pMethods->xTruncate(id, size);
}
int sqlite3OsSync(sqlite3_file *id, int flags){
  DO_OS_MALLOC_TEST(id);
  return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
}
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xFileSize(id, pSize);
}
int sqlite3OsLock(sqlite3_file *id, int lockType){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xLock(id, lockType);
}
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
  return id->pMethods->xUnlock(id, lockType);
}
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xCheckReservedLock(id, pResOut);
}

/*
Use sqlite3OsFileControl() when we are doing something that might fail
and we need to know about the failures. Use sqlite3OsFileControlHint()
when simply tossing information over the wall to the VFS and we do not
really care if the VFS receives and understands the information since it
is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
routine has no return value since the return value would be meaningless.
当可能发生错误并且我们想要知道发生了什么错误的时候需要使用sqlite3OsFileControl方法。当只是将信息从墙上翻到 VFS 时,请使用 sqlite3OsFileControlHint(),我们并不真正关心 VFS 是否接收和理解这些信息,因为它只是一个提示,可以安全地忽略。sqlite3OsFileControlHint例程没有返回值,因为返回值没有意义。
*/

int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
  if( id->pMethods==0 ) return SQLITE_NOTFOUND;
#ifdef SQLITE_TEST
  if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
   && op!=SQLITE_FCNTL_LOCK_TIMEOUT
  ){
    /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
is using a regular VFS, it is called after the corresponding
transaction has been committed. Injecting a fault at this point
confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
but the transaction is committed anyway.
在提交阶段不会注入错误,因为假定SQLite正在使用一个常规的VFS,在事务被提交之后VFS被调
用。此时注入错误会使脚本混淆-Commit command返回SQLITE_NOMEN,但是事务无论如何都
将被提交。
The core must call OsFileControl() though, not OsFileControlHint(),
as if a custom VFS (e.g. zipvfs) returns an error here, it probably
means the commit really has failed and an error should be returned
尽管没有OsFileControlHint,核心必须调用OsFileControl方法,就像是自定义VFS(例如zipvfs)在这
里返回了错误,它大多意味着提交真的失败了并且这种失败还需要被返回。
to the user.  */
    DO_OS_MALLOC_TEST(id);
  }
#endif
  return id->pMethods->xFileControl(id, op, pArg);
}
void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
  if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
}

int sqlite3OsSectorSize(sqlite3_file *id){
  int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
  return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
  return id->pMethods->xDeviceCharacteristics(id);
}
#ifndef SQLITE_OMIT_WAL
int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
  return id->pMethods->xShmLock(id, offset, n, flags);
}
void sqlite3OsShmBarrier(sqlite3_file *id){
  id->pMethods->xShmBarrier(id);
}
int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
  return id->pMethods->xShmUnmap(id, deleteFlag);
}
int sqlite3OsShmMap(
  sqlite3_file *id,               /* Database file handle */
  int iPage,
  int pgsz,
  int bExtend,                    /* True to extend file if necessary */
  void volatile **pp              /* OUT: Pointer to mapping */
){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
}
#endif /* SQLITE_OMIT_WAL */

#if SQLITE_MAX_MMAP_SIZE>0
/* The real implementation of xFetch and xUnfetch */
int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xFetch(id, iOff, iAmt, pp);
}
int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
  return id->pMethods->xUnfetch(id, iOff, p);
}
#else
/* No-op stubs to use when memory-mapped I/O is disabled */
int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
  *pp = 0;
  return SQLITE_OK;
}
int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
  return SQLITE_OK;
}
#endif

/*
The next group of routines are convenience wrappers around the
VFS methods.
下一组例程是围绕VFS方法的便利包装器。
*/

int sqlite3OsOpen(
  sqlite3_vfs *pVfs, //这是xOpen方法的VFS
  const char *zPath, //要打开的文件的路径名
  sqlite3_file *pFile, //要填写的文件描述符
  int flags, //输入标志来控制opening
  int *pFlagsOut //输出标志返回到SQLite核心
){
  int rc;
  DO_OS_MALLOC_TEST(0);
  /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
  down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  reaching the VFS. 
0x87f7f是SQLIET_OPEN的掩码,可以被VFS底层解析。一些SQLITE_OPEN_标志
(例如SQLITE_OPEN_FULLMUTEX或者SQLITE_OPEN_SHAREDCACHE)在访问VFS之前就已经被锁住了
  */
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  DO_OS_MALLOC_TEST(0);
  assert( dirSync==0 || dirSync==1 );
  return pVfs->xDelete(pVfs, zPath, dirSync);
}
int sqlite3OsAccess(
  sqlite3_vfs *pVfs,
  const char *zPath,
  int flags,
  int *pResOut
){
  DO_OS_MALLOC_TEST(0);
  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}
int sqlite3OsFullPathname(
  sqlite3_vfs *pVfs,
  const char *zPath,
  int nPathOut,
  char *zPathOut
){
  DO_OS_MALLOC_TEST(0);
  zPathOut[0] = 0;
  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return pVfs->xDlOpen(pVfs, zPath);
}
void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  pVfs->xDlError(pVfs, nByte, zBufOut);
}
void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
  return pVfs->xDlSym(pVfs, pHdle, zSym);
}
void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
  pVfs->xDlClose(pVfs, pHandle);
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  return pVfs->xRandomness(pVfs, nByte, zBufOut);
}
int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
  return pVfs->xSleep(pVfs, nMicro);
}
int sqlite3OsGetLastError(sqlite3_vfs *pVfs){
  return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;
}
int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
  int rc;
  /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
  method to get the current date and time if that method is available
  (if iVersion is 2 or greater and the function pointer is not NULL) and
  will fall back to xCurrentTime() if xCurrentTimeInt64() is
  unavailable.
  如果方法可用,SQLite使用xCurrentTimeInt64方法来获取到当前的日期和时间。
  (如果iVersion>=2并且方法的指针不空)。如果xCurrentTimeInt64方法不可用,将会退化成xCurrentTime方法
  */
  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
    rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
  }else{
    double r;
    rc = pVfs->xCurrentTime(pVfs, &r);
    *pTimeOut = (sqlite3_int64)(r*86400000.0);
  }
  return rc;
}
int sqlite3OsOpenMalloc(
  sqlite3_vfs *pVfs,
  const char *zFile,
  sqlite3_file **ppFile,
  int flags,
  int *pOutFlags
){
  int rc;
  sqlite3_file *pFile;
  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
  if( pFile ){
    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
    if( rc!=SQLITE_OK ){//如果没有打开成功,就释放pFile文件描述符
      sqlite3_free(pFile);
    }else{//如果打开成功了,就更新ppFile指针,让指针ppFile指向的内容为pFile
      *ppFile = pFile;
    }
  }else{
    rc = SQLITE_NOMEM_BKPT;
  }
  return rc;
}
void sqlite3OsCloseFree(sqlite3_file *pFile){
  assert( pFile );
  sqlite3OsClose(pFile);//调用文件描述符自身的方法关闭文件描述符
  sqlite3_free(pFile);//释放文件描述符占用的内存
}

/*
This function is a wrapper around the OS specific implementation of
sqlite3_os_init(). The purpose of the wrapper is to provide the
ability to simulate a malloc failure, so that the handling of an
error in sqlite3_os_init() by the upper layers can be tested.
这个方法是一个围绕OS的sqliet3_os_init()特殊实现的封装。
这个封装的目的是提供模拟malloc失败的功能,所以在sqliet3_os_init上层可以
对在sqlite3_os_init()中出现的错误进行测试。
*/

int sqlite3OsInit(void){
  void *p = sqlite3_malloc(10);
  if( p==0 ) return SQLITE_NOMEM_BKPT;
  sqlite3_free(p);
  return sqlite3_os_init();
}

/*
The list of all registered VFS implementations.
所有已经注册的VFS实现的列表
*/

static sqlite3_vfs * SQLITE_WSD vfsList = 0;/*指针不可变,即vfsList不可变,但是该指针指向的内容可以变化。
所以把指针变量vfsList放入到全局变量中*/
#define vfsList GLOBAL(sqlite3_vfs *, vfsList)

/*
Locate a VFS by name. If no name is given, simply return the
first VFS on the list.
通过名字来定位VFS,如果没有给出名字,那么就返回列表中的第一个VFS
*/

sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
  sqlite3_vfs *pVfs = 0;
#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return 0;
#endif
#if SQLITE_THREADSAFE
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;//如果名字不相等,就跳出for循环
  }
  sqlite3_mutex_leave(mutex);
  return pVfs;
}

/*
Unlink a VFS from the linked list
从列表中将VFS去除
*/

static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
  if( pVfs==0 ){
    /* No-op */
  }else if( vfsList==pVfs ){//存在且相等
    vfsList = pVfs->pNext;//vfsList变为指向下一个
  }else if( vfsList ){//如果不相等,那么就在VFS列表中进行寻找
    sqlite3_vfs *p = vfsList;
    while( p->pNext && p->pNext!=pVfs ){//往后看一步
      p = p->pNext;
    }
    if( p->pNext==pVfs ){//如果后面的VFS存在,并且和pVfs不相等
      p->pNext = pVfs->pNext;//那么就把这个pVfs从列表中去除
    }
  }
}

/*
Register a VFS with the system. It is harmless to register the same
VFS multiple times. The new VFS becomes the default if makeDflt is
true.
在系统中注册VFS。多次注册一个相同的VFS是无害的。如果makeDflt为true,那么新的VFS将变成默认的
*/

int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
  MUTEX_LOGIC(sqlite3_mutex *mutex;)
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
#endif
  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  if( makeDflt || vfsList==0 ){//把pVfs作为默认的(放在第一个位置)
    pVfs->pNext = vfsList;
    vfsList = pVfs;
  }else{//把pVfs放在第二个位置
    pVfs->pNext = vfsList->pNext;
    vfsList->pNext = pVfs;
  }
  assert(vfsList);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}

/*
Unregister a VFS so that it is no longer accessible.
把一个VFS取消注册,那么它将不再可用
*/

int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
  MUTEX_LOGIC(sqlite3_mutex *mutex;)
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值