diff options
author | drh <drh@noemail.net> | 2005-11-29 03:13:21 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2005-11-29 03:13:21 +0000 |
commit | 9cbe635219f7f157766e532ec6dd766841c5661c (patch) | |
tree | 081aaf3872f721c7df6a0279f65d453ecb9461af /src | |
parent | 9267bdcecdb472ee6d302e25fc27b6e936eb57a6 (diff) | |
download | sqlite-9cbe635219f7f157766e532ec6dd766841c5661c.tar.gz sqlite-9cbe635219f7f157766e532ec6dd766841c5661c.zip |
Make the OsFile structure opaque with its internal structure known only to
the appropriate os_*.c implementation. Omit the os_unix.h and os_win.h
include files. The crash tests are broken by this patch. (CVS 2791)
FossilOrigin-Name: 058f31753871b16b40fe4048e3adcee411e0f87d
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 19 | ||||
-rw-r--r-- | src/os.h | 35 | ||||
-rw-r--r-- | src/os_unix.c | 248 | ||||
-rw-r--r-- | src/os_win.c | 149 | ||||
-rw-r--r-- | src/pager.c | 178 | ||||
-rw-r--r-- | src/test1.c | 13 | ||||
-rw-r--r-- | src/test2.c | 9 | ||||
-rw-r--r-- | src/test6.c | 35 | ||||
-rw-r--r-- | src/vdbeaux.c | 11 |
9 files changed, 436 insertions, 261 deletions
diff --git a/src/expr.c b/src/expr.c index 24def4f39..50edb902d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.239 2005/11/28 12:36:36 drh Exp $ +** $Id: expr.c,v 1.240 2005/11/29 03:13:22 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1274,17 +1274,16 @@ struct QueryCoder { /* -** Generate code for subqueries and IN operators. +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: ** -** IN operators comes in two forms: +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery +** x IN (4,5,11) -- IN operator with list on right-hand side +** x IN (SELECT a FROM b) -- IN operator with subquery on the right ** -** expr IN (exprlist) -** and -** expr IN (SELECT ...) -** -** The first form is handled by creating a set holding the list -** of allowed values. The second form causes the SELECT to generate -** a temporary table. +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. */ #ifndef SQLITE_OMIT_SUBQUERY void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ @@ -43,24 +43,17 @@ #endif /* -** Invoke the appropriate operating-system specific header file. +** The OsFile object describes an open disk file in an OS-dependent way. */ -#if OS_ALT -# include "os_alt.h" -#endif -#if OS_UNIX -# include "os_unix.h" -#endif -#if OS_WIN -# include "os_win.h" -#endif +typedef struct OsFile OsFile; -/* os_other.c and os_other.h are not delivered with SQLite. These files -** are place-holders that can be filled in by third-party developers to -** implement backends to their on proprietary operating systems. +/* +** Define the maximum size of a temporary filename */ -#if OS_OTHER -# include "os_other.h" +#if OS_WIN +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#else +# define SQLITE_TEMPNAME_SIZE 200 #endif /* If the SET_FULLSYNC macro is not defined above, then make it @@ -179,14 +172,14 @@ extern unsigned int sqlite3_pending_byte; extern struct sqlite3IoVtbl { int (*xDelete)(const char*); int (*xFileExists)(const char*); - int (*xOpenReadWrite)(const char*, OsFile*, int*); - int (*xOpenExclusive)(const char*, OsFile*, int); - int (*xOpenReadOnly)(const char*, OsFile*); + int (*xOpenReadWrite)(const char*, OsFile**, int*); + int (*xOpenExclusive)(const char*, OsFile**, int); + int (*xOpenReadOnly)(const char*, OsFile**); int (*xOpenDirectory)(const char*, OsFile*); int (*xSyncDirectory)(const char*); int (*xTempFileName)(char*); int (*xIsDirWritable)(char*); - int (*xClose)(OsFile*); + int (*xClose)(OsFile**); int (*xRead)(OsFile*, void*, int amt); int (*xWrite)(OsFile*, const void*, int amt); int (*xSeek)(OsFile*, i64 offset); @@ -197,7 +190,9 @@ extern struct sqlite3IoVtbl { int (*xLock)(OsFile*, int); int (*xUnlock)(OsFile*, int); int (*xCheckReservedLock)(OsFile *id); - void (*xCopyOsFile)(OsFile *pDest, OsFile *pSrc); + void (*xSetFullSync)(OsFile *id, int setting); + int (*xFileHandle)(OsFile *id); + int (*xLockState)(OsFile *id); } sqlite3Io; /* The interface for file I/O is above. Other miscellaneous functions diff --git a/src/os_unix.c b/src/os_unix.c index b6ef2081f..cf8552770 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -15,12 +15,82 @@ #include "sqliteInt.h" #include "os.h" #if OS_UNIX /* This file is used on unix only */ +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif - +/* +** standard include files. +*/ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> #include <time.h> #include <sys/time.h> #include <errno.h> -#include <unistd.h> + +/* +** Macros used to determine whether or not to use threads. The +** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for +** Posix threads and SQLITE_W32_THREADS is defined if we are +** synchronizing using Win32 threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# include <pthread.h> +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + + + +/* +** The OsFile structure is a operating-system dependent representation +** of an open file handle. It is defined differently for each architecture. +** +** This is the definition for Unix. +** +** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK, +** PENDING_LOCK or EXCLUSIVE_LOCK. +*/ +struct OsFile { + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; /* Use F_FULLSYNC if available */ + int dirfd; /* File descriptor for the directory */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* The thread authorized to use this OsFile */ +#endif +}; + /* ** Do not include any of the File I/O interface procedures if the @@ -82,8 +152,8 @@ ** by mistake. */ #if defined(SQLITE_UNIX_THREADS) && !defined(SQLITE_ALLOW_XTHREAD_CONNECTIONS) -# define SET_THREADID(X) X->tid = pthread_self() -# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self())) +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (!pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 @@ -494,6 +564,22 @@ static int unixFileExists(const char *zFilename){ } /* +** 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 ){ + close(pInit->h); + }else{ + *pNew = *pInit; + } + return pNew; +} + +/* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. @@ -508,23 +594,25 @@ static int unixFileExists(const char *zFilename){ */ static int unixOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ int rc; - assert( !id->isOpen ); - id->dirfd = -1; - SET_THREADID(id); - id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, + OsFile f; + + assert( 0==*pId ); + f.dirfd = -1; + SET_THREADID(&f); + f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ #ifdef EISDIR if( errno==EISDIR ){ return SQLITE_CANTOPEN; } #endif - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; @@ -532,17 +620,21 @@ static int unixOpenReadWrite( *pReadonly = 0; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + f.locktype = 0; + TRACE3("OPEN %-3d %s\n", f.h, zFilename); + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } @@ -560,36 +652,42 @@ static int unixOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -static int unixOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; - assert( !id->isOpen ); + OsFile f; + + assert( 0==*pId ); if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, + SET_THREADID(&f); + f.dirfd = -1; + f.h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); unlink(zFilename); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; + f.locktype = 0; if( delFlag ){ unlink(zFilename); } - TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename); + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } /* @@ -599,27 +697,33 @@ static int unixOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -static int unixOpenReadOnly(const char *zFilename, OsFile *id){ +static int unixOpenReadOnly(const char *zFilename, OsFile **pId){ int rc; - assert( !id->isOpen ); - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + OsFile f; + + assert( 0==*pId ); + SET_THREADID(&f); + f.dirfd = -1; + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + f.locktype = 0; + TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename); + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } /* @@ -631,7 +735,7 @@ static int unixOpenReadOnly(const char *zFilename, OsFile *id){ ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** -** On success, a handle for a previously open file is at *id is +** On success, a handle for a previously open file at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** @@ -642,7 +746,7 @@ static int unixOpenDirectory( const char *zDirname, OsFile *id ){ - if( !id->isOpen ){ + if( id==0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; @@ -727,7 +831,7 @@ static int unixIsDirWritable(char *zBuf){ */ static int unixRead(OsFile *id, void *pBuf, int amt){ int got; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); TIMER_START; got = read(id->h, pBuf, amt); @@ -748,7 +852,7 @@ static int unixRead(OsFile *id, void *pBuf, int amt){ */ static int unixWrite(OsFile *id, const void *pBuf, int amt){ int wrote = 0; - assert( id->isOpen ); + assert( id ); assert( amt>0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; @@ -770,7 +874,7 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){ ** Move the read/write pointer in a file. */ static int unixSeek(OsFile *id, i64 offset){ - assert( id->isOpen ); + assert( id ); SEEK(offset/1024 + 1); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError @@ -864,7 +968,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ ** will not roll back - possibly leading to database corruption. */ static int unixSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); TRACE2("SYNC %-3d\n", id->h); if( full_fsync(id->h, id->fullSync, dataOnly) ){ @@ -913,7 +1017,7 @@ static int unixSyncDirectory(const char *zDirname){ ** Truncate an open file to a specified size */ static int unixTruncate(OsFile *id, i64 nByte){ - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; } @@ -923,7 +1027,7 @@ static int unixTruncate(OsFile *id, i64 nByte){ */ static int unixFileSize(OsFile *id, i64 *pSize){ struct stat buf; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); if( fstat(id->h, &buf)!=0 ){ return SQLITE_IOERR; @@ -941,7 +1045,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){ static int unixCheckReservedLock(OsFile *id){ int r = 0; - assert( id->isOpen ); + assert( id ); if( CHECK_THREADID(id) ) return SQLITE_MISUSE; sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ @@ -1056,7 +1160,7 @@ static int unixLock(OsFile *id, int locktype){ struct flock lock; int s; - assert( id->isOpen ); + assert( id ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype), locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt ,getpid() ); @@ -1213,7 +1317,7 @@ static int unixUnlock(OsFile *id, int locktype){ struct flock lock; int rc = SQLITE_OK; - assert( id->isOpen ); + assert( id ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, id->pLock->locktype, id->pLock->cnt, getpid()); if( CHECK_THREADID(id) ) return SQLITE_MISUSE; @@ -1291,8 +1395,9 @@ static int unixUnlock(OsFile *id, int locktype){ /* ** Close a file. */ -static int unixClose(OsFile *id){ - if( !id->isOpen ) return SQLITE_OK; +static int unixClose(OsFile **pId){ + OsFile *id = *pId; + if( !id ) return SQLITE_OK; if( CHECK_THREADID(id) ) return SQLITE_MISUSE; sqlite3Io.xUnlock(id, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); @@ -1324,6 +1429,8 @@ static int unixClose(OsFile *id){ id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); + sqliteFree(id); + *pId = 0; return SQLITE_OK; } @@ -1351,10 +1458,25 @@ static char *unixFullPathname(const char *zRelative){ } /* -** Make a copy of an OsFile object. +** Change the value of the fullsync flag in the given file descriptor. +*/ +static void unixSetFullSync(OsFile *id, int v){ + id->fullSync = v; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int unixFileHandle(OsFile *id){ + return id->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) */ -static void unixCopyOsFile(OsFile *pDest, OsFile *pSrc){ - *pDest = *pSrc; +static int unixLockState(OsFile *id){ + return id->locktype; } /* @@ -1381,7 +1503,9 @@ struct sqlite3IoVtbl sqlite3Io = { unixLock, unixUnlock, unixCheckReservedLock, - unixCopyOsFile, + unixSetFullSync, + unixFileHandle, + unixLockState, }; diff --git a/src/os_win.c b/src/os_win.c index 45ff7af62..e1833b766 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -16,6 +16,7 @@ #include "os.h" #if OS_WIN /* This file is used for windows only */ +#include <windows.h> #include <winbase.h> #ifdef __CYGWIN__ @@ -35,6 +36,20 @@ #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. +*/ +struct OsFile { + 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 ** will be in-memory only) @@ -153,6 +168,23 @@ 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; +} + /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, @@ -168,12 +200,13 @@ static int winFileExists(const char *zFilename){ */ static int winOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ + OsFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ | GENERIC_WRITE, @@ -227,13 +260,17 @@ static int winOpenReadWrite( *pReadonly = 0; } } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; + f.locktype = NO_LOCK; + f.sharedLockByte = 0; TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } @@ -251,11 +288,12 @@ static int winOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +static int winOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ + OsFile f; HANDLE h; int fileflags; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId == 0 ); if( delFlag ){ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE; @@ -285,13 +323,17 @@ static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; + f.locktype = NO_LOCK; + f.sharedLockByte = 0; TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } /* @@ -301,10 +343,11 @@ static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -static int winOpenReadOnly(const char *zFilename, OsFile *id){ +static int winOpenReadOnly(const char *zFilename, OsFile **pId){ + OsFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ, @@ -328,13 +371,17 @@ static int winOpenReadOnly(const char *zFilename, OsFile *id){ if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; + f.locktype = NO_LOCK; + f.sharedLockByte = 0; TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + *pId = allocateOsFile(&f); + if( *pId==0 ){ + return SQLITE_NOMEM; + }else{ + OpenCounter(+1); + return SQLITE_OK; + } } /* @@ -413,12 +460,13 @@ static int winTempFileName(char *zBuf){ /* ** Close a file. */ -static int winClose(OsFile *id){ - if( id->isOpen ){ - TRACE2("CLOSE %d\n", id->h); - CloseHandle(id->h); +static int winClose(OsFile **pId){ + if( *pId ){ + TRACE2("CLOSE %d\n", (*pId)->h); + CloseHandle((*pId)->h); OpenCounter(-1); - id->isOpen = 0; + sqliteFree(*pId); + *pId = 0; } return SQLITE_OK; } @@ -430,7 +478,7 @@ static int winClose(OsFile *id){ */ static int winRead(OsFile *id, void *pBuf, int amt){ DWORD got; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); TRACE3("READ %d lock=%d\n", id->h, id->locktype); if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ @@ -450,7 +498,7 @@ static int winRead(OsFile *id, void *pBuf, int amt){ static int winWrite(OsFile *id, const void *pBuf, int amt){ int rc = 0; DWORD wrote; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); @@ -479,7 +527,7 @@ static int winSeek(OsFile *id, i64 offset){ LONG upperBits = offset>>32; LONG lowerBits = offset & 0xffffffff; DWORD rc; - assert( id->isOpen ); + assert( id!=0 ); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif @@ -496,7 +544,7 @@ static int winSeek(OsFile *id, i64 offset){ ** Make sure all writes to a particular file are committed to disk. */ static int winSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); + assert( id!=0 ); TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); if( FlushFileBuffers(id->h) ){ return SQLITE_OK; @@ -519,7 +567,7 @@ static int winSyncDirectory(const char *zDirname){ */ static int winTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; - assert( id->isOpen ); + assert( id!=0 ); TRACE3("TRUNCATE %d %lld\n", id->h, nByte); SimulateIOError(SQLITE_IOERR); SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); @@ -532,7 +580,7 @@ static int winTruncate(OsFile *id, i64 nByte){ */ static int winFileSize(OsFile *id, i64 *pSize){ DWORD upperBits, lowerBits; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); lowerBits = GetFileSize(id->h, &upperBits); *pSize = (((i64)upperBits)<<32) + lowerBits; @@ -631,7 +679,7 @@ static int winLock(OsFile *id, int locktype){ int newLocktype; /* Set id->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ - assert( id->isOpen ); + assert( id!=0 ); TRACE5("LOCK %d %d was %d(%d)\n", id->h, locktype, id->locktype, id->sharedLockByte); @@ -737,7 +785,7 @@ static int winLock(OsFile *id, int locktype){ */ static int winCheckReservedLock(OsFile *id){ int rc; - assert( id->isOpen ); + assert( id!=0 ); if( id->locktype>=RESERVED_LOCK ){ rc = 1; TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); @@ -766,7 +814,7 @@ static int winCheckReservedLock(OsFile *id){ static int winUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; - assert( id->isOpen ); + assert( id!=0 ); assert( locktype<=SHARED_LOCK ); TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, id->locktype, id->sharedLockByte); @@ -830,10 +878,25 @@ static char *winFullPathname(const char *zRelative){ } /* -** Make a copy of an OsFile object. +** 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)id->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) */ -static void winCopyOsFile(OsFile *pDest, OsFile *pSrc){ - *pDest = *pSrc; +static int winLockState(OsFile *id){ + return id->locktype; } @@ -861,7 +924,9 @@ struct sqlite3IoVtbl sqlite3Io = { winLock, winUnlock, winCheckReservedLock, - winCopyOsFile, + winSetFullSync, + winFileHandle, + winLockState, }; #endif /* SQLITE_OMIT_DISKIO */ diff --git a/src/pager.c b/src/pager.c index 17a5c3192..1b6dc8846 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.220 2005/11/26 03:51:19 drh Exp $ +** @(#) $Id: pager.c,v 1.221 2005/11/29 03:13:22 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -52,8 +52,8 @@ ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile ** struct as it's argument. */ -#define PAGERID(p) (p->fd.h) -#define FILEHANDLEID(fd) (fd.h) +#define PAGERID(p) FILEHANDLEID(&(p)->fd) +#define FILEHANDLEID(fd) (sqlite3Io.xFileHandle(&fd)) /* ** The page cache as a whole is always in one of the following @@ -262,8 +262,8 @@ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ - OsFile fd, jfd; /* File descriptors for database and journal */ - OsFile stfd; /* File descriptor for the statement subjournal*/ + OsFile *fd, *jfd; /* File descriptors for database and journal */ + OsFile *stfd; /* File descriptor for the statement subjournal*/ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ @@ -590,7 +590,7 @@ static int seekJournalHdr(Pager *pPager){ assert( offset>=c ); assert( (offset-c)<JOURNAL_HDR_SZ(pPager) ); pPager->journalOff = offset; - return sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff); + return sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); } /* @@ -626,33 +626,33 @@ static int writeJournalHdr(Pager *pPager){ ** Actually maybe the whole journal header should be delayed until that ** point. Think about this. */ - rc = sqlite3Io.xWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3Io.xWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); if( rc==SQLITE_OK ){ /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ - rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); + rc = write32bits(pPager->jfd, pPager->noSync ? 0xffffffff : 0); } if( rc==SQLITE_OK ){ /* The random check-hash initialiser */ sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - rc = write32bits(&pPager->jfd, pPager->cksumInit); + rc = write32bits(pPager->jfd, pPager->cksumInit); } if( rc==SQLITE_OK ){ /* The initial database size */ - rc = write32bits(&pPager->jfd, pPager->dbSize); + rc = write32bits(pPager->jfd, pPager->dbSize); } if( rc==SQLITE_OK ){ /* The assumed sector size for this process */ - rc = write32bits(&pPager->jfd, pPager->sectorSize); + rc = write32bits(pPager->jfd, pPager->sectorSize); } /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ - rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff-1); + rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff-1); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xWrite(&pPager->jfd, "\000", 1); + rc = sqlite3Io.xWrite(pPager->jfd, "\000", 1); } } return rc; @@ -690,20 +690,20 @@ static int readJournalHdr( return SQLITE_DONE; } - rc = sqlite3Io.xRead(&pPager->jfd, aMagic, sizeof(aMagic)); + rc = sqlite3Io.xRead(pPager->jfd, aMagic, sizeof(aMagic)); if( rc ) return rc; if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ return SQLITE_DONE; } - rc = read32bits(&pPager->jfd, pNRec); + rc = read32bits(pPager->jfd, pNRec); if( rc ) return rc; - rc = read32bits(&pPager->jfd, &pPager->cksumInit); + rc = read32bits(pPager->jfd, &pPager->cksumInit); if( rc ) return rc; - rc = read32bits(&pPager->jfd, pDbSize); + rc = read32bits(pPager->jfd, pDbSize); if( rc ) return rc; /* Update the assumed sector-size to match the value used by @@ -712,11 +712,11 @@ static int readJournalHdr( ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ - rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize); + rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize); if( rc ) return rc; pPager->journalOff += JOURNAL_HDR_SZ(pPager); - rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); return rc; } @@ -761,19 +761,19 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ } pPager->journalOff += (len+20); - rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager)); + rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager)); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xWrite(&pPager->jfd, zMaster, len); + rc = sqlite3Io.xWrite(pPager->jfd, zMaster, len); if( rc!=SQLITE_OK ) return rc; - rc = write32bits(&pPager->jfd, len); + rc = write32bits(pPager->jfd, len); if( rc!=SQLITE_OK ) return rc; - rc = write32bits(&pPager->jfd, cksum); + rc = write32bits(pPager->jfd, cksum); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3Io.xWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); pPager->needSync = !pPager->noSync; return rc; } @@ -851,7 +851,7 @@ static void pager_reset(Pager *pPager){ if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; @@ -923,7 +923,7 @@ static int pager_unwritelock(Pager *pPager){ assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } - rc = sqlite3Io.xUnlock(&pPager->fd, SHARED_LOCK); + rc = sqlite3Io.xUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; @@ -978,7 +978,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ /* useCksum should be true for the main journal and false for ** statement journals. Verify that this is always the case */ - assert( jfd == (useCksum ? &pPager->jfd : &pPager->stfd) ); + assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); rc = read32bits(jfd, &pgno); @@ -1033,9 +1033,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 ); TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ - rc = sqlite3Io.xSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); + rc = sqlite3Io.xSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xWrite(&pPager->fd, aData, pPager->pageSize); + rc = sqlite3Io.xWrite(pPager->fd, aData, pPager->pageSize); } if( pPg ) pPg->dirty = 0; } @@ -1075,18 +1075,17 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ static int pager_delmaster(const char *zMaster){ int rc; int master_open = 0; - OsFile master; + OsFile *master = 0; char *zMasterJournal = 0; /* Contents of master journal file */ i64 nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ - memset(&master, 0, sizeof(master)); rc = sqlite3Io.xOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3Io.xFileSize(&master, &nMasterJournal); + rc = sqlite3Io.xFileSize(master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ @@ -1101,7 +1100,7 @@ static int pager_delmaster(const char *zMaster){ rc = SQLITE_NOMEM; goto delmaster_out; } - rc = sqlite3Io.xRead(&master, zMasterJournal, nMasterJournal); + rc = sqlite3Io.xRead(master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; @@ -1111,16 +1110,15 @@ static int pager_delmaster(const char *zMaster){ ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ - OsFile journal; + OsFile *journal = 0; int c; - memset(&journal, 0, sizeof(journal)); rc = sqlite3Io.xOpenReadOnly(zJournal, &journal); if( rc!=SQLITE_OK ){ goto delmaster_out; } - rc = readMasterJournal(&journal, &zMasterPtr); + rc = readMasterJournal(journal, &zMasterPtr); sqlite3Io.xClose(&journal); if( rc!=SQLITE_OK ){ goto delmaster_out; @@ -1165,9 +1163,9 @@ static int pager_reload_cache(Pager *pPager){ char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ - rc = sqlite3Io.xSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); + rc = sqlite3Io.xSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xRead(&pPager->fd, zBuf, pPager->pageSize); + rc = sqlite3Io.xRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; @@ -1198,7 +1196,7 @@ static int pager_reload_cache(Pager *pPager){ */ static int pager_truncate(Pager *pPager, int nPage){ assert( pPager->state>=PAGER_EXCLUSIVE ); - return sqlite3Io.xTruncate(&pPager->fd, pPager->pageSize*(i64)nPage); + return sqlite3Io.xTruncate(pPager->fd, pPager->pageSize*(i64)nPage); } /* @@ -1266,7 +1264,7 @@ static int pager_playback(Pager *pPager){ ** the journal is empty. */ assert( pPager->journalOpen ); - rc = sqlite3Io.xFileSize(&pPager->jfd, &szJ); + rc = sqlite3Io.xFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1276,7 +1274,7 @@ static int pager_playback(Pager *pPager){ ** present on disk, then the journal is not hot and does not need to be ** played back. */ - rc = readMasterJournal(&pPager->jfd, &zMaster); + rc = readMasterJournal(pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK || (zMaster && !sqlite3Io.xFileExists(zMaster)) ){ sqliteFree(zMaster); @@ -1284,7 +1282,7 @@ static int pager_playback(Pager *pPager){ if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } - sqlite3Io.xSeek(&pPager->jfd, 0); + sqlite3Io.xSeek(pPager->jfd, 0); pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns @@ -1327,13 +1325,13 @@ static int pager_playback(Pager *pPager){ pPager->dbSize = mxPg; } - /* rc = sqlite3Io.xSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ + /* rc = sqlite3Io.xSeek(pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ if( rc!=SQLITE_OK ) goto end_playback; /* Copy original pages out of the journal and back into the database file. */ for(i=0; i<nRec; i++){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; @@ -1400,7 +1398,7 @@ static int pager_stmt_playback(Pager *pPager){ #ifndef NDEBUG { i64 os_szJ; - rc = sqlite3Io.xFileSize(&pPager->jfd, &os_szJ); + rc = sqlite3Io.xFileSize(pPager->jfd, &os_szJ); if( rc!=SQLITE_OK ) return rc; assert( szJ==os_szJ ); } @@ -1426,7 +1424,7 @@ static int pager_stmt_playback(Pager *pPager){ /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); - sqlite3Io.xSeek(&pPager->stfd, 0); + sqlite3Io.xSeek(pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the @@ -1435,7 +1433,7 @@ static int pager_stmt_playback(Pager *pPager){ ** journals. */ for(i=nRec-1; i>=0; i--){ - rc = pager_playback_one_page(pPager, &pPager->stfd, 0); + rc = pager_playback_one_page(pPager, pPager->stfd, 0); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1448,7 +1446,7 @@ static int pager_stmt_playback(Pager *pPager){ ** If it is not zero, then Pager.stmtHdrOff is the offset to the start ** of the first journal header written during this statement transaction. */ - rc = sqlite3Io.xSeek(&pPager->jfd, pPager->stmtJSize); + rc = sqlite3Io.xSeek(pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } @@ -1456,7 +1454,7 @@ static int pager_stmt_playback(Pager *pPager){ pPager->cksumInit = pPager->stmtCksum; assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1473,7 +1471,7 @@ static int pager_stmt_playback(Pager *pPager){ nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); } for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1553,14 +1551,14 @@ int sqlite3_opentemp_count = 0; ** The OS will automatically delete the temporary file when it is ** closed. */ -static int sqlite3pager_opentemp(char *zFile, OsFile *fd){ +static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){ int cnt = 8; int rc; sqlite3_opentemp_count++; /* Used for testing and analysis only */ do{ cnt--; sqlite3Io.xTempFileName(zFile); - rc = sqlite3Io.xOpenExclusive(zFile, fd, 1); + rc = sqlite3Io.xOpenExclusive(zFile, pFd, 1); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } @@ -1588,7 +1586,7 @@ int sqlite3pager_open( Pager *pPager; char *zFullPathname = 0; int nameLen; - OsFile fd; + OsFile *fd; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1652,7 +1650,7 @@ int sqlite3pager_open( strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); - sqlite3Io.xCopyOsFile(&pPager->fd,&fd); + pPager->fd = fd; pPager->journalOpen = 0; pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; @@ -1763,8 +1761,8 @@ void enable_simulated_io_errors(void){ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ memset(pDest, 0, N); if( MEMDB==0 ){ - sqlite3Io.xSeek(&pPager->fd, 0); - sqlite3Io.xRead(&pPager->fd, pDest, N); + sqlite3Io.xSeek(pPager->fd, 0); + sqlite3Io.xRead(pPager->fd, pDest, N); clear_simulated_io_error(); } } @@ -1784,7 +1782,7 @@ int sqlite3pager_pagecount(Pager *pPager){ if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { - if( sqlite3Io.xFileSize(&pPager->fd, &n)!=SQLITE_OK ){ + if( sqlite3Io.xFileSize(pPager->fd, &n)!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_DISK; return 0; } @@ -1916,7 +1914,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ rc = SQLITE_OK; }else{ do { - rc = sqlite3Io.xLock(&pPager->fd, locktype); + rc = sqlite3Io.xLock(pPager->fd, locktype); }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); if( rc==SQLITE_OK ){ pPager->state = locktype; @@ -1984,14 +1982,14 @@ int sqlite3pager_close(Pager *pPager){ sqlite3pager_rollback(pPager); enable_simulated_io_errors(); if( !MEMDB ){ - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); } assert( pPager->errMask || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); } break; } @@ -2133,7 +2131,7 @@ static int syncJournal(Pager *pPager){ ** with the nRec computed from the size of the journal file. */ i64 jSz; - rc = sqlite3Io.xFileSize(&pPager->jfd, &jSz); + rc = sqlite3Io.xFileSize(pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->journalOff==jSz ); } @@ -2146,20 +2144,20 @@ static int syncJournal(Pager *pPager){ */ if( pPager->fullSync ){ TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3Io.xSync(&pPager->jfd, 0); + rc = sqlite3Io.xSync(pPager->jfd, 0); if( rc!=0 ) return rc; } - rc = sqlite3Io.xSeek(&pPager->jfd, + rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); if( rc ) return rc; - rc = write32bits(&pPager->jfd, pPager->nRec); + rc = write32bits(pPager->jfd, pPager->nRec); if( rc ) return rc; - rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); if( rc ) return rc; } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3Io.xSync(&pPager->jfd, pPager->fullSync); + rc = sqlite3Io.xSync(pPager->jfd, pPager->fullSync); if( rc!=0 ) return rc; pPager->journalStarted = 1; } @@ -2224,7 +2222,7 @@ static int pager_write_pagelist(PgHdr *pList){ while( pList ){ assert( pList->dirty ); - rc = sqlite3Io.xSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); + rc = sqlite3Io.xSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to @@ -2234,7 +2232,7 @@ static int pager_write_pagelist(PgHdr *pList){ if( pList->pgno<=pPager->dbSize ){ CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); - rc = sqlite3Io.xWrite(&pPager->fd, PGHDR_TO_DATA(pList), + rc = sqlite3Io.xWrite(pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); TEST_INCR(pPager->nWrite); @@ -2282,7 +2280,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ static int hasHotJournal(Pager *pPager){ if( !pPager->useJournal ) return 0; if( !sqlite3Io.xFileExists(pPager->zJournal) ) return 0; - if( sqlite3Io.xCheckReservedLock(&pPager->fd) ) return 0; + if( sqlite3Io.xCheckReservedLock(pPager->fd) ) return 0; if( sqlite3pager_pagecount(pPager)==0 ){ sqlite3Io.xDelete(pPager->zJournal); return 0; @@ -2361,9 +2359,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** second process will get to this point in the code and fail to ** obtain it's own EXCLUSIVE lock on the database file. */ - rc = sqlite3Io.xLock(&pPager->fd, EXCLUSIVE_LOCK); + rc = sqlite3Io.xLock(pPager->fd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } @@ -2379,7 +2377,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ rc = sqlite3Io.xOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return SQLITE_BUSY; } @@ -2536,16 +2534,16 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ }else{ int rc; assert( MEMDB==0 ); - rc = sqlite3Io.xSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); + rc = sqlite3Io.xSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xRead(&pPager->fd, PGHDR_TO_DATA(pPg), + rc = sqlite3Io.xRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ i64 fileSize; - if( sqlite3Io.xFileSize(&pPager->fd,&fileSize)!=SQLITE_OK + if( sqlite3Io.xFileSize(pPager->fd,&fileSize)!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; @@ -2675,9 +2673,9 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } - SET_FULLSYNC(pPager->jfd, pPager->fullSync); - SET_FULLSYNC(pPager->fd, pPager->fullSync); - sqlite3Io.xOpenDirectory(pPager->zDirectory, &pPager->jfd); + sqlite3Io.xSetFullSync(pPager->jfd, pPager->fullSync); + sqlite3Io.xSetFullSync(pPager->fd, pPager->fullSync); + sqlite3Io.xOpenDirectory(pPager->zDirectory, pPager->jfd); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; @@ -2705,7 +2703,7 @@ static int pager_open_journal(Pager *pPager){ failed_to_open_journal: sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; - sqlite3Io.xUnlock(&pPager->fd, NO_LOCK); + sqlite3Io.xUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } @@ -2749,7 +2747,7 @@ int sqlite3pager_begin(void *pData, int exFlag){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ - rc = sqlite3Io.xLock(&pPager->fd, RESERVED_LOCK); + rc = sqlite3Io.xLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ @@ -2860,7 +2858,7 @@ int sqlite3pager_write(void *pData){ store32bits(cksum, pPg, pPager->pageSize); szPg = pPager->pageSize+8; store32bits(pPg->pgno, pPg, -4); - rc = sqlite3Io.xWrite(&pPager->jfd, &((char*)pData)[-4], szPg); + rc = sqlite3Io.xWrite(pPager->jfd, &((char*)pData)[-4], szPg); pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); @@ -2909,7 +2907,7 @@ int sqlite3pager_write(void *pData){ }else{ store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); - rc = sqlite3Io.xWrite(&pPager->stfd,((char*)pData)-4, + rc = sqlite3Io.xWrite(pPager->stfd,((char*)pData)-4, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); @@ -3272,11 +3270,11 @@ int sqlite3pager_stmt_begin(Pager *pPager){ assert( pPager->journalOpen ); pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ - sqlite3Io.xLock(&pPager->fd, SHARED_LOCK); + sqlite3Io.xLock(pPager->fd, SHARED_LOCK); return SQLITE_NOMEM; } #ifndef NDEBUG - rc = sqlite3Io.xFileSize(&pPager->jfd, &pPager->stmtJSize); + rc = sqlite3Io.xFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->journalOff ); #endif @@ -3309,8 +3307,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ - sqlite3Io.xSeek(&pPager->stfd, 0); - /* sqlite3Io.xTruncate(&pPager->stfd, 0); */ + sqlite3Io.xSeek(pPager->stfd, 0); + /* sqlite3Io.xTruncate(pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; } @@ -3513,7 +3511,7 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){ /* Sync the database file. */ if( !pPager->noSync ){ - rc = sqlite3Io.xSync(&pPager->fd, 0); + rc = sqlite3Io.xSync(pPager->fd, 0); } pPager->state = PAGER_SYNCED; @@ -3627,11 +3625,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ -#ifdef OS_TEST - return pPager->fd->fd.locktype; -#else - return pPager->fd.locktype; -#endif + return sqlite3Io.xLockState(pPager->fd); } #endif diff --git a/src/test1.c b/src/test1.c index 402ff8c42..870b729d0 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.166 2005/11/26 00:25:03 drh Exp $ +** $Id: test1.c,v 1.167 2005/11/29 03:13:22 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -2429,7 +2429,7 @@ static int test_sqlite3OsOpenReadWrite( int objc, Tcl_Obj *CONST objv[] ){ - OsFile * pFile; + OsFile *pFile; int rc; int dummy; char zBuf[100]; @@ -2440,10 +2440,8 @@ static int test_sqlite3OsOpenReadWrite( return TCL_ERROR; } - pFile = sqliteMalloc(sizeof(OsFile)); - rc = sqlite3Io.xOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); + rc = sqlite3Io.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy); if( rc!=SQLITE_OK ){ - sqliteFree(pFile); Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } @@ -2461,7 +2459,7 @@ static int test_sqlite3OsClose( int objc, Tcl_Obj *CONST objv[] ){ - OsFile * pFile; + OsFile *pFile; int rc; if( objc!=2 ){ @@ -2473,12 +2471,11 @@ static int test_sqlite3OsClose( if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ return TCL_ERROR; } - rc = sqlite3Io.xClose(pFile); + rc = sqlite3Io.xClose(&pFile); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } - sqliteFree(pFile); return TCL_OK; } diff --git a/src/test2.c b/src/test2.c index bb02af5da..39e914897 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.36 2005/11/26 00:25:04 drh Exp $ +** $Id: test2.c,v 1.37 2005/11/29 03:13:22 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -524,7 +524,7 @@ static int fake_big_file( int rc; int n; i64 offset; - OsFile fd; + OsFile *fd = 0; int readOnly = 0; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -532,7 +532,6 @@ static int fake_big_file( return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; - memset(&fd, 0, sizeof(fd)); rc = sqlite3Io.xOpenReadWrite(argv[2], &fd, &readOnly); if( rc ){ Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); @@ -540,12 +539,12 @@ static int fake_big_file( } offset = n; offset *= 1024*1024; - rc = sqlite3Io.xSeek(&fd, offset); + rc = sqlite3Io.xSeek(fd, offset); if( rc ){ Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0); return TCL_ERROR; } - rc = sqlite3Io.xWrite(&fd, "Hello, World!", 14); + rc = sqlite3Io.xWrite(fd, "Hello, World!", 14); sqlite3Io.xClose(&fd); if( rc ){ Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); diff --git a/src/test6.c b/src/test6.c index 414480ba0..3407ff2b5 100644 --- a/src/test6.c +++ b/src/test6.c @@ -18,6 +18,7 @@ #include "sqliteInt.h" #include "os.h" #include "tcl.h" +#if 0 /* ** A copy of the original sqlite3Io structure @@ -25,16 +26,16 @@ static struct sqlite3IoVtbl origIo; /* -** The pAux part of OsFile points to this structure. +** The OsFile structure for the crash-test backend. The pBase field +** points to an OsFile structure for the native backend. */ -typedef struct OsTestFile OsTestFile; -struct OsTestFile { +struct OsFile { u8 **apBlk; /* Array of blocks that have been written to. */ int nBlk; /* Size of apBlock. */ int nMaxWrite; /* Largest offset written to. */ char *zName; /* File name */ OsFile *pBase; /* Base class */ - OsTestFile *pNext; /* Next in a list of them all */ + OsFile *pNext; /* Next in a list of them all */ }; /* @@ -102,9 +103,8 @@ static OsTestFile *pAllFiles = 0; /* ** Initialise the os_test.c specific fields of pFile. */ -static void initFile(OsFile *id, char const *zName){ - OsTestFile *pFile = sqliteMalloc(sizeof(OsTestFile) + strlen(zName)+1); - id->pAux = pFile; +static void initFile(OsFile **pId, char const *zName){ + OsFile *pFile = *pId = sqliteMalloc(sizeof(OsFile) + strlen(zName)+1); pFile->nMaxWrite = 0; pFile->nBlk = 0; pFile->apBlk = 0; @@ -120,11 +120,11 @@ static void initFile(OsFile *id, char const *zName){ ** and unlink the structure from the pAllFiles list. */ static void closeFile(OsFile *id){ - OsTestFile *pFile = (OsTestFile*)id->pAux; + OsFile *pFile = id; if( pFile==pAllFiles ){ pAllFiles = pFile->pNext; }else{ - OsTestFile *p; + OsFile *p; for(p=pAllFiles; p->pNext!=pFile; p=p->pNext ){ assert( p ); } @@ -137,14 +137,14 @@ static void closeFile(OsFile *id){ ** Return the current seek offset from the start of the file. This ** is unix-only code. */ -static i64 osTell(OsTestFile *pFile){ +static i64 osTell(OsFile *pFile){ return lseek(pFile->pBase->h, 0, SEEK_CUR); } /* ** Load block 'blk' into the cache of pFile. */ -static int cacheBlock(OsTestFile *pFile, int blk){ +static int cacheBlock(OsFile *pFile, int blk){ if( blk>=pFile->nBlk ){ int n = ((pFile->nBlk * 2) + 100 + blk); /* if( pFile->nBlk==0 ){ printf("DIRTY %s\n", pFile->zName); } */ @@ -184,7 +184,7 @@ static int cacheBlock(OsTestFile *pFile, int blk){ ** Write the cache of pFile to disk. If crash is non-zero, randomly ** skip blocks when writing. The cache is deleted before returning. */ -static int writeCache2(OsTestFile *pFile, int crash){ +static int writeCache2(OsFile *pFile, int crash){ int i; int nMax = pFile->nMaxWrite; i64 offset; @@ -249,7 +249,7 @@ printf("Writing block %d of %s\n", i, pFile->zName); /* ** Write the cache to disk. */ -static int writeCache(OsTestFile *pFile){ +static int writeCache(OsFile *pFile){ if( pFile->apBlk ){ int c = crashRequired(pFile->zName); if( c ){ @@ -275,8 +275,8 @@ static int crashClose(OsFile *id){ if( id->pAux ) return SQLITE_OK; if( id->isOpen ){ /* printf("CLOSE %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */ - writeCache((OsTestFile*)id->pAux); - origIo.xClose(id); + writeCache(id); + origIo.xClose(&id->pBase); } closeFile(id); return SQLITE_OK; @@ -472,15 +472,18 @@ static int crashParamsObjCmd( sqlite3Io.xOpenReadWrite = crashOpenReadWrite; sqlite3Io.xOpenExclusive = crashOpenExclusive; sqlite3Io.xOpenReadOnly = crashOpenReadOnly; - sqlite3Io.xCopyOsFile = crashCopyOsFile; + sqlite3Io.xSet return TCL_OK; } +#endif /* ** This procedure registers the TCL procedures defined in this file. */ int Sqlitetest6_Init(Tcl_Interp *interp){ +#if 0 Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); +#endif return TCL_OK; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 145664044..782e0163c 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -202,7 +202,7 @@ static int opcodeNoPush(u8 op){ NOPUSH_MASK_6 + (NOPUSH_MASK_7<<16), NOPUSH_MASK_8 + (NOPUSH_MASK_9<<16) }; - assert( op>=0 && op<32*5 ); + assert( op<32*5 ); return (masks[op>>5] & (1<<(op&0x1F))); } @@ -967,7 +967,7 @@ static int vdbeCommit(sqlite3 *db){ int needSync = 0; char *zMaster = 0; /* File-name for the master journal */ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); - OsFile master; + OsFile *master = 0; /* Select a master journal file name */ do { @@ -981,7 +981,6 @@ static int vdbeCommit(sqlite3 *db){ }while( sqlite3Io.xFileExists(zMaster) ); /* Open the master journal. */ - memset(&master, 0, sizeof(master)); rc = sqlite3Io.xOpenExclusive(zMaster, &master, 0); if( rc!=SQLITE_OK ){ sqliteFree(zMaster); @@ -1003,7 +1002,7 @@ static int vdbeCommit(sqlite3 *db){ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ needSync = 1; } - rc = sqlite3Io.xWrite(&master, zFile, strlen(zFile)+1); + rc = sqlite3Io.xWrite(master, zFile, strlen(zFile)+1); if( rc!=SQLITE_OK ){ sqlite3Io.xClose(&master); sqlite3Io.xDelete(zMaster); @@ -1018,9 +1017,9 @@ static int vdbeCommit(sqlite3 *db){ ** the master journal file is store in so that it gets synced too. */ zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); - rc = sqlite3Io.xOpenDirectory(zMainFile, &master); + rc = sqlite3Io.xOpenDirectory(zMainFile, master); if( rc!=SQLITE_OK || - (needSync && (rc=sqlite3Io.xSync(&master,0))!=SQLITE_OK) ){ + (needSync && (rc=sqlite3Io.xSync(master,0))!=SQLITE_OK) ){ sqlite3Io.xClose(&master); sqlite3Io.xDelete(zMaster); sqliteFree(zMaster); |