1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Continuing work on the os_unix.c refactoring. Removed all of the

LOCKING_STYLE_* constants and instead pass around pointers to the
underlying sqlite3_io_method objects. (CVS 5966)

FossilOrigin-Name: 1017d2fb1935a278ef442030bf7bdf5e112c566a
This commit is contained in:
drh
2008-11-29 00:56:52 +00:00
parent 734c9864cb
commit 7708e9720b
5 changed files with 431 additions and 426 deletions

View File

@@ -1,5 +1,5 @@
C First\sstep\sin\srefactoring\sos_unix.c.\s\sThis\sis\swork\sin\sprogress.\s\sThe\scode\ncompiles\sand\sruns\son\sLinux\sand\sMacOSX\s(as\slong\sas\sSQLITE_ENABLE_LOCKING_STYLE\nis\sturned\soff),\sbut\sthere\sare\sa\sfew\stest\sfailures.\s(CVS\s5965)
D 2008-11-28T15:37:20
C Continuing\swork\son\sthe\sos_unix.c\srefactoring.\s\sRemoved\sall\sof\sthe\nLOCKING_STYLE_*\sconstants\sand\sinstead\spass\saround\spointers\sto\sthe\nunderlying\ssqlite3_io_method\sobjects.\s(CVS\s5966)
D 2008-11-29T00:56:53
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 0aa7bbe3be6acc4045706e3bb3fd0b8f38f4a3b5
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -137,7 +137,7 @@ F src/os.c 0b411644b87ad689d7250bbfd1834d99b81a3df4
F src/os.h ef8abeb9afc694b82dbd169a91c9b7e26db3c892
F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
F src/os_os2.c 36196e71292a44bf2d393413cd8c86199694b8b4
F src/os_unix.c 26f4b3dde5bac6ba8c8dc86a547a4053d5f9cfc3
F src/os_unix.c 9c5269d610ec2d43a19733e964e89f3e61323b29
F src/os_win.c 3dff41670fb9798a869c636626bb7d6d8b6a45bb
F src/pager.c 2e9182e181bbd3d758436d9ccce2a3910400dd30
F src/pager.h a02ef8e6cc7e78b54874166e5ce786c9d4c489bf
@@ -159,7 +159,7 @@ F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
F src/tclsqlite.c 96049bd454f1547abff0a57c45f0dfa57701e076
F src/test1.c f407faafb17ad328057fe86800518a64046e2766
F src/test1.c 737638299302ef85e34f6d04c40d8155db251736
F src/test2.c 897528183edf2839c2a3c991d415905db56f1240
F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14
F src/test4.c f79ab52d27ff49b784b631a42e2ccd52cfd5c84c
@@ -171,7 +171,7 @@ F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
F src/test_async.c 45024094ed7cf780c5d5dccda645145f95cf78ef
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
F src/test_btree.c d7b8716544611c323860370ee364e897c861f1b0
F src/test_config.c 47c66ced0faa6b18fbab72cbe77098ee04789722
F src/test_config.c 4fcc391cbd5d2334c67cf3ec643c2c2bcc3025fa
F src/test_devsym.c 802d10e65b4217208cb47059b84adf46318bcdf4
F src/test_func.c a55c4d5479ff2eb5c0a22d4d88e9528ab59c953b
F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
@@ -662,7 +662,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P f9c7359065829b016d8cd04304c02509c254fe05
R f18bbe219fdf4c9d3849fc41eab92317
P 7825cd63e5cb390a9c2c05957ebc9b189612f04a
R 2259cba8f622d2dabcb4ffff89e3fb5a
U drh
Z 31ecaef0fd8fa5ecc70a0ec198476cc9
Z 276dfeea88fd39cbd9c4b8d08e052ab2

View File

@@ -1 +1 @@
7825cd63e5cb390a9c2c05957ebc9b189612f04a
1017d2fb1935a278ef442030bf7bdf5e112c566a

View File

@@ -40,7 +40,7 @@
** * sqlite3_file methods not associated with locking
** * Implementations of sqlite3_os_init() and sqlite3_os_end()
**
** $Id: os_unix.c,v 1.222 2008/11/28 15:37:20 drh Exp $
** $Id: os_unix.c,v 1.223 2008/11/29 00:56:53 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX /* This file is used on unix only */
@@ -156,49 +156,6 @@
*/
#define MAX_PATHNAME 512
/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.
**
** POSIX support for shared and exclusive byte-range locks
**
** NONE no locking will be attempted, this is only used for
** read-only file systems currently
**
** DOTLOCK isn't a true locking style, it refers to the use of a special
** file named the same as the database file with a '.lock'
** extension, this can be used on file systems that do not
** offer any reliable file locking
**
** FLOCK only a single file-global exclusive lock (Not on VxWorks)
**
** NAMEDSEM similar to DOTLOCK but uses a named semaphore instead of an
** indicator file. (VxWorks only)
**
** AFP support exclusive byte-range locks (MacOSX only)
**
** PROXY uses a second file to represent the lock state of the database
** file which is never actually locked, a third file controls
** access to the proxy (MacOSX only)
**
** Note that because FLOCK and NAMEDSEM are never used together, they
** share the same code number (3). The locking mode numbering is
** chosen so that a set of locking modes that are contiguous integers
** from 1 to N. On generic unix systems without flock() support,
** the modes are 1..3. On generic unix with flock() support, the modes
** are 1..4. On VxWorks, the modes are 1..4. On MacOSX the modes
** are 1..6.
*/
#define LOCKING_STYLE_POSIX 1
#define LOCKING_STYLE_NONE 2
#define LOCKING_STYLE_DOTFILE 3
#define LOCKING_STYLE_FLOCK 4
#define LOCKING_STYLE_NAMEDSEM 4
#define LOCKING_STYLE_AFP 5
#define LOCKING_STYLE_PROXY 6
#define LOCKING_STYLE_AUTOMATIC 0 /* Choose lock style automatically */
/*
** Only set the lastErrno if the error code is a real error and not
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
@@ -863,57 +820,6 @@ static void testThreadLockingBehavior(int fd_orig){
}
#endif /* SQLITE_THERADSAFE && defined(__linux__) */
/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
** A unixFile is only owned by a thread on systems where one thread is
** unable to override locks created by a different thread. RedHat9 is
** an example of such a system.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
*/
#if SQLITE_THREADSAFE && defined(__linux__)
static int transferOwnership(unixFile *pFile){
int rc;
pthread_t hSelf;
if( threadsOverrideEachOthersLocks ){
/* Ownership transfers not needed on this system */
return SQLITE_OK;
}
hSelf = pthread_self();
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE;
}
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
rc = findLockInfo(pFile, &pFile->pLock, 0);
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
return rc;
} else {
return SQLITE_OK;
}
}
#else /* if not SQLITE_THREADSAFE */
/* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
#endif /* SQLITE_THREADSAFE */
/*
** Release a unixLockInfo structure previously allocated by findLockInfo().
*/
@@ -1087,6 +993,54 @@ exit_findlockinfo:
return rc;
}
/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
** A unixFile is only owned by a thread on systems that use LinuxThreads.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
*/
#if SQLITE_THREADSAFE && defined(__linux__)
static int transferOwnership(unixFile *pFile){
int rc;
pthread_t hSelf;
if( threadsOverrideEachOthersLocks ){
/* Ownership transfers not needed on this system */
return SQLITE_OK;
}
hSelf = pthread_self();
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE;
}
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
rc = findLockInfo(pFile, &pFile->pLock, 0);
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
return rc;
} else {
return SQLITE_OK;
}
}
#else /* if not SQLITE_THREADSAFE */
/* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
#endif /* SQLITE_THREADSAFE */
/*
** This routine checks if there is a RESERVED lock held on the specified
@@ -1646,6 +1600,11 @@ static int nolockClose(sqlite3_file *id) {
**
** Nevertheless, a dotlock is an appropriate locking mode for use if no
** other locking strategy is available.
**
** Dotfile locking works by creating a file in the same directory as the
** database and with the same name but with a ".lock" extension added.
** The existance of a lock file implies an EXCLUSIVE lock. All other lock
** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
*/
/*
@@ -1654,8 +1613,16 @@ static int nolockClose(sqlite3_file *id) {
*/
#define DOTLOCK_SUFFIX ".lock"
/* Dotlock-style reserved lock checking following the behavior of
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
**
** In dotfile locking, either a lock exists or it does not. So in this
** variation of CheckReservedLock(), *pResOut is set to true if any lock
** is held on the file and false if the file is unlocked.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
@@ -1667,55 +1634,63 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
reserved = 1;
}
/* Otherwise see if some other process holds it. */
if( !reserved ){
char *zLockFile = (char *)pFile->lockingContext;
struct stat statBuf;
if( lstat(zLockFile, &statBuf)==0 ){
/* file exists, someone else has the lock */
/* Either this connection or some other connection in the same process
** holds a lock on the file. No need to check further. */
reserved = 1;
}else{
/* file does not exist, we could have it if we want it */
int tErrno = errno;
if( ENOENT != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
pFile->lastErrno = tErrno;
}
}
/* The lock is held if and only if the lockfile exists */
const char *zLockFile = (const char*)pFile->lockingContext;
reserved = access(zLockFile, 0)==0;
}
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
**
** With dotfile locking, we really only support state (4): EXCLUSIVE.
** But we track the other locking levels internally.
*/
static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
int rc = SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
/* If we have any lock, then the lock file already exists. All we have
** to do is adjust our internal record of the lock level.
*/
if( pFile->locktype > NO_LOCK ){
pFile->locktype = locktype;
#if !OS_VXWORKS
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
#endif
rc = SQLITE_OK;
goto dotlock_end_lock;
}
/* check to see if lock file already exists */
struct stat statBuf;
if (lstat(zLockFile,&statBuf) == 0){
rc = SQLITE_BUSY; /* it does, busy */
goto dotlock_end_lock;
return SQLITE_OK;
}
/* grab an exclusive lock */
@@ -1731,7 +1706,7 @@ static int dotlockLock(sqlite3_file *id, int locktype) {
pFile->lastErrno = tErrno;
}
}
goto dotlock_end_lock;
return rc;
}
if( close(fd) ){
pFile->lastErrno = errno;
@@ -1740,11 +1715,18 @@ static int dotlockLock(sqlite3_file *id, int locktype) {
/* got it, set the type and return ok */
pFile->locktype = locktype;
dotlock_end_lock:
return rc;
}
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
**
** When the locking level reaches NO_LOCK, delete the lock file.
*/
static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
@@ -1759,13 +1741,16 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
return SQLITE_OK;
}
/* shared can just be set because we always have an exclusive */
/* To downgrade to shared, simply update our internal notion of the
** lock state. No need to mess with the file on disk.
*/
if( locktype==SHARED_LOCK ){
pFile->locktype = locktype;
pFile->locktype = SHARED_LOCK;
return SQLITE_OK;
}
/* no, really, unlock. */
/* To fully unlock the database, delete the lock file */
assert( locktype==NO_LOCK );
if( unlink(zLockFile) ){
int rc, tErrno = errno;
if( ENOENT != tErrno ){
@@ -1807,6 +1792,7 @@ static int dotlockClose(sqlite3_file *id) {
** compiling for VXWORKS.
*/
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
#include <sys/file.h>
/*
** The flockLockingContext is not used
@@ -1870,7 +1856,6 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
int lrc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
@@ -2629,39 +2614,12 @@ static int afpClose(sqlite3_file *id) {
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
static int getLockPath(const char *dbPath, char *lPath, size_t maxLen);
static sqlite3_io_methods *ioMethodForLockingStyle(int style);
static int createProxyUnixFile(const char *path, unixFile **ppFile);
static int fillInUnixFile(sqlite3_vfs *pVfs, int h, int dirfd, sqlite3_file *pId, const char *zFilename, int noLock, int isDelete);
static int takeConch(unixFile *pFile);
static int releaseConch(unixFile *pFile);
static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf);
/*
** Tests a byte-range locking query to see if byte range locks are
** supported, if not we fall back to dotlockLockingStyle.
** On vxWorks we fall back to semLockingStyle.
*/
static int testLockingStyle(int fd){
struct flock lockInfo;
/* Test byte-range lock using fcntl(). If the call succeeds,
** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
return LOCKING_STYLE_POSIX;
}
/* Testing for flock() can give false positives. So if if the above
** test fails, then we fall back to using dot-file style locking (or
** named-semaphore locking on vxworks).
*/
return (OS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
}
#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
@@ -3022,8 +2980,7 @@ end_takeconch:
if( tLockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath);
if( pCtx->lockProxy->pMethod ==
ioMethodForLockingStyle(LOCKING_STYLE_AFP) ){
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath =
pCtx->lockProxyPath;
}
@@ -3212,7 +3169,7 @@ end_transform_file:
pCtx->oldLockingContext = pFile->lockingContext;
pFile->lockingContext = pCtx;
pCtx->pOldMethod = pFile->pMethod;
pFile->pMethod = ioMethodForLockingStyle(LOCKING_STYLE_PROXY);
pFile->pMethod = &proxyIoMethods;
}else{
if( pCtx->conchFile ){
rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
@@ -3646,10 +3603,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = ((unixFile*)id)->locktype;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = ((unixFile*)id)->lastErrno;
return SQLITE_OK;
}
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
case SQLITE_GET_LOCKPROXYFILE: {
#if SQLITE_ENABLE_LOCKING_STYLE
unixFile *pFile = (unixFile*)id;
if( pFile->pMethod == ioMethodForLockingStyle(LOCKING_STYLE_PROXY) ){
if( pFile->pMethod == &proxyIoMethods ){
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
takeConch(pFile);
if( pCtx->lockProxyPath ){
@@ -3660,22 +3621,18 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
} else {
*(const char **)pArg = NULL;
}
#else
*(void**)pArg = NULL;
#endif
return SQLITE_OK;
}
case SQLITE_SET_LOCKPROXYFILE: {
#if SQLITE_ENABLE_LOCKING_STYLE
unixFile *pFile = (unixFile*)id;
int rc = SQLITE_OK;
int isProxyStyle = (pFile->pMethod == ioMethodForLockingStyle(LOCKING_STYLE_PROXY));
int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
if( pArg==NULL || (const char *)pArg==0 ){
if( isProxyStyle ){
// turn off proxy locking - not supported
/* turn off proxy locking - not supported */
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}else{
// turn off proxy locking - already off - NOOP
/* turn off proxy locking - already off - NOOP */
rc = SQLITE_OK;
}
}else{
@@ -3683,26 +3640,22 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
if( isProxyStyle ){
proxyLockingContext *pCtx =
(proxyLockingContext*)pFile->lockingContext;
if( !strcmp(pArg, ":auto:") || (pCtx->lockProxyPath && !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN)) ){
if( !strcmp(pArg, ":auto:")
|| (pCtx->lockProxyPath &&
!strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
){
rc = SQLITE_OK;
}else{
rc = switchLockProxyPath(pFile, proxyPath);
}
}else{
// turn on proxy file locking
/* turn on proxy file locking */
rc = transformUnixFileForLockProxy(pFile, proxyPath);
}
}
return rc;
#else
return SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}
#endif
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = ((unixFile*)id)->lastErrno;
return SQLITE_OK;
}
}
return SQLITE_ERROR;
}
@@ -3737,46 +3690,173 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
******************************************************************************/
/*
** The following constant array describes all of the methods for the
** sqlite3_file object for each of the various locking modes.
** Each instance of this macro generates two objects:
**
** The order in which the methods are defined is important and must
** agree with the numeric values of the method identifier constants.
** For example, LOCKING_STYLE_UNIX has a numeric value of zero, so
** it must be the 0-th entry in the array.
** * A constant sqlite3_io_methods object call METHOD that has locking
** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
**
** * An I/O method finder function called FINDER that returns a pointer
** to the METHOD object in the previous bullet.
*/
#define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \
#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \
static const sqlite3_io_methods METHOD = { \
1, /* iVersion */ \
xClose, /* xClose */ \
CLOSE, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
unixTruncate, /* xTruncate */ \
unixSync, /* xSync */ \
unixFileSize, /* xFileSize */ \
xLock, /* xLock */ \
xUnlock, /* xUnlock */ \
xCheckReservedLock, /* xCheckReservedLock */ \
LOCK, /* xLock */ \
UNLOCK, /* xUnlock */ \
CKLOCK, /* xCheckReservedLock */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics /* xDeviceCapabilities */ \
}; \
static const sqlite3_io_methods *FINDER(const char *z, int h){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(h); \
return &METHOD; \
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock),
IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock),
IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock),
#if OS_VXWORKS
IOMETHODS(semClose, semLock, semUnlock, semCheckReservedLock),
#elif SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock),
#endif
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock),
IOMETHODS(proxyClose, proxyLock, proxyUnlock, proxyCheckReservedLock),
#endif
/* The order of the IOMETHODS macros above is important. It must be the
** same order as the LOCKING_STYLE numbers
/*
** Here are all of the sqlite3_io_methods objects for each of the
** locking strategies. Functions that return pointers to these methods
** are also created.
*/
IOMETHODS(
posixIoFinder, /* Finder function name */
posixIoMethods, /* sqlite3_io_methods object name */
unixClose, /* xClose method */
unixLock, /* xLock method */
unixUnlock, /* xUnlock method */
unixCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
nolockCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
dotlockIoFinder, /* Finder function name */
dotlockIoMethods, /* sqlite3_io_methods object name */
dotlockClose, /* xClose method */
dotlockLock, /* xLock method */
dotlockUnlock, /* xUnlock method */
dotlockCheckReservedLock /* xCheckReservedLock method */
);
#if SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
flockClose, /* xClose method */
flockLock, /* xLock method */
flockUnlock, /* xUnlock method */
flockCheckReservedLock /* xCheckReservedLock method */
);
#endif
#if OS_VXWORKS
IOMETHODS(
semIoFinder, /* Finder function name */
semIoMethods, /* sqlite3_io_methods object name */
semClose, /* xClose method */
semLock, /* xLock method */
semUnlock, /* xUnlock method */
semCheckReservedLock /* xCheckReservedLock method */
);
#endif
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(
afpIoFinder, /* Finder function name */
afpIoMethods, /* sqlite3_io_methods object name */
afpClose, /* xClose method */
afpLock, /* xLock method */
afpUnlock, /* xUnlock method */
afpCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
proxyIoFinder, /* Finder function name */
proxyIoMethods, /* sqlite3_io_methods object name */
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
proxyCheckReservedLock /* xCheckReservedLock method */
);
#endif
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** This procedure attempts to determine the best locking strategy for
** the given database file. It then returns the sqlite3_io_methods
** object that implements that strategy.
**
** This is for MacOSX only.
*/
static const sqlite3_io_methods *autolockIoFinder(
const char *filePath, /* name of the database file */
int fd /* file descriptor open on the database file */
){
static const struct Mapping {
const char *zFilesystem;
const sqlite3_io_methods *pMethods;
} aMap[] = {
{ "hfs", &posixIoMethods },
{ "ufs", &posixIoMethods },
{ "afpfs", &afpIoMethods },
#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
{ "smbfs", &afpIoMethods },
#else
{ "smbfs", &flockIoMethods },
#endif
{ "webdav", &nolockIoMethods },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
struct flock lockInfo;
if( !filePath ){
return &nolockIoMethods;
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
return &nolockIoMethods;
}
for(i=0; aMap[i].zFilesystem; i++){
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
return aMap[i].pMethods;
}
}
}
/* Default case. Handles, amongst others, "nfs".
** Test byte-range lock using fcntl(). If the call succeeds,
** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
return &posixIoMethods;
}else{
return &dotlockIoMethods;
}
}
#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
/*
** An abstract type for a pointer to a IO method finder function:
*/
typedef const sqlite3_io_methods *(*finder_type)(const char*,int);
/****************************************************************************
**************************** sqlite3_vfs methods ****************************
@@ -3785,87 +3865,8 @@ static sqlite3_io_methods aIoMethod[] = {
** sqlite3_vfs object.
*/
/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the
** f_fstypename entry in the statfs structure as returned by stat() for
** the file system hosting the database file and selects the appropriate
** locking style based on its value. These values and assignments are
** based on Darwin/OSX behavior and have not been thoroughly tested on
** other systems.
**
** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always
** returns LOCKING_STYLE_POSIX.
*/
#if SQLITE_ENABLE_LOCKING_STYLE
static int detectLockingStyle(
sqlite3_vfs *pVfs,
const char *filePath,
int fd
){
#if OS_VXWORKS
if( !filePath ){
return LOCKING_STYLE_NONE;
}
if( pVfs->pAppData ){
return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if (access(filePath, 0) != -1){
return testLockingStyle(fd);
}
#else
struct Mapping {
const char *zFilesystem;
int eLockingStyle;
} aMap[] = {
{ "hfs", LOCKING_STYLE_POSIX },
{ "ufs", LOCKING_STYLE_POSIX },
{ "afpfs", LOCKING_STYLE_AFP },
#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
{ "smbfs", LOCKING_STYLE_AFP },
#else
{ "smbfs", LOCKING_STYLE_FLOCK },
#endif
{ "webdav", LOCKING_STYLE_NONE },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
if( !filePath ){
return LOCKING_STYLE_NONE;
}
if( pVfs && pVfs->pAppData ){
return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
return LOCKING_STYLE_NONE;
}
for(i=0; aMap[i].zFilesystem; i++){
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
return aMap[i].eLockingStyle;
}
}
}
/* Default case. Handles, amongst others, "nfs". */
return testLockingStyle(fd);
#endif /* if OS_VXWORKS */
return LOCKING_STYLE_POSIX;
}
#else
#define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
#endif /* if SQLITE_ENABLE_LOCKING_STYLE */
/*
** Initialize the contents of the unixFile structure pointed to by pId.
**
** When locking extensions are enabled, the filepath and locking style
** are needed to determine the unixFile pMethod to use for locking operations.
** The locking-style specific lockingContext data structure is created
** and assigned here also.
*/
static int fillInUnixFile(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
@@ -3876,7 +3877,7 @@ static int fillInUnixFile(
int noLock, /* Omit locking if true */
int isDelete /* Delete on close if true */
){
int eLockingStyle;
const sqlite3_io_methods *pLockingStyle;
unixFile *pNew = (unixFile *)pId;
int rc = SQLITE_OK;
@@ -3887,9 +3888,15 @@ static int fillInUnixFile(
** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly
** here to prevent compiler warnings about unused parameters.
*/
if( !OS_VXWORKS ) UNUSED_PARAMETER(isDelete);
if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
if( !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);
#if !OS_VXWORKS
UNUSED_PARAMETER(isDelete);
#endif
#if !SQLITE_ENABLE_LOCKING_STYLE
UNUSED_PARAMETER(pVfs);
#endif
#if !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE
UNUSED_PARAMETER(zFilename);
#endif
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
@@ -3905,9 +3912,9 @@ static int fillInUnixFile(
#endif
if( noLock ){
eLockingStyle = LOCKING_STYLE_NONE;
pLockingStyle = &nolockIoMethods;
}else{
eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
pLockingStyle = (*(finder_type)pVfs->pAppData)(zFilename, h);
#if SQLITE_ENABLE_LOCKING_STYLE
/* Cache zFilename in the locking context (AFP and dotlock override) for
** proxyLock activation is possible (remote proxy is based on db name)
@@ -3916,20 +3923,14 @@ static int fillInUnixFile(
#endif
}
switch( eLockingStyle ){
case LOCKING_STYLE_POSIX: {
if( pLockingStyle == &posixIoMethods ){
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
unixLeaveMutex();
break;
}
#if SQLITE_ENABLE_LOCKING_STYLE
#if !OS_VXWORKS
case LOCKING_STYLE_AFP: {
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
else if( pLockingStyle == &apfIoMethods ){
/* AFP locking uses the file path so it needs to be included in
** the afpLockingContext.
*/
@@ -3947,11 +3948,11 @@ static int fillInUnixFile(
rc = findLockInfo(pNew, NULL, &pNew->pOpen);
unixLeaveMutex();
}
break;
}
#endif
case LOCKING_STYLE_DOTFILE: {
#if SQLITE_ENABLE_LOCKING_STYLE
else if( pLockingStyle == &dotlockIoMethods ){
/* Dotfile locking uses the file path so it needs to be included in
** the dotlockLockingContext
*/
@@ -3965,11 +3966,11 @@ static int fillInUnixFile(
sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
}
pNew->lockingContext = zLockFile;
break;
}
#endif
#if OS_VXWORKS
case LOCKING_STYLE_NAMEDSEM: {
else if( pLockingStyle == &semIoMethods ){
/* Named semaphore locking uses the file path so it needs to be
** included in the semLockingContext
*/
@@ -3989,16 +3990,9 @@ static int fillInUnixFile(
}
}
unixLeaveMutex();
break;
}
#endif
case LOCKING_STYLE_FLOCK:
case LOCKING_STYLE_NONE:
break;
#endif
}
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
@@ -4011,34 +4005,32 @@ static int fillInUnixFile(
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
close(h);
}else{
pNew->pMethod = &aIoMethod[eLockingStyle-1];
pNew->pMethod = pLockingStyle;
OpenCounter(+1);
}
return rc;
}
#if SQLITE_ENABLE_LOCKING_STYLE
static sqlite3_io_methods *ioMethodForLockingStyle(int style){
return &aIoMethod[style];
}
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath){
if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_AFP) ){
#if defined(__DARWIN__)
if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
MAXPATHLEN);
return SQLITE_OK;
}
if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_DOTFILE) ){
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath)
}else
#endif
if( pFile->pMethod == &dotlockIoMethods ){
/* dot lock style uses the locking context to store the dot lock
** file path */
int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
strlcpy(dbPath, (char *)pFile->lockingContext, len + 1);
return SQLITE_OK;
}
memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
}else{
/* all other styles use the locking context to store the db file path */
strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strcpy(dbPath, (char *)pFile->lockingContext);
}
return SQLITE_OK;
}
#endif
@@ -4595,13 +4587,13 @@ int sqlite3_os_init(void){
** the sqlite3_vfs.zName and sqlite3_vfs.pAppData fields, respectively.
**
*/
#define UNIXVFS(zVfsName, pVfsAppData) { \
#define UNIXVFS(VFSNAME, FINDER) { \
1, /* iVersion */ \
sizeof(unixFile), /* szOsFile */ \
MAX_PATHNAME, /* mxPathname */ \
0, /* pNext */ \
zVfsName, /* zName */ \
(void *)pVfsAppData, /* pAppData */ \
VFSNAME, /* zName */ \
(void*)FINDER, /* pAppData */ \
unixOpen, /* xOpen */ \
unixDelete, /* xDelete */ \
unixAccess, /* xAccess */ \
@@ -4616,21 +4608,25 @@ int sqlite3_os_init(void){
unixGetLastError /* xGetLastError */ \
}
int i;
unsigned int i;
static sqlite3_vfs aVfs[] = {
UNIXVFS("unix", LOCKING_STYLE_AUTOMATIC),
UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
UNIXVFS("unix-none", LOCKING_STYLE_NONE),
UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE),
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
UNIXVFS("unix", autolockIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
#endif
UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ),
#if OS_VXWORKS
UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
UNIXVFS("unix-namedsem", semIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK),
UNIXVFS("unix-posix", posixIoFinder ),
UNIXVFS("unix-flock", flockIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
UNIXVFS("unix-proxy", LOCKING_STYLE_PROXY)
UNIXVFS("unix-afp", afpIoFinder ),
UNIXVFS("unix-proxy", proxyIoFinder ),
#endif
};
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){

View File

@@ -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.332 2008/11/28 15:37:20 drh Exp $
** $Id: test1.c,v 1.333 2008/11/29 00:56:53 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -4527,20 +4527,29 @@ static int file_control_lockproxy_test(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
#ifdef SQLITE_ENABLE_LOCKING_STYLE
#if defined(SQLITE_ENABLE_LOCKING_STYLE) && defined(__DARWIN__)
{
char *proxyPath = "test.proxy";
char *testPath;
rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
if( rc ) { Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; }
if( rc ){
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR;
}
rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
if( strncmp(proxyPath,testPath,11) ) {
Tcl_AppendResult(interp, "Lock proxy file did not match the previously assigned value", 0);
Tcl_AppendResult(interp, "Lock proxy file did not match the "
"previously assigned value", 0);
return TCL_ERROR;
}
if( rc ){
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return TCL_ERROR;
}
if( rc ) { Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; }
rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
if( rc ) { Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; }
if( rc ){
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return TCL_ERROR;
}
}
#endif
return TCL_OK;

View File

@@ -16,7 +16,7 @@
** The focus of this file is providing the TCL testing layer
** access to compile-time constants.
**
** $Id: test_config.c,v 1.43 2008/11/21 00:10:35 aswift Exp $
** $Id: test_config.c,v 1.44 2008/11/29 00:56:54 drh Exp $
*/
#include "sqliteLimit.h"
@@ -392,7 +392,7 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_LOCKING_STYLE
#if defined(SQLITE_ENABLE_LOCKING_STYLE) && defined(__DARWIN__)
Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","1",TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY);