ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Sqlite源码解读(十)

2021-11-24 14:59:28  阅读:183  来源: 互联网

标签:Sqlite int pShmNode SQLITE winShmNode 解读 源码 static sqlite3


2021SC@SDUSC

接着LockFile继续讲解关于锁的内容。

如果*pArg最初是负的,那么这就是一个查询。将*pArg设置为1或0,这取决于是否设置了pfile->ctrlFlags的位掩码。如果*pArg为0或1,则清除或设置pfile->ctrlFlags的掩码位。

static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){

  if( *pArg<0 ){

    *pArg = (pFile->ctrlFlags & mask)!=0;

  }else if( (*pArg)==0 ){

    pFile->ctrlFlags &= ~mask;

  }else{

    pFile->ctrlFlags |= mask;

  }

}

转发对用于临时文件的VFS助手方法的引用

static int winGetTempname(sqlite3_vfs *, char **);

static int winIsDir(const void *);

static BOOL winIsLongPathPrefix(const char *);

static BOOL winIsDriveLetterAndColon(const char *);

返回指定文件的基础块设备的扇区大小(以字节为单位)。SQLite代码假定此函数不会失败。它还假设如果在同一个文件系统目录中创建了两个文件,则这两个文件的扇区大小相同。

static int winSectorSize(sqlite3_file *id){

  (void)id;

  return SQLITE_DEFAULT_SECTOR_SIZE;

}

返回设备的特征向量

static int winDeviceCharacteristics(sqlite3_file *id){

  winFile *p = (winFile*)id;

  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |

         ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);

}

帮助函数获得并放弃全局互斥。全局互斥被用来保护文件所使用的winLockInfo对象,所有这些都可以由多个线程共享。

static sqlite3_mutex *winBigLock = 0;

static void winShmEnterMutex(void){

  sqlite3_mutex_enter(winBigLock);

}

static void winShmLeaveMutex(void){

  sqlite3_mutex_leave(winBigLock);

}

#ifndef NDEBUG

static int winShmMutexHeld(void) {

  return sqlite3_mutex_held(winBigLock);

}

#endif

所有winShmNode对象的全局数组。在读取或写入此列表时,winShmMutexHeld()必须为true。

struct winShm {

  winShmNode *pShmNode;      /* 底层 winShmNode 对象 */

  winShm *pNext;             /* 使用相同的winShmNode的下一个winshm */

  u8 hasMutex;               /* 如果持有winShmNode互斥体,则为true */

  u16 sharedMask;            /* 共享锁的掩码 */

  u16 exclMask;              /* 独占锁的掩码 */

#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)

  u8 id;                     /* 使用winShmNode 的连接的ID*/

#endif

};

对以ofst开始的所有n个字节应用咨询锁。

#define WINSHM_UNLCK  1

#define WINSHM_RDLCK  2

#define WINSHM_WRLCK  3

static int winShmSystemLock(

  winShmNode *pFile,  /* 将锁应用到这个打开的共享内存段*/

  int lockType,        /* WINSHM_UNLCK、WINSHM_RDLCK 或 WINSHM_WRLCK类型*/

  int ofst,            /*偏移量到要锁定或解锁的第一个字节 */

  int nByte           /* 要锁定或解锁的字节数 */

){

  int rc = 0;          /* Lock/UnlockFileEx()的结果代码 */

  /*调用方序列化对winShmNode对象的访问*/

  assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );

  OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",

           pFile->hFile.h, lockType, ofst, nByte));

  /* 释放或获取系统级锁*/

  if( lockType==WINSHM_UNLCK ){

    rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);

  }else{

    /* Initialize the locking parameters */

    DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;

    if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;

    rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);

  }

  if( rc!= 0 ){

    rc = SQLITE_OK;

  }else{

    pFile->lastErrno =  osGetLastError();

    rc = SQLITE_BUSY;

  }

  OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",

           pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :

           "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));

  return rc;

}

清除winShmNode.nRef==0的所有条目的winShmNodeList列表。

这不是一个VFS共享内存方法;它是一个由VFS共享内存方法调用的实用函数。

static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){

  winShmNode **pp;

  winShmNode *p;

  assert( winShmMutexHeld() );

  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",

           osGetCurrentProcessId(), deleteFlag));

  pp = &winShmNodeList;

  while( (p = *pp)!=0 ){

    if( p->nRef==0 ){

      int i;

      if( p->mutex ){ sqlite3_mutex_free(p->mutex); }

      for(i=0; i<p->nRegion; i++){

        BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);

        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",

                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));

        UNUSED_VARIABLE_VALUE(bRc);

        bRc = osCloseHandle(p->aRegion[i].hMap);

        OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",

                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));

        UNUSED_VARIABLE_VALUE(bRc);

      }

      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){

        SimulateIOErrorBenign(1);

        winClose((sqlite3_file *)&p->hFile);

        SimulateIOErrorBenign(0);

      }

      if( deleteFlag ){

        SimulateIOErrorBenign(1);

        sqlite3BeginBenignMalloc();

        winDelete(pVfs, p->zFilename, 0);

        sqlite3EndBenignMalloc();

        SimulateIOErrorBenign(0);

      }

      *pp = p->pNext;

      sqlite3_free(p->aRegion);

      sqlite3_free(p);

    }else{

      pp = &p->pNext;

    }

  }

}

尚未对SHM文件pShmNode执行DMS锁。现在就试着把它拿走。如果成功,返回SQLITE_OK,否则返回SQLite错误代码。如果DMS由于这是readonly_shm=1连接而无法锁定,并且没有其他进程已经持有锁,则返回SQLITE_READONLY_CANTINIT并设置pShmNode->isUnlock=1。

static int winLockSharedMemory(winShmNode *pShmNode){

  int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);

  if( rc==SQLITE_OK ){

    if( pShmNode->isReadonly ){

      pShmNode->isUnlocked = 1;

      winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);

      return SQLITE_READONLY_CANTINIT;

    }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){

      winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);

      return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),

                         "winLockSharedMemory", pShmNode->zFilename);

    }

  }

  if( rc==SQLITE_OK ){

    winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);

  }

  return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);

}

打开与数据库文件pDbFd关联的共享内存区域。当打开一个新的共享内存文件时,如果当前没有打开该文件的其他实例,则该文件必须被截断为零长度或清除其标头。

static int winOpenSharedMemory(winFile *pDbFd){

  struct winShm *p;                   /* 要打开的连接*/

  winShmNode *pShmNode = 0;         /*底层mmapped文件*/

  int rc = SQLITE_OK;                 /* 结果代码*/

  winShmNode *pNew;                  /*新分配的winShmNode */

  int nName;                        /*zName的大小(以字节为单位)*/

  assert( pDbFd->pShm==0 );         /*以前没有打开 */

/*为新sqlite3_SHM对象分配空间。此外,还为新的winShmNode和文件名分配空间。*/

p = sqlite3MallocZero( sizeof(*p) );

  if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;

  nName = sqlite3Strlen30(pDbFd->zPath);

  pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );

  if( pNew==0 ){

    sqlite3_free(p);

    return SQLITE_IOERR_NOMEM_BKPT;

  }

  pNew->zFilename = (char*)&pNew[1];

  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);

  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);

查看是否存在可以使用的现有winShmNode。如果当前不存在匹配的winShmNode,则创建一个新的。

winShmEnterMutex();

  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){

    /*TBD需要在这里找到更好的匹配。也许使用file_id_ANY_DIR_INFO结构。*/  if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;

  }

  if( pShmNode ){

    sqlite3_free(pNew);

  }else{

    int inFlags = SQLITE_OPEN_WAL;

int outFlags = 0;

/*使新连接成为winShmNode的子节点*/

p->pShmNode = pShmNode;

#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)

  p->id = pShmNode->nextShmId++;

#endif

  pShmNode->nRef++;

  pDbFd->pShm = p;

  winShmLeaveMutex();

标签:Sqlite,int,pShmNode,SQLITE,winShmNode,解读,源码,static,sqlite3
来源: https://blog.csdn.net/qq_53825872/article/details/121515677

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有