2021SC@SDUSC
上次讲了各种字符串相互转换的方法及对应的公共包装器,接下来将讲解SQLITE_OS_WINCE,即sqlite在操作系统WinCE上的代码。
获取手柄上的锁
static void winceMutexAcquire(HANDLE h){
DWORD dwErr;
do {
dwErr = osWaitForSingleObject(h, INFINITE);
} while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
}
释放锁
#define winceMutexRelease(h) ReleaseMutex(h)
创建用于锁定文件描述符Pfile的互斥和共享内存
static int winceCreateLock(const char *zFilename, winFile *pFile){
LPWSTR zTok;
LPWSTR zName;
DWORD lastErrno;
BOOL bLogged = FALSE;
BOOL bInit = TRUE;
zName = winUtf8ToUnicode(zFilename);
if( zName==0 ){
/*内存不足*/
return SQLITE_IOERR_NOMEM_BKPT;
}
/*初始化本地锁数据*/
memset(&pFile->local, 0, sizeof(pFile->local));
替换文件名中的反斜杠,并将其小写以派生互斥名称。
zTok = osCharLowerW(zName);
for (;*zTok;zTok++){
if (*zTok == '\\') *zTok = '_';
}
创建或打开命名的互斥体
pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
if (!pFile->hMutex){
pFile->lastErrno = osGetLastError();
sqlite3_free(zName);
return winLogError(SQLITE_IOERR, pFile->lastErrno, "winceCreateLock1", zFilename);
}
/*在继续下一步之前获取互斥体*/
winceMutexAcquire(pFile->hMutex);
注:由于命名互斥体、信号量、文件映射等的名称都是区分大小写的,因此可以利用这一点,将互斥名称大写,并将其用作共享的文件映射名称。
osCharUpperW(zName);
pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(winceLock),
zName);
设置一个标志,指示我们是第一个创建内存的,因此它必须为零初始化
lastErrno = osGetLastError();
if (lastErrno == ERROR_ALREADY_EXISTS){
bInit = FALSE;
}
sqlite3_free(zName);
如果我们成功地创建了共享内存句柄,则映射它。
if( pFile->hShared ){
pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
/* 如果映射失败,则关闭共享内存句柄并清除它*/
if( !pFile->shared ){
pFile->lastErrno = osGetLastError();
winLogError(SQLITE_IOERR, pFile->lastErrno,
"winceCreateLock2", zFilename);
bLogged = TRUE;
osCloseHandle(pFile->hShared);
pFile->hShared = NULL;
}
}
/*如果无法创建共享内存,则关闭互斥锁并失败*/
if( pFile->hShared==NULL ){
if( !bLogged ){
pFile->lastErrno = lastErrno;
winLogError(SQLITE_IOERR, pFile->lastErrno,
"winceCreateLock3", zFilename);
bLogged = TRUE;
}
winceMutexRelease(pFile->hMutex);
osCloseHandle(pFile->hMutex);
pFile->hMutex = NULL;
return SQLITE_IOERR;
}
初始化共享内存(如果我们需要的话)
if( bInit ){
memset(pFile->shared, 0, sizeof(winceLock));
}
winceMutexRelease(pFile->hMutex);
return SQLITE_OK;
}
销毁winFile中处理WinCE锁的部分
static void winceDestroyLock(winFile *pFile){
if (pFile->hMutex){
/* 获取互斥体 */
winceMutexAcquire(pFile->hMutex);
/* 以下块可能应该在调试模式下断言,但它们将被清除,以防任何锁仍然处于打开状态*/
if (pFile->local.nReaders){
pFile->shared->nReaders --;
}
if (pFile->local.bReserved){
pFile->shared->bReserved = FALSE;
}
if (pFile->local.bPending){
pFile->shared->bPending = FALSE;
}
if (pFile->local.bExclusive){
pFile->shared->bExclusive = FALSE;
}
/* 取消引用并关闭共享内存句柄的副本。 */
osUnmapViewOfFile(pFile->shared);
osCloseHandle(pFile->hShared);
/* 完成互斥 */
winceMutexRelease(pFile->hMutex);
osCloseHandle(pFile->hMutex);
pFile->hMutex = NULL;
}
}
WindowsforCE中LockFile() API的一种实现
static BOOL winceLockFile(
LPHANDLE phFile,
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh
){
winFile *pFile = HANDLE_TO_WINFILE(phFile);
BOOL bReturn = FALSE;
UNUSED_PARAMETER(dwFileOffsetHigh);
UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
if (!pFile->hMutex) return TRUE;
winceMutexAcquire(pFile->hMutex);
/*独占锁*/
if (dwFileOffsetLow == (DWORD)SHARED_FIRST
&& nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
pFile->shared->bExclusive = TRUE;
pFile->local.bExclusive = TRUE;
bReturn = TRUE;
}
}
/*只读锁*/
else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
nNumberOfBytesToLockLow == 1){
if (pFile->shared->bExclusive == 0){
pFile->local.nReaders ++;
if (pFile->local.nReaders == 1){
pFile->shared->nReaders ++;
}
bReturn = TRUE;
}
}
/*挂起锁*/
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
&& nNumberOfBytesToLockLow == 1){
/* 如果还未获取挂起锁,则获取它 */
if (pFile->shared->bPending == 0) {
pFile->shared->bPending = TRUE;
pFile->local.bPending = TRUE;
bReturn = TRUE;
}
}
/*保留锁*/
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
&& nNumberOfBytesToLockLow == 1){
if (pFile->shared->bReserved == 0) {
pFile->shared->bReserved = TRUE;
pFile->local.bReserved = TRUE;
bReturn = TRUE;
}
}
winceMutexRelease(pFile->hMutex);
return bReturn;
}
对应地,以下是WindowsforCE中UnlockFile() API的一种实现
static BOOL winceUnlockFile(
LPHANDLE phFile,
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToUnlockLow,
DWORD nNumberOfBytesToUnlockHigh
){
winFile *pFile = HANDLE_TO_WINFILE(phFile);
BOOL bReturn = FALSE;
UNUSED_PARAMETER(dwFileOffsetHigh);
UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
if (!pFile->hMutex) return TRUE;
winceMutexAcquire(pFile->hMutex);
/*释放一个读卡器锁或者是独占锁*/
if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
/* Did we have an exclusive lock? */
if (pFile->local.bExclusive){
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
pFile->local.bExclusive = FALSE;
pFile->shared->bExclusive = FALSE;
bReturn = TRUE;
}
/*我们有一个读卡器锁吗*/
if (pFile->local.bExclusive){
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
pFile->local.bExclusive = FALSE;
pFile->shared->bExclusive = FALSE;
bReturn = TRUE;
}
/*释放挂起锁*/
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
&& nNumberOfBytesToUnlockLow == 1){
if (pFile->local.bPending){
pFile->local.bPending = FALSE;
pFile->shared->bPending = FALSE;
bReturn = TRUE;
}
}
/*释放保留锁*/
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
&& nNumberOfBytesToUnlockLow == 1){
if (pFile->local.bReserved) {
pFile->local.bReserved = FALSE;
pFile->shared->bReserved = FALSE;
bReturn = TRUE;
}
}
winceMutexRelease(pFile->hMutex);
return bReturn;
}
以上即是WinCE的特殊代码,SQLITE_OS_WINCE部分结束。