Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | In the unix OS implementation, replace inode hash tables with linked lists. (CVS 5503) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
db4022db64dc5864e6f1d0a206721838 |
User & Date: | drh 2008-07-30 15:27:54.000 |
Context
2008-07-30
| ||
17:28 | When opening a zero-size database on unix, write one byte into the file before interrogating the inode number. This works around issues with msdos filesystems mounted on OS-X. Ticket #3260. (CVS 5504) (check-in: a480a8845f user: drh tags: trunk) | |
15:27 | In the unix OS implementation, replace inode hash tables with linked lists. (CVS 5503) (check-in: db4022db64 user: drh tags: trunk) | |
13:27 | Implicit string->numeric conversion should go to an integer value when possible. Ticket #3257. (CVS 5502) (check-in: da0e4bff30 user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to Unix systems. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to Unix systems. ** ** $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 */ /* ** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different ** locking implementations are provided: |
︙ | ︙ | |||
307 308 309 310 311 312 313 314 315 316 317 318 319 320 | ** object keeps a count of the number of unixFile pointing to it. */ struct lockInfo { struct lockKey key; /* The lookup key */ int cnt; /* Number of SHARED locks held */ int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ int nRef; /* Number of pointers to this structure */ }; /* ** An instance of the following structure serves as the key used ** to locate a particular openCnt structure given its inode. This ** is the same as the lockKey except that the thread ID is omitted. */ | > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | ** object keeps a count of the number of unixFile pointing to it. */ struct lockInfo { struct lockKey key; /* The lookup key */ 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 */ }; /* ** An instance of the following structure serves as the key used ** to locate a particular openCnt structure given its inode. This ** is the same as the lockKey except that the thread ID is omitted. */ |
︙ | ︙ | |||
332 333 334 335 336 337 338 339 340 | */ struct openCnt { struct openKey key; /* The lookup key */ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; | > | < | | > > | | | | | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | */ struct openCnt { struct openKey key; /* The lookup key */ int nRef; /* Number of pointers to this structure */ 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 */ }; /* ** 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 struct lockInfo *lockList = 0; static struct openCnt *openList = 0; /* ** The locking styles are associated with the different file locking ** capabilities supported by different file systems. ** ** POSIX locking style fully supports shared and exclusive byte-range locks ** AFP locking only supports exclusive byte-range locks ** FLOCK only supports a single file-global exclusive lock ** 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 ** NO locking means that no locking will be attempted, this is only used for ** read-only file systems currently ** UNSUPPORTED means that no locking will be attempted, this is only used for ** file systems that are known to be unsupported */ #define LOCKING_STYLE_POSIX 1 #define LOCKING_STYLE_NONE 2 #define LOCKING_STYLE_DOTFILE 3 #define LOCKING_STYLE_FLOCK 4 #define LOCKING_STYLE_AFP 5 /* ** Helper functions to obtain and relinquish the global mutex. */ static void enterMutex(){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); |
︙ | ︙ | |||
519 520 521 522 523 524 525 | /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ if( pLock ){ pLock->nRef--; if( pLock->nRef==0 ){ | | > > > > > > > > > > | > > > > > > > > > > | | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ if( pLock ){ pLock->nRef--; if( pLock->nRef==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); } } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ if( pOpen ){ pOpen->nRef--; if( pOpen->nRef==0 ){ 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); } } } #ifdef SQLITE_ENABLE_LOCKING_STYLE /* |
︙ | ︙ | |||
659 660 661 662 663 664 665 | testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; | > | > > < < < | | | | < > | > > < | < | | < | < < | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = lockList; while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){ pLock = pLock->pNext; } if( pLock==0 ){ pLock = sqlite3_malloc( sizeof(*pLock) ); if( pLock==0 ){ rc = SQLITE_NOMEM; goto exit_findlockinfo; } pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pLock->pNext = lockList; pLock->pPrev = 0; if( lockList ) lockList->pPrev = pLock; lockList = pLock; }else{ pLock->nRef++; } *ppLock = pLock; if( ppOpen!=0 ){ pOpen = openList; while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){ pOpen = pOpen->pNext; } if( pOpen==0 ){ pOpen = sqlite3_malloc( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = SQLITE_NOMEM; goto exit_findlockinfo; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOpen->pNext = openList; pOpen->pPrev = 0; if( openList ) openList->pPrev = pOpen; openList = pOpen; }else{ pOpen->nRef++; } *ppOpen = pOpen; } exit_findlockinfo: |
︙ | ︙ | |||
1420 1421 1422 1423 1424 1425 1426 | pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; i<pOpen->nPending; i++){ close(pOpen->aPending[i]); } | | | 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 | pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; i<pOpen->nPending; i++){ close(pOpen->aPending[i]); } sqlite3_free(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } } leaveMutex(); if( rc==SQLITE_OK ) pFile->locktype = locktype; |
︙ | ︙ | |||
1469 1470 1471 1472 1473 1474 1475 | /* 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 pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = pFile->pOpen; | | | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 | /* 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 pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = pFile->pOpen; aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending] = pFile->h; pOpen->nPending++; pFile->h = -1; |
︙ | ︙ | |||
1966 1967 1968 1969 1970 1971 1972 | dotlockUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); } return closeUnixFile(id); } | | | 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 | dotlockUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); } return closeUnixFile(id); } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** The nolockLockingContext is void */ typedef void nolockLockingContext; static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) { |
︙ | ︙ | |||
1993 1994 1995 1996 1997 1998 1999 | /* ** Close a file. */ static int nolockClose(sqlite3_file *id) { return closeUnixFile(id); } | < < | 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 | /* ** Close a file. */ static int nolockClose(sqlite3_file *id) { return closeUnixFile(id); } /* ** Information and control of an open file handle. */ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { |
︙ | ︙ | |||
2043 2044 2045 2046 2047 2048 2049 | ** and assigned here also. */ static int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ int h, /* Open file descriptor of file being opened */ int dirfd, /* Directory file descriptor */ sqlite3_file *pId, /* Write to the unixFile structure here */ | | > > > > > | 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 | ** and assigned here also. */ static int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ 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 */ 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 ** xCheckReservedLock methods. */ #define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \ 1, /* iVersion */ \ |
︙ | ︙ | |||
2067 2068 2069 2070 2071 2072 2073 2074 | xCheckReservedLock, /* xCheckReservedLock */ \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics /* xDeviceCapabilities */ \ } static sqlite3_io_methods aIoMethod[] = { IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) #ifdef SQLITE_ENABLE_LOCKING_STYLE | > < | | | | | > > > > | < < | | | > | 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 | xCheckReservedLock, /* xCheckReservedLock */ \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics /* xDeviceCapabilities */ \ } static sqlite3_io_methods aIoMethod[] = { IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) #ifdef SQLITE_ENABLE_LOCKING_STYLE ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock) ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock) ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock) #endif }; /* 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 ); OSTRACE3("OPEN %-3d %s\n", h, zFilename); pNew->h = h; pNew->dirfd = dirfd; SET_THREADID(pNew); if( noLock ){ eLockingStyle = LOCKING_STYLE_NONE; }else{ eLockingStyle = detectLockingStyle(pVfs, zFilename, h); } switch( eLockingStyle ){ case LOCKING_STYLE_POSIX: { enterMutex(); rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); leaveMutex(); |
︙ | ︙ | |||
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 | int flags, int *pOutFlags ){ int fd = 0; /* File descriptor returned by open() */ int dirfd = -1; /* Directory file descriptor */ int oflags = 0; /* Flags to pass to open() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); int isReadonly = (flags & SQLITE_OPEN_READONLY); int isReadWrite = (flags & SQLITE_OPEN_READWRITE); | > | 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 | int flags, int *pOutFlags ){ int fd = 0; /* File descriptor returned by open() */ 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); int isCreate = (flags & SQLITE_OPEN_CREATE); int isReadonly = (flags & SQLITE_OPEN_READONLY); int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
︙ | ︙ | |||
2371 2372 2373 2374 2375 2376 2377 | } } #ifdef FD_CLOEXEC fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif | > | | 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 | } } #ifdef FD_CLOEXEC fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock); } /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.316 2008/07/30 15:27:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
3783 3784 3785 3786 3787 3788 3789 | if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 | if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); return TCL_OK; } /* ** Usage: sqlite_set_magic DB MAGIC-NUMBER ** ** Set the db->magic value. This is used to test error recovery logic. */ static int sqlite_set_magic( void * clientData, |
︙ | ︙ | |||
4805 4806 4807 4808 4809 4810 4811 | { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "file_control_test", file_control_test, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, /* Functions from os.h */ | < < < < < < < < < < < | 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 | { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "file_control_test", file_control_test, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, #endif { "sqlite3_test_errstr", test_errstr, 0 }, { "tcl_variable_type", tcl_variable_type, 0 }, |
︙ | ︙ |