diff --git a/manifest b/manifest index a031cf3eb0..58f528f71a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sadding\smutexes.\s\sCompiles\swithout\sSQLITE_OMIT_SHARED_CACHE\sbut\swe\nget\san\sassertion\sfault\son\sthe\sshared\scache\stesting.\s(CVS\s4239) -D 2007-08-17T01:14:38 +C Begin\smigration\sto\susing\ssqlite3_vfs\sinterface.\s(CVS\s4240) +D 2007-08-17T15:53:36 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -68,7 +68,7 @@ F src/alter.c f0aac0060ae8102e58f210b44d35b53438d53173 F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8 F src/auth.c 5ea90bc93dfea46e9fe4bf531e14c7cd98219ecb -F src/btree.c 409e7362338d3cf1f72961a01e75e9fbb577cc9f +F src/btree.c c4e563b8a8301413984156909461dea882eabed8 F src/btree.h 91ee529d581c1473d8e6e15299acc3b8de1d0674 F src/btreeInt.h 6329e955a7dadd8628d5866e2465721b5fd25ef2 F src/build.c add67be992307b4b11849a6611bfd3352aacde92 @@ -84,46 +84,46 @@ F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c F src/legacy.c 6013a7cb7da1b72550b3d35d4fc598b3c3e5b8c1 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 -F src/loadext.c aa1c6e584d39cc241226ec9390387bc2d4a23e8f -F src/main.c 6e12fdab03efb8fb17aee8cfcd3bc32329cf1cda +F src/loadext.c c0ccda3dbda109da087a8fd762deebe5fdf24a1d +F src/main.c cb6635a4d2fe2b140942338ff5ab605f4c08fa5d F src/malloc.c 613c65f12ff0ee4edd017aa458209ab7a23cd7b1 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 -F src/mem1.c 2c6a6e3b2c9c7cb8d398a8468095032407c3e0b7 +F src/mem1.c 30bf8be3846f92fdf88c490c5e5378512383bcbe F src/mem2.c 661ca7ebf6e4b964fecc95d24e8c89dbcfc9dfea F src/mutex.c 67b2efd36a1e67a7dc7b7fa852fd69953462c943 -F src/os.c e2faefbe0f5a8ca5e3b1c49ee1b5c6cfa0f0e279 -F src/os.h 8eff07babf74e5bc3f895f8a6c7c294dad5ff997 +F src/os.c c8034df18a06cd1e9dde7d6e096b6709345ee72e +F src/os.h e54a81bc851724ad17206bfcb4a474f9481f9fc0 F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c F src/os_os2.c cba4e96fadb949076c717108fe0599d1a3c2e446 F src/os_os2.h e5f17dd69333632bbc3112881ea407c37d245eb3 F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 -F src/os_unix.c e685354a7f21cb47741efc6c681c5acea74597fc +F src/os_unix.c bf86c474a5febb67684b967a8d2816b1d7f26891 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c d868d5f9e95ec9c1b9e2a30c54c996053db6dddd F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 812a3f78ea398764991d668d2d3d81a951e58fa3 -F src/pager.h 94110a5570dca30d54a883e880a3633b2e4c05ae +F src/pager.c ee60b932e7b4ba355f2606505415b4d5183b1de1 +F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8 F src/parse.y c03529c3b82702ada98ce405b390e3a9409708cf -F src/pragma.c 873b0b2ab56248ef76d0387193b8f7a87782b73c +F src/pragma.c 8f5e37c3cf6dbdeb3645bb80cc58cfc3324c0178 F src/prepare.c 03292beeffce2d65debab12508a8ec1f5aec7241 F src/printf.c a8f46e0ed360c18d40e89aa636533be300b406c2 -F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88 +F src/random.c 00b30565f018f3a256c157432935de070231c73b F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb -F src/sqlite.h.in 07eea55853b739b372d4744ceefd08795d013be9 +F src/sqlite.h.in f29eb4bc8dc8f4dc61690f339ebb82fec010d4c1 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b -F src/sqliteInt.h 7298c560e00f2305e2ecc1d2cbdd66134f5049de +F src/sqliteInt.h 442a6861cf3f535f410acad19a55b2fbca2564a7 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008 F src/tclsqlite.c 0606c4f31711492eb4d7480a981eebb80914f3d9 -F src/test1.c a1d6eb85149053fac75b01b71439f00908a07c68 -F src/test2.c 4db48e4a487d4d18c2926d9600875613ad286ba8 +F src/test1.c a226ab03048491aa6c5d43d26097df96bdb162e7 +F src/test2.c 47bb59a0198651a9f0551ec956de151da7c24575 F src/test3.c b87e8fcce45e1d3153aae9f04236076b7707a714 F src/test4.c d22cb3ab4f9fdfd0a595b70d5328cee923b7322c F src/test5.c 7bc8a87c2b6fd076ec2ca9972946e71a367883ad -F src/test6.c 14919eef8504da6814db7ab19608c786d836fcb2 +F src/test6.c 80990810f64ee96ba27cda5c09624bff383caa60 F src/test7.c 91d914c2c2b2806157213f41f4185ad3a4970c07 F src/test8.c 719c284607c1e91a893f5425df1e92b74c859aef F src/test9.c c0f38f7795cc51d37db6c63874d90f40f10d0f0e @@ -144,11 +144,11 @@ F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9 F src/utf.c 853f97ce0d3cff8dbaef517a6dc475f7001a67c5 F src/util.c 0273ba16dbf9bab423b1b84c6d548d8f14c25f64 F src/vacuum.c f45bd9d3aad8d68bb3b85cf89d7a797be5075fde -F src/vdbe.c 10052a4f1e42e629aee0466b40983e2b61e0295a +F src/vdbe.c b5cd895a0516466daacc564da332589a903e2eb0 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 F src/vdbeInt.h 8e360d326328e7a66100f468697edf9cfb4567dc -F src/vdbeapi.c a503e3762826d55e808b28393ae1d7b0fa36b1e9 -F src/vdbeaux.c c6d50887e8f29706ae35b965298e58fa6ba0e9bf +F src/vdbeapi.c ddfe341249929b89c47a0ff77f8043ef0987612b +F src/vdbeaux.c 6468d5665a3dd932c2e7e4f6b1c0319334b9887a F src/vdbeblob.c cf9ee3c7d9977cbd896f8b118da4fb4268637f4f F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 019952d44066a24aef70ca8c284cfd2d1073c398 @@ -529,7 +529,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 160593dcc5690af715b775c81137c6e09cca6454 -R 5d5493a8682338889467b44d542e4cdc -U drh -Z d35e1fbff49f629248bfcae9f72cc56d +P 4c1e9ffebe7c611a8b6a89153ae97ab9bca19ea3 +R 473ba7528424cad7a8d671117a18b080 +U danielk1977 +Z ac059cef33a845a67fcbf5f572a89687 diff --git a/manifest.uuid b/manifest.uuid index 8ac8ae7697..660adc2420 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c1e9ffebe7c611a8b6a89153ae97ab9bca19ea3 \ No newline at end of file +af3e3c7acdc67013dd733effebe981620d922dd1 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index ce78a46e8d..f1ad2d3ce9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.399 2007/08/17 01:14:38 drh Exp $ +** $Id: btree.c,v 1.400 2007/08/17 15:53:36 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -1063,6 +1063,7 @@ int sqlite3BtreeOpen( Btree **ppBtree, /* Pointer to new Btree object written here */ int flags /* Options */ ){ + sqlite3_vfs *pVfs = (pSqlite?pSqlite->pVfs:sqlite3_find_vfs(0)); BtShared *pBt = 0; /* Shared part of btree structure */ Btree *p; /* Handle to return */ int rc = SQLITE_OK; @@ -1137,7 +1138,7 @@ int sqlite3BtreeOpen( rc = SQLITE_NOMEM; goto btree_open_out; } - rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags); + rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc==SQLITE_OK ){ rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } diff --git a/src/loadext.c b/src/loadext.c index de085c7f14..4f6e3b3dbd 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -267,6 +267,7 @@ int sqlite3_load_extension( const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ){ + sqlite3_vfs *pVfs = db->pVfs; void *handle; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); char *zErrmsg = 0; @@ -289,7 +290,7 @@ int sqlite3_load_extension( zProc = "sqlite3_extension_init"; } - handle = sqlite3OsDlopen(zFile); + handle = sqlite3OsDlOpen(pVfs, zFile); if( handle==0 ){ if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("unable to open shared library [%s]", zFile); @@ -297,20 +298,20 @@ int sqlite3_load_extension( return SQLITE_ERROR; } xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - sqlite3OsDlsym(handle, zProc); + sqlite3OsDlSym(pVfs, handle, zProc); if( xInit==0 ){ if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]", zProc, zFile); } - sqlite3OsDlclose(handle); + sqlite3OsDlClose(pVfs, handle); return SQLITE_ERROR; }else if( xInit(db, &zErrmsg, &sqlite3_apis) ){ if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); } sqlite3_free(zErrmsg); - sqlite3OsDlclose(handle); + sqlite3OsDlClose(pVfs, handle); return SQLITE_ERROR; } @@ -337,7 +338,7 @@ int sqlite3_load_extension( void sqlite3CloseExtensions(sqlite3 *db){ int i; for(i=0; inExtension; i++){ - sqlite3OsDlclose(db->aExtension[i]); + sqlite3OsDlClose(db->pVfs, db->aExtension[i]); } sqlite3_free(db->aExtension); } @@ -372,14 +373,14 @@ static void **aAutoExtension = 0; int sqlite3_auto_extension(void *xInit){ int i; int rc = SQLITE_OK; - sqlite3OsEnterMutex(); + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL); + sqlite3_mutex_enter(mutex); for(i=0; i=nAutoExtension ){ xInit = 0; go = 0; @@ -426,7 +429,7 @@ int sqlite3AutoLoadExtensions(sqlite3 *db){ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) aAutoExtension[i]; } - sqlite3OsLeaveMutex(); + sqlite3_mutex_leave(mutex); if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){ sqlite3Error(db, SQLITE_ERROR, "automatic extension loading failed: %s", zErrmsg); diff --git a/src/main.c b/src/main.c index 4e8b7a8a77..b3eab17579 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.383 2007/08/17 01:14:38 drh Exp $ +** $Id: main.c,v 1.384 2007/08/17 15:53:36 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -304,7 +304,8 @@ static int sqliteDefaultBusyCallback( static const u8 totals[] = { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; # define NDELAY (sizeof(delays)/sizeof(delays[0])) - int timeout = ((sqlite3 *)ptr)->busyTimeout; + sqlite3 *db = (sqlite3 *)ptr; + int timeout = db->busyTimeout; int delay, prior; assert( count>=0 ); @@ -319,7 +320,7 @@ static int sqliteDefaultBusyCallback( delay = timeout - prior; if( delay<=0 ) return 0; } - sqlite3OsSleep(delay); + sqlite3OsSleep(db->pVfs, delay); return 1; #else int timeout = ((sqlite3 *)ptr)->busyTimeout; @@ -898,6 +899,7 @@ static int openDatabase( /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; + db->pVfs = sqlite3_find_vfs(0); db->errMask = 0xff; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; @@ -1374,7 +1376,9 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ ** Sleep for a little while. Return the amount of time slept. */ int sqlite3_sleep(int ms){ - return sqlite3OsSleep(ms); + sqlite3_vfs *pVfs; + pVfs = sqlite3_find_vfs(0); + return sqlite3OsSleep(pVfs, 1000*ms); } /* diff --git a/src/mem1.c b/src/mem1.c index 4fc77b04fe..52f61547f3 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -12,7 +12,7 @@ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem1.c,v 1.5 2007/08/16 19:40:17 drh Exp $ +** $Id: mem1.c,v 1.6 2007/08/17 15:53:36 danielk1977 Exp $ */ /* @@ -204,7 +204,7 @@ void *sqlite3_realloc(void *pPrior, unsigned int nBytes){ } if( nBytes==0 ){ sqlite3_free(pPrior); - return; + return 0; } p = pPrior; p--; diff --git a/src/os.c b/src/os.c index d55cfa7032..4307a57c60 100644 --- a/src/os.c +++ b/src/os.c @@ -24,16 +24,9 @@ ** of this would be completely automatic if SQLite were coded using ** C++ instead of plain old C. */ -int sqlite3OsClose(sqlite3_file **pId){ - int rc = SQLITE_OK; - sqlite3_file *id; - if( pId!=0 && (id = *pId)!=0 ){ - rc = id->pMethods->xClose(id); - if( rc==SQLITE_OK ){ - *pId = 0; - } - } - return rc; +int sqlite3OsClose(sqlite3_file *pId){ + if( !pId->pMethods ) return SQLITE_OK; + return pId->pMethods->xClose(pId); } int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ return id->pMethods->xRead(id, pBuf, amt, offset); @@ -82,17 +75,83 @@ int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ } #endif -#ifdef SQLITE_ENABLE_REDEF_IO -/* -** A function to return a pointer to the virtual function table. -** This routine really does not accomplish very much since the -** virtual function table is a global variable and anybody who -** can call this function can just as easily access the variable -** for themselves. Nevertheless, we include this routine for -** backwards compatibility with an earlier redefinable I/O -** interface design. -*/ -struct sqlite3OsVtbl *sqlite3_os_switch(void){ - return &sqlite3Os; +int sqlite3OsOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pFlagsOut +){ + return pVfs->xOpen(pVfs->pAppData, zPath, pFile, flags, pFlagsOut); } -#endif +int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath){ + return pVfs->xDelete(pVfs->pAppData, zPath); +} +int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ + return pVfs->xAccess(pVfs->pAppData, zPath, flags); +} +int sqlite3OsGetTempName(sqlite3_vfs *pVfs, char *zBufOut){ + return pVfs->xGetTempName(pVfs->pAppData, zBufOut); +} +int sqlite3OsFullPathname(sqlite3_vfs *pVfs, const char *zPath, char *zPathOut){ + return pVfs->xFullPathname(pVfs->pAppData, zPath, zPathOut); +} +void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return pVfs->xDlOpen(pVfs->pAppData, zPath); +} +void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + pVfs->xDlError(pVfs->pAppData, nByte, zBufOut); +} +void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return pVfs->xDlSym(pHandle, zSymbol); +} +void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ + pVfs->xDlClose(pHandle); +} +int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return pVfs->xRandomness(pVfs->pAppData, nByte, zBufOut); +} +int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ + return pVfs->xSleep(pVfs->pAppData, nMicro); +} +int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut); +} + +int sqlite3OsOpenMalloc( + sqlite3_vfs *pVfs, + const char *zFile, + sqlite3_file **ppFile, + int flags +){ + int rc = SQLITE_NOMEM; + sqlite3_file *pFile; + pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile); + if( pFile ){ + rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, 0); + if( rc!=SQLITE_OK ){ + sqlite3_free(pFile); + }else{ + *ppFile = pFile; + } + } + return rc; +} +int sqlite3OsCloseFree(sqlite3_file *pFile){ + int rc = SQLITE_OK; + if( pFile ){ + rc = sqlite3OsClose(pFile); + sqlite3_free(pFile); + } + return rc; +} + +/* +** Default vfs implementation. Defined by the various os_X.c implementations. +*/ +extern sqlite3_vfs sqlite3DefaultVfs; + +sqlite3_vfs *sqlite3_find_vfs(const char *zVfs){ + return &sqlite3DefaultVfs; +} + diff --git a/src/os.h b/src/os.h index 30bc914433..d6b3f5a339 100644 --- a/src/os.h +++ b/src/os.h @@ -121,6 +121,8 @@ # define TEMP_FILE_PREFIX "etilqs_" #endif +#if 0 + /* ** Define the interfaces for Unix, Windows, and OS/2. */ @@ -200,6 +202,7 @@ #define sqlite3OsDlclose sqlite3Os2Dlclose #endif +#endif @@ -345,10 +348,10 @@ extern unsigned int sqlite3_pending_byte; #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 -/* -** Prototypes for operating system interface routines. +/* +** Functions for accessing sqlite3_file methods */ -int sqlite3OsClose(sqlite3_file**); +int sqlite3OsClose(sqlite3_file*); int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); int sqlite3OsTruncate(sqlite3_file*, i64 size); @@ -361,10 +364,33 @@ int sqlite3OsCheckReservedLock(sqlite3_file *id); int sqlite3OsSectorSize(sqlite3_file *id); int sqlite3OsDeviceCharacteristics(sqlite3_file *id); +/* +** Functions for accessing sqlite3_vfs methods +*/ +int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +int sqlite3OsDelete(sqlite3_vfs *, const char *); +int sqlite3OsAccess(sqlite3_vfs *, const char *, int); +int sqlite3OsGetTempName(sqlite3_vfs *, char *); +int sqlite3OsFullPathname(sqlite3_vfs *, const char *, char *); +void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +void sqlite3OsDlError(sqlite3_vfs *, int, char *); +void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *); +void sqlite3OsDlClose(sqlite3_vfs *, void *); +int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +int sqlite3OsSleep(sqlite3_vfs *, int); +int sqlite3OsCurrentTime(sqlite3_vfs *, double*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int); +int sqlite3OsCloseFree(sqlite3_file *); + +#if 0 int sqlite3OsOpenReadWrite(const char*, sqlite3_file**, int*); int sqlite3OsOpenExclusive(const char*, sqlite3_file**, int); int sqlite3OsOpenReadOnly(const char*, sqlite3_file**); - int sqlite3OsDelete(const char*); int sqlite3OsFileExists(const char*); char *sqlite3OsFullPathname(const char*); @@ -385,6 +411,7 @@ int sqlite3OsAllocationSize(void *); void *sqlite3OsDlopen(const char*); void *sqlite3OsDlsym(void*, const char*); int sqlite3OsDlclose(void*); +#endif #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) int sqlite3OsFileHandle(sqlite3_file *id); @@ -478,7 +505,7 @@ struct sqlite3OsVtbl { sqlite3OsEnterMutex, sqlite3OsLeaveMutex, sqlite3OsInMutex, - sqlite3OsThreadSpecificData, + 0, sqlite3OsMalloc, sqlite3OsRealloc, sqlite3OsFree, diff --git a/src/os_unix.c b/src/os_unix.c index 71f4bafdd8..a3d3ba4ec5 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -74,6 +74,10 @@ # define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 #endif +/* +** Maximum supported path-length. +*/ +#define MAX_PATHNAME 512 /* @@ -386,6 +390,13 @@ typedef enum { } sqlite3LockingStyle; #endif /* SQLITE_ENABLE_LOCKING_STYLE */ +static void enterMutex(){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); +} +static void leaveMutex(){ + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); +} + #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others @@ -529,7 +540,6 @@ static void testThreadLockingBehavior(int fd_orig){ ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ - assert( sqlite3OsInMutex(1) ); if (pLock == NULL) return; pLock->nRef--; @@ -543,7 +553,6 @@ static void releaseLockInfo(struct lockInfo *pLock){ ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ - assert( sqlite3OsInMutex(1) ); if (pOpen == NULL) return; pOpen->nRef--; @@ -646,7 +655,6 @@ static int findLockInfo( rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; - assert( sqlite3OsInMutex(1) ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; @@ -820,6 +828,7 @@ static int allocateUnixFile( ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ +#if 0 int sqlite3UnixOpenReadWrite( const char *zFilename, sqlite3_file **pId, @@ -903,6 +912,7 @@ int sqlite3UnixOpenReadOnly(const char *zFilename, sqlite3_file **pId){ zFilename, pId, allocateUnixFile(h, pId, zFilename, 0) ); } +#endif /* ** Attempt to open a file descriptor for the directory that contains a @@ -943,46 +953,6 @@ static int unixOpenDirectory( return SQLITE_OK; } -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least SQLITE_TEMPNAME_SIZE characters. -*/ -int sqlite3UnixTempFileName(char *zBuf){ - static const char *azDirs[] = { - 0, - "/var/tmp", - "/usr/tmp", - "/tmp", - ".", - }; - static const unsigned char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - struct stat buf; - const char *zDir = "."; - azDirs[0] = sqlite3_temp_directory; - for(i=0; ipLock is shared across threads */ + enterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ @@ -1346,7 +1316,7 @@ static int unixCheckReservedLock(sqlite3_file *id){ } } - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; @@ -1428,7 +1398,7 @@ static int unixLock(sqlite3_file *id, int locktype){ /* 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. + ** enterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -1444,13 +1414,13 @@ static int unixLock(sqlite3_file *id, int locktype){ /* This mutex is needed because pFile->pLock is shared across threads */ - sqlite3OsEnterMutex(); + enterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } pLock = pFile->pLock; @@ -1565,7 +1535,7 @@ static int unixLock(sqlite3_file *id, int locktype){ } end_lock: - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -1595,7 +1565,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - sqlite3OsEnterMutex(); + enterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ @@ -1656,7 +1626,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ pOpen->aPending = 0; } } - sqlite3OsLeaveMutex(); + leaveMutex(); pFile->locktype = locktype; return rc; } @@ -1670,7 +1640,7 @@ static int unixClose(sqlite3_file *id){ unixUnlock(id, NO_LOCK); if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); if( pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just @@ -1695,11 +1665,11 @@ static int unixClose(sqlite3_file *id){ releaseLockInfo(pFile->pLock); releaseOpenCnt(pFile->pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); pFile->isOpen = 0; OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); - sqlite3_free(id); + memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } @@ -1806,7 +1776,7 @@ static int afpUnixLock(OsFile *id, int locktype) locktypeName(locktype), locktypeName(pFile->locktype), getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the afp_end_lock: exit path, as - ** sqlite3OsEnterMutex() hasn't been called yet. + ** enterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -1822,13 +1792,13 @@ static int afpUnixLock(OsFile *id, int locktype) /* This mutex is needed because pFile->pLock is shared across threads */ - sqlite3OsEnterMutex(); + enterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } @@ -1915,7 +1885,7 @@ static int afpUnixLock(OsFile *id, int locktype) } afp_end_lock: - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -1945,7 +1915,7 @@ static int afpUnixUnlock(OsFile *id, int locktype) { if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - sqlite3OsEnterMutex(); + enterMutex(); if( pFile->locktype>SHARED_LOCK ){ if( locktype==SHARED_LOCK ){ int failed = 0; @@ -1989,7 +1959,7 @@ static int afpUnixUnlock(OsFile *id, int locktype) { } if (rc == SQLITE_OK) pFile->locktype = locktype; - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } @@ -2103,10 +2073,10 @@ static int flockUnixClose(OsFile **pId) { if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2221,11 +2191,11 @@ static int dotlockUnixClose(OsFile **pId) { if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2263,11 +2233,11 @@ static int nolockUnixClose(OsFile **pId) { if( !id ) return SQLITE_OK; if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2278,56 +2248,6 @@ static int nolockUnixClose(OsFile **pId) { #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -/* -** Turn a relative pathname into a full pathname. Return a pointer -** to the full pathname stored in space obtained from sqliteMalloc(). -** The calling function is responsible for freeing this space once it -** is no longer needed. -*/ -char *sqlite3UnixFullPathname(const char *zRelative){ - char *zFull = 0; - if( zRelative[0]=='/' ){ - sqlite3SetString(&zFull, zRelative, (char*)0); - }else{ - char *zBuf = sqlite3_malloc(5000); - if( zBuf==0 ){ - return 0; - } - zBuf[0] = 0; - sqlite3SetString(&zFull, getcwd(zBuf, 5000), "/", zRelative, - (char*)0); - sqlite3_free(zBuf); - } - -#if 0 - /* - ** Remove "/./" path elements and convert "/A/./" path elements - ** to just "/". - */ - if( zFull ){ - int i, j; - for(i=j=0; zFull[i]; i++){ - if( zFull[i]=='/' ){ - if( zFull[i+1]=='/' ) continue; - if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ - i += 1; - continue; - } - if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ - while( j>0 && zFull[j-1]!='/' ){ j--; } - i += 3; - continue; - } - } - zFull[j++] = zFull[i]; - } - zFull[j] = 0; - } -#endif - - return zFull; -} - /* ** Change the value of the fullsync flag in the given file descriptor. */ @@ -2510,9 +2430,9 @@ static int allocateUnixFile( memset(&f, 0, sizeof(f)); lockingStyle = sqlite3DetectLockingStyle(zFilename, h); if ( lockingStyle == posixLockingStyle ) { - sqlite3OsEnterMutex(); + enterMutex(); rc = findLockInfo(h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); if( rc ){ close(h); unlink(zFilename); @@ -2532,10 +2452,10 @@ static int allocateUnixFile( pNew = sqlite3_malloc( sizeof(unixFile) ); if( pNew==0 ){ close(h); - sqlite3OsEnterMutex(); + enterMutex(); releaseLockInfo(f.pLock); releaseOpenCnt(f.pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); *pId = 0; return SQLITE_NOMEM; }else{ @@ -2590,50 +2510,34 @@ static int allocateUnixFile( } } #else /* SQLITE_ENABLE_LOCKING_STYLE */ -static int allocateUnixFile( +static int fillInUnixFile( int h, /* Open file descriptor on file being opened */ - sqlite3_file **pId, /* Write the resul unixFile structure here */ - const char *zFilename, /* Name of the file being opened */ - int delFlag /* If true, delete the file on or before closing */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename /* Name of the file being opened */ ){ - unixFile *pNew; - unixFile f; + unixFile *pNew = (unixFile *)pId; int rc; #ifdef FD_CLOEXEC fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); #endif - memset(&f, 0, sizeof(f)); - sqlite3OsEnterMutex(); - rc = findLockInfo(h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); - if( delFlag ){ - unlink(zFilename); - } + + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); if( rc ){ close(h); return SQLITE_NOMEM; } + OSTRACE3("OPEN %-3d %s\n", h, zFilename); - f.dirfd = -1; - f.h = h; - SET_THREADID(&f); - pNew = sqlite3_malloc( sizeof(unixFile) ); - if( pNew==0 ){ - close(h); - sqlite3OsEnterMutex(); - releaseLockInfo(f.pLock); - releaseOpenCnt(f.pOpen); - sqlite3OsLeaveMutex(); - *pId = 0; - return SQLITE_NOMEM; - }else{ - *pNew = f; - pNew->pMethod = &sqlite3UnixIoMethod; - *pId = (sqlite3_file*)pNew; - OpenCounter(+1); - return SQLITE_OK; - } + pNew->dirfd = -1; + pNew->h = h; + SET_THREADID(pNew); + + pNew->pMethod = &sqlite3UnixIoMethod; + OpenCounter(+1); + return SQLITE_OK; } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -2643,6 +2547,199 @@ static int allocateUnixFile( ** with other miscellanous aspects of the operating system interface ****************************************************************************/ +/* +** Previously, the SQLite OS layer used three functions in place of this +** one: +** +** sqlite3OsOpenReadWrite(); +** sqlite3OsOpenReadOnly(); +** sqlite3OsOpenExclusive(); +** +** These calls correspond to the following combinations of flags: +** +** ReadWrite() -> (READWRITE | CREATE) +** ReadOnly() -> (READONLY) +** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) +** +** The old OpenExclusive() accepted a boolean argument - "delFlag". If +** true, the file was configured to be automatically deleted when the +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for +** OpenExclusive(). +*/ +static int unixOpen( + void *pNotUsed, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + int fd = 0; + int oflags = 0; + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); + + /* Exactly one of the READWRITE and READONLY flags must be set */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + + /* If isCreate is true, then the file must be opened for read/write access. */ + assert(isCreate==0 || isReadWrite); + + /* If isExclusive is true, then isCreate must also be true */ + assert(isExclusive==0 || isCreate); + + if( isReadonly ) oflags |= O_RDONLY; + if( isReadWrite ) oflags |= O_RDWR; + if( isCreate ) oflags |= O_CREAT; + if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW); + oflags |= (O_LARGEFILE|O_BINARY); + + memset(pFile, 0, sizeof(unixFile)); + fd = open(zPath, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + if( fd<0 && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; + return unixOpen(pNotUsed, zPath, pFile, flags, pOutFlags); + } + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + if( isDelete ){ + unlink(zPath); + } + if( pOutFlags ){ + *pOutFlags = flags; + } + + assert(fd!=0); + return fillInUnixFile(fd, pFile, zPath); +} + +/* +** Delete the file at zPath. +*/ +static int unixDelete(void *pNotUsed, const char *zPath){ + SimulateIOError(return SQLITE_IOERR_DELETE); + unlink(zPath); + return SQLITE_OK; +} + +static int unixAccess(void *pNotUsed, const char *zPath, int flags){ + int amode; + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READONLY: + amode = R_OK; + break; + + default: + assert(!"Invalid flags argument"); + } + return (access(zPath, amode)==0); +} + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at least MAX_PATHNAME characters. +*/ +static int unixGetTempName(void *pNotUsed, char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + azDirs[0] = sqlite3_temp_directory; + for(i=0; i0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif +} + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -2650,23 +2747,46 @@ static int allocateUnixFile( ** within the shared library, and closing the shared library. */ #include -void *sqlite3UnixDlopen(const char *zFilename){ +static void *unixDlOpen(void *pNotUsed, const char *zFilename){ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); } -void *sqlite3UnixDlsym(void *pHandle, const char *zSymbol){ +static void unixDlError(void *pNotUsed, int nBuf, char *zBufOut){ + char *zErr; + enterMutex(); + zErr = dlerror(); + if( zErr ){ + strncpy(zBufOut, zErr, nBuf-1); + zBufOut[nBuf-1] = '\0'; + }else if(nBuf>0) { + zBufOut[0] = '\0'; + } + leaveMutex(); +} +void *unixDlSym(void *pHandle, const char *zSymbol){ return dlsym(pHandle, zSymbol); } -int sqlite3UnixDlclose(void *pHandle){ - return dlclose(pHandle); +void unixDlClose(void *pHandle){ + dlclose(pHandle); } -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define unixDlOpen 0 + #define unixDlError 0 + #define unixDlSym 0 + #define unixDlClose 0 +#endif + +/* +** Both arguments are integers. This macro returns the lowest of the +** two arguments. +*/ +#define MIN(x,y) ((x)>(y)?(y):(x)) /* ** Get information to seed the random number generator. The seed ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3UnixRandomSeed(char *zBuf){ +static int unixRandomness(void *pNotUsed, int nBuf, 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 @@ -2679,7 +2799,7 @@ int sqlite3UnixRandomSeed(char *zBuf){ ** that we always use the same random number sequence. This makes the ** tests repeatable. */ - memset(zBuf, 0, 256); + memset(zBuf, 0, nBuf); #if !defined(SQLITE_TEST) { int pid, fd; @@ -2687,11 +2807,13 @@ int sqlite3UnixRandomSeed(char *zBuf){ if( fd<0 ){ time_t t; time(&t); - memcpy(zBuf, &t, sizeof(t)); - pid = getpid(); - memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); + memcpy(zBuf, &t, MIN(nBuf, sizeof(t))); + if( (nBuf-sizeof(t))>0 ){ + pid = getpid(); + memcpy(&zBuf[sizeof(t)], &pid, MIN(nBuf-sizeof(t), sizeof(pid))); + } }else{ - read(fd, zBuf, 256); + read(fd, zBuf, nBuf); close(fd); } } @@ -2699,120 +2821,19 @@ int sqlite3UnixRandomSeed(char *zBuf){ return SQLITE_OK; } + /* ** Sleep for a little while. Return the amount of time slept. -** The argument is the number of milliseconds we want to sleep. +** The argument is the number of microseconds we want to sleep. */ -int sqlite3UnixSleep(int ms){ +static int unixSleep(void *pNotUsed, int microseconds){ #if defined(HAVE_USLEEP) && HAVE_USLEEP - usleep(ms*1000); - return ms; + usleep(microseconds); + return microseconds; #else - sleep((ms+999)/1000); - return 1000*((ms+999)/1000); -#endif -} - -/* -** Static variables used for thread synchronization. -** -** inMutex the nesting depth of the recursive mutex. The thread -** holding mutexMain can read this variable at any time. -** But is must hold mutexAux to change this variable. Other -** threads must hold mutexAux to read the variable and can -** never write. -** -** mutexOwner The thread id of the thread holding mutexMain. Same -** access rules as for inMutex. -** -** mutexOwnerValid True if the value in mutexOwner is valid. The same -** access rules apply as for inMutex. -** -** mutexMain The main mutex. Hold this mutex in order to get exclusive -** access to SQLite data structures. -** -** mutexAux An auxiliary mutex needed to access variables defined above. -** -** Mutexes are always acquired in this order: mutexMain mutexAux. It -** is not necessary to acquire mutexMain in order to get mutexAux - just -** do not attempt to acquire them in the reverse order: mutexAux mutexMain. -** Either get the mutexes with mutexMain first or get mutexAux only. -** -** When running on a platform where the three variables inMutex, mutexOwner, -** and mutexOwnerValid can be set atomically, the mutexAux is not required. -** On many systems, all three are 32-bit integers and writing to a 32-bit -** integer is atomic. I think. But there are no guarantees. So it seems -** safer to protect them using mutexAux. -*/ -static int inMutex = 0; -#ifdef SQLITE_UNIX_THREADS -static pthread_t mutexOwner; /* Thread holding mutexMain */ -static int mutexOwnerValid = 0; /* True if mutexOwner is valid */ -static pthread_mutex_t mutexMain = PTHREAD_MUTEX_INITIALIZER; /* The mutex */ -static pthread_mutex_t mutexAux = PTHREAD_MUTEX_INITIALIZER; /* Aux mutex */ -#endif - -/* -** The following pair of routine implement mutual exclusion for -** multi-threaded processes. Only a single thread is allowed to -** executed code that is surrounded by EnterMutex() and LeaveMutex(). -** -** SQLite uses only a single Mutex. There is not much critical -** code and what little there is executes quickly and without blocking. -** -** As of version 3.3.2, this mutex must be recursive. -*/ -void sqlite3UnixEnterMutex(){ -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutexAux); - if( !mutexOwnerValid || !pthread_equal(mutexOwner, pthread_self()) ){ - pthread_mutex_unlock(&mutexAux); - pthread_mutex_lock(&mutexMain); - assert( inMutex==0 ); - assert( !mutexOwnerValid ); - pthread_mutex_lock(&mutexAux); - mutexOwner = pthread_self(); - mutexOwnerValid = 1; - } - inMutex++; - pthread_mutex_unlock(&mutexAux); -#else - inMutex++; -#endif -} -void sqlite3UnixLeaveMutex(){ - assert( inMutex>0 ); -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutexAux); - inMutex--; - assert( pthread_equal(mutexOwner, pthread_self()) ); - if( inMutex==0 ){ - assert( mutexOwnerValid ); - mutexOwnerValid = 0; - pthread_mutex_unlock(&mutexMain); - } - pthread_mutex_unlock(&mutexAux); -#else - inMutex--; -#endif -} - -/* -** Return TRUE if the mutex is currently held. -** -** If the thisThrd parameter is true, return true only if the -** calling thread holds the mutex. If the parameter is false, return -** true if any thread holds the mutex. -*/ -int sqlite3UnixInMutex(int thisThrd){ -#ifdef SQLITE_UNIX_THREADS - int rc; - pthread_mutex_lock(&mutexAux); - rc = inMutex>0 && (thisThrd==0 || pthread_equal(mutexOwner,pthread_self())); - pthread_mutex_unlock(&mutexAux); - return rc; -#else - return inMutex>0; + int seconds = (microseconds+999999)/1000000; + sleep(seconds); + return seconds; #endif } @@ -2829,7 +2850,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 sqlite3UnixCurrentTime(double *prNow){ +static int unixCurrentTime(void *pNotUsed, double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); @@ -2846,5 +2867,31 @@ int sqlite3UnixCurrentTime(double *prNow){ #endif return 0; } + + +sqlite3_vfs sqlite3DefaultVfs = { + 1, /* iVersion */ + sizeof(unixFile), /* szOsFile */ + MAX_PATHNAME, /* mxPathname */ + 0, /* nRef */ + 0, /* vfsMutex */ + 0, /* pNext */ + 0, /* pPrev */ + "unix", /* zName */ + 0, /* pAppData */ + + unixOpen, /* xOpen */ + unixDelete, /* xDelete */ + unixAccess, /* xAccess */ + unixGetTempName, /* xGetTempName */ + unixFullPathname, /* xFullPathname */ + unixDlOpen, /* xDlOpen */ + unixDlError, /* xDlError */ + unixDlSym, /* xDlSym */ + unixDlClose, /* xDlClose */ + unixRandomness, /* xRandomness */ + unixSleep, /* xSleep */ + unixCurrentTime /* xCurrentTime */ +}; #endif /* OS_UNIX */ diff --git a/src/pager.c b/src/pager.c index 418b13ef14..5fbedba319 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.358 2007/08/16 10:09:03 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.359 2007/08/17 15:53:37 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -297,6 +297,7 @@ struct PgHistory { ** APIs, they may still be used successfully. */ struct Pager { + sqlite3_vfs *pVfs; /* OS functions to use for IO */ u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ @@ -1011,7 +1012,7 @@ static int pager_end_transaction(Pager *pPager){ } sqlite3PagerStmtCommit(pPager); if( pPager->stmtOpen && !pPager->exclusiveMode ){ - sqlite3OsClose(&pPager->stfd); + sqlite3OsClose(pPager->stfd); pPager->stmtOpen = 0; } if( pPager->journalOpen ){ @@ -1020,10 +1021,10 @@ static int pager_end_transaction(Pager *pPager){ pPager->journalOff = 0; pPager->journalStarted = 0; }else{ - sqlite3OsClose(&pPager->jfd); + sqlite3OsClose(pPager->jfd); pPager->journalOpen = 0; if( rc==SQLITE_OK ){ - rc = sqlite3OsDelete(pPager->zJournal); + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal); } } sqlite3_free( pPager->aInJournal ); @@ -1225,21 +1226,29 @@ static int pager_playback_one_page( ** children. If all children are either missing or do not refer to ** a different master journal, then this master journal can be deleted. */ -static int pager_delmaster(const char *zMaster){ +static int pager_delmaster(Pager *pPager, const char *zMaster){ + sqlite3_vfs *pVfs = pPager->pVfs; int rc; int master_open = 0; - sqlite3_file *master = 0; + sqlite3_file *pMaster; + sqlite3_file *pJournal; char *zMasterJournal = 0; /* Contents of master journal file */ i64 nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ - rc = sqlite3OsOpenReadOnly(zMaster, &master); - assert( rc!=SQLITE_OK || master ); + pMaster = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile * 2); + if( !pMaster ){ + rc = SQLITE_NOMEM; + }else{ + pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, SQLITE_OPEN_READONLY, 0); + } if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3OsFileSize(master, &nMasterJournal); + + rc = sqlite3OsFileSize(pMaster, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ @@ -1254,27 +1263,25 @@ static int pager_delmaster(const char *zMaster){ rc = SQLITE_NOMEM; goto delmaster_out; } - rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal, 0); + rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; while( (zJournal-zMasterJournal)pVfs; i64 szJ; /* Size of the journal file in bytes */ u32 nRec; /* Number of Records in the journal */ int i; /* Loop counter */ @@ -1411,7 +1420,9 @@ static int pager_playback(Pager *pPager, int isHot){ */ rc = readMasterJournal(pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); - if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ + if( rc!=SQLITE_OK + || (zMaster && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS)) + ){ sqlite3_free(zMaster); zMaster = 0; if( rc==SQLITE_DONE ) rc = SQLITE_OK; @@ -1496,7 +1507,7 @@ end_playback: ** see if it is possible to delete the master journal. */ if( rc==SQLITE_OK ){ - rc = pager_delmaster(zMaster); + rc = pager_delmaster(pPager, zMaster); } sqlite3_free(zMaster); } @@ -1681,20 +1692,36 @@ int sqlite3_opentemp_count = 0; ** The OS will automatically delete the temporary file when it is ** closed. */ -static int sqlite3PagerOpentemp(sqlite3_file **pFd){ +static int sqlite3PagerOpentemp( + sqlite3_vfs *pVfs, + sqlite3_file *pFile, + char *zNameOut +){ int cnt = 8; int rc; - char zFile[SQLITE_TEMPNAME_SIZE]; + int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_EXCLUSIVE); + + char *zFree = 0; + if( zNameOut==0 ){ + zFree = (char *)sqlite3_malloc(pVfs->mxPathname); + if( !zFree ){ + return SQLITE_NOMEM; + } + zNameOut = zFree; + } #ifdef SQLITE_TEST sqlite3_opentemp_count++; /* Used for testing and analysis only */ #endif + do{ cnt--; - sqlite3OsTempFileName(zFile); - rc = sqlite3OsOpenExclusive(zFile, pFd, 1); - assert( rc!=SQLITE_OK || *pFd ); + sqlite3OsGetTempName(pVfs, zNameOut); + rc = sqlite3OsOpen(pVfs, zNameOut, pFile, flags, 0); + assert( rc!=SQLITE_OK || pFile->pMethods ); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); + + sqlite3_free(zFree); return rc; } @@ -1713,15 +1740,15 @@ static int sqlite3PagerOpentemp(sqlite3_file **pFd){ ** in-memory database. */ int sqlite3PagerOpen( + sqlite3_vfs *pVfs, Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ + u8 *pPtr; Pager *pPager = 0; char *zFullPathname = 0; - int nameLen; /* Compiler is wrong. This is always initialized before use */ - sqlite3_file *fd = 0; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1729,7 +1756,7 @@ int sqlite3PagerOpen( int readOnly = 0; int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; - char zTemp[SQLITE_TEMPNAME_SIZE]; + #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to ** malloc() must have already been made by this thread before it gets @@ -1750,6 +1777,24 @@ int sqlite3PagerOpen( */ *ppPager = 0; + /* Allocate memory for the pager structure */ + pPager = sqlite3MallocZero( + sizeof(*pPager) + /* Pager structure */ + pVfs->szOsFile * 3 + /* The db, journal and stmt journal files */ + pVfs->mxPathname * 3 + 30 /* zFilename, zDirectory, zJournal */ + ); + if( !pPager ){ + return SQLITE_NOMEM; + } + pPtr = (u8 *)&pPager[1]; + pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0]; + pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1]; + pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2]; + pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*3]; + pPager->zDirectory = &pPager->zFilename[pVfs->mxPathname]; + pPager->zJournal = &pPager->zDirectory[pVfs->mxPathname]; + pPager->pVfs = pVfs; + /* Open the pager file and set zFullPathname to point at malloc()ed ** memory containing the complete filename (i.e. including the directory). */ @@ -1757,65 +1802,56 @@ int sqlite3PagerOpen( #ifndef SQLITE_OMIT_MEMORYDB if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; - zFullPathname = sqlite3StrDup(""); + pPager->zFilename[0] = '\0'; }else #endif { - zFullPathname = sqlite3OsFullPathname(zFilename); - if( zFullPathname ){ - rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); - assert( rc!=SQLITE_OK || fd ); + rc = sqlite3OsFullPathname(pVfs, zFilename, pPager->zFilename); + if( rc==SQLITE_OK ){ + if( strlen(pPager->zFilename)>(pVfs->mxPathname - strlen("-journal")) ){ + rc = SQLITE_CANTOPEN; + }else{ + int flag = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + int fout = 0; + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, flag, &fout); + readOnly = (fout&SQLITE_OPEN_READONLY); + } } } }else{ - rc = sqlite3PagerOpentemp(&fd); - sqlite3OsTempFileName(zTemp); - zFilename = zTemp; - zFullPathname = sqlite3OsFullPathname(zFilename); + rc = sqlite3PagerOpentemp(pVfs, pPager->fd, pPager->zFilename); if( rc==SQLITE_OK ){ tempFile = 1; } } - /* Allocate the Pager structure. As part of the same allocation, allocate - ** space for the full paths of the file, directory and journal - ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal). - */ - if( zFullPathname ){ - nameLen = strlen(zFullPathname); - pPager = sqlite3MallocZero( sizeof(*pPager) + nameLen*3 + 30 ); - if( pPager && rc==SQLITE_OK ){ - pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE); - } + if( pPager && rc==SQLITE_OK ){ + pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE); } - /* If an error occured in either of the blocks above, free the memory ** pointed to by zFullPathname, free the Pager structure and close the ** file. Since the pager is not allocated there is no need to set ** any Pager.errMask variables. */ - if( !pPager || !zFullPathname || !pPager->pTmpSpace || rc!=SQLITE_OK ){ - sqlite3OsClose(&fd); - sqlite3_free(zFullPathname); + if( !pPager || !pPager->pTmpSpace ){ + sqlite3OsClose(pPager->fd); sqlite3_free(pPager); return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); IOTRACE(("OPEN %p %s\n", pPager, zFullPathname)) - pPager->zFilename = (char*)&pPager[1]; - pPager->zDirectory = &pPager->zFilename[nameLen+1]; - pPager->zJournal = &pPager->zDirectory[nameLen+1]; - memcpy(pPager->zFilename, zFullPathname, nameLen+1); - memcpy(pPager->zDirectory, zFullPathname, nameLen+1); - for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} + /* Fill in Pager.zDirectory[] */ + memcpy(pPager->zDirectory, pPager->zFilename, pVfs->mxPathname); + for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; - memcpy(pPager->zJournal, zFullPathname,nameLen); - sqlite3_free(zFullPathname); - memcpy(&pPager->zJournal[nameLen], "-journal",sizeof("-journal")); - pPager->fd = fd; + + /* Fill in Pager.zJournal[] */ + memcpy(pPager->zJournal, pPager->zFilename, pVfs->mxPathname); + memcpy(&pPager->zJournal[strlen(pPager->zJournal)], "-journal", 9); + /* pPager->journalOpen = 0; */ pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; @@ -1846,7 +1882,7 @@ int sqlite3PagerOpen( /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); - assert(fd||memDb); + assert(pPager->fd->pMethods||memDb); if( !memDb ){ setSectorSize(pPager); } @@ -2229,13 +2265,13 @@ int sqlite3PagerClose(Pager *pPager){ IOTRACE(("CLOSE %p\n", pPager)) assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ - sqlite3OsClose(&pPager->jfd); + sqlite3OsClose(pPager->jfd); } sqlite3_free(pPager->aInJournal); if( pPager->stmtOpen ){ - sqlite3OsClose(&pPager->stfd); + sqlite3OsClose(pPager->stfd); } - sqlite3OsClose(&pPager->fd); + sqlite3OsClose(pPager->fd); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqlite3OsDelete(pPager->zFilename); @@ -2579,15 +2615,16 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ ** database with the same name. Just delete the journal. */ static int hasHotJournal(Pager *pPager){ + sqlite3_vfs *pVfs = pPager->pVfs; if( !pPager->useJournal ) return 0; - if( !sqlite3OsFileExists(pPager->zJournal) ){ + if( !sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ return 0; } if( sqlite3OsCheckReservedLock(pPager->fd) ){ return 0; } if( sqlite3PagerPagecount(pPager)==0 ){ - sqlite3OsDelete(pPager->zJournal); + sqlite3OsDelete(pVfs, pPager->zJournal); return 0; }else{ return 1; @@ -2702,9 +2739,11 @@ int sqlite3PagerReleaseMemory(int nReq){ ** some of the code invoked by this function may also ** try to obtain the mutex, resulting in a deadlock. */ +#if 0 if( sqlite3OsInMutex(0) ){ return 0; } +#endif /* Outermost loop runs for at most two iterations. First iteration we ** try to find memory that can be released without calling fsync(). Second @@ -2817,6 +2856,7 @@ static int pagerSharedLock(Pager *pPager){ int rc = SQLITE_OK; if( pPager->state==PAGER_UNLOCK ){ + sqlite3_vfs *pVfs = pPager->pVfs; if( !MEMDB ){ assert( pPager->nRef==0 ); if( !pPager->noReadlock ){ @@ -2864,14 +2904,15 @@ static int pagerSharedLock(Pager *pPager){ ** a read/write file handle. */ rc = SQLITE_BUSY; - if( sqlite3OsFileExists(pPager->zJournal) ){ - int ro; + if( sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ + int fout = 0; + int flags = SQLITE_OPEN_READWRITE; assert( !pPager->tempFile ); - rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro); - assert( rc!=SQLITE_OK || pPager->jfd ); - if( ro ){ + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, &fout); + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + if( fout&SQLITE_OPEN_READONLY ){ rc = SQLITE_BUSY; - sqlite3OsClose(&pPager->jfd); + sqlite3OsClose(pPager->jfd); } } if( rc!=SQLITE_OK ){ @@ -3294,6 +3335,9 @@ int sqlite3PagerUnref(DbPage *pPg){ ** write lock if anything goes wrong. */ static int pager_open_journal(Pager *pPager){ + sqlite3_vfs *pVfs = pPager->pVfs; + int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE); + int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); @@ -3306,15 +3350,18 @@ static int pager_open_journal(Pager *pPager){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } - rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd, - pPager->tempFile); - assert( rc!=SQLITE_OK || pPager->jfd ); + + if( pPager->tempFile ){ + flags |= SQLITE_OPEN_DELETEONCLOSE; + } + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ){ - sqlite3OsDelete(pPager->zJournal); + sqlite3OsDelete(pVfs, pPager->zJournal); } goto failed_to_open_journal; } @@ -4180,7 +4227,7 @@ int sqlite3PagerStmtBegin(Pager *pPager){ pPager->stmtHdrOff = 0; pPager->stmtCksum = pPager->cksumInit; if( !pPager->stmtOpen ){ - rc = sqlite3PagerOpentemp(&pPager->stfd); + rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->stfd, 0); if( rc ) goto stmt_begin_failed; pPager->stmtOpen = 1; pPager->stmtNRec = 0; diff --git a/src/pager.h b/src/pager.h index ca193dae1d..554c4999ad 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.61 2007/05/08 21:45:28 drh Exp $ +** @(#) $Id: pager.h,v 1.62 2007/08/17 15:53:37 danielk1977 Exp $ */ #ifndef _PAGER_H_ @@ -54,8 +54,7 @@ typedef struct PgHdr DbPage; ** See source code comments for a detailed description of the following ** routines: */ -int sqlite3PagerOpen(Pager **ppPager, const char *zFilename, - int nExtra, int flags); +int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char *, int, int); void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int)); void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int)); diff --git a/src/pragma.c b/src/pragma.c index 66edcee87b..f5ed28a4e0 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.144 2007/08/16 10:09:03 danielk1977 Exp $ +** $Id: pragma.c,v 1.145 2007/08/17 15:53:37 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -557,7 +557,9 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } }else{ - if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){ + if( zRight[0] + && !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE) + ){ sqlite3ErrorMsg(pParse, "not a writable directory"); goto pragma_out; } diff --git a/src/random.c b/src/random.c index 03ed7a424b..27ee0e508c 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.16 2007/01/05 14:38:56 drh Exp $ +** $Id: random.c,v 1.17 2007/08/17 15:53:37 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -63,7 +63,7 @@ static int randomByte(void){ char k[256]; prng.j = 0; prng.i = 0; - sqlite3OsRandomSeed(k); + sqlite3OsRandomness(sqlite3_find_vfs(0), 256, k); for(i=0; i<256; i++){ prng.s[i] = i; } @@ -92,9 +92,9 @@ static int randomByte(void){ */ void sqlite3Randomness(int N, void *pBuf){ unsigned char *zBuf = pBuf; - sqlite3OsEnterMutex(); + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_PRNG)); while( N-- ){ *(zBuf++) = randomByte(); } - sqlite3OsLeaveMutex(); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_PRNG)); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 8492399d2e..2378b7861f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.227 2007/08/17 01:14:38 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.228 2007/08/17 15:53:37 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -644,10 +644,10 @@ struct sqlite3_vfs { int (*xAccess)(void *pAppData, const char *zName, int flags); int (*xGetTempName)(void *pAppData, char *zOut); int (*xFullPathname)(void *pAppData, const char *zName, char *zOut); - void *(*xDlOpen)(void *pAppData, char *zFilename); - void (*xDlError)(void*, int nByte, char *zErrMsg); + void *(*xDlOpen)(void *pAppData, const char *zFilename); + void (*xDlError)(void *pAppData, int nByte, char *zErrMsg); void *(*xDlSym)(void*, const char *zSymbol); - void (*xDlclose)(void*); + void (*xDlClose)(void*); int (*xRandomness)(void *pAppData, int nByte, char *zOut); int (*xSleep)(void *pAppData, int microseconds); int (*xCurrentTime)(void *pAppData, double*); @@ -655,6 +655,10 @@ struct sqlite3_vfs { ** value will increment whenever this happens. */ }; +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 +#define SQLITE_ACCESS_READONLY 2 + /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7a7238320d..7ae793c602 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.590 2007/08/17 01:14:38 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.591 2007/08/17 15:53:37 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -187,7 +187,7 @@ typedef UINT8_TYPE i8; /* 1-byte signed integer */ */ #define SQLITE_MUTEX_MEM 1 /* Used by the memory allocator */ #define SQLITE_MUTEX_PRNG 2 /* Used by pseudorandom generator */ -#define SQLITE_MUTEX_CACHE 3 /* Used by shared cache */ +#define SQLITE_MUTEX_GLOBAL 3 /* Used by global variables */ #define SQLITE_MUTEX_STATIC_MAX 3 /* diff --git a/src/test1.c b/src/test1.c index 599ef2fac6..012f22a71e 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.263 2007/08/17 01:14:38 drh Exp $ +** $Id: test1.c,v 1.264 2007/08/17 15:53:37 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -3587,6 +3587,7 @@ static int test_stmt_int( } #ifndef SQLITE_OMIT_DISKIO +#if 0 /* ** Usage: sqlite3OsOpenReadWrite */ @@ -3744,6 +3745,7 @@ static int test_sqlite3OsTempFileName( return TCL_OK; } #endif +#endif /* ** Usage: sqlite_set_magic DB MAGIC-NUMBER @@ -4285,6 +4287,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ /* Functions from os.h */ #ifndef SQLITE_OMIT_DISKIO +#if 0 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, { "sqlite3OsClose", test_sqlite3OsClose, 0 }, { "sqlite3OsLock", test_sqlite3OsLock, 0 }, @@ -4293,6 +4296,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ /* Custom test interfaces */ { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, #endif +#endif #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, diff --git a/src/test2.c b/src/test2.c index c8464c6c94..a45d60c965 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.45 2007/08/16 10:09:03 danielk1977 Exp $ +** $Id: test2.c,v 1.46 2007/08/17 15:53:37 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -78,7 +78,7 @@ static int pager_open( return TCL_ERROR; } if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; - rc = sqlite3PagerOpen(&pPager, argv[1], 0, 0); + rc = sqlite3PagerOpen(sqlite3_find_vfs(0), &pPager, argv[1], 0, 0); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; @@ -528,18 +528,21 @@ static int fake_big_file( int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ + sqlite3_vfs *pVfs; + sqlite3_file *fd = 0; + int flags = SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; int rc; int n; i64 offset; - sqlite3_file *fd = 0; - int readOnly = 0; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N-MEGABYTES FILE\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; - rc = sqlite3OsOpenReadWrite(argv[2], &fd, &readOnly); + + pVfs = sqlite3_find_vfs(0); + rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, flags); if( rc ){ Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); return TCL_ERROR; @@ -547,7 +550,7 @@ static int fake_big_file( offset = n; offset *= 1024*1024; rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); - sqlite3OsClose(&fd); + sqlite3OsCloseFree(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 6c9dc6787f..cc02b5f315 100644 --- a/src/test6.c +++ b/src/test6.c @@ -263,7 +263,7 @@ static int writeListAppend( assert((zBuf && nBuf) || (!nBuf && !zBuf)); - pNew = (WriteBuffer *)sqlite3_malloc(sizeof(WriteBuffer) + nBuf); + pNew = (WriteBuffer *)sqlite3MallocZero(sizeof(WriteBuffer) + nBuf); pNew->iOffset = iOffset; pNew->nBuf = nBuf; pNew->pFile = (CrashFile *)pFile; @@ -544,8 +544,8 @@ static int crashParamsObjCmd( int objc, Tcl_Obj *CONST objv[] ){ + sqlite3_vfs *pVfs; int i; - int iDelay; const char *zCrashFile; int nCrashFile; @@ -575,17 +575,19 @@ static int crashParamsObjCmd( if( objc<3 ){ Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE"); - return TCL_ERROR; + goto error; } - zCrashFile = sqlite3OsFullPathname(Tcl_GetString(objv[objc-1])); + pVfs = sqlite3_find_vfs(0); + zCrashFile = sqlite3_malloc(pVfs->mxPathname); + sqlite3OsFullPathname(pVfs, Tcl_GetString(objv[objc-1]), zCrashFile); nCrashFile = strlen(zCrashFile); if( nCrashFile>=sizeof(g.zCrashFile) ){ Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0); - return TCL_ERROR; + goto error; } if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){ - return TCL_ERROR; + goto error; } for(i=1; i<(objc-2); i+=2){ @@ -599,16 +601,16 @@ static int crashParamsObjCmd( "Bad option: \"", zOpt, "\" - must be \"-characteristics\" or \"-sectorsize\"", 0 ); - return TCL_ERROR; + goto error; } if( i==objc-3 ){ Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0); - return TCL_ERROR; + goto error; } if( zOpt[1]=='s' ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){ - return TCL_ERROR; + goto error; } setSectorsize = 1; }else{ @@ -616,7 +618,7 @@ static int crashParamsObjCmd( Tcl_Obj **apObj; int nObj; if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){ - return TCL_ERROR; + goto error; } for(j=0; jdb->flags & SQLITE_VdbeListing)!=0 - || sqlite3OsFileExists("vdbe_explain") + || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS) ){ int i; printf("VDBE Program Listing:\n"); @@ -495,7 +495,7 @@ int sqlite3VdbeExec( sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); } } - if( sqlite3OsFileExists("vdbe_trace") ){ + if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){ p->trace = stdout; } #endif @@ -519,7 +519,8 @@ int sqlite3VdbeExec( } sqlite3VdbePrintOp(p->trace, pc, pOp); } - if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){ + if( p->trace==0 && pc==0 + && sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){ sqlite3VdbePrintSql(p); } #endif diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 948d4b0428..e8d9ddad56 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -221,7 +221,7 @@ static int sqlite3Step(Vdbe *p){ } if( db->xProfile && !db->init.busy ){ double rNow; - sqlite3OsCurrentTime(&rNow); + sqlite3OsCurrentTime(db->pVfs, &rNow); p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0; } #endif @@ -258,7 +258,7 @@ static int sqlite3Step(Vdbe *p){ double rNow; u64 elapseTime; - sqlite3OsCurrentTime(&rNow); + sqlite3OsCurrentTime(db->pVfs, &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 ec8bd84876..3771296d40 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1132,10 +1132,12 @@ static int vdbeCommit(sqlite3 *db){ */ #ifndef SQLITE_OMIT_DISKIO else{ + sqlite3_vfs *pVfs = db->pVfs; + int flag = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_EXCLUSIVE); int needSync = 0; char *zMaster = 0; /* File-name for the master journal */ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); - sqlite3_file *master = 0; + sqlite3_file *pMaster = 0; i64 offset = 0; /* Select a master journal file name */ @@ -1147,12 +1149,14 @@ static int vdbeCommit(sqlite3 *db){ if( !zMaster ){ return SQLITE_NOMEM; } - }while( sqlite3OsFileExists(zMaster) ); + }while( sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS) ); /* Open the master journal. */ - rc = sqlite3OsOpenExclusive(zMaster, &master, 0); + pMaster = sqlite3_malloc(pVfs->szOsFile); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flag, 0); if( rc!=SQLITE_OK ){ sqlite3_free(zMaster); + sqlite3_free(pMaster); return rc; } @@ -1171,12 +1175,13 @@ static int vdbeCommit(sqlite3 *db){ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ needSync = 1; } - rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1, offset); + rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset); offset += strlen(zFile)+1; if( rc!=SQLITE_OK ){ - sqlite3OsClose(&master); - sqlite3OsDelete(zMaster); + sqlite3OsClose(pMaster); + sqlite3OsDelete(pVfs, zMaster); sqlite3_free(zMaster); + sqlite3_free(pMaster); return rc; } } @@ -1214,9 +1219,10 @@ static int vdbeCommit(sqlite3 *db){ rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); } } - sqlite3OsClose(&master); + sqlite3OsClose(pMaster); if( rc!=SQLITE_OK ){ sqlite3_free(zMaster); + sqlite3_free(pMaster); return rc; } @@ -1224,13 +1230,17 @@ static int vdbeCommit(sqlite3 *db){ ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3OsDelete(zMaster); + rc = sqlite3OsDelete(pVfs, zMaster); sqlite3_free(zMaster); + sqlite3_free(pMaster); zMaster = 0; + pMaster = 0; if( rc ){ return rc; } +#if 0 rc = sqlite3OsSyncDirectory(zMainFile); +#endif 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