📄 os_win.c
字号:
** non-zero, otherwise zero.*/static int winCheckReservedLock(OsFile *id){ int rc; winFile *pFile = (winFile*)id; assert( pFile!=0 ); if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); }else{ rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); } return rc;}/*** Lower the locking level on file descriptor id to locktype. locktype** must be either NO_LOCK or SHARED_LOCK.**** If the locking level of the file descriptor is already at or below** the requested locking level, this routine is a no-op.**** It is not possible for this routine to fail if the second argument** is NO_LOCK. If the second argument is SHARED_LOCK then this routine** might return SQLITE_IOERR;*/static int winUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; winFile *pFile = (winFile*)id; assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = SQLITE_IOERR_UNLOCK; } } if( type>=RESERVED_LOCK ){ UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } pFile->locktype = locktype; return rc;}/*** Turn a relative pathname into a full pathname. Return a pointer** to the full pathname stored in space obtained from sqliteMalloc().** The calling function is responsible for freeing this space once it** is no longer needed.*/char *sqlite3WinFullPathname(const char *zRelative){ char *zFull;#if defined(__CYGWIN__) int nByte; nByte = strlen(zRelative) + MAX_PATH + 1001; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;#elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ zFull = sqliteStrDup(zRelative);#else int nByte; void *zConverted; zConverted = convertUtf8Filename(zRelative); if( isNT() ){ WCHAR *zTemp; nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqliteFree(zConverted); return 0; } GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); sqliteFree(zConverted); zFull = unicodeToUtf8(zTemp); sqliteFree(zTemp); }else{ char *zTemp; nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqliteFree(zConverted); return 0; } GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); sqliteFree(zConverted); zFull = mbcsToUtf8(zTemp); sqliteFree(zTemp); }#endif return zFull;}/*** The fullSync option is meaningless on windows. This is a no-op.*/static void winSetFullSync(OsFile *id, int v){ return;}/*** Return the underlying file handle for an OsFile*/static int winFileHandle(OsFile *id){ return (int)((winFile*)id)->h;}/*** Return an integer that indices the type of lock currently held** by this handle. (Used for testing and analysis only.)*/static int winLockState(OsFile *id){ return ((winFile*)id)->locktype;}/*** Return the sector size in bytes of the underlying block device for** the specified file. This is almost always 512 bytes, but may be** larger for some devices.**** SQLite code assumes this function cannot fail. It also assumes that** if two files are created in the same file-system directory (i.e.** a database and it's journal file) that the sector size will be the** same for both.*/static int winSectorSize(OsFile *id){ return SQLITE_DEFAULT_SECTOR_SIZE;}/*** This vector defines all the methods that can operate on an OsFile** for win32.*/static const IoMethod sqlite3WinIoMethod = { winClose, winOpenDirectory, winRead, winWrite, winSeek, winTruncate, winSync, winSetFullSync, winFileHandle, winFileSize, winLock, winUnlock, winLockState, winCheckReservedLock, winSectorSize,};/*** Allocate memory for an OsFile. Initialize the new OsFile** to the value given in pInit and return a pointer to the new** OsFile. If we run out of memory, close the file and return NULL.*/static int allocateWinFile(winFile *pInit, OsFile **pId){ winFile *pNew; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ){ CloseHandle(pInit->h);#if OS_WINCE sqliteFree(pInit->zDeleteOnClose);#endif *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3WinIoMethod; pNew->locktype = NO_LOCK; pNew->sharedLockByte = 0; *pId = (OsFile*)pNew; OpenCounter(+1); return SQLITE_OK; }}#endif /* SQLITE_OMIT_DISKIO *//***************************************************************************** Everything above deals with file I/O. Everything that follows deals** with other miscellanous aspects of the operating system interface****************************************************************************/#if !defined(SQLITE_OMIT_LOAD_EXTENSION)/*** Interfaces for opening a shared library, finding entry points** within the shared library, and closing the shared library.*/void *sqlite3WinDlopen(const char *zFilename){ HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return 0; } if( isNT() ){ h = LoadLibraryW((WCHAR*)zConverted); }else{#if OS_WINCE return 0;#else h = LoadLibraryA((char*)zConverted);#endif } sqliteFree(zConverted); return (void*)h; }void *sqlite3WinDlsym(void *pHandle, const char *zSymbol){#if OS_WINCE /* The GetProcAddressA() routine is only available on wince. */ return GetProcAddressA((HANDLE)pHandle, zSymbol);#else /* All other windows platforms expect GetProcAddress() to take ** an Ansi string regardless of the _UNICODE setting */ return GetProcAddress((HANDLE)pHandle, zSymbol);#endif}int sqlite3WinDlclose(void *pHandle){ return FreeLibrary((HANDLE)pHandle);}#endif /* !SQLITE_OMIT_LOAD_EXTENSION *//*** Get information to seed the random number generator. The seed** is written into the buffer zBuf[256]. The calling function must** supply a sufficiently large buffer.*/int sqlite3WinRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence.* This makes the ** tests repeatable. */ memset(zBuf, 0, 256); GetSystemTime((LPSYSTEMTIME)zBuf); return SQLITE_OK;}/*** Sleep for a little while. Return the amount of time slept.*/int sqlite3WinSleep(int ms){ Sleep(ms); return ms;}/*** Static variables used for thread synchronization*/static int inMutex = 0;#ifdef SQLITE_W32_THREADS static DWORD mutexOwner; static CRITICAL_SECTION cs;#endif/*** The following pair of routines implement mutual exclusion for** multi-threaded processes. Only a single thread is allowed to** executed code that is surrounded by EnterMutex() and LeaveMutex().**** SQLite uses only a single Mutex. There is not much critical** code and what little there is executes quickly and without blocking.**** Version 3.3.1 and earlier used a simple mutex. Beginning with** version 3.3.2, a recursive mutex is required.*/void sqlite3WinEnterMutex(){#ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ static long lock = 0; if( InterlockedIncrement(&lock)==1 ){ InitializeCriticalSection(&cs); isInit = 1; }else{ Sleep(1); } } EnterCriticalSection(&cs); mutexOwner = GetCurrentThreadId();#endif inMutex++;}void sqlite3WinLeaveMutex(){ assert( inMutex ); inMutex--;#ifdef SQLITE_W32_THREADS assert( mutexOwner==GetCurrentThreadId() ); LeaveCriticalSection(&cs);#endif}/*** Return TRUE if the mutex is currently held.**** If the thisThreadOnly parameter is true, return true if and only if the** calling thread holds the mutex. If the parameter is false, return** true if any thread holds the mutex.*/int sqlite3WinInMutex(int thisThreadOnly){#ifdef SQLITE_W32_THREADS return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId());#else return inMutex>0;#endif}/*** The following variable, if set to a non-zero value, becomes the result** returned from sqlite3OsCurrentTime(). This is used for testing.*/#ifdef SQLITE_TESTint sqlite3_current_time = 0;#endif/*** Find the current time (in Universal Coordinated Time). Write the** current time and date as a Julian Day number into *prNow and** return 0. Return 1 if the time and date cannot be found.*/int sqlite3WinCurrentTime(double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now;#if OS_WINCE SYSTEMTIME time; GetSystemTime(&time); SystemTimeToFileTime(&time,&ft);#else GetSystemTimeAsFileTime( &ft );#endif now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;#ifdef SQLITE_TEST if( sqlite3_current_time ){ *prNow = sqlite3_current_time/86400.0 + 2440587.5; }#endif return 0;}/*** Remember the number of thread-specific-data blocks allocated.** Use this to verify that we are not leaking thread-specific-data.** Ticket #1601*/#ifdef SQLITE_TESTint sqlite3_tsd_count = 0;# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)#else# define TSD_COUNTER_INCR /* no-op */# define TSD_COUNTER_DECR /* no-op */#endif/*** If called with allocateFlag>1, then return a pointer to thread** specific data for the current thread. Allocate and zero the** thread-specific data if it does not already exist necessary.**** If called with allocateFlag==0, then check the current thread** specific data. Return it if it exists. If it does not exist,** then return NULL.**** If called with allocateFlag<0, check to see if the thread specific** data is allocated and is all zero. If it is then deallocate it.** Return a pointer to the thread specific data or NULL if it is** unallocated or gets deallocated.*/ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ static int key; static int keyInit = 0; static const ThreadData zeroData = {0}; ThreadData *pTsd; if( !keyInit ){ sqlite3OsEnterMutex(); if( !keyInit ){ key = TlsAlloc(); if( key==0xffffffff ){ sqlite3OsLeaveMutex(); return 0; } keyInit = 1; } sqlite3OsLeaveMutex(); } pTsd = TlsGetValue(key); if( allocateFlag>0 ){ if( !pTsd ){ pTsd = sqlite3OsMalloc( sizeof(zeroData) ); if( pTsd ){ *pTsd = zeroData; TlsSetValue(key, pTsd); TSD_COUNTER_INCR; } } }else if( pTsd!=0 && allocateFlag<0 && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ sqlite3OsFree(pTsd); TlsSetValue(key, 0); TSD_COUNTER_DECR; pTsd = 0; } return pTsd;}#endif /* OS_WIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -