2021SC@SDUSC
本篇开始解读代码:
开头一堆注释主要说明此文件是基于Windows NT操作系统内核(区分于Unix)
开始分析代码:
#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
# error "WAL mode requires support from the Windows NT kernel, compile\
with SQLITE_OMIT_WAL."
如果不是windows NT 操作系统且没有引入WAL模式,则会报错。
关于WAL模式:Write ahead logging.WAL是一种日志模式,在3.7版本后被引入,用来保证日志一定先于对应的脏页落盘。Sqlite日志文件主要有DELETE和WAL两种。WAL较于DELETE的优点是:1.WAL支持读写并发,而DELETE读写互斥;2.WAL只需一次fsync调用,而且WAL的顺序写日志优于DELETE 的离散写日志。
#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
# error "Memory mapped files require support from the Windows NT kernel,\
compile with SQLITE_MAX_MMAP_SIZE=0."
#endif
mmap是一个内存映射文件的方法,将该文件的磁盘地址映射到进程的虚拟地址。这样进程就可以用指针读写操作该内存,省去了对read()和write()系统函数的调用。
#ifndef NTDDI_WIN8
# define NTDDI_WIN8 0x06020000
#endif
#ifndef NTDDI_WINBLUE
# define NTDDI_WINBLUE 0x06030000
#endif
#ifndef NTDDI_WINTHRESHOLD
# define NTDDI_WINTHRESHOLD 0x06040000
#endif
定义需要用到的SDK版本的常数
SDK包含了开发本Windows版本所需的函数、常数、API、相关工具及示例。
#ifndef SQLITE_WIN32_MAX_PATH_BYTES
# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4)
#endif
#ifndef SQLITE_WINNT_MAX_PATH_BYTES
# define SQLITE_WINNT_MAX_PATH_BYTES \
(sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
#endif
对Win32路径名长度规定,每个字符用4个字节表示,采用UTF8编码。
对WinNT路径名长度规定,用Wchar长度乘unicode最大char长度。
#if SQLITE_OS_WINCE
typedef struct winceLock {
int nReaders; /* Number of reader locks obtained */
BOOL bPending; /* Indicates a pending lock has been obtained */
BOOL bReserved; /* Indicates a reserved lock has been obtained */
BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
} winceLock;
#endif
WINCE是一个操作界面源于Windows的嵌入式新型操作系统。
创建wincelock结构体,并指出三个布尔变量。
typedef struct winFile winFile;
struct winFile {
const sqlite3_io_methods *pMethod; /*** Must be first ***/
sqlite3_vfs *pVfs; /* The VFS used to open this file */
HANDLE h; /* Handle for accessing the file */
u8 locktype; /* Type of lock currently held on this file */
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
u8 ctrlFlags; /* Flags. See WINFILE_* below */
DWORD lastErrno; /* The Windows errno from the last I/O error */
#ifndef SQLITE_OMIT_WAL
winShm *pShm; /* Instance of shared memory on this file */
#endif
const char *zPath; /* Full pathname of this file */
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
HANDLE hMutex; /* Mutex used to control access to shared lock */
HANDLE hShared; /* Shared memory segment used for locking */
winceLock local; /* Locks obtained by this instance of winFile */
winceLock *shared; /* Global shared lock memory for the file */
#endif
#if SQLITE_MAX_MMAP_SIZE>0
int nFetchOut; /* Number of outstanding xFetch references */
HANDLE hMap; /* Handle for accessing memory mapping */
void *pMapRegion; /* Area memory mapped */
sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
};
typedef struct winVfsAppData winVfsAppData;
struct winVfsAppData {
const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */
void *pAppData; /* The extra pAppData, if any. */
BOOL bNoLock; /* Non-zero if locking is disabled. */
};
创建了winFile结构体
注册时首先声明VFS接口函数,在tvfs_vfs结构体里
static sqlite3_vfs tvfs_vfs
在pAppData记录原来默认的VFS
pVfs->pAppData = (void *)p;//把信息存到pVfs->pAppData里
void *pAppData:该指针指向一个存储有各种文件io操作方法的结构体地址
在Win下默认使用的是win32 vfs,VFS首先要注册,使用sqlite3_vfs_register函数。
接下来是tcl命令参数。假设注册VFS时新建的命令是tvfs,使用格式为:tvfs shm FILE VALUE。
db eval {CREATE TABLE t1(a TEXT, b INTEGER)} #新建表
db eval {
INSERT INTO t1 VALUES('one',1);
INSERT INTO t1 VALUES('two',2);
INSERT INTO t1 VALUES(NULL,3);
} #插入行
puts [db eval {SELECT * FROM t1}] #显示表的所有行并输出结果