Sqlite源码解读(十二)
2021SC@SDUSC
第八篇到第十一篇讲解了所有sqlite3_file方法的实现。
接下来是Sqlite的OS Interface部分收尾阶段。
首先是定义了win32一些vfs方法的两个向量。
/*该向量定义了对Win 32的sqlite 3_file进行操作的所有方法。*/
static const sqlite3_io_methods winIoMethod = {
3, /* 版本号 */
winClose,
winRead,
winWrite,
winTruncate,
winSync,
winFileSize,
winLock,
winUnlock,
winCheckReservedLock,
winFileControl,
winSectorSize,
winDeviceCharacteristics,
winShmMap,
winShmLock,
winShmBarrier,
winShmUnmap,
winFetch,
winUnfetch
};
/*该向量定义了所有可以对Win 32的sqlite 3_file进行操作而不执行任何锁定的方法。*/
static const sqlite3_io_methods winIoNolockMethod = {
3, /* 版本号 */
winClose,
winRead,
winWrite,
winTruncate,
winSync,
winFileSize,
winNolockLock,
winNolockUnlock,
winNolockCheckReservedLock,
winFileControl,
winSectorSize,
winDeviceCharacteristics,
winShmMap,
winShmLock,
winShmBarrier,
winShmUnmap,
winFetch,
winUnfetch
};
static winVfsAppData winAppData = {
&winIoMethod, /* pMethod */
0, /* pAppData */
0 /* bNoLock */
};
static winVfsAppData winNolockAppData = {
&winIoNolockMethod, /* pMethod */
0, /* pAppData */
1 /* bNoLock */
};
/*此分区包含sqlite3_VFS对象上方法的实现*/
#if defined(__CYGWIN__)
/* 将文件名从任何底层操作系统支持的文件名转换为UTF-8。保存结果的空间是从malloc获得的,必须由调用函数释放*/
static char *winConvertToUtf8Filename(const void *zFilename){
char *zConverted = 0;
if( osIsNT() ){
zConverted = winUnicodeToUtf8(zFilename);
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
}
#endif
/* 调用者将处理内存不足 */
return zConverted;
}
#endif
/*是上面的逆操作。将UTF-8文件名转换为底层操作系统想要的任何形式的文件名。保存结果的空间同样是从malloc获得的,必须通过调用函数来释放。*/
static void *winConvertFromUtf8Filename(const char *zFilename){
void *zConverted = 0;
if( osIsNT() ){
zConverted = winUtf8ToUnicode(zFilename);
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
}
#endif
/* 调用者将处理内存不足 */
return zConverted;
}
如果指定的UTF-8字符串缓冲区以目录分隔符结束,或者成功地将一个字符添加到其中,则此函数返回非零。
static int winMakeEndInDirSep(int nBuf, char *zBuf){
if( zBuf ){
int nLen = sqlite3Strlen30(zBuf);
if( nLen>0 ){
if( winIsDirSep(zBuf[nLen-1]) ){
return 1;
}else if( nLen+1<nBuf ){
zBuf[nLen] = winGetDirSep();
zBuf[nLen+1] = '\0';
return 1;
}
}
}
return 0;
}
创建一个临时文件名,并将结果指针存储到pzBuf中。必须通过sqlite 3_free()释放pzBuf中返回的指针。
static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
static char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
int nMax, nBuf, nDir, nLen;
char *zBuf;
/*计算出有效的临时目录。首先,检查应用程序是否显式设置了一个;否则,使用操作系统配置的一个*/
nDir = nMax - (nPre + 15);
assert( nDir>0 );
if( sqlite3_temp_directory ){
int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
if( nDirLen>0 ){
if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
nDirLen++;
}
if( nDirLen>nDir ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
}
sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
}
}
如果指定的文件实际上是目录,则返回true。如果它不是目录,或者是任何类型的内存分配失败,则返回False。
static int winIsDir(const void *zConverted){
DWORD attr;
int rc = 0;
DWORD lastErrno;
if( osIsNT() ){
int cnt = 0;
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
GetFileExInfoStandard,
&sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
if( !rc ){
return 0; /* 无效名? */
}
attr = sAttrData.dwFileAttributes;
#if SQLITE_OS_WINCE==0
}else{
attr = osGetFileAttributesA((char*)zConverted);
#endif
}
return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
}
/*前瞻性参考*/
static int winAccess(
sqlite3_vfs *pVfs, /* 未用于win32 */
const char *zFilename, /* 要检查的文件名*/
int flags, /* 要对此文件进行测试的类型 */
int *pResOut /*退出:结果 */
);
/* 打开一个文件*/
static int winOpen(
sqlite3_vfs *pVfs, /* 用来获取最大路径长度和AppData */
const char *zName, /* 文件名 (UTF-8) */
sqlite3_file *id, /* 在这里写入SQLite 文件句柄 */
int flags, /* 打开模式标志 */
int *pOutFlags /* 状态返回标志 */
){
HANDLE h;
DWORD lastErrno = 0;
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
DWORD dwFlagsAndAttributes = 0;
#if SQLITE_OS_WINCE
int isTemp = 0;
#endif
winVfsAppData *pAppData;
winFile *pFile = (winFile*)id;
void *zConverted; /* OS编码中的文件名*/
const char *zUtf8Name = zName; /* UTF-8编码中的文件名 */
int cnt = 0;
/* 如果参数zPath是空指针, 则需要这个函数打开一个临时文件。用这个缓冲区来存储文件名 */
char *zTmpname = 0; /*用于临时文件名,如果需要的话 */
int rc = SQLITE_OK; /* 函数返回代码 */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
int eType = flags&0xFFFFFF00; /* 要打开的文件类型 */
#endif
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
#ifndef NDEBUG
int isOpenJournal = (isCreate && (
eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
#endif
OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
zUtf8Name, id, flags, pOutFlags));
检查以下语句为true
/*必须设置READWRITE 或READONLY标志之一*/
/*如果CREATE被设置,则READWRITE也必须被设置*/
/*如果EXCLUSIVE被设置,则CREATE也必须被设置*/
/*如果DELETEONCLOSE被设置,则CREATE也必须被设置*/
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
assert(isCreate==0 || isReadWrite);
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
主数据库、主日志、WAL文件和超级日志永远不会被自动删除,它们也不是临时文件
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
断言上层设置了“文件类型”标志之一
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
如果这个函数的第二个参数为空,则生成一个临时文件名使用
if( !zUtf8Name ){
assert( isDelete && !isOpenJournal );
rc = winGetTempname(pVfs, &zTmpname);
if( rc!=SQLITE_OK ){
OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
return rc;
}
zUtf8Name = zTmpname;
}
如果数据库文件名不是带参数的URI,则为双零终止。因此,它们总是可以传递给sqlite3_uri_parameter()。
assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );
把文件名转化为系统编码
zConverted = winConvertFromUtf8Filename(zUtf8Name);
if( zConverted==0 ){
sqlite3_free(zTmpname);
OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
return SQLITE_IOERR_NOMEM_BKPT;
}
if( winIsDir(zConverted) ){
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
return SQLITE_CANTOPEN_ISDIR;
}
if( isReadWrite ){
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
}else{
dwDesiredAccess = GENERIC_READ;
}
Sqlite源码解读(十二)相关推荐
- 价值4500的国际版多语言点赞抖音分享点赞任务平台源码(十二种语言)
介绍: 平台会员分享给我的,他自己搭建成功了,测试可用!我就不测试了,需要的拿! 九种语言 :西班牙语,泰语.日语,印度尼西亚语言.越南语言.英文.繁体中文,简体中文,印度语 前台支持更换5种颜色风格 ...
- 【vue-router源码】十二、useRoute、useRouter、useLink源码分析
[vue-rouer源码]系列文章 [vue-router源码]一.router.install解析 [vue-router源码]二.createWebHistory.createWebHashHis ...
- print python 带回车_python标准库threading源码解读【二】
紧接着上一篇文章继续解析源码 甘蔗:python标准库threading源码解读[一]zhuanlan.zhihu.com 目录 Event的介绍和用法 Event源码解析 以后的内容尽量少一点并且 ...
- x264源码解读(二)- VCL和NAL那些事
目录 ANNEXB vs. AVCC VCL vs. NAL signal函数响应键盘事件 收尾清理工作 x264的编码 ANNEXB vs. AVCC 今天我们继续来说一下x264结构中非常重要的属 ...
- JAVA ssm b2b2c多用户商城系统源码 (十二)springboot集成apidoc
首先声明下,apidoc是基于注释来生成文档的,它不基于任何框架,而且支持大多数编程语言,为了springboot系列的完整性,所以标了个题. 一.apidoc简介 apidoc通过在你代码的注释来生 ...
- ReactiveCocoa源码解读(二)
上一篇解读了ReactiveCocoa的三个重要的类的底层实现,本篇继续. 一.RACMulticastConnection 1.应用 RACMulticastConnection: 用于当一个信号被 ...
- Spring源码系列(十二)Spring创建Bean的过程(二)
1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...
- jpcsp源码解读之二:main函数与jpcsp的初始化流程
虽然这个软件是用java语言编写,面向对象,可是总要有个开始的入口,这里关心的就是,main函数在哪里. 似乎java中也可以没有main函数,也可能是我的错误认识.暂且不管,jpcsp中是有main ...
- 【转】ABP源码分析十二:本地化
本文逐个分析ABP中涉及到localization的接口和类,以及他们之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Local ...
- PhotoSwipe源码解读系列(二)
作者: 铁锚 日期: 2013年12月19日 说明: 本系列文章为草稿,等待后期完善.源码是jQuery版本的,code.photoswipe-3.0.5.js 1. 代码开头,就是一些版权申明,没什 ...
最新文章
- 研究生应当具备的三种基本技能
- BASIC-3 字母图形
- 基于单样本单统计推断-假设检验
- 两次被简书签约作者拉黑的经历
- 在matlab中实现PCA算法
- Flutter RotatedBox旋转容器
- DSP28335的RS232串口通讯试验
- 【头像变更】自己瞎做一个头像,放真实头像做头像虽然真诚,但是心里实在不想!
- 聚合直播,直播接口的使用
- 中控,中控系统,中控会议室
- 戒指你戴对了吗?Meet Surprise教你正确的戴法
- Shader学习7——法线贴图
- 怎么设置计算机网络打印机共享,打印机共享设置,告诉你打印机共享怎么设置...
- [ML-03] Matplotlib-3
- bind9 dlz mysql_源码安装Bind 9.10 正式版 开启DLZ数据库支持 和 数据库view查询
- 可以DIY装修的商城系统,你也能拥有
- php点击同一个按钮实现正序倒叙,php foreach正序倒序输出
- day2-----k8s集群管理常用知识点(1)
- 使用Pandas读取CSV文件:sep操作
- github Action使用
热门文章
- java程序毕设javaweb程序分享
- k8s --> 19 k8s集群down机
- 计算机设置位蓝牙播放xp,winxp系统电脑连接蓝牙耳机听音乐的方法
- 2016服务器文件夹权限设置,Server 2016特定用户权限划分,只显示有权限的文件夹,无法权限文件夹无法看到...
- k8s问题及解决方法
- python回溯算法_回溯算法经典问题及python代码实现
- ZOJ The Sum of Unitary Totient
- python爬取饿了么订单_python爬虫:爬取某图外卖数据有这篇文章就够了
- 2022-2028年全球与中国智能停车系统行业竞争格局与投资战略研究
- matlab绘制曲线相交的交点