2021SC@SDUSC

上次讲解了SQLITE_OS_WINCE部分。接来下一组例程将实现sqlite3_io_method对象指定的I/O方法。

/*有些微软编译器缺少这个定义*/

#ifndef INVALID_SET_FILE_POINTER

# define INVALID_SET_FILE_POINTER ((DWORD)-1)

#endif

移动作为第一个参数传递的文件句柄的当前位置,以在文件中偏移iOffset。如果成功,则返回0。否则,设置pfile->lastErrno并返回非零。
static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){

#if !SQLITE_OS_WINRT

LONG upperBits;                  /*采用32位偏移量*/

LONG lowerBits;                  /*采用32位偏移量*/

DWORD dwRet;                  /*由SetFilePoter()返回值*/

DWORD lastErrno;                /*由 GetLastError() 返回值*/

OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));

upperBits = (LONG)((iOffset>>32) & 0x7fffffff);

lowerBits = (LONG)(iOffset & 0xffffffff);

API奇异点:如果成功,SetFilePoter()将返回一个dword,其中包含新文件偏移量的较低的32位。或者,如果失败,它返回INVALID_SET_FILE_POINTER。但是,根据MSDN,INVALID_SET_FILE_POINTER也可能是一个有效的新偏移量。因此,要确定是否实际发生了错误,还需要调用GetLastError()。

dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);

if( (dwRet==INVALID_SET_FILE_POINTER

&& ((lastErrno = osGetLastError())!=NO_ERROR)) ){

pFile->lastErrno = lastErrno;

winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,

"winSeekFile", pFile->zPath);

OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));

return 1;

}

OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));

return 0;

#else

/* 跟上面一样,但这个实现只适用于WinRT*/

LARGE_INTEGER x;                /* 新的偏移量 */

BOOL bRet;                      /* 由SetFilePointerEx() 返回值*/

x.QuadPart = iOffset;

bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);

if(!bRet){

pFile->lastErrno = osGetLastError();

winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,

"winSeekFile", pFile->zPath);

OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));

return 1;

}

OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));

return 0;

#endif

#if SQLITE_MAX_MMAP_SIZE>0

/*转发用于内存映射文件的VFS助手方法的引用*/

static int winMapfile(winFile*, sqlite3_int64);

static int winUnmapfile(winFile*);

#endif

将数据从文件中读取到缓冲区中。如果所有字节都已成功读取,则返回SQLITE_OK;如果出现任何错误,则返回SQLITE_IOERR。

static int winRead(

sqlite3_file *id,          /* 要读取的文件 */

void *pBuf,                /* 将内容写入此缓冲区 */

int amt,                   /* 要读取的字节数*/

sqlite3_int64 offset       /*开始阅读此偏移量 */

){

#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)

OVERLAPPED overlapped;          /* ReadFile的偏移量 */

#endif

winFile *pFile = (winFile*)id;          /*文件句柄 */

DWORD nRead;                    /* 实际从文件读取的字节数*/

int nRetry = 0;                     /* 重试次数 */

assert( id!=0 );

assert( amt>0 );

assert( offset>=0 );

SimulateIOError(return SQLITE_IOERR_READ);

OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "

"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,

pFile->h, pBuf, amt, offset, pFile->locktype));

#if SQLITE_MAX_MMAP_SIZE>0

/* 通过使用memcpy()从内存映射中传输数据来处理尽可能多的读取请求 */

if( offset<pFile->mmapSize ){

if( offset+amt <= pFile->mmapSize ){

memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);

OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",

osGetCurrentProcessId(), pFile, pFile->h));

return SQLITE_OK;

}else{

int nCopy = (int)(pFile->mmapSize - offset);

memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);

pBuf = &((u8 *)pBuf)[nCopy];

amt -= nCopy;

offset += nCopy;

}

}

#endif

将数据从缓冲区写入文件。在成功时返回SQLITE_OK或在失败时返回其他错误代码。(参照上面将数据从文件读取到缓冲区)

static int winWrite(

sqlite3_file *id,                  /* 要读取的文件 */

const void *pBuf,               /* 要写入的字节 */

int amt,                       /* 要读取的字节数*/

sqlite3_int64 offset             /*开始阅读此偏移量 */

){

int rc = 0;                     /* 如果发生错误则为True,否则为False*/

winFile *pFile = (winFile*)id;      /* 文件句柄 */

int nRetry = 0;                 /* 重试次数 */

assert( amt>0 );

assert( pFile );

SimulateIOError(return SQLITE_IOERR_WRITE);

SimulateDiskfullError(return SQLITE_FULL);

OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "

"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,

pFile->h, pBuf, amt, offset, pFile->locktype));

将打开的文件截断到指定的大小。

static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){

winFile *pFile = (winFile*)id;      /*文件句柄对象 */

int rc = SQLITE_OK;             /* 此函数的返回代码 */

DWORD lastErrno;

#if SQLITE_MAX_MMAP_SIZE>0

sqlite3_int64 oldMmapSize;

if( pFile->nFetchOut>0 ){

return SQLITE_OK;   ①

}

#endif

assert( pFile );

SimulateIOError(return SQLITE_IOERR_TRUNCATE);

OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",

osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));

①:如果有未完成的内存映射页,则文件截断是无操作的。这是因为截断文件意味着暂时取消映射文件,这可能会从现有游标下删除内存,可能导致增量真空,而不是截断文件,唯一可行的工作是将截断推迟到所有对内存映射内容的引用都关闭之后。这是可行的,因此,现在决定,只要有挂起的读操作,就把截断文件变成不操作。

/*SetEndOfFile()在成功时返回非零,在失败时返回零。*/

if( winSeekFile(pFile, nByte) ){

rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,

"winTruncate1", pFile->zPath);

}else if( 0==osSetEndOfFile(pFile->h) &&

((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){

pFile->lastErrno = lastErrno;

rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,

"winTruncate2", pFile->zPath);

}

Sqlite源码解读(八)相关推荐

  1. Sqlite源码解读(十二)

    2021SC@SDUSC 第八篇到第十一篇讲解了所有sqlite3_file方法的实现. 接下来是Sqlite的OS Interface部分收尾阶段. 首先是定义了win32一些vfs方法的两个向量. ...

  2. Sqlite源码解读(九)

    2021SC@SDUSC 上次讲解了实现sqlite3_io_method对象指定的I/O方法的一组例程.接来下一组例程将执行检查所有进程是否在指定文件上有特定锁.设置锁.解锁等操作. 首先我们先了解 ...

  3. Sqlite源码解读(十一)

    2021SC@SDUSC 接着winShmNode继续讲. PShmNode上的引用计数已经在winShmEnterMutex()互斥体的覆盖下递增,并且指向pShmNode的新对象的指针已经设置.剩 ...

  4. Sqlite源码解读(十)

    2021SC@SDUSC 接着LockFile继续讲解关于锁的内容. 如果*pArg最初是负的,那么这就是一个查询.将*pArg设置为1或0,这取决于是否设置了pfile->ctrlFlags的 ...

  5. rocketmq的broker源码解读八(MappedFile与MappedFileQueue)

    8)MappedFile与MappedFileQueue 8.1)MappedFile内存映射类 commitLog,consumeQueue,indexFile文件都是基于mappedFile去管理 ...

  6. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(下)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.初始化特定上下文子类中的其他特殊bean 2.1.初始化主体资源 2.2.创建web服务 三.检查监听器bean并注册它们 四.实 ...

  7. spring源码解读系列(八):观察者模式--spring监听器详解

    一.前言 在前面的文章spring源码解读系列(七)中,我们继续剖析了spring的核心refresh()方法中的registerBeanPostProcessors(beanFactory)(完成B ...

  8. 网页游戏开发例子php,PHP网页游戏学习之Xnova(ogame)源码解读(八)

    这篇文章主要介绍了PHP网页游戏Xnova(ogame)源码解读的公共函数部分,需要的朋友可以参考下 十一.公共函数(functions.php) 本来打算写建筑页面的分析,但是建筑页面东西比较多,一 ...

  9. Alamofire源码解读系列(九)之响应封装(Response)

    本篇主要带来Alamofire中Response的解读 前言 在每篇文章的前言部分,我都会把我认为的本篇最重要的内容提前讲一下.我更想同大家分享这些顶级框架在设计和编码层次究竟有哪些过人的地方?当然, ...

最新文章

  1. Activity在有Dialog时按Home键的生命周期
  2. python【力扣LeetCode算法题库】16- 最接近的三数之和
  3. SHA256安全散列算法
  4. python编程入门详解_python编程入门知识练习
  5. 【大数据】如何用形象的比喻描述大数据的技术生态?Hadoop、Hive、Spark 之间是什么关系?
  6. rtems 4.11 RTC驱动 (arm, beagle)
  7. 【转载】Java方向如何准备BAT技术面试答案(汇总版)
  8. 马来游记(2)- 漂浮云顶间。。。
  9. Python学习入门基础教程(learning Python)--5.4 Python读文件详解
  10. .net环境下如何使用MySql数据库
  11. ASP.NET MVC学习系列 WebAPI初探
  12. 第九届河南省程序设计大赛-----表达式求值-------递归+模拟
  13. 上百套HTML5登录页面模板
  14. ( 方框打勾 java_Java 11手册:Java 11是否在所有正确的方框中打勾?
  15. IPSec:IKEv2协议详解
  16. 快速实现B站(B ili b ili)手机缓存m4s文件转mp4(批量升级版)
  17. iOS 联系在线客服功能
  18. 【kali Linux 的1024种玩法】一.在VMware Workstation上安装Kali Linux 2020.1(超详细!)
  19. 华硕主板无盘启动bios设置_【华硕主板bios启动顺序】华硕主板bois启动项_华硕主板bios硬盘启动...
  20. 1 Introduction  介绍

热门文章

  1. 苹果系统安装 php,mysql
  2. VTK CT重建(一) MPR 多层面重建 四视图
  3. web服务器市场占有率最新排行
  4. STM32F407ZET6最小系统板
  5. 程序猿技术不是你的全部
  6. 计算机硬盘的主流型号,四款主流2.5英寸笔记本机械硬盘性能对比
  7. (搬运工)推荐!国外程序员整理的 C++ 资源大全
  8. cad-家装平面图(三)
  9. Python并行处理充分利用CPU实现加速
  10. 【项目经验】——ASP.NET页面间传值