From: drh Date: Wed, 30 Nov 2005 03:20:31 +0000 (+0000) Subject: Restructure the OS interface yet again. This time make the OsFile object X-Git-Tag: version-3.6.10~3365 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=054889ec6d2df4754468d2acfe6c92973f54ea2c;p=thirdparty%2Fsqlite.git 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 --- diff --git a/Makefile.in b/Makefile.in index 3505149f6a..4322a8d00b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -115,7 +115,7 @@ TCC += -DSQLITE_OMIT_CURSOR LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \ callback.lo complete.lo date.lo \ delete.lo expr.lo func.lo hash.lo insert.lo \ - main.lo opcodes.lo os_unix.lo os_win.lo \ + main.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ select.lo table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ @@ -143,6 +143,7 @@ SRC = \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ $(TOP)/src/main.c \ + $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ @@ -327,6 +328,9 @@ opcodes.c: opcodes.h $(TOP)/mkopcodec.awk opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h +os.lo: $(TOP)/src/os.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os.c + os_unix.lo: $(TOP)/src/os_unix.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/os_unix.c diff --git a/main.mk b/main.mk index c903354dae..133e93af3e 100644 --- a/main.mk +++ b/main.mk @@ -57,7 +57,7 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \ callback.o complete.o date.o delete.o \ expr.o func.o hash.o insert.o \ - main.o opcodes.o os_unix.o os_win.o \ + main.o opcodes.o os.o os_unix.o os_win.o \ pager.o parse.o pragma.o prepare.o printf.o random.o \ select.o table.o tclsqlite.o tokenize.o trigger.o \ update.o util.o vacuum.o \ @@ -85,6 +85,7 @@ SRC = \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ $(TOP)/src/main.c \ + $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ @@ -261,6 +262,9 @@ opcodes.c: opcodes.h $(TOP)/mkopcodec.awk opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h +os.o: $(TOP)/src/os.c $(HDR) + $(TCCX) -c $(TOP)/src/os.c + os_unix.o: $(TOP)/src/os_unix.c $(HDR) $(TCCX) -c $(TOP)/src/os_unix.c diff --git a/manifest b/manifest index ceab987923..12ee3373b2 100644 --- a/manifest +++ b/manifest @@ -1,6 +1,6 @@ -C The\scrash\stest\sworks\snow,\sat\sleast\son\sunix.\s\sUntested\son\swindows.\sBut\sit\snever\nworked\son\swindows\sbefore\sso\sif\sit\sstill\sdoes\snot\sthere\sis\sno\sbig\sloss.\s\sI\sam\nstill\stroubled\sby\sthe\scurrent\sdesign\sof\sthe\sOS\soverloading\smechanism.\s\sExpect\nto\ssee\smore\schanges.\s(CVS\s2794) -D 2005-11-29T19:56:32 -F Makefile.in eac4c98a32a0eae9d6bb2779ac74bbb5441758d3 +C Restructure\sthe\sOS\sinterface\syet\sagain.\s\sThis\stime\smake\sthe\sOsFile\sobject\na\svirtual\sbase\sclass\swhich\sis\ssubclassed\sfor\sunix,\swindows,\sand\sthe\scrash\ntest\ssimulator.\s\sAdd\sthe\snew\sfile\s"os.c"\sfor\scommon\sos\slayer\scode.\s\sMove\nall\sOS-specific\sroutines\sinto\sthe\ssqlite3Os\sstructure.\s(CVS\s2795) +D 2005-11-30T03:20:31 +F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F VERSION b818cce180263e590a00ad4509a713892c3eecea @@ -19,7 +19,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 -F main.mk 76d9e7bcebea556f0db40811b9273d6b704df88e +F main.mk 19f33320f3ce5fc000de87abafca07ef4b6dffb4 F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512 F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d F mkopcodeh.awk 071dbba4eaf56c8d643baf4604a043af35683316 @@ -39,7 +39,7 @@ F src/btree.h 1ed561263ca0e335bc3e81d761c9d5ff8c22f61e F src/build.c 8c93ae10563e8b92d3d7ea532a606424be3cb4f7 F src/callback.c 90ab4f235a2603c4cb8e6a2497091a71fb732bfa F src/complete.c 4de937dfdd4c79a501772ab2035b26082f337a79 -F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940 +F src/date.c 8bc8d084a17d19c44d9cbf357b5f656db6706ce1 F src/delete.c 29dac493f4d83b05f91233b116827c133bcdab72 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d F src/expr.c 80ceb8c7d15dd53985831f0b4c660b3c3df796a3 @@ -48,46 +48,47 @@ F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c da031c3ed8e1675fac891990095d277c2ba6e205 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b -F src/main.c 97bb830cdbd378d1f87469618471f52d9d263d09 +F src/main.c 7d719efe04b760c5e0faa9e910c6d4f00f85f2f3 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 -F src/os.h 4172cf1dfb84ce13fe5f1073accbc320b4b25ad2 +F src/os.c bdd3a2fd089777e7ad18b57c896f1141d5a0c1fd +F src/os.h c5decb84948b4ec614903caa8da31ce86c25031e F src/os_common.h d74a11728ad2444b6b695b94c28c06881f049e49 F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 -F src/os_unix.c 471d3642d0f41ecd4113b17b618f487cf8237f0f +F src/os_unix.c 1a7278bf7ad95f8c62a946d6b1726a539ab5e790 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e -F src/os_win.c 2095cae6b283edc4e6b9d9d6a8a509210ea51eac +F src/os_win.c d962ac2dd0e482847e42b846d46cd044f97d1c32 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 18cc5b274a0df28dc9145da522a6e281f80b925f +F src/pager.c bcb54653c3020d7cde88b4e8bad81ff6f93402b4 F src/pager.h e7b41ce8e7b5f629d456708b7ad9a8c8ede37140 F src/parse.y e4d57c2fd5cc02f19822ec41f6dc2bfc9bc85609 -F src/pragma.c e278b3f722379ab9d630a1569ac05f586f01f4db +F src/pragma.c 2793699ab0d73fa730fa8c1c7521e9436604f024 F src/prepare.c fc098db25d2a121affb08686cf04833fd50452d4 F src/printf.c 3ea3a17d25d7ac498efc18007c70371a42c968f8 -F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4 +F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d F src/select.c 4a9e5366f4a16bd2e6e93c05f585633887be6372 F src/shell.c 3596c1e559b82663057940d19ba533ad421c7dd3 F src/sqlite.h.in 8e648e1f386e4509f2f96c09ded7c07b0df0c9a2 F src/sqliteInt.h 4148c9778e350014c2e27b332d7a2ef7278fe62e F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 F src/tclsqlite.c a497c3adfd2c85da6a934331ec0041e47884fbcb -F src/test1.c c2c307a4cbbf4670f43a7b4b144dce866d1d701f -F src/test2.c 02d639d515ddf99a3bbc00f640d8544ecb925a9b +F src/test1.c 014f00eda1007e21631148e4168f00c9ee2568ae +F src/test2.c 36390cdfc70c08e5ee0b466d0654a117f398bbff F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7 F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5 -F src/test6.c 951effde62e2032a3d6702a33ba2c2c2f993f412 +F src/test6.c cb811391ec0b7c75f29e545d4820a9cf19f3637e F src/tokenize.c bdb79702217af49eba44c2a3b4f5fc7bd9ed2917 F src/trigger.c aea0283a3ef729a3e9c8dc5dc1a11c9fcc0a12a7 F src/update.c fec7665138ccf2a2133f11dcd24c1134c6b33526 F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c F src/util.c 48fecbbef4391d102a23096d32f0d74173428406 -F src/vacuum.c 3a9d801b642a2004e8a99efa8d19ceef3f79d8df -F src/vdbe.c 88a85e681522e82e14c8d08adacccbe4e96dd1c9 +F src/vacuum.c c9fe2660919bd1595a7fbdeddadc16c7d9723400 +F src/vdbe.c 91b91272446d0a62b2d27d330d6a1a622acfb0fb F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 F src/vdbeInt.h 0055c37eccbf3a189fd893a90f8eb6a5fa60c871 -F src/vdbeapi.c 85bbe1d0243a89655433d60711b4bd71979b59cd -F src/vdbeaux.c 09b9bcfed1101b53b433e5d0d7b80943bdf3d1b2 +F src/vdbeapi.c 73d56a8899d46cf0353e32a85aa1ff7f36cb24ea +F src/vdbeaux.c 0c4af4af29d42a7f008c7562afee58b470dd6d4a F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c cd9609c1e7f71ec76d9840c84c3a57ebfa6539cf F src/where.c a9fed5a5b549f5dae1aa95dc9463cd1f35efa0f1 @@ -323,7 +324,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 59bdca2552b2e5c09d5ca2b7a02ee34460139d7b -R 017afb31f003c30d6ff4dc490b01097c +P fa1d7ecfcc648fbe9fc6d92e080cf937bdc9c439 +R 9be695e305d95d89dc0ca507829a93a0 U drh -Z 38c6fa4706794e96cb17051f7e19d848 +Z 170795265fa237ab9dcb51e37d55abf3 diff --git a/manifest.uuid b/manifest.uuid index 237589d16a..96802387d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa1d7ecfcc648fbe9fc6d92e080cf937bdc9c439 \ No newline at end of file +bd8740d1aecba69e1b5d64d43db07e8ad8841f07 \ No newline at end of file diff --git a/src/date.c b/src/date.c index 35c0bf64a8..e4b8f3ab48 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.45 2005/06/25 18:42:14 drh Exp $ +** $Id: date.c,v 1.46 2005/11/30 03:20:31 drh Exp $ ** ** NOTES: ** @@ -311,7 +311,7 @@ static int parseDateOrTime(const char *zDate, DateTime *p){ return 0; }else if( sqlite3StrICmp(zDate,"now")==0){ double r; - sqlite3OsCurrentTime(&r); + sqlite3Os.xCurrentTime(&r); p->rJD = r; p->validJD = 1; return 0; @@ -409,7 +409,7 @@ static double localtimeOffset(DateTime *p){ x.validJD = 0; computeJD(&x); t = (x.rJD-2440587.5)*86400.0 + 0.5; - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); pTm = localtime(&t); y.Y = pTm->tm_year + 1900; y.M = pTm->tm_mon + 1; @@ -417,7 +417,7 @@ static double localtimeOffset(DateTime *p){ y.h = pTm->tm_hour; y.m = pTm->tm_min; y.s = pTm->tm_sec; - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); y.validYMD = 1; y.validHMS = 1; y.validJD = 0; @@ -942,9 +942,9 @@ static void currentTimeFunc( } #endif - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); strftime(zBuf, 20, zFormat, gmtime(&t)); - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } diff --git a/src/main.c b/src/main.c index 192b5e200c..4efdb39bf0 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.303 2005/10/20 07:28:18 drh Exp $ +** $Id: main.c,v 1.304 2005/11/30 03:20:31 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -189,7 +189,7 @@ int sqlite3_close(sqlite3 *db){ #ifndef SQLITE_OMIT_GLOBALRECOVER { sqlite3 *pPrev; - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); pPrev = pDbList; while( pPrev && pPrev->pNext!=db ){ pPrev = pPrev->pNext; @@ -200,7 +200,7 @@ int sqlite3_close(sqlite3 *db){ assert( pDbList==db ); pDbList = db->pNext; } - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); } #endif @@ -292,14 +292,14 @@ static int sqliteDefaultBusyCallback( delay = timeout - prior; if( delay<=0 ) return 0; } - sqlite3OsSleep(delay); + sqlite3Os.xSleep(delay); return 1; #else int timeout = ((sqlite3 *)ptr)->busyTimeout; if( (count+1)*1000 > timeout ){ return 0; } - sqlite3OsSleep(1000); + sqlite3Os.xSleep(1000); return 1; #endif } @@ -792,10 +792,10 @@ opendb_out: *ppDb = db; #ifndef SQLITE_OMIT_GLOBALRECOVER if( db ){ - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); db->pNext = pDbList; pDbList = db; - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); } #endif return sqlite3_errcode(db); diff --git a/src/os.c b/src/os.c new file mode 100644 index 0000000000..97036746a3 --- /dev/null +++ b/src/os.c @@ -0,0 +1,71 @@ +/* +** 2005 November 29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains OS interface code that is common to all +** architectures. +*/ +#include "sqliteInt.h" +#include "os.h" + +/* +** The following routines are convenience wrappers around methods +** of the OsFile object. This is mostly just syntactic sugar. All +** of this would be completely automatic if SQLite were coded using +** C++ instead of plain old C. +*/ +int sqlite3OsClose(OsFile **pId){ + OsFile *id; + if( pId!=0 && (id = *pId)!=0 ){ + return id->pMethod->xClose(pId); + }else{ + return SQLITE_OK; + } +} +int sqlite3OsOpenDirectory(OsFile *id, const char *zName){ + return id->pMethod->xOpenDirectory(id, zName); +} +int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ + return id->pMethod->xRead(id, pBuf, amt); +} +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ + return id->pMethod->xWrite(id, pBuf, amt); +} +int sqlite3OsSeek(OsFile *id, i64 offset){ + return id->pMethod->xSeek(id, offset); +} +int sqlite3OsTruncate(OsFile *id, i64 size){ + return id->pMethod->xTruncate(id, size); +} +int sqlite3OsSync(OsFile *id, int fullsync){ + return id->pMethod->xSync(id, fullsync); +} +void sqlite3OsSetFullSync(OsFile *id, int value){ + id->pMethod->xSetFullSync(id, value); +} +int sqlite3OsFileHandle(OsFile *id){ + return id->pMethod->xFileHandle(id); +} +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ + return id->pMethod->xFileSize(id, pSize); +} +int sqlite3OsLock(OsFile *id, int lockType){ + return id->pMethod->xLock(id, lockType); +} +int sqlite3OsUnlock(OsFile *id, int lockType){ + return id->pMethod->xUnlock(id, lockType); +} +int sqlite3OsLockState(OsFile *id){ + return id->pMethod->xLockState(id); +} +int sqlite3OsCheckReservedLock(OsFile *id){ + return id->pMethod->xCheckReservedLock(id); +} diff --git a/src/os.h b/src/os.h index 5996cecc2a..5bbc724177 100644 --- a/src/os.h +++ b/src/os.h @@ -42,10 +42,43 @@ # endif #endif + /* -** The OsFile object describes an open disk file in an OS-dependent way. +** Forward declarations */ typedef struct OsFile OsFile; +typedef struct IoMethod IoMethod; + +/* +** An instance of the following structure contains pointers to all +** methods on an OsFile object. +*/ +struct IoMethod { + int (*xClose)(OsFile**); + int (*xOpenDirectory)(OsFile*, const char*); + int (*xRead)(OsFile*, void*, int amt); + int (*xWrite)(OsFile*, const void*, int amt); + int (*xSeek)(OsFile*, i64 offset); + int (*xTruncate)(OsFile*, i64 size); + int (*xSync)(OsFile*, int); + void (*xSetFullSync)(OsFile *id, int setting); + int (*xFileHandle)(OsFile *id); + int (*xFileSize)(OsFile*, i64 *pSize); + int (*xLock)(OsFile*, int); + int (*xUnlock)(OsFile*, int); + int (*xLockState)(OsFile *id); + int (*xCheckReservedLock)(OsFile *id); +}; + +/* +** The OsFile object describes an open disk file in an OS-dependent way. +** The version of OsFile defined here is a generic versions. Each Os +** implementation defines its own subclass of this structure that contains +** additional information needed to handle file I/O. +*/ +struct OsFile { + IoMethod const *pMethod; +}; /* ** Define the maximum size of a temporary filename @@ -168,42 +201,44 @@ extern unsigned int sqlite3_pending_byte; /* ** A single global instance of the following structure holds pointers to the -** various disk I/O routines. +** various system-specific interface routines. */ -extern struct sqlite3IoVtbl { - int (*xDelete)(const char*); - int (*xFileExists)(const char*); +extern struct sqlite3OsVtbl { int (*xOpenReadWrite)(const char*, OsFile**, int*); int (*xOpenExclusive)(const char*, OsFile**, int); int (*xOpenReadOnly)(const char*, OsFile**); - int (*xOpenDirectory)(const char*, OsFile*); + + int (*xDelete)(const char*); + int (*xFileExists)(const char*); + char *(*xFullPathname)(const char*); + int (*xIsDirWritable)(char*); int (*xSyncDirectory)(const char*); int (*xTempFileName)(char*); - int (*xIsDirWritable)(char*); - int (*xClose)(OsFile**); - int (*xRead)(OsFile*, void*, int amt); - int (*xWrite)(OsFile*, const void*, int amt); - int (*xSeek)(OsFile*, i64 offset); - int (*xSync)(OsFile*, int); - int (*xTruncate)(OsFile*, i64 size); - int (*xFileSize)(OsFile*, i64 *pSize); - char *(*xFullPathname)(const char*); - int (*xLock)(OsFile*, int); - int (*xUnlock)(OsFile*, int); - int (*xCheckReservedLock)(OsFile *id); - 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 -** are below */ + int (*xRandomSeed)(char*); + int (*xSleep)(int ms); + int (*xCurrentTime)(double*); + void (*xEnterMutex)(void); + void (*xLeaveMutex)(void); +} sqlite3Os; -int sqlite3OsRandomSeed(char*); -int sqlite3OsSleep(int ms); -int sqlite3OsCurrentTime(double*); -void sqlite3OsEnterMutex(void); -void sqlite3OsLeaveMutex(void); +/* +** Prototypes for routines found in os.c +*/ +int sqlite3OsClose(OsFile**); +int sqlite3OsOpenDirectory(OsFile*, const char*); +int sqlite3OsRead(OsFile*, void*, int amt); +int sqlite3OsWrite(OsFile*, const void*, int amt); +int sqlite3OsSeek(OsFile*, i64 offset); +int sqlite3OsTruncate(OsFile*, i64 size); +int sqlite3OsSync(OsFile*, int); +void sqlite3OsSetFullSync(OsFile *id, int setting); +int sqlite3OsFileHandle(OsFile *id); +int sqlite3OsFileSize(OsFile*, i64 *pSize); +int sqlite3OsLock(OsFile*, int); +int sqlite3OsUnlock(OsFile*, int); +int sqlite3OsLockState(OsFile *id); +int sqlite3OsCheckReservedLock(OsFile *id); #endif /* _SQLITE_OS_H_ */ diff --git a/src/os_unix.c b/src/os_unix.c index c12c59b0c9..7074c546ec 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -70,15 +70,12 @@ /* -** 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. +** The unixFile structure is subclass of OsFile specific for the unix +** protability layer. */ -struct OsFile { +typedef struct unixFile unixFile; +struct unixFile { + IoMethod const *pMethod; /* Always the first entry */ 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 */ @@ -563,21 +560,8 @@ static int unixFileExists(const char *zFilename){ return access(zFilename, 0)==0; } -/* -** 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; -} +/* Forward declaration */ +static int allocateUnixFile(unixFile *pInit, OsFile **pId); /* ** Attempt to open a file for both reading and writing. If that @@ -598,7 +582,7 @@ static int unixOpenReadWrite( int *pReadonly ){ int rc; - OsFile f; + unixFile f; assert( 0==*pId ); f.dirfd = -1; @@ -619,22 +603,16 @@ static int unixOpenReadWrite( }else{ *pReadonly = 0; } - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); rc = findLockInfo(f.h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); if( rc ){ close(f.h); return SQLITE_NOMEM; } 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; - } + return allocateUnixFile(&f, pId); } @@ -654,7 +632,7 @@ static int unixOpenReadWrite( */ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; - OsFile f; + unixFile f; assert( 0==*pId ); if( access(zFilename, 0)==0 ){ @@ -668,9 +646,9 @@ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ if( f.h<0 ){ return SQLITE_CANTOPEN; } - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); rc = findLockInfo(f.h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); if( rc ){ close(f.h); unlink(zFilename); @@ -681,13 +659,7 @@ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ unlink(zFilename); } TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename); - *pId = allocateOsFile(&f); - if( *pId==0 ){ - return SQLITE_NOMEM; - }else{ - OpenCounter(+1); - return SQLITE_OK; - } + return allocateUnixFile(&f, pId); } /* @@ -699,7 +671,7 @@ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ */ static int unixOpenReadOnly(const char *zFilename, OsFile **pId){ int rc; - OsFile f; + unixFile f; assert( 0==*pId ); SET_THREADID(&f); @@ -708,22 +680,16 @@ static int unixOpenReadOnly(const char *zFilename, OsFile **pId){ if( f.h<0 ){ return SQLITE_CANTOPEN; } - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); rc = findLockInfo(f.h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); if( rc ){ close(f.h); return SQLITE_NOMEM; } 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; - } + return allocateUnixFile(&f, pId); } /* @@ -743,21 +709,22 @@ static int unixOpenReadOnly(const char *zFilename, OsFile **pId){ ** *id unchanged. */ static int unixOpenDirectory( - const char *zDirname, - OsFile *id + OsFile *id, + const char *zDirname ){ - if( id==0 ){ + unixFile *pFile = (unixFile*)id; + if( pFile==0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } - SET_THREADID(id); - assert( id->dirfd<0 ); - id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); - if( id->dirfd<0 ){ + SET_THREADID(pFile); + assert( pFile->dirfd<0 ); + pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); + if( pFile->dirfd<0 ){ return SQLITE_CANTOPEN; } - TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); + TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname); return SQLITE_OK; } @@ -834,9 +801,10 @@ static int unixRead(OsFile *id, void *pBuf, int amt){ assert( id ); SimulateIOError(SQLITE_IOERR); TIMER_START; - got = read(id->h, pBuf, amt); + got = read(((unixFile*)id)->h, pBuf, amt); TIMER_END; - TRACE5("READ %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED); + TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got, + last_page, TIMER_ELAPSED); SEEK(0); /* if( got<0 ) got = 0; */ if( got==amt ){ @@ -857,12 +825,13 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){ SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TIMER_START; - while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){ + while( amt>0 && (wrote = write(((unixFile*)id)->h, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } TIMER_END; - TRACE5("WRITE %-3d %5d %7d %d\n", id->h, wrote, last_page, TIMER_ELAPSED); + TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote, + last_page, TIMER_ELAPSED); SEEK(0); if( amt>0 ){ return SQLITE_FULL; @@ -879,7 +848,7 @@ static int unixSeek(OsFile *id, i64 offset){ #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif - lseek(id->h, offset, SEEK_SET); + lseek(((unixFile*)id)->h, offset, SEEK_SET); return SQLITE_OK; } @@ -968,21 +937,22 @@ 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 ); + unixFile *pFile = (unixFile*)id; + assert( pFile ); SimulateIOError(SQLITE_IOERR); - TRACE2("SYNC %-3d\n", id->h); - if( full_fsync(id->h, id->fullSync, dataOnly) ){ + TRACE2("SYNC %-3d\n", pFile->h); + if( full_fsync(pFile->h, pFile->fullSync, dataOnly) ){ return SQLITE_IOERR; } - if( id->dirfd>=0 ){ - TRACE2("DIRSYNC %-3d\n", id->dirfd); + if( pFile->dirfd>=0 ){ + TRACE2("DIRSYNC %-3d\n", pFile->dirfd); #ifndef SQLITE_DISABLE_DIRSYNC - if( full_fsync(id->dirfd, id->fullSync, 0) ){ + if( full_fsync(pFile->dirfd, pFile->fullSync, 0) ){ return SQLITE_IOERR; } #endif - close(id->dirfd); /* Only need to sync once, so close the directory */ - id->dirfd = -1; /* when we are done. */ + close(pFile->dirfd); /* Only need to sync once, so close the directory */ + pFile->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } @@ -1019,7 +989,7 @@ static int unixSyncDirectory(const char *zDirname){ static int unixTruncate(OsFile *id, i64 nByte){ assert( id ); SimulateIOError(SQLITE_IOERR); - return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; + return ftruncate(((unixFile*)id)->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; } /* @@ -1029,7 +999,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){ struct stat buf; assert( id ); SimulateIOError(SQLITE_IOERR); - if( fstat(id->h, &buf)!=0 ){ + if( fstat(((unixFile*)id)->h, &buf)!=0 ){ return SQLITE_IOERR; } *pSize = buf.st_size; @@ -1044,13 +1014,14 @@ static int unixFileSize(OsFile *id, i64 *pSize){ */ static int unixCheckReservedLock(OsFile *id){ int r = 0; + unixFile *pFile = (unixFile*)id; - assert( id ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ + assert( pFile ); + if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; + sqlite3Os.xEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ - if( id->pLock->locktype>SHARED_LOCK ){ + if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } @@ -1062,14 +1033,14 @@ static int unixCheckReservedLock(OsFile *id){ lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; - fcntl(id->h, F_GETLK, &lock); + fcntl(pFile->h, F_GETLK, &lock); if( lock.l_type!=F_UNLCK ){ r = 1; } } - sqlite3OsLeaveMutex(); - TRACE3("TEST WR-LOCK %d %d\n", id->h, r); + sqlite3Os.xLeaveMutex(); + TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } @@ -1080,7 +1051,7 @@ static int unixCheckReservedLock(OsFile *id){ ** binaries. This returns the string represetation of the supplied ** integer lock-type. */ -static const char * locktypeName(int locktype){ +static const char *locktypeName(int locktype){ switch( locktype ){ case NO_LOCK: return "NONE"; case SHARED_LOCK: return "SHARED"; @@ -1156,39 +1127,41 @@ static int unixLock(OsFile *id, int locktype){ ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; - struct lockInfo *pLock = id->pLock; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; struct flock lock; int s; - 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() ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; + assert( pFile ); + TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), + locktypeName(pLock->locktype), pLock->cnt , getpid()); + if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; /* 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. + ** sqlite3Os.xEnterMutex() hasn't been called yet. */ - if( id->locktype>=locktype ){ - TRACE3("LOCK %d %s ok (already held)\n", id->h, locktypeName(locktype)); + if( pFile->locktype>=locktype ){ + TRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(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 ); - /* This mutex is needed because id->pLock is shared across threads + /* This mutex is needed because pFile->pLock is shared across threads */ - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ - if( (id->locktype!=pLock->locktype && + if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ rc = SQLITE_BUSY; @@ -1202,11 +1175,11 @@ static int unixLock(OsFile *id, int locktype){ if( locktype==SHARED_LOCK && (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ assert( locktype==SHARED_LOCK ); - assert( id->locktype==0 ); + assert( pFile->locktype==0 ); assert( pLock->cnt>0 ); - id->locktype = SHARED_LOCK; + pFile->locktype = SHARED_LOCK; pLock->cnt++; - id->pOpen->nLock++; + pFile->pOpen->nLock++; goto end_lock; } @@ -1219,11 +1192,11 @@ static int unixLock(OsFile *id, int locktype){ ** be released. */ if( locktype==SHARED_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktypelocktypeh, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; @@ -1241,21 +1214,21 @@ static int unixLock(OsFile *id, int locktype){ /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ rc = SQLITE_IOERR; /* This should never happen */ goto end_lock; } if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ - id->locktype = SHARED_LOCK; - id->pOpen->nLock++; + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; pLock->cnt = 1; } }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ @@ -1267,7 +1240,7 @@ static int unixLock(OsFile *id, int locktype){ ** assumed that there is a SHARED or greater lock on the file ** already. */ - assert( 0!=id->locktype ); + assert( 0!=pFile->locktype ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: @@ -1280,29 +1253,29 @@ static int unixLock(OsFile *id, int locktype){ default: assert(0); } - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } if( rc==SQLITE_OK ){ - id->locktype = locktype; + pFile->locktype = locktype; pLock->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ - id->locktype = PENDING_LOCK; + pFile->locktype = PENDING_LOCK; pLock->locktype = PENDING_LOCK; } end_lock: - sqlite3OsLeaveMutex(); - TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype), + sqlite3Os.xLeaveMutex(); + TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } /* -** Lower the locking level on file descriptor id to locktype. locktype +** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below @@ -1316,27 +1289,28 @@ static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; - 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; + assert( pFile ); + TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); + if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; assert( locktype<=SHARED_LOCK ); - if( id->locktype<=locktype ){ + if( pFile->locktype<=locktype ){ return SQLITE_OK; } - sqlite3OsEnterMutex(); - pLock = id->pLock; + sqlite3Os.xEnterMutex(); + pLock = pFile->pLock; assert( pLock->cnt!=0 ); - if( id->locktype>SHARED_LOCK ){ - assert( pLock->locktype==id->locktype ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ /* This should never happen */ rc = SQLITE_IOERR; } @@ -1345,7 +1319,7 @@ static int unixUnlock(OsFile *id, int locktype){ lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = SHARED_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1363,7 +1337,7 @@ static int unixUnlock(OsFile *id, int locktype){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = NO_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1374,7 +1348,7 @@ static int unixUnlock(OsFile *id, int locktype){ ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ - pOpen = id->pOpen; + pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ @@ -1387,8 +1361,8 @@ static int unixUnlock(OsFile *id, int locktype){ pOpen->aPending = 0; } } - sqlite3OsLeaveMutex(); - id->locktype = locktype; + sqlite3Os.xLeaveMutex(); + pFile->locktype = locktype; return rc; } @@ -1396,13 +1370,13 @@ static int unixUnlock(OsFile *id, int locktype){ ** Close a file. */ static int unixClose(OsFile **pId){ - OsFile *id = *pId; + unixFile *id = (unixFile*)*pId; if( !id ) return SQLITE_OK; if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - unixUnlock(id, NO_LOCK); + unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file @@ -1425,7 +1399,7 @@ static int unixClose(OsFile **pId){ } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -1461,14 +1435,14 @@ static char *unixFullPathname(const char *zRelative){ ** Change the value of the fullsync flag in the given file descriptor. */ static void unixSetFullSync(OsFile *id, int v){ - id->fullSync = v; + ((unixFile*)id)->fullSync = v; } /* ** Return the underlying file handle for an OsFile */ static int unixFileHandle(OsFile *id){ - return id->h; + return ((unixFile*)id)->h; } /* @@ -1476,38 +1450,51 @@ static int unixFileHandle(OsFile *id){ ** by this handle. (Used for testing and analysis only.) */ static int unixLockState(OsFile *id){ - return id->locktype; + return ((unixFile*)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 unix. */ -struct sqlite3IoVtbl sqlite3Io = { - unixDelete, - unixFileExists, - unixOpenReadWrite, - unixOpenExclusive, - unixOpenReadOnly, - unixOpenDirectory, - unixSyncDirectory, - unixTempFileName, - unixIsDirWritable, +static const IoMethod sqlite3UnixIoMethod = { unixClose, + unixOpenDirectory, unixRead, unixWrite, unixSeek, - unixSync, unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, unixFileSize, - unixFullPathname, unixLock, unixUnlock, - unixCheckReservedLock, - unixSetFullSync, - unixFileHandle, unixLockState, + unixCheckReservedLock, }; +/* +** Allocate memory for a unixFile. Initialize the new unixFile +** 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 allocateUnixFile(unixFile *pInit, OsFile **pId){ + unixFile *pNew; + pNew = sqliteMalloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(pInit->h); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3UnixIoMethod; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** @@ -1521,7 +1508,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 unixRandomSeed(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 @@ -1555,7 +1542,7 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. */ -int sqlite3OsSleep(int ms){ +static int unixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; @@ -1581,14 +1568,14 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ** 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 unixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif assert( !inMutex ); inMutex = 1; } -void sqlite3OsLeaveMutex(){ +static void unixLeaveMutex(){ assert( inMutex ); inMutex = 0; #ifdef SQLITE_UNIX_THREADS @@ -1598,7 +1585,7 @@ void sqlite3OsLeaveMutex(){ /* ** The following variable, if set to a non-zero value, becomes the result -** returned from sqlite3OsCurrentTime(). This is used for testing. +** returned from sqlite3Os.xCurrentTime(). This is used for testing. */ #ifdef SQLITE_TEST int sqlite3_current_time = 0; @@ -1609,7 +1596,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 unixCurrentTime(double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); @@ -1628,4 +1615,34 @@ 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( unixOpenReadWrite ), + IF_DISKIO( unixOpenExclusive ), + IF_DISKIO( unixOpenReadOnly ), + IF_DISKIO( unixDelete ), + IF_DISKIO( unixFileExists ), + IF_DISKIO( unixFullPathname ), + IF_DISKIO( unixIsDirWritable ), + IF_DISKIO( unixSyncDirectory ), + IF_DISKIO( unixTempFileName ), + unixRandomSeed, + unixSleep, + unixCurrentTime, + unixEnterMutex, + unixLeaveMutex, +}; + + + #endif /* OS_UNIX */ diff --git a/src/os_win.c b/src/os_win.c index b07115ff19..be561b75f3 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 */ diff --git a/src/pager.c b/src/pager.c index 1b6dc8846d..6583493ad2 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.221 2005/11/29 03:13:22 drh Exp $ +** @(#) $Id: pager.c,v 1.222 2005/11/30 03:20:31 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -53,7 +53,7 @@ ** struct as it's argument. */ #define PAGERID(p) FILEHANDLEID(&(p)->fd) -#define FILEHANDLEID(fd) (sqlite3Io.xFileHandle(&fd)) +#define FILEHANDLEID(fd) (sqlite3OsFileHandle(&fd)) /* ** The page cache as a whole is always in one of the following @@ -406,7 +406,7 @@ static const unsigned char aJournalMagic[] = { static int read32bits(OsFile *fd, u32 *pRes){ u32 res; int rc; - rc = sqlite3Io.xRead(fd, &res, sizeof(res)); + rc = sqlite3OsRead(fd, &res, sizeof(res)); if( rc==SQLITE_OK ){ unsigned char ac[4]; memcpy(ac, &res, 4); @@ -426,7 +426,7 @@ static int write32bits(OsFile *fd, u32 val){ ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; - return sqlite3Io.xWrite(fd, ac, 4); + return sqlite3OsWrite(fd, ac, 4); } /* @@ -517,10 +517,10 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){ *pzMaster = 0; - rc = sqlite3Io.xFileSize(pJrnl, &szJ); + rc = sqlite3OsFileSize(pJrnl, &szJ); if( rc!=SQLITE_OK || szJ<16 ) return rc; - rc = sqlite3Io.xSeek(pJrnl, szJ-16); + rc = sqlite3OsSeek(pJrnl, szJ-16); if( rc!=SQLITE_OK ) return rc; rc = read32bits(pJrnl, &len); @@ -529,17 +529,17 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){ rc = read32bits(pJrnl, &cksum); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xRead(pJrnl, aMagic, 8); + rc = sqlite3OsRead(pJrnl, aMagic, 8); if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; - rc = sqlite3Io.xSeek(pJrnl, szJ-16-len); + rc = sqlite3OsSeek(pJrnl, szJ-16-len); if( rc!=SQLITE_OK ) return rc; *pzMaster = (char *)sqliteMalloc(len+1); if( !*pzMaster ){ return SQLITE_NOMEM; } - rc = sqlite3Io.xRead(pJrnl, *pzMaster, len); + rc = sqlite3OsRead(pJrnl, *pzMaster, len); if( rc!=SQLITE_OK ){ sqliteFree(*pzMaster); *pzMaster = 0; @@ -590,7 +590,7 @@ static int seekJournalHdr(Pager *pPager){ assert( offset>=c ); assert( (offset-c)journalOff = offset; - return sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); + return sqlite3OsSeek(pPager->jfd, pPager->journalOff); } /* @@ -626,7 +626,7 @@ 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 = sqlite3OsWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); if( rc==SQLITE_OK ){ /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ @@ -650,9 +650,9 @@ static int writeJournalHdr(Pager *pPager){ ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ - rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff-1); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xWrite(pPager->jfd, "\000", 1); + rc = sqlite3OsWrite(pPager->jfd, "\000", 1); } } return rc; @@ -690,7 +690,7 @@ static int readJournalHdr( return SQLITE_DONE; } - rc = sqlite3Io.xRead(pPager->jfd, aMagic, sizeof(aMagic)); + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic)); if( rc ) return rc; if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ @@ -716,7 +716,7 @@ static int readJournalHdr( if( rc ) return rc; pPager->journalOff += JOURNAL_HDR_SZ(pPager); - rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); return rc; } @@ -764,7 +764,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager)); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xWrite(pPager->jfd, zMaster, len); + rc = sqlite3OsWrite(pPager->jfd, zMaster, len); if( rc!=SQLITE_OK ) return rc; rc = write32bits(pPager->jfd, len); @@ -773,7 +773,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ rc = write32bits(pPager->jfd, cksum); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(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); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; @@ -900,13 +900,13 @@ static int pager_unwritelock(Pager *pPager){ } sqlite3pager_stmt_commit(pPager); if( pPager->stmtOpen ){ - sqlite3Io.xClose(&pPager->stfd); + sqlite3OsClose(&pPager->stfd); pPager->stmtOpen = 0; } if( pPager->journalOpen ){ - sqlite3Io.xClose(&pPager->jfd); + sqlite3OsClose(&pPager->jfd); pPager->journalOpen = 0; - sqlite3Io.xDelete(pPager->zJournal); + sqlite3Os.xDelete(pPager->zJournal); sqliteFree( pPager->aInJournal ); pPager->aInJournal = 0; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ @@ -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 = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; @@ -983,7 +983,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ rc = read32bits(jfd, &pgno); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3Io.xRead(jfd, &aData, pPager->pageSize); + rc = sqlite3OsRead(jfd, &aData, pPager->pageSize); if( rc!=SQLITE_OK ) return rc; pPager->journalOff += pPager->pageSize + 4; @@ -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 = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xWrite(pPager->fd, aData, pPager->pageSize); + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize); } if( pPg ) pPg->dirty = 0; } @@ -1082,10 +1082,10 @@ static int pager_delmaster(const char *zMaster){ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ - rc = sqlite3Io.xOpenReadOnly(zMaster, &master); + rc = sqlite3Os.xOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3Io.xFileSize(master, &nMasterJournal); + rc = sqlite3OsFileSize(master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ @@ -1100,12 +1100,12 @@ static int pager_delmaster(const char *zMaster){ rc = SQLITE_NOMEM; goto delmaster_out; } - rc = sqlite3Io.xRead(master, zMasterJournal, nMasterJournal); + rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; while( (zJournal-zMasterJournal)dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ - rc = sqlite3Io.xSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); + rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xRead(pPager->fd, zBuf, pPager->pageSize); + rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; @@ -1196,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 sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); } /* @@ -1264,7 +1264,7 @@ static int pager_playback(Pager *pPager){ ** the journal is empty. */ assert( pPager->journalOpen ); - rc = sqlite3Io.xFileSize(pPager->jfd, &szJ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1276,13 +1276,13 @@ static int pager_playback(Pager *pPager){ */ rc = readMasterJournal(pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); - if( rc!=SQLITE_OK || (zMaster && !sqlite3Io.xFileExists(zMaster)) ){ + if( rc!=SQLITE_OK || (zMaster && !sqlite3Os.xFileExists(zMaster)) ){ sqliteFree(zMaster); zMaster = 0; if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } - sqlite3Io.xSeek(pPager->jfd, 0); + sqlite3OsSeek(pPager->jfd, 0); pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns @@ -1325,7 +1325,7 @@ static int pager_playback(Pager *pPager){ pPager->dbSize = mxPg; } - /* rc = sqlite3Io.xSeek(pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ + /* rc = sqlite3OsSeek(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. @@ -1398,7 +1398,7 @@ static int pager_stmt_playback(Pager *pPager){ #ifndef NDEBUG { i64 os_szJ; - rc = sqlite3Io.xFileSize(pPager->jfd, &os_szJ); + rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); if( rc!=SQLITE_OK ) return rc; assert( szJ==os_szJ ); } @@ -1424,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); + sqlite3OsSeek(pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the @@ -1446,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 = sqlite3OsSeek(pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } @@ -1506,7 +1506,7 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ ** or power failures by changing the number of syncs()s when writing ** the rollback journal. There are three levels: ** -** OFF sqlite3Io.xSync() is never called. This is the default +** OFF sqlite3OsSync() is never called. This is the default ** for temporary and transient files. ** ** NORMAL The journal is synced once before writes begin on the @@ -1557,8 +1557,8 @@ static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){ sqlite3_opentemp_count++; /* Used for testing and analysis only */ do{ cnt--; - sqlite3Io.xTempFileName(zFile); - rc = sqlite3Io.xOpenExclusive(zFile, pFd, 1); + sqlite3Os.xTempFileName(zFile); + rc = sqlite3Os.xOpenExclusive(zFile, pFd, 1); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } @@ -1610,32 +1610,32 @@ int sqlite3pager_open( }else #endif { - zFullPathname = sqlite3Io.xFullPathname(zFilename); + zFullPathname = sqlite3Os.xFullPathname(zFilename); if( zFullPathname ){ - rc = sqlite3Io.xOpenReadWrite(zFullPathname, &fd, &readOnly); + rc = sqlite3Os.xOpenReadWrite(zFullPathname, &fd, &readOnly); } } }else{ rc = sqlite3pager_opentemp(zTemp, &fd); zFilename = zTemp; - zFullPathname = sqlite3Io.xFullPathname(zFilename); + zFullPathname = sqlite3Os.xFullPathname(zFilename); if( rc==SQLITE_OK ){ tempFile = 1; } } if( !zFullPathname ){ - sqlite3Io.xClose(&fd); + sqlite3OsClose(&fd); return SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ - sqlite3Io.xClose(&fd); + sqlite3OsClose(&fd); sqliteFree(zFullPathname); return rc; } nameLen = strlen(zFullPathname); pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); if( pPager==0 ){ - sqlite3Io.xClose(&fd); + sqlite3OsClose(&fd); sqliteFree(zFullPathname); return SQLITE_NOMEM; } @@ -1761,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); + sqlite3OsSeek(pPager->fd, 0); + sqlite3OsRead(pPager->fd, pDest, N); clear_simulated_io_error(); } } @@ -1782,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( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_DISK; return 0; } @@ -1914,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 = sqlite3OsLock(pPager->fd, locktype); }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); if( rc==SQLITE_OK ){ pPager->state = locktype; @@ -1982,14 +1982,14 @@ int sqlite3pager_close(Pager *pPager){ sqlite3pager_rollback(pPager); enable_simulated_io_errors(); if( !MEMDB ){ - sqlite3Io.xUnlock(pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } assert( pPager->errMask || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ - sqlite3Io.xUnlock(pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } break; } @@ -2013,16 +2013,16 @@ int sqlite3pager_close(Pager *pPager){ TRACE2("CLOSE %d\n", PAGERID(pPager)); assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ - sqlite3Io.xClose(&pPager->jfd); + sqlite3OsClose(&pPager->jfd); } sqliteFree(pPager->aInJournal); if( pPager->stmtOpen ){ - sqlite3Io.xClose(&pPager->stfd); + sqlite3OsClose(&pPager->stfd); } - sqlite3Io.xClose(&pPager->fd); + sqlite3OsClose(&pPager->fd); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ - ** sqlite3Io.xDelete(pPager->zFilename); + ** sqlite3Os.xDelete(pPager->zFilename); ** } */ @@ -2131,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 = sqlite3OsFileSize(pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->journalOff==jSz ); } @@ -2144,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 = sqlite3OsSync(pPager->jfd, 0); if( rc!=0 ) return rc; } - rc = sqlite3Io.xSeek(pPager->jfd, + rc = sqlite3OsSeek(pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); if( rc ) return rc; rc = write32bits(pPager->jfd, pPager->nRec); if( rc ) return rc; - rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); if( rc ) return rc; } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3Io.xSync(pPager->jfd, pPager->fullSync); + rc = sqlite3OsSync(pPager->jfd, pPager->fullSync); if( rc!=0 ) return rc; pPager->journalStarted = 1; } @@ -2201,7 +2201,7 @@ static int pager_write_pagelist(PgHdr *pList){ /* At this point there may be either a RESERVED or EXCLUSIVE lock on the ** database file. If there is already an EXCLUSIVE lock, the following - ** calls to sqlite3Io.xLock() are no-ops. + ** calls to sqlite3OsLock() are no-ops. ** ** Moving the lock from RESERVED to EXCLUSIVE actually involves going ** through an intermediate state PENDING. A PENDING lock prevents new @@ -2222,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 = sqlite3OsSeek(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 @@ -2232,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 = sqlite3OsWrite(pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); TEST_INCR(pPager->nWrite); @@ -2279,10 +2279,10 @@ 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( !sqlite3Os.xFileExists(pPager->zJournal) ) return 0; + if( sqlite3OsCheckReservedLock(pPager->fd) ) return 0; if( sqlite3pager_pagecount(pPager)==0 ){ - sqlite3Io.xDelete(pPager->zJournal); + sqlite3Os.xDelete(pPager->zJournal); return 0; }else{ return 1; @@ -2359,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 = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - sqlite3Io.xUnlock(pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } @@ -2375,9 +2375,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** a write lock, so there is never any chance of two or more ** processes opening the journal at the same time. */ - rc = sqlite3Io.xOpenReadOnly(pPager->zJournal, &pPager->jfd); + rc = sqlite3Os.xOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ - sqlite3Io.xUnlock(pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return SQLITE_BUSY; } @@ -2534,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 = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3Io.xRead(pPager->fd, PGHDR_TO_DATA(pPg), + rc = sqlite3OsRead(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( sqlite3OsFileSize(pPager->fd,&fileSize)!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; @@ -2665,7 +2665,7 @@ static int pager_open_journal(Pager *pPager){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } - rc = sqlite3Io.xOpenExclusive(pPager->zJournal, &pPager->jfd, + rc = sqlite3Os.xOpenExclusive(pPager->zJournal, &pPager->jfd, pPager->tempFile); pPager->journalOff = 0; pPager->setMaster = 0; @@ -2673,9 +2673,9 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } - sqlite3Io.xSetFullSync(pPager->jfd, pPager->fullSync); - sqlite3Io.xSetFullSync(pPager->fd, pPager->fullSync); - sqlite3Io.xOpenDirectory(pPager->zDirectory, pPager->jfd); + sqlite3OsSetFullSync(pPager->jfd, pPager->fullSync); + sqlite3OsSetFullSync(pPager->fd, pPager->fullSync); + sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; @@ -2703,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); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } @@ -2747,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 = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ @@ -2858,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 = sqlite3OsWrite(pPager->jfd, &((char*)pData)[-4], szPg); pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); @@ -2907,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 = sqlite3OsWrite(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); @@ -3111,7 +3111,7 @@ int sqlite3pager_commit(Pager *pPager){ return SQLITE_OK; } if( pPager->dirtyCache==0 ){ - /* Exit early (without doing the time-consuming sqlite3Io.xSync() calls) + /* Exit early (without doing the time-consuming sqlite3OsSync() calls) ** if there have been no changes to the database file. */ assert( pPager->needSync==0 ); rc = pager_unwritelock(pPager); @@ -3270,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); + sqlite3OsLock(pPager->fd, SHARED_LOCK); return SQLITE_NOMEM; } #ifndef NDEBUG - rc = sqlite3Io.xFileSize(pPager->jfd, &pPager->stmtJSize); + rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->journalOff ); #endif @@ -3307,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); */ + sqlite3OsSeek(pPager->stfd, 0); + /* sqlite3OsTruncate(pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; } @@ -3511,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 = sqlite3OsSync(pPager->fd, 0); } pPager->state = PAGER_SYNCED; @@ -3625,7 +3625,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ - return sqlite3Io.xLockState(pPager->fd); + return sqlite3OsLockState(pPager->fd); } #endif diff --git a/src/pragma.c b/src/pragma.c index 318e807154..b459afde0f 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.104 2005/11/26 00:25:03 drh Exp $ +** $Id: pragma.c,v 1.105 2005/11/30 03:20:31 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -392,7 +392,7 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } }else{ - if( zRight[0] && !sqlite3Io.xIsDirWritable(zRight) ){ + if( zRight[0] && !sqlite3Os.xIsDirWritable(zRight) ){ sqlite3ErrorMsg(pParse, "not a writable directory"); goto pragma_out; } diff --git a/src/random.c b/src/random.c index 3d0903b4e9..7f38ef0ec7 100644 --- a/src/random.c +++ b/src/random.c @@ -15,7 +15,7 @@ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.13 2005/06/12 21:35:52 drh Exp $ +** $Id: random.c,v 1.14 2005/11/30 03:20:32 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -63,7 +63,7 @@ static int randomByte(){ char k[256]; prng.j = 0; prng.i = 0; - sqlite3OsRandomSeed(k); + sqlite3Os.xRandomSeed(k); for(i=0; i<256; i++){ prng.s[i] = i; } @@ -92,9 +92,9 @@ static int randomByte(){ */ void sqlite3Randomness(int N, void *pBuf){ unsigned char *zBuf = pBuf; - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); while( N-- ){ *(zBuf++) = randomByte(); } - sqlite3OsLeaveMutex(); + sqlite3Os.xLeaveMutex(); } diff --git a/src/test1.c b/src/test1.c index 870b729d02..00c5772c75 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.167 2005/11/29 03:13:22 drh Exp $ +** $Id: test1.c,v 1.168 2005/11/30 03:20:32 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -2440,7 +2440,7 @@ static int test_sqlite3OsOpenReadWrite( return TCL_ERROR; } - rc = sqlite3Io.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy); + rc = sqlite3Os.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; @@ -2471,7 +2471,7 @@ static int test_sqlite3OsClose( if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ return TCL_ERROR; } - rc = sqlite3Io.xClose(&pFile); + rc = sqlite3OsClose(&pFile); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; @@ -2503,16 +2503,16 @@ static int test_sqlite3OsLock( } if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ - rc = sqlite3Io.xLock(pFile, SHARED_LOCK); + rc = sqlite3OsLock(pFile, SHARED_LOCK); } else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ - rc = sqlite3Io.xLock(pFile, RESERVED_LOCK); + rc = sqlite3OsLock(pFile, RESERVED_LOCK); } else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ - rc = sqlite3Io.xLock(pFile, PENDING_LOCK); + rc = sqlite3OsLock(pFile, PENDING_LOCK); } else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ - rc = sqlite3Io.xLock(pFile, EXCLUSIVE_LOCK); + rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); }else{ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetString(objv[0]), @@ -2548,7 +2548,7 @@ static int test_sqlite3OsUnlock( if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ return TCL_ERROR; } - rc = sqlite3Io.xUnlock(pFile, NO_LOCK); + rc = sqlite3OsUnlock(pFile, NO_LOCK); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; @@ -2568,7 +2568,7 @@ static int test_sqlite3OsTempFileName( char zFile[SQLITE_TEMPNAME_SIZE]; int rc; - rc = sqlite3Io.xTempFileName(zFile); + rc = sqlite3Os.xTempFileName(zFile); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; diff --git a/src/test2.c b/src/test2.c index 39e9148974..b7b1c487ee 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.37 2005/11/29 03:13:22 drh Exp $ +** $Id: test2.c,v 1.38 2005/11/30 03:20:32 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -532,20 +532,20 @@ static int fake_big_file( return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; - rc = sqlite3Io.xOpenReadWrite(argv[2], &fd, &readOnly); + rc = sqlite3Os.xOpenReadWrite(argv[2], &fd, &readOnly); if( rc ){ Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); return TCL_ERROR; } offset = n; offset *= 1024*1024; - rc = sqlite3Io.xSeek(fd, offset); + rc = sqlite3OsSeek(fd, offset); if( rc ){ Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0); return TCL_ERROR; } - rc = sqlite3Io.xWrite(fd, "Hello, World!", 14); - sqlite3Io.xClose(&fd); + rc = sqlite3OsWrite(fd, "Hello, World!", 14); + sqlite3OsClose(&fd); if( rc ){ Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); return TCL_ERROR; diff --git a/src/test6.c b/src/test6.c index 87e54f632f..d8f510ecc6 100644 --- a/src/test6.c +++ b/src/test6.c @@ -20,22 +20,24 @@ #include "tcl.h" /* -** A copy of the original sqlite3Io structure +** A copy of the original sqlite3Os structure */ -static struct sqlite3IoVtbl origIo; +static struct sqlite3OsVtbl origOs; /* -** The OsFile structure for the crash-test backend. The pBase field -** points to an OsFile structure for the native backend. +** crashFile is a subclass of OsFile that is taylored for the +** crash test module. */ -struct OsFile { - u8 **apBlk; /* Array of blocks that have been written to. */ - int nBlk; /* Size of apBlock. */ - i64 offset; /* Next character to be read from the file */ - int nMaxWrite; /* Largest offset written to. */ - char *zName; /* File name */ - OsFile *pBase; /* Base class */ - OsFile *pNext; /* Next in a list of them all */ +typedef struct crashFile crashFile; +struct crashFile { + IoMethod const *pMethod; /* Must be first */ + u8 **apBlk; /* Array of blocks that have been written to. */ + int nBlk; /* Size of apBlock. */ + i64 offset; /* Next character to be read from the file */ + int nMaxWrite; /* Largest offset written to. */ + char *zName; /* File name */ + OsFile *pBase; /* The real file */ + crashFile *pNext; /* Next in a list of them all */ }; /* @@ -63,11 +65,11 @@ static char zCrashFile[500]; ** Set the value of the two crash parameters. */ static void setCrashParams(int iDelay, char const *zFile){ - sqlite3OsEnterMutex(); + sqlite3Os.xEnterMutex(); assert( strlen(zFile)nMaxWrite = 0; - pFile->offset = 0; - pFile->nBlk = 0; - pFile->apBlk = 0; - pFile->zName = (char *)(&pFile[1]); - strcpy(pFile->zName, zName); - pFile->pBase = pBase; - pFile->pNext = pAllFiles; - pAllFiles = pFile; -} +/* Forward reference */ +static void initFile(OsFile **pId, char const *zName, OsFile *pBase); /* ** Undo the work done by initFile. Delete the OsFile structure ** and unlink the structure from the pAllFiles list. */ -static void closeFile(OsFile **pId){ - OsFile *pFile = *pId; +static void closeFile(crashFile **pId){ + crashFile *pFile = *pId; if( pFile==pAllFiles ){ pAllFiles = pFile->pNext; }else{ - OsFile *p; + crashFile *p; for(p=pAllFiles; p->pNext!=pFile; p=p->pNext ){ assert( p ); } @@ -138,7 +127,7 @@ static void closeFile(OsFile **pId){ /* ** Read block 'blk' off of the real disk file and into the cache of pFile. */ -static int readBlockIntoCache(OsFile *pFile, int blk){ +static int readBlockIntoCache(crashFile *pFile, int blk){ if( blk>=pFile->nBlk ){ int n = ((pFile->nBlk * 2) + 100 + blk); /* if( pFile->nBlk==0 ){ printf("DIRTY %s\n", pFile->zName); } */ @@ -156,17 +145,17 @@ static int readBlockIntoCache(OsFile *pFile, int blk){ if( !p ) return SQLITE_NOMEM; pFile->apBlk[blk] = p; - rc = origIo.xFileSize(pFile->pBase, &filesize); + rc = sqlite3OsFileSize(pFile->pBase, &filesize); if( rc!=SQLITE_OK ) return rc; if( BLOCK_OFFSET(blk)pBase, blk*BLOCKSIZE); + rc = sqlite3OsSeek(pFile->pBase, blk*BLOCKSIZE); if( BLOCK_OFFSET(blk+1)>filesize ){ len = filesize - BLOCK_OFFSET(blk); } if( rc!=SQLITE_OK ) return rc; - rc = origIo.xRead(pFile->pBase, p, len); + rc = sqlite3OsRead(pFile->pBase, p, len); if( rc!=SQLITE_OK ) return rc; } } @@ -178,7 +167,7 @@ static int readBlockIntoCache(OsFile *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(OsFile *pFile, int crash){ +static int writeCache2(crashFile *pFile, int crash){ int i; int nMax = pFile->nMaxWrite; int rc = SQLITE_OK; @@ -210,7 +199,7 @@ printf("Writing block %d of %s\n", i, pFile->zName); } } if( rc==SQLITE_OK ){ - rc = origIo.xSeek(pFile->pBase, BLOCK_OFFSET(i)); + rc = sqlite3OsSeek(pFile->pBase, BLOCK_OFFSET(i)); } if( rc==SQLITE_OK && !skip ){ int len = BLOCKSIZE; @@ -221,7 +210,7 @@ printf("Writing block %d of %s\n", i, pFile->zName); if( trash ){ sqlite3Randomness(len, p); } - rc = origIo.xWrite(pFile->pBase, p, len); + rc = sqlite3OsWrite(pFile->pBase, p, len); } } sqliteFree(p); @@ -237,11 +226,11 @@ printf("Writing block %d of %s\n", i, pFile->zName); /* ** Write the cache to disk. */ -static int writeCache(OsFile *pFile){ +static int writeCache(crashFile *pFile){ if( pFile->apBlk ){ int c = crashRequired(pFile->zName); if( c ){ - OsFile *p; + crashFile *p; #ifdef TRACE_WRITECACHE printf("\nCrash during sync of %s\n", pFile->zName); #endif @@ -260,18 +249,19 @@ static int writeCache(OsFile *pFile){ ** Close the file. */ static int crashClose(OsFile **pId){ - OsFile *pFile = *pId; + crashFile *pFile = (crashFile*)*pId; if( pFile ){ /* printf("CLOSE %s (%d blocks)\n", pFile->zName, pFile->nBlk); */ writeCache(pFile); - origIo.xClose(&pFile->pBase); + sqlite3OsClose(&pFile->pBase); } - closeFile(pId); + closeFile(&pFile); + *pId = 0; return SQLITE_OK; } static int crashSeek(OsFile *id, i64 offset){ - id->offset = offset; + ((crashFile*)id)->offset = offset; return SQLITE_OK; } @@ -282,7 +272,7 @@ static int crashRead(OsFile *id, void *pBuf, int amt){ int i; u8 *zCsr; int rc = SQLITE_OK; - OsFile *pFile = id; + crashFile *pFile = (crashFile*)id; offset = pFile->offset; end = offset+amt; @@ -306,9 +296,9 @@ static int crashRead(OsFile *id, void *pBuf, int amt){ u8 *pBlk = pFile->apBlk[i]; memcpy(zCsr, &pBlk[off], len); }else{ - rc = origIo.xSeek(id->pBase, BLOCK_OFFSET(i) + off); + rc = sqlite3OsSeek(pFile->pBase, BLOCK_OFFSET(i) + off); if( rc!=SQLITE_OK ) return rc; - rc = origIo.xRead(id->pBase, zCsr, len); + rc = sqlite3OsRead(pFile->pBase, zCsr, len); if( rc!=SQLITE_OK ) return rc; } @@ -316,7 +306,7 @@ static int crashRead(OsFile *id, void *pBuf, int amt){ } assert( zCsr==&((u8 *)pBuf)[amt] ); - id->offset = end; + pFile->offset = end; return rc; } @@ -327,8 +317,9 @@ static int crashWrite(OsFile *id, const void *pBuf, int amt){ int i; const u8 *zCsr; int rc = SQLITE_OK; + crashFile *pFile = (crashFile*)id; - offset = id->offset; + offset = pFile->offset; end = offset+amt; blk = (offset/BLOCKSIZE); @@ -339,11 +330,11 @@ static int crashWrite(OsFile *id, const void *pBuf, int amt){ int len = 0; /* Make sure the block is in the cache */ - rc = readBlockIntoCache(id, i); + rc = readBlockIntoCache(pFile, i); if( rc!=SQLITE_OK ) return rc; /* Write into the cache */ - pBlk = id->apBlk[i]; + pBlk = pFile->apBlk[i]; assert( pBlk ); if( BLOCK_OFFSET(i) < offset ){ @@ -356,11 +347,11 @@ static int crashWrite(OsFile *id, const void *pBuf, int amt){ memcpy(&pBlk[off], zCsr, len); zCsr += len; } - if( id->nMaxWritenMaxWrite = end; + if( pFile->nMaxWritenMaxWrite = end; } assert( zCsr==&((u8 *)pBuf)[amt] ); - id->offset = end; + pFile->offset = end; return rc; } @@ -369,11 +360,7 @@ static int crashWrite(OsFile *id, const void *pBuf, int amt){ ** real sync() function. */ static int crashSync(OsFile *id, int dataOnly){ - int rc; - /* printf("SYNC %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */ - rc = writeCache(id); - /* if( rc!=SQLITE_OK ) return rc; rc = origIo.xSync(id->pBase, dataOnly); */ - return rc; + return writeCache((crashFile*)id); } /* @@ -382,8 +369,9 @@ static int crashSync(OsFile *id, int dataOnly){ ** is written to disk. */ static int crashTruncate(OsFile *id, i64 nByte){ - id->nMaxWrite = nByte; - return origIo.xTruncate(id->pBase, nByte); + crashFile *pFile = (crashFile*)id; + pFile->nMaxWrite = nByte; + return sqlite3OsTruncate(pFile->pBase, nByte); } /* @@ -391,9 +379,10 @@ static int crashTruncate(OsFile *id, i64 nByte){ ** the file, then return this size instead of the on-disk size. */ static int crashFileSize(OsFile *id, i64 *pSize){ - int rc = origIo.xFileSize(id->pBase, pSize); - if( rc==SQLITE_OK && pSize && *pSizenMaxWrite ){ - *pSize = id->nMaxWrite; + crashFile *pFile = (crashFile*)id; + int rc = sqlite3OsFileSize(pFile->pBase, pSize); + if( rc==SQLITE_OK && pSize && *pSizenMaxWrite ){ + *pSize = pFile->nMaxWrite; } return rc; } @@ -405,7 +394,7 @@ static int crashFileSize(OsFile *id, i64 *pSize){ */ static int crashOpenReadWrite(const char *zFilename, OsFile **pId,int *pRdonly){ OsFile *pBase = 0; - int rc = origIo.xOpenReadWrite(zFilename, &pBase, pRdonly); + int rc = origOs.xOpenReadWrite(zFilename, &pBase, pRdonly); if( !rc ){ initFile(pId, zFilename, pBase); } @@ -413,7 +402,7 @@ static int crashOpenReadWrite(const char *zFilename, OsFile **pId,int *pRdonly){ } static int crashOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ OsFile *pBase = 0; - int rc = origIo.xOpenExclusive(zFilename, &pBase, delFlag); + int rc = origOs.xOpenExclusive(zFilename, &pBase, delFlag); if( !rc ){ initFile(pId, zFilename, pBase); } @@ -421,7 +410,7 @@ static int crashOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ } static int crashOpenReadOnly(const char *zFilename, OsFile **pId){ OsFile *pBase = 0; - int rc = origIo.xOpenReadOnly(zFilename, &pBase); + int rc = origOs.xOpenReadOnly(zFilename, &pBase); if( !rc ){ initFile(pId, zFilename, pBase); } @@ -429,12 +418,9 @@ static int crashOpenReadOnly(const char *zFilename, OsFile **pId){ } /* -** OpenDirectory and SyncDirectory are no-ops +** OpenDirectory is a no-op */ -static int crashOpenDir(const char *zName, OsFile *id){ - return SQLITE_OK; -} -static int crashSyncDir(const char *zName){ +static int crashOpenDir(OsFile *id, const char *zName){ return SQLITE_OK; } @@ -443,28 +429,69 @@ static int crashSyncDir(const char *zName){ ** file descriptor. */ int crashLock(OsFile *id, int lockType){ - return origIo.xLock(id->pBase, lockType); + return sqlite3OsLock(((crashFile*)id)->pBase, lockType); } int crashUnlock(OsFile *id, int lockType){ - return origIo.xUnlock(id->pBase, lockType); + return sqlite3OsUnlock(((crashFile*)id)->pBase, lockType); } int crashCheckReservedLock(OsFile *id){ - return origIo.xCheckReservedLock(id->pBase); + return sqlite3OsCheckReservedLock(((crashFile*)id)->pBase); } void crashSetFullSync(OsFile *id, int setting){ return; /* This is a no-op */ } int crashLockState(OsFile *id){ - return origIo.xLockState(id->pBase); + return sqlite3OsLockState(((crashFile*)id)->pBase); } /* ** Return the underlying file handle. */ int crashFileHandle(OsFile *id){ - return origIo.xFileHandle(id->pBase); + return sqlite3OsFileHandle(((crashFile*)id)->pBase); } +/* +** This vector defines all the methods that can operate on an OsFile +** for the crash tester. +*/ +static const IoMethod crashIoMethod = { + crashClose, + crashOpenDir, + crashRead, + crashWrite, + crashSeek, + crashTruncate, + crashSync, + crashSetFullSync, + crashFileHandle, + crashFileSize, + crashLock, + crashUnlock, + crashLockState, + crashCheckReservedLock, +}; + + +/* +** Initialise the os_test.c specific fields of pFile. +*/ +static void initFile(OsFile **pId, char const *zName, OsFile *pBase){ + crashFile *pFile = sqliteMalloc(sizeof(crashFile) + strlen(zName)+1); + pFile->pMethod = &crashIoMethod; + pFile->nMaxWrite = 0; + pFile->offset = 0; + pFile->nBlk = 0; + pFile->apBlk = 0; + pFile->zName = (char *)(&pFile[1]); + strcpy(pFile->zName, zName); + pFile->pBase = pBase; + pFile->pNext = pAllFiles; + pAllFiles = pFile; + *pId = (OsFile*)pFile; +} + + /* ** tclcmd: sqlite_crashparams DELAY CRASHFILE ** @@ -491,30 +518,12 @@ static int crashParamsObjCmd( return TCL_ERROR; } setCrashParams(delay, zFile); - origIo = sqlite3Io; - /* xDelete unchanged */ - /* xFileExists unchanged */ - sqlite3Io.xOpenReadWrite = crashOpenReadWrite; - sqlite3Io.xOpenExclusive = crashOpenExclusive; - sqlite3Io.xOpenReadOnly = crashOpenReadOnly; - sqlite3Io.xOpenDirectory = crashOpenDir; - sqlite3Io.xSyncDirectory = crashSyncDir; - /* xTempFileName unchanged */ - /* xIsDirWritable unchanged */ - sqlite3Io.xClose = crashClose; - sqlite3Io.xRead = crashRead; - sqlite3Io.xWrite = crashWrite; - sqlite3Io.xSeek = crashSeek; - sqlite3Io.xSync = crashSync; - sqlite3Io.xTruncate = crashTruncate; - sqlite3Io.xFileSize = crashFileSize; - /* xFullPathname unchanged */ - sqlite3Io.xLock = crashLock; - sqlite3Io.xUnlock = crashUnlock; - sqlite3Io.xCheckReservedLock = crashCheckReservedLock; - sqlite3Io.xSetFullSync = crashSetFullSync; - sqlite3Io.xFileHandle = crashFileHandle; - sqlite3Io.xLockState = crashLockState; + if( origOs.xOpenReadWrite==0 ){ + origOs = sqlite3Os; + sqlite3Os.xOpenReadWrite = crashOpenReadWrite; + sqlite3Os.xOpenExclusive = crashOpenExclusive; + sqlite3Os.xOpenReadOnly = crashOpenReadOnly; + } return TCL_OK; } diff --git a/src/vacuum.c b/src/vacuum.c index bf9fd66b99..b0b1a6d516 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -14,7 +14,7 @@ ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.48 2005/11/26 00:25:04 drh Exp $ +** $Id: vacuum.c,v 1.49 2005/11/30 03:20:32 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -146,7 +146,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ do { zTemp[nFilename] = '-'; randomName((unsigned char*)&zTemp[nFilename+1]); - } while( sqlite3Io.xFileExists(zTemp) ); + } while( sqlite3Os.xFileExists(zTemp) ); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash @@ -300,7 +300,7 @@ end_of_vacuum: rc = rc2; } if( zTemp ){ - sqlite3Io.xDelete(zTemp); + sqlite3Os.xDelete(zTemp); sqliteFree(zTemp); } sqliteFree( zSql ); diff --git a/src/vdbe.c b/src/vdbe.c index 8684af553b..e4cba6c37f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.500 2005/11/26 00:25:04 drh Exp $ +** $Id: vdbe.c,v 1.501 2005/11/30 03:20:32 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -422,7 +422,7 @@ int sqlite3VdbeExec( } sqlite3VdbePrintOp(p->trace, pc, pOp); } - if( p->trace==0 && pc==0 && sqlite3Io.xFileExists("vdbe_sqltrace") ){ + if( p->trace==0 && pc==0 && sqlite3Os.xFileExists("vdbe_sqltrace") ){ sqlite3VdbePrintSql(p); } #endif diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 2fd54f38e3..4a5dc985f7 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -191,7 +191,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ } if( db->xProfile && !db->init.busy ){ double rNow; - sqlite3OsCurrentTime(&rNow); + sqlite3Os.xCurrentTime(&rNow); p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0; } #endif @@ -228,7 +228,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ double rNow; u64 elapseTime; - sqlite3OsCurrentTime(&rNow); + sqlite3Os.xCurrentTime(&rNow); elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime; assert( p->nOp>0 ); assert( p->aOp[p->nOp-1].opcode==OP_Noop ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 782e0163c6..0c62c07d4b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -273,7 +273,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){ /* If we never rollback a statement transaction, then statement ** transactions are not needed. So change every OP_Statement - ** opcode into an OP_Noop. This avoid a call to sqlite3Io.xOpenExclusive() + ** opcode into an OP_Noop. This avoid a call to sqlite3Os.xOpenExclusive() ** which can be expensive on some platforms. */ if( hasStatementBegin && !doesStatementRollback ){ @@ -755,7 +755,7 @@ void sqlite3VdbeMakeReady( #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 - || sqlite3Io.xFileExists("vdbe_explain") + || sqlite3Os.xFileExists("vdbe_explain") ){ int i; printf("VDBE Program Listing:\n"); @@ -764,7 +764,7 @@ void sqlite3VdbeMakeReady( sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); } } - if( sqlite3Io.xFileExists("vdbe_trace") ){ + if( sqlite3Os.xFileExists("vdbe_trace") ){ p->trace = stdout; } #endif @@ -978,10 +978,10 @@ static int vdbeCommit(sqlite3 *db){ if( !zMaster ){ return SQLITE_NOMEM; } - }while( sqlite3Io.xFileExists(zMaster) ); + }while( sqlite3Os.xFileExists(zMaster) ); /* Open the master journal. */ - rc = sqlite3Io.xOpenExclusive(zMaster, &master, 0); + rc = sqlite3Os.xOpenExclusive(zMaster, &master, 0); if( rc!=SQLITE_OK ){ sqliteFree(zMaster); return rc; @@ -1002,10 +1002,10 @@ static int vdbeCommit(sqlite3 *db){ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ needSync = 1; } - rc = sqlite3Io.xWrite(master, zFile, strlen(zFile)+1); + rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1); if( rc!=SQLITE_OK ){ - sqlite3Io.xClose(&master); - sqlite3Io.xDelete(zMaster); + sqlite3OsClose(&master); + sqlite3Os.xDelete(zMaster); sqliteFree(zMaster); return rc; } @@ -1017,11 +1017,11 @@ 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 = sqlite3OsOpenDirectory(master, zMainFile); if( rc!=SQLITE_OK || - (needSync && (rc=sqlite3Io.xSync(master,0))!=SQLITE_OK) ){ - sqlite3Io.xClose(&master); - sqlite3Io.xDelete(zMaster); + (needSync && (rc=sqlite3OsSync(master,0))!=SQLITE_OK) ){ + sqlite3OsClose(&master); + sqlite3Os.xDelete(zMaster); sqliteFree(zMaster); return rc; } @@ -1041,23 +1041,23 @@ static int vdbeCommit(sqlite3 *db){ if( pBt && sqlite3BtreeIsInTrans(pBt) ){ rc = sqlite3BtreeSync(pBt, zMaster); if( rc!=SQLITE_OK ){ - sqlite3Io.xClose(&master); + sqlite3OsClose(&master); sqliteFree(zMaster); return rc; } } } - sqlite3Io.xClose(&master); + sqlite3OsClose(&master); /* Delete the master journal file. This commits the transaction. After ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3Io.xDelete(zMaster); + rc = sqlite3Os.xDelete(zMaster); assert( rc==SQLITE_OK ); sqliteFree(zMaster); zMaster = 0; - rc = sqlite3Io.xSyncDirectory(zMainFile); + rc = sqlite3Os.xSyncDirectory(zMainFile); if( rc!=SQLITE_OK ){ /* This is not good. The master journal file has been deleted, but ** the directory sync failed. There is no completely safe course of