Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Experimental change to os_unix.c to delay creating a database file until it is first written. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | deferred-open |
Files: | files | file ages | folders |
SHA1: |
538f7b25e436682adba10a158f082de2 |
User & Date: | dan 2014-02-10 19:37:03.413 |
Context
2014-02-10
| ||
21:09 | Fix a bug causing the POWERSAFE_OVERWRITE device-characteristic flag to be set incorrectly if file opening is deferred. (check-in: 95d0c58d27 user: dan tags: deferred-open) | |
19:37 | Experimental change to os_unix.c to delay creating a database file until it is first written. (check-in: 538f7b25e4 user: dan tags: deferred-open) | |
2014-02-08
| ||
04:24 | Enable constant expression factoring even if no tables are read and no transaction is started. (check-in: a45b87713c user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
199 200 201 202 203 204 205 | sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ void *pMapRegion; /* Memory mapped region */ #endif #ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #endif | < < | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ void *pMapRegion; /* Memory mapped region */ #endif #ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #endif int openFlags; /* The flags specified at open() */ #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_DEBUG |
︙ | ︙ | |||
251 252 253 254 255 256 257 | #else # define UNIXFILE_DIRSYNC 0x00 #endif #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ | | > | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | #else # define UNIXFILE_DIRSYNC 0x00 #endif #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ #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() has issued warnings */ #define UNIXFILE_DEFERRED 0x0200 /* File has not yet been opened */ /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* |
︙ | ︙ | |||
1353 1354 1355 1356 1357 1358 1359 1360 1361 | ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); | > > > > > | | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 | ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); 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 */ if( pFile->pInode->eFileLock>SHARED_LOCK ){ reserved = 1; } |
︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | rc = 0; } }else{ rc = osFcntl(pFile->h, F_SETLK, pLock); } return rc; } /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK | > > | 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 | rc = 0; } }else{ rc = osFcntl(pFile->h, F_SETLK, 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: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK |
︙ | ︙ | |||
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 | */ if( pFile->eFileLock>=eFileLock ){ OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h, azFileLock(eFileLock))); return SQLITE_OK; } /* 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. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); assert( eFileLock!=PENDING_LOCK ); | > > > > > > > > > > > > > > > > > > > > > | 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | */ if( pFile->eFileLock>=eFileLock ){ OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h, azFileLock(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. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); assert( eFileLock!=PENDING_LOCK ); |
︙ | ︙ | |||
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | getpid())); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } unixEnterMutex(); pInode = pFile->pInode; assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start | > | 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 | getpid())); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } unixEnterMutex(); if( pFile->ctrlFlags==UNIXFILE_DEFERRED ) goto end_unlock; pInode = pFile->pInode; assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start |
︙ | ︙ | |||
1929 1930 1931 1932 1933 1934 1935 | int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; verifyDbFile(pFile); unixUnlock(id, NO_LOCK); unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close | | < | > > > > | > | 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 | int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; verifyDbFile(pFile); unixUnlock(id, NO_LOCK); unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close ** 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); } rc = closeUnixFile(id); unixLeaveMutex(); return rc; } /************** End of the posix advisory lock implementation ***************** ******************************************************************************/ |
︙ | ︙ | |||
3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 | #if 0 assert( pFile->pUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); #endif #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(). */ if( offset<pFile->mmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); return SQLITE_OK; | > > > > > > > > > > > > > > > > > | 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 | #if 0 assert( pFile->pUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); #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(). */ if( offset<pFile->mmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); return SQLITE_OK; |
︙ | ︙ | |||
3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 | } } /* ** Determine the current size of a file in bytes */ static int unixFileSize(sqlite3_file *id, i64 *pSize){ int rc; struct stat buf; assert( id ); | > > > > > > > > | > < | 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 | } } /* ** 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 ); 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; return SQLITE_IOERR_FSTAT; } *pSize = buf.st_size; /* When opening a zero-size database, the findInodeInfo() procedure ** writes a single byte into that file in order to work around a bug ** in the OS-X msdos filesystem. In order to avoid problems with upper ** layers, we need to report this file size as zero even though it is ** really 1. Ticket #3260. */ if( *pSize==1 ) *pSize = 0; return SQLITE_OK; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) /* ** Handler for proxy-locking file-control verbs. Defined below in the |
︙ | ︙ | |||
5172 5173 5174 5175 5176 5177 5178 | /* No locking occurs in temporary files */ assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; pNew->pVfs = pVfs; pNew->zPath = zFilename; | | | 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 | /* No locking occurs in temporary files */ assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; pNew->pVfs = pVfs; pNew->zPath = zFilename; pNew->ctrlFlags = (unsigned short)ctrlFlags; #if SQLITE_MAX_MMAP_SIZE>0 pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap; #endif if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0), "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pNew->ctrlFlags |= UNIXFILE_PSOW; } |
︙ | ︙ | |||
5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 | open_finished: if( rc!=SQLITE_OK ){ sqlite3_free(p->pUnused); } return rc; } /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ static int unixDelete( sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 | open_finished: if( rc!=SQLITE_OK ){ sqlite3_free(p->pUnused); } 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() ** the directory after deleting the file. */ static int unixDelete( sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ |
︙ | ︙ | |||
7372 7373 7374 7375 7376 7377 7378 | #define UNIXVFS(VFSNAME, FINDER) { \ 3, /* iVersion */ \ sizeof(unixFile), /* szOsFile */ \ MAX_PATHNAME, /* mxPathname */ \ 0, /* pNext */ \ VFSNAME, /* zName */ \ (void*)&FINDER, /* pAppData */ \ | | | 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 | #define UNIXVFS(VFSNAME, FINDER) { \ 3, /* iVersion */ \ sizeof(unixFile), /* szOsFile */ \ MAX_PATHNAME, /* mxPathname */ \ 0, /* pNext */ \ VFSNAME, /* zName */ \ (void*)&FINDER, /* pAppData */ \ unixOpenDeferred, /* xOpen */ \ unixDelete, /* xDelete */ \ unixAccess, /* xAccess */ \ unixFullPathname, /* xFullPathname */ \ unixDlOpen, /* xDlOpen */ \ unixDlError, /* xDlError */ \ unixDlSym, /* xDlSym */ \ unixDlClose, /* xDlClose */ \ |
︙ | ︙ |
Changes to src/test2.c.
︙ | ︙ | |||
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 | if( rc ){ Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0); sqlite3_free(zFile); return TCL_ERROR; } offset = n; offset *= 1024*1024; rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); sqlite3OsCloseFree(fd); sqlite3_free(zFile); if( rc ){ Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0); return TCL_ERROR; } return TCL_OK; | > > > | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | if( rc ){ Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0); sqlite3_free(zFile); return TCL_ERROR; } 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 ){ Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0); return TCL_ERROR; } return TCL_OK; |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
131 132 133 134 135 136 137 | lappend ::testsuitelist xxx test_suite "veryquick" -prefix "" -description { "Very" quick test suite. Runs in less than 5 minutes on a workstation. This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ | | > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | lappend ::testsuitelist xxx test_suite "veryquick" -prefix "" -description { "Very" quick test suite. Runs in less than 5 minutes on a workstation. 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* \ *multiplex* *quota* walbak.test ] test_suite "mmap" -prefix "mm-" -description { Similar to veryquick. Except with memory mapping disabled. } -presql { pragma mmap_size = 268435456; } -files [ |
︙ | ︙ |