From: drh Date: Wed, 30 Jul 2008 15:27:54 +0000 (+0000) Subject: In the unix OS implementation, replace inode hash tables with linked lists. (CVS... X-Git-Tag: version-3.6.10~674 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da0e768be29110dd4707923a6273cbc34a682e58;p=thirdparty%2Fsqlite.git In the unix OS implementation, replace inode hash tables with linked lists. (CVS 5503) FossilOrigin-Name: db4022db64dc5864e6f1d0a20672183879ad43aa --- diff --git a/manifest b/manifest index 0614359670..efd953eb30 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Implicit\sstring->numeric\sconversion\sshould\sgo\sto\san\sinteger\svalue\swhen\npossible.\s\sTicket\s#3257.\s(CVS\s5502) -D 2008-07-30T13:27:11 +C In\sthe\sunix\sOS\simplementation,\sreplace\sinode\shash\stables\swith\slinked\slists.\s(CVS\s5503) +D 2008-07-30T15:27:54 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in bbb62eecc851379aef5a48a1bf8787eb13e6ec06 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -133,7 +133,7 @@ F src/os.c 939ae7690a01d9401685ba124b4ba45fd4a7a2ad F src/os.h ef8abeb9afc694b82dbd169a91c9b7e26db3c892 F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c 676ed273b17bd260f905df81375c9f9950d85517 -F src/os_unix.c 1df6108efdb7957a9f28b9700600e58647c9c12d +F src/os_unix.c c778a6b7098f54ee2e4420150265ad3d26824c96 F src/os_win.c 50ec783403b418ddc9e6e05d541c6027dfd41070 F src/pager.c a6ecad26297469a8a3d1fd7a7c3dc2d603955044 F src/pager.h 588c1ac195228b2da45c4e5f7ab6c2fd253d1751 @@ -151,7 +151,7 @@ F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/status.c ca61c18b6f1c632b771514e0c39a7d662c805bbf F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8 F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3 -F src/test1.c 346e9262793be825ebadd9e69600d1b4682650f1 +F src/test1.c c7d37c6d6ce5a84c45546dfafae12e5c46c656ce F src/test2.c 7a634c1e044be3ea5845e65155fdd1cab13936cb F src/test3.c e00795839be38f0345a4845170426fb17d828bf9 F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406 @@ -614,7 +614,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 4a6ee88697ddc28e0c7df1954d1526de18191827 -R 1fc491d5b31cb2a2cf0986670de436ee +P da0e4bff30a77f72ae283406b547401c2ebb42c5 +R 4761a1459dbfe21d158c4e02d11ac727 U drh -Z 6e72d4e65f10edd96172495856b81fe0 +Z 2fbbc6538919439da5b60f94f6787348 diff --git a/manifest.uuid b/manifest.uuid index 2035441ac0..660828ab40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -da0e4bff30a77f72ae283406b547401c2ebb42c5 \ No newline at end of file +db4022db64dc5864e6f1d0a20672183879ad43aa \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index ca65836f46..48d2ff1769 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; inPending; 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); } /* diff --git a/src/test1.c b/src/test1.c index 529ed84b45..1062d87c66 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.315 2008/07/12 14:52:20 drh Exp $ +** $Id: test1.c,v 1.316 2008/07/30 15:27:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -3787,167 +3787,6 @@ static int test_stmt_int( return TCL_OK; } -#ifndef SQLITE_OMIT_DISKIO -#if 0 -/* -** Usage: sqlite3OsOpenReadWrite -*/ -static int test_sqlite3OsOpenReadWrite( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_file *pFile; - int rc; - int dummy; - char zBuf[100]; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " filename", 0); - return TCL_ERROR; - } - - rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_ERROR; - } - sqlite3TestMakePointerStr(interp, zBuf, pFile); - Tcl_SetResult(interp, zBuf, 0); - return TCL_ERROR; -} - -/* -** Usage: sqlite3OsClose -*/ -static int test_sqlite3OsClose( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_file *pFile; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " filehandle", 0); - return TCL_ERROR; - } - - if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ - return TCL_ERROR; - } - rc = sqlite3OsClose(&pFile); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: sqlite3OsLock -*/ -static int test_sqlite3OsLock( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_file * pFile; - int rc; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), - " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); - return TCL_ERROR; - } - - if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ - return TCL_ERROR; - } - - if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ - rc = sqlite3OsLock(pFile, SHARED_LOCK); - } - else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ - rc = sqlite3OsLock(pFile, RESERVED_LOCK); - } - else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ - rc = sqlite3OsLock(pFile, PENDING_LOCK); - } - else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ - rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); - }else{ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), - " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); - return TCL_ERROR; - } - - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: sqlite3OsUnlock -*/ -static int test_sqlite3OsUnlock( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_file * pFile; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " filehandle", 0); - return TCL_ERROR; - } - - if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ - return TCL_ERROR; - } - rc = sqlite3OsUnlock(pFile, NO_LOCK); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: sqlite3OsTempFileName -*/ -static int test_sqlite3OsTempFileName( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char zFile[SQLITE_TEMPNAME_SIZE]; - int rc; - - rc = sqlite3OsTempFileName(zFile); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_ERROR; - } - Tcl_AppendResult(interp, zFile, 0); - return TCL_OK; -} -#endif -#endif - /* ** Usage: sqlite_set_magic DB MAGIC-NUMBER ** @@ -4809,17 +4648,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_vfs_list", vfs_list, 0 }, /* Functions from os.h */ -#ifndef SQLITE_OMIT_DISKIO -#if 0 - { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, - { "sqlite3OsClose", test_sqlite3OsClose, 0 }, - { "sqlite3OsLock", test_sqlite3OsLock, 0 }, - { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 }, - - /* 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 },