From: dan Date: Mon, 10 Feb 2014 19:37:03 +0000 (+0000) Subject: Experimental change to os_unix.c to delay creating a database file until it is first... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c913126272896b743d4d023e2155df61fa8774d0;p=thirdparty%2Fsqlite.git Experimental change to os_unix.c to delay creating a database file until it is first written. FossilOrigin-Name: 538f7b25e436682adba10a158f082de24782cf00 --- diff --git a/manifest b/manifest index e73dfc19e1..1b2f1a34d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sconstant\sexpression\sfactoring\seven\sif\sno\stables\sare\sread\sand\sno\ntransaction\sis\sstarted. -D 2014-02-08T04:24:37.181 +C Experimental\schange\sto\sos_unix.c\sto\sdelay\screating\sa\sdatabase\sfile\suntil\sit\sis\sfirst\swritten. +D 2014-02-10T19:37:03.413 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -205,7 +205,7 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 -F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5 +F src/os_unix.c dcb7dd4fb2ef823b534383bb7e58efdf8cb7d582 F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b F src/pager.c efa923693e958696eee69b205a20bfbc402c8480 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 @@ -230,7 +230,7 @@ F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c 649d373f2a3cfbefe8e935a8dec83686616f9a85 F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299 -F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35 +F src/test2.c 0f8bd858c127fd5236dd965d534622422fbe0b2f F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013 @@ -737,7 +737,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04 +F test/permutations.test 64771d6c1cbe270acb788dfdc32ede157a627583 F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -1152,7 +1152,10 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 192dea97316144f15f6dd0eabff08a0bf9ef203e -R e90c019788474c8101c0d70d2228b12b -U drh -Z 46adb7aa7b0c0d2f1d0d873b94d6c7bb +P a45b87713c0afca2be2ace9500513620a024c0a2 +R 116d1a6917169d2dbbd8194f87400b30 +T *branch * deferred-open +T *sym-deferred-open * +T -sym-trunk * +U dan +Z 79711705a6aa2396617bcc4018494171 diff --git a/manifest.uuid b/manifest.uuid index c2f346156d..0ecd57ff12 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a45b87713c0afca2be2ace9500513620a024c0a2 \ No newline at end of file +538f7b25e436682adba10a158f082de24782cf00 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index deb9e51d07..b133f9878f 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -203,9 +203,7 @@ struct unixFile { int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #endif -#if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ -#endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif @@ -255,7 +253,8 @@ static int randomnessPid = 0; #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ -#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() has issued warnings */ +#define UNIXFILE_DEFERRED 0x0200 /* File has not yet been opened */ /* ** Include code that is common to all os_*.c files @@ -1357,9 +1356,14 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ int reserved = 0; unixFile *pFile = (unixFile*)id; + assert( pFile ); SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - assert( pFile ); + if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){ + *pResOut = 0; + return SQLITE_OK; + } + unixEnterMutex(); /* Because pFile->pInode is shared across threads */ /* Check if a thread in this process holds such a lock */ @@ -1439,6 +1443,8 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ return rc; } +static int unixOpen(sqlite3_vfs*, const char*, sqlite3_file*, int, int *); + /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: @@ -1523,6 +1529,27 @@ static int unixLock(sqlite3_file *id, int eFileLock){ return SQLITE_OK; } + if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){ + int eOrigLock = pFile->eFileLock; + if( eFileLock==SHARED_LOCK ){ + int statrc; + struct stat sBuf; + memset(&sBuf, 0, sizeof(sBuf)); + statrc = osStat(pFile->zPath, &sBuf); + if( statrc && errno==ENOENT ){ + pFile->eFileLock = SHARED_LOCK; + return SQLITE_OK; + } + } + + rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0); + if( rc==SQLITE_OK && eOrigLock ){ + rc = unixLock(id, eOrigLock); + } + if( rc!=SQLITE_OK ) return rc; + } + assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 ); + /* Make sure the locking sequence is correct. ** (1) We never move from unlocked to anything higher than shared lock. ** (2) SQLite never explicitly requests a pendig lock. @@ -1726,6 +1753,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ return SQLITE_OK; } unixEnterMutex(); + if( pFile->ctrlFlags==UNIXFILE_DEFERRED ) goto end_unlock; pInode = pFile->pInode; assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ @@ -1933,18 +1961,22 @@ static int unixClose(sqlite3_file *id){ unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close - ** routine (e.g. nolockClose()) would be called instead. - */ - assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); - if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->pUnused list. It will be automatically closed - ** when the last lock is cleared. - */ - setPendingFd(pFile); + ** routine (e.g. nolockClose()) would be called instead. */ + assert( pFile->pInode==0 + || pFile->pInode->nLock>0 + || pFile->pInode->bProcessLock==0 + ); + if( pFile->pInode ){ + if( pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->pUnused list. It will be automatically closed + ** when the last lock is cleared. + */ + setPendingFd(pFile); + } + releaseInodeInfo(pFile); } - releaseInodeInfo(pFile); rc = closeUnixFile(id); unixLeaveMutex(); return rc; @@ -3173,6 +3205,23 @@ static int unixRead( ); #endif + if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){ + int rc; + struct stat sBuf; + memset(&sBuf, 0, sizeof(sBuf)); + rc = osStat(pFile->zPath, &sBuf); + if( rc!=0 ){ + memset(pBuf, 0, amt); + rc = (errno==ENOENT ? SQLITE_IOERR_SHORT_READ : SQLITE_IOERR_FSTAT); + }else{ + rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0); + } + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 ); + #if SQLITE_MAX_MMAP_SIZE>0 /* Deal with as much of this read request as possible by transfering ** data from the memory mapping using memcpy(). */ @@ -3625,10 +3674,19 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ ** Determine the current size of a file in bytes */ static int unixFileSize(sqlite3_file *id, i64 *pSize){ + unixFile *pFile = (unixFile*)id; int rc; struct stat buf; assert( id ); - rc = osFstat(((unixFile*)id)->h, &buf); + if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){ + rc = osStat(pFile->zPath, &buf); + if( rc && errno==ENOENT ){ + rc = 0; + buf.st_size = 0; + } + }else{ + rc = osFstat(pFile->h, &buf); + } SimulateIOError( rc=1 ); if( rc!=0 ){ ((unixFile*)id)->lastErrno = errno; @@ -3644,7 +3702,6 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){ */ if( *pSize==1 ) *pSize = 0; - return SQLITE_OK; } @@ -5176,7 +5233,7 @@ static int fillInUnixFile( pNew->h = h; pNew->pVfs = pVfs; pNew->zPath = zFilename; - pNew->ctrlFlags = (u8)ctrlFlags; + pNew->ctrlFlags = (unsigned short)ctrlFlags; #if SQLITE_MAX_MMAP_SIZE>0 pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap; #endif @@ -5822,6 +5879,37 @@ open_finished: return rc; } +static int unixOpenDeferred( + sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ + const char *zPath, /* Pathname of file to be opened */ + sqlite3_file *pFile, /* The file descriptor to be filled in */ + int flags, /* Input flags to control the opening */ + int *pOutFlags /* Output flags returned to SQLite core */ +){ + const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE + | SQLITE_OPEN_CREATE; + const int mask2 = SQLITE_OPEN_READONLY | SQLITE_OPEN_DELETEONCLOSE + | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY; + int rc = SQLITE_OK; /* Return code */ + + /* If all the flags in mask1 are set, and all the flags in mask2 are + ** clear, then this will be a deferred open. */ + if( zPath && (flags & (mask1 | mask2))==mask1 ){ + unixFile *p = (unixFile*)pFile; + memset(p, 0, sizeof(unixFile)); + + p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0); + p->pVfs = pVfs; + p->h = -1; + p->ctrlFlags = UNIXFILE_DEFERRED; + p->openFlags = flags; + p->zPath = zPath; + if( pOutFlags ) *pOutFlags = flags; + }else{ + rc = unixOpen(pVfs, zPath, pFile, flags, pOutFlags); + } + return rc; +} /* ** Delete the file at zPath. If the dirSync argument is true, fsync() @@ -7376,7 +7464,7 @@ int sqlite3_os_init(void){ 0, /* pNext */ \ VFSNAME, /* zName */ \ (void*)&FINDER, /* pAppData */ \ - unixOpen, /* xOpen */ \ + unixOpenDeferred, /* xOpen */ \ unixDelete, /* xDelete */ \ unixAccess, /* xAccess */ \ unixFullPathname, /* xFullPathname */ \ diff --git a/src/test2.c b/src/test2.c index d130e9d01b..a68293280e 100644 --- a/src/test2.c +++ b/src/test2.c @@ -534,7 +534,10 @@ static int fake_big_file( } offset = n; offset *= 1024*1024; + sqlite3OsLock(fd, SHARED_LOCK); + sqlite3OsLock(fd, EXCLUSIVE_LOCK); rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); + sqlite3OsUnlock(fd, NO_LOCK); sqlite3OsCloseFree(fd); sqlite3_free(zFile); if( rc ){ diff --git a/test/permutations.test b/test/permutations.test index 7f1485f831..ad087c9476 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -135,7 +135,8 @@ test_suite "veryquick" -prefix "" -description { This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ - test_set $allquicktests -exclude *malloc* *ioerr* *fault* + test_set $allquicktests -exclude *malloc* *ioerr* *fault* \ + *multiplex* *quota* walbak.test ] test_suite "mmap" -prefix "mm-" -description {