diff options
author | drh <drh@noemail.net> | 2005-11-30 03:20:31 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2005-11-30 03:20:31 +0000 |
commit | 054889ec6d2df4754468d2acfe6c92973f54ea2c (patch) | |
tree | 0dd1f8d5015e064fd666cb6253ad10c202ba4e34 /src/os_win.c | |
parent | 392b3ddf2ebe613d701ff3f912ac04b294ce0070 (diff) | |
download | sqlite-054889ec6d2df4754468d2acfe6c92973f54ea2c.tar.gz sqlite-054889ec6d2df4754468d2acfe6c92973f54ea2c.zip |
Restructure the OS interface yet again. This time make the OsFile object
a virtual base class which is subclassed for unix, windows, and the crash
test simulator. Add the new file "os.c" for common os layer code. Move
all OS-specific routines into the sqlite3Os structure. (CVS 2795)
FossilOrigin-Name: bd8740d1aecba69e1b5d64d43db07e8ad8841f07
Diffstat (limited to 'src/os_win.c')
-rw-r--r-- | src/os_win.c | 269 |
1 files changed, 141 insertions, 128 deletions
diff --git a/src/os_win.c b/src/os_win.c index b07115ff1..be561b75f 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -35,19 +35,18 @@ #include "os_common.h" /* -** The OsFile structure is a operating-system independing representation -** of an open file handle. It is defined differently for each architecture. -** -** This is the definition for Win32. +** The winFile structure is a subclass of OsFile specific to the win32 +** portability layer. */ -struct OsFile { +typedef struct winFile winFile; +struct winFile { + IoMethod const *pMethod;/* Must be first */ HANDLE h; /* Handle for accessing the file */ unsigned char locktype; /* Type of lock currently held on this file */ short sharedLockByte; /* Randomly chosen byte used as a shared lock */ }; - /* ** Do not include any of the File I/O interface procedures if the ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database @@ -167,22 +166,8 @@ static int winFileExists(const char *zFilename){ return exists; } - -/* -** 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 OsFile *allocateOsFile(OsFile *pInit){ - OsFile *pNew; - pNew = sqliteMalloc( sizeof(OsFile) ); - if( pNew==0 ){ - CloseHandle(pInit->h); - }else{ - *pNew = *pInit; - } - return pNew; -} +/* Forward declaration */ +int allocateWinFile(winFile *pInit, OsFile **pId); /* ** Attempt to open a file for both reading and writing. If that @@ -202,7 +187,7 @@ static int winOpenReadWrite( OsFile **pId, int *pReadonly ){ - OsFile f; + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); assert( *pId==0 ); @@ -263,13 +248,7 @@ static int winOpenReadWrite( f.locktype = NO_LOCK; f.sharedLockByte = 0; TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); - *pId = allocateOsFile(&f); - if( *pId==0 ){ - return SQLITE_NOMEM; - }else{ - OpenCounter(+1); - return SQLITE_OK; - } + return allocateWinFile(&f, pId); } @@ -288,7 +267,7 @@ static int winOpenReadWrite( ** On failure, return SQLITE_CANTOPEN. */ static int winOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ - OsFile f; + winFile f; HANDLE h; int fileflags; WCHAR *zWide = utf8ToUnicode(zFilename); @@ -326,13 +305,7 @@ static int winOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ f.locktype = NO_LOCK; f.sharedLockByte = 0; TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); - *pId = allocateOsFile(&f); - if( *pId==0 ){ - return SQLITE_NOMEM; - }else{ - OpenCounter(+1); - return SQLITE_OK; - } + return allocateWinFile(&f, pId); } /* @@ -343,7 +316,7 @@ static int winOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ ** On failure, return SQLITE_CANTOPEN. */ static int winOpenReadOnly(const char *zFilename, OsFile **pId){ - OsFile f; + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); assert( *pId==0 ); @@ -374,13 +347,7 @@ static int winOpenReadOnly(const char *zFilename, OsFile **pId){ f.locktype = NO_LOCK; f.sharedLockByte = 0; TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); - *pId = allocateOsFile(&f); - if( *pId==0 ){ - return SQLITE_NOMEM; - }else{ - OpenCounter(+1); - return SQLITE_OK; - } + return allocateWinFile(&f, pId); } /* @@ -400,8 +367,8 @@ static int winOpenReadOnly(const char *zFilename, OsFile **pId){ ** *id unchanged. */ static int winOpenDirectory( - const char *zDirname, - OsFile *id + OsFile *id, + const char *zDirname ){ return SQLITE_OK; } @@ -450,7 +417,7 @@ static int winTempFileName(char *zBuf){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; - if( !sqlite3Io.xFileExists(zBuf) ) break; + if( !sqlite3Os.xFileExists(zBuf) ) break; } TRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; @@ -460,11 +427,12 @@ static int winTempFileName(char *zBuf){ ** Close a file. */ static int winClose(OsFile **pId){ - if( *pId ){ - TRACE2("CLOSE %d\n", (*pId)->h); - CloseHandle((*pId)->h); + winFile *pFile; + if( pId && (pFile = (winFile*)*pId)!=0 ){ + TRACE2("CLOSE %d\n", pFile->h); + CloseHandle(pFile->h); OpenCounter(-1); - sqliteFree(*pId); + sqliteFree(pFile); *pId = 0; } return SQLITE_OK; @@ -479,8 +447,8 @@ static int winRead(OsFile *id, void *pBuf, int amt){ DWORD got; assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - TRACE3("READ %d lock=%d\n", id->h, id->locktype); - if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ + TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ @@ -500,9 +468,10 @@ static int winWrite(OsFile *id, const void *pBuf, int amt){ assert( id!=0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; - TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); + TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); assert( amt>0 ); - while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ + while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } @@ -531,8 +500,8 @@ static int winSeek(OsFile *id, i64 offset){ if( offset ) SimulateDiskfullError #endif SEEK(offset/1024 + 1); - rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); - TRACE3("SEEK %d %lld\n", id->h, offset); + rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); + TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ return SQLITE_FULL; } @@ -544,8 +513,8 @@ static int winSeek(OsFile *id, i64 offset){ */ static int winSync(OsFile *id, int dataOnly){ assert( id!=0 ); - TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); - if( FlushFileBuffers(id->h) ){ + TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( FlushFileBuffers(((winFile*)id)->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; @@ -567,10 +536,10 @@ static int winSyncDirectory(const char *zDirname){ static int winTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; assert( id!=0 ); - TRACE3("TRUNCATE %d %lld\n", id->h, nByte); + TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); SimulateIOError(SQLITE_IOERR); - SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); - SetEndOfFile(id->h); + SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); + SetEndOfFile(((winFile*)id)->h); return SQLITE_OK; } @@ -581,7 +550,7 @@ static int winFileSize(OsFile *id, i64 *pSize){ DWORD upperBits, lowerBits; assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - lowerBits = GetFileSize(id->h, &upperBits); + lowerBits = GetFileSize(((winFile*)id)->h, &upperBits); *pSize = (((i64)upperBits)<<32) + lowerBits; return SQLITE_OK; } @@ -591,7 +560,7 @@ static int winFileSize(OsFile *id, i64 *pSize){ ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ -static int getReadLock(OsFile *id){ +static int getReadLock(winFile *id){ int res; if( isNT() ){ OVERLAPPED ovlp; @@ -611,12 +580,12 @@ static int getReadLock(OsFile *id){ /* ** Undo a readlock */ -static int unlockReadLock(OsFile *id){ +static int unlockReadLock(winFile *pFile){ int res; if( isNT() ){ - res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); }else{ - res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0); + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); } return res; } @@ -677,35 +646,36 @@ static int winLock(OsFile *id, int locktype){ int res = 1; /* Result of a windows lock call */ int newLocktype; /* Set id->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; - assert( id!=0 ); + assert( pFile!=0 ); TRACE5("LOCK %d %d was %d(%d)\n", - id->h, locktype, id->locktype, id->sharedLockByte); + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ - if( id->locktype>=locktype ){ + if( pFile->locktype>=locktype ){ return SQLITE_OK; } /* Make sure the locking sequence is correct */ - assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of ** the PENDING_LOCK byte is temporary. */ - newLocktype = id->locktype; - if( id->locktype==NO_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ int cnt = 3; - while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ @@ -718,8 +688,8 @@ static int winLock(OsFile *id, int locktype){ /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res ){ - assert( id->locktype==NO_LOCK ); - res = getReadLock(id); + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); if( res ){ newLocktype = SHARED_LOCK; } @@ -728,8 +698,8 @@ static int winLock(OsFile *id, int locktype){ /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res ){ - assert( id->locktype==SHARED_LOCK ); - res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; } @@ -745,10 +715,10 @@ static int winLock(OsFile *id, int locktype){ /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ - assert( id->locktype>=SHARED_LOCK ); - res = unlockReadLock(id); + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); TRACE2("unreadlock = %d\n", res); - res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -760,7 +730,7 @@ static int winLock(OsFile *id, int locktype){ ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then @@ -769,11 +739,11 @@ static int winLock(OsFile *id, int locktype){ if( res ){ rc = SQLITE_OK; }else{ - TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, + TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype); rc = SQLITE_BUSY; } - id->locktype = newLocktype; + pFile->locktype = newLocktype; return rc; } @@ -784,17 +754,18 @@ static int winLock(OsFile *id, int locktype){ */ static int winCheckReservedLock(OsFile *id){ int rc; - assert( id!=0 ); - if( id->locktype>=RESERVED_LOCK ){ + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; - TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); }else{ - rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; - TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); } return rc; } @@ -813,29 +784,30 @@ static int winCheckReservedLock(OsFile *id){ static int winUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; - assert( id!=0 ); + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); - TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, - id->locktype, id->sharedLockByte); - type = id->locktype; + TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ - UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - if( locktype==SHARED_LOCK && !getReadLock(id) ){ + 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; } } if( type>=RESERVED_LOCK ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ - unlockReadLock(id); + unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } - id->locktype = locktype; + pFile->locktype = locktype; return rc; } @@ -887,7 +859,7 @@ static void winSetFullSync(OsFile *id, int v){ ** Return the underlying file handle for an OsFile */ static int winFileHandle(OsFile *id){ - return (int)id->h; + return (int)((winFile*)id)->h; } /* @@ -895,39 +867,51 @@ static int winFileHandle(OsFile *id){ ** by this handle. (Used for testing and analysis only.) */ static int winLockState(OsFile *id){ - return id->locktype; + return ((winFile*)id)->locktype; } - /* -** This is the structure that defines all of the I/O routines. +** This vector defines all the methods that can operate on an OsFile +** for win32. */ -struct sqlite3IoVtbl sqlite3Io = { - winDelete, - winFileExists, - winOpenReadWrite, - winOpenExclusive, - winOpenReadOnly, - winOpenDirectory, - winSyncDirectory, - winTempFileName, - winIsDirWritable, +static const IoMethod sqlite3WinIoMethod = { winClose, + winOpenDirectory, winRead, winWrite, winSeek, - winSync, winTruncate, + winSync, + winSetFullSync, + winFileHandle, winFileSize, - winFullPathname, winLock, winUnlock, - winCheckReservedLock, - winSetFullSync, - winFileHandle, winLockState, + winCheckReservedLock, }; +/* +** 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. +*/ +int allocateWinFile(winFile *pInit, OsFile **pId){ + winFile *pNew; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ){ + CloseHandle(pInit->h); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3WinIoMethod; + *pId = pNew; + return SQLITE_OK; + } +} + + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** ** Everything above deals with file I/O. Everything that follows deals @@ -939,7 +923,7 @@ struct sqlite3IoVtbl sqlite3Io = { ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3OsRandomSeed(char *zBuf){ +static int winRandomSeed(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 @@ -960,7 +944,7 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. */ -int sqlite3OsSleep(int ms){ +static int winSleep(int ms){ Sleep(ms); return ms; } @@ -981,7 +965,7 @@ static int inMutex = 0; ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. */ -void sqlite3OsEnterMutex(){ +static void winEnterMutex(){ #ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ @@ -998,7 +982,7 @@ void sqlite3OsEnterMutex(){ assert( !inMutex ); inMutex = 1; } -void sqlite3OsLeaveMutex(){ +static void winLeaveMutex(){ assert( inMutex ); inMutex = 0; #ifdef SQLITE_W32_THREADS @@ -1019,7 +1003,7 @@ int sqlite3_current_time = 0; ** 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 sqlite3OsCurrentTime(double *prNow){ +static int winCurrentTime(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). @@ -1036,4 +1020,33 @@ int sqlite3OsCurrentTime(double *prNow){ return 0; } +/* Macro used to comment out routines that do not exists when there is +** no disk I/O +*/ +#ifdef SQLITE_OMIT_DISKIO +# define IF_DISKIO(X) 0 +#else +# define IF_DISKIO(X) X +#endif + +/* +** This is the structure that defines all of the I/O routines. +*/ +struct sqlite3OsVtbl sqlite3Os = { + IF_DISKIO( winOpenReadWrite ), + IF_DISKIO( winOpenExclusive ), + IF_DISKIO( winOpenReadOnly ), + IF_DISKIO( winDelete ), + IF_DISKIO( winFileExists ), + IF_DISKIO( winFullPathname ), + IF_DISKIO( winIsDirWritable ), + IF_DISKIO( winSyncDirectory ), + IF_DISKIO( winTempFileName ), + winRandomSeed, + winSleep, + winCurrentTime, + winEnterMutex, + winLeaveMutex, +}; + #endif /* OS_WIN */ |