aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c128
1 files changed, 78 insertions, 50 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index ca65836f4..48d2ff176 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -12,7 +12,7 @@
**
** This file contains code that is specific to Unix systems.
**
-** $Id: os_unix.c,v 1.193 2008/07/10 00:32:42 drh Exp $
+** $Id: os_unix.c,v 1.194 2008/07/30 15:27:54 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX /* This file is used on unix only */
@@ -311,6 +311,7 @@ struct lockInfo {
int cnt; /* Number of SHARED locks held */
int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
int nRef; /* Number of pointers to this structure */
+ struct lockInfo *pNext, *pPrev; /* List of all lockInfo objects */
};
/*
@@ -336,15 +337,17 @@ struct openCnt {
int nLock; /* Number of outstanding locks */
int nPending; /* Number of pending close() operations */
int *aPending; /* Malloced space holding fd's awaiting a close() */
+ struct openCnt *pNext, *pPrev; /* List of all openCnt objects */
};
-/*
-** These hash tables map inodes and file descriptors (really, lockKey and
-** openKey structures) into lockInfo and openCnt structures. Access to
-** these hash tables must be protected by a mutex.
+/*
+** List of all lockInfo and openCnt objects. This used to be a hash
+** table. But the number of objects is rarely more than a dozen and
+** never exceeds a few thousand. And lookup is not on a critical
+** path oo a simple linked list will suffice.
*/
-static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
-static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
+static struct lockInfo *lockList = 0;
+static struct openCnt *openList = 0;
/*
** The locking styles are associated with the different file locking
@@ -362,9 +365,9 @@ static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
** file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX 1
-#define LOCKING_STYLE_FLOCK 2
+#define LOCKING_STYLE_NONE 2
#define LOCKING_STYLE_DOTFILE 3
-#define LOCKING_STYLE_NONE 4
+#define LOCKING_STYLE_FLOCK 4
#define LOCKING_STYLE_AFP 5
/*
@@ -523,7 +526,17 @@ static void releaseLockInfo(struct lockInfo *pLock){
if( pLock ){
pLock->nRef--;
if( pLock->nRef==0 ){
- sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
+ if( pLock->pPrev ){
+ assert( pLock->pPrev->pNext==pLock );
+ pLock->pPrev->pNext = pLock->pNext;
+ }else{
+ assert( lockList==pLock );
+ lockList = pLock->pNext;
+ }
+ if( pLock->pNext ){
+ assert( pLock->pNext->pPrev==pLock );
+ pLock->pNext->pPrev = pLock->pPrev;
+ }
sqlite3_free(pLock);
}
}
@@ -536,8 +549,18 @@ static void releaseOpenCnt(struct openCnt *pOpen){
if( pOpen ){
pOpen->nRef--;
if( pOpen->nRef==0 ){
- sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
- free(pOpen->aPending);
+ if( pOpen->pPrev ){
+ assert( pOpen->pPrev->pNext==pOpen );
+ pOpen->pPrev->pNext = pOpen->pNext;
+ }else{
+ assert( openList==pOpen );
+ openList = pOpen->pNext;
+ }
+ if( pOpen->pNext ){
+ assert( pOpen->pNext->pPrev==pOpen );
+ pOpen->pNext->pPrev = pOpen->pPrev;
+ }
+ sqlite3_free(pOpen->aPending);
sqlite3_free(pOpen);
}
}
@@ -663,9 +686,11 @@ static int findLockInfo(
memset(&key2, 0, sizeof(key2));
key2.dev = statbuf.st_dev;
key2.ino = statbuf.st_ino;
- pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));
+ pLock = lockList;
+ while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
+ pLock = pLock->pNext;
+ }
if( pLock==0 ){
- struct lockInfo *pOld;
pLock = sqlite3_malloc( sizeof(*pLock) );
if( pLock==0 ){
rc = SQLITE_NOMEM;
@@ -675,21 +700,20 @@ static int findLockInfo(
pLock->nRef = 1;
pLock->cnt = 0;
pLock->locktype = 0;
- pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
- if( pOld!=0 ){
- assert( pOld==pLock );
- sqlite3_free(pLock);
- rc = SQLITE_NOMEM;
- goto exit_findlockinfo;
- }
+ pLock->pNext = lockList;
+ pLock->pPrev = 0;
+ if( lockList ) lockList->pPrev = pLock;
+ lockList = pLock;
}else{
pLock->nRef++;
}
*ppLock = pLock;
if( ppOpen!=0 ){
- pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));
+ pOpen = openList;
+ while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
+ pOpen = pOpen->pNext;
+ }
if( pOpen==0 ){
- struct openCnt *pOld;
pOpen = sqlite3_malloc( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
@@ -701,14 +725,10 @@ static int findLockInfo(
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
- pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
- if( pOld!=0 ){
- assert( pOld==pOpen );
- sqlite3_free(pOpen);
- releaseLockInfo(pLock);
- rc = SQLITE_NOMEM;
- goto exit_findlockinfo;
- }
+ pOpen->pNext = openList;
+ pOpen->pPrev = 0;
+ if( openList ) openList->pPrev = pOpen;
+ openList = pOpen;
}else{
pOpen->nRef++;
}
@@ -1424,7 +1444,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
for(i=0; i<pOpen->nPending; i++){
close(pOpen->aPending[i]);
}
- free(pOpen->aPending);
+ sqlite3_free(pOpen->aPending);
pOpen->nPending = 0;
pOpen->aPending = 0;
}
@@ -1473,7 +1493,7 @@ static int unixClose(sqlite3_file *id){
*/
int *aNew;
struct openCnt *pOpen = pFile->pOpen;
- aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
+ aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
@@ -1970,7 +1990,7 @@ static int dotlockClose(sqlite3_file *id) {
}
-#pragma mark No locking
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
** The nolockLockingContext is void
@@ -1997,8 +2017,6 @@ static int nolockClose(sqlite3_file *id) {
return closeUnixFile(id);
}
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
/*
** Information and control of an open file handle.
@@ -2047,8 +2065,13 @@ static int fillInUnixFile(
int h, /* Open file descriptor of file being opened */
int dirfd, /* Directory file descriptor */
sqlite3_file *pId, /* Write to the unixFile structure here */
- const char *zFilename /* Name of the file being opened */
+ const char *zFilename, /* Name of the file being opened */
+ int noLock /* Omit locking if true */
){
+ int eLockingStyle;
+ unixFile *pNew = (unixFile *)pId;
+ int rc = SQLITE_OK;
+
/* Macro to define the static contents of an sqlite3_io_methods
** structure for a unix backend file. Different locking methods
** require different functions for the xClose, xLock, xUnlock and
@@ -2071,17 +2094,21 @@ static int fillInUnixFile(
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock)
+ ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#ifdef SQLITE_ENABLE_LOCKING_STYLE
- ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
+ ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
#endif
};
-
- int eLockingStyle;
- unixFile *pNew = (unixFile *)pId;
- int rc = SQLITE_OK;
+ /* The order of the IOMETHODS macros above is important. It must be the
+ ** same order as the LOCKING_STYLE numbers
+ */
+ assert(LOCKING_STYLE_POSIX==1);
+ assert(LOCKING_STYLE_NONE==2);
+ assert(LOCKING_STYLE_DOTFILE==3);
+ assert(LOCKING_STYLE_FLOCK==4);
+ assert(LOCKING_STYLE_AFP==5);
assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL );
@@ -2091,12 +2118,11 @@ static int fillInUnixFile(
pNew->dirfd = dirfd;
SET_THREADID(pNew);
- assert(LOCKING_STYLE_POSIX==1);
- assert(LOCKING_STYLE_FLOCK==2);
- assert(LOCKING_STYLE_DOTFILE==3);
- assert(LOCKING_STYLE_NONE==4);
- assert(LOCKING_STYLE_AFP==5);
- eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
+ if( noLock ){
+ eLockingStyle = LOCKING_STYLE_NONE;
+ }else{
+ eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
+ }
switch( eLockingStyle ){
@@ -2280,6 +2306,7 @@ static int unixOpen(
int dirfd = -1; /* Directory file descriptor */
int oflags = 0; /* Flags to pass to open() */
int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int noLock; /* True to omit locking primitives */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
@@ -2375,7 +2402,8 @@ static int unixOpen(
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
- return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath);
+ noLock = eType!=SQLITE_OPEN_MAIN_DB;
+ return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock);
}
/*