Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Cleanup the locking-style code in os_unix.c. (CVS 4837) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
40f55c09dbd31f861b9f9c7641cce925 |
User & Date: | drh 2008-03-07 15:34:11.000 |
Context
2008-03-07
| ||
19:51 | Correctly handle I/O errors that occur during OsUnlock(). Before this fix, an I/O error during OsUnlock() could lead to database corruption. That is not a serious problem, though, since errors during OsUnlock() are not possible on most systems. (CVS 4838) (check-in: b4c1258edb user: drh tags: trunk) | |
15:34 | Cleanup the locking-style code in os_unix.c. (CVS 4837) (check-in: 40f55c09db user: drh tags: trunk) | |
03:20 | Trivial documentation fixes (CVS 4836) (check-in: 9819cefbd7 user: mlcreech tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
348 349 350 351 352 353 354 | ** 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 */ typedef enum { | | | | | | | | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | ** 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 */ typedef enum { posixLockingStyle = 0, /* standard posix-advisory locks */ afpLockingStyle, /* use afp locks */ flockLockingStyle, /* use flock() */ dotlockLockingStyle, /* use <file>.lock files */ noLockingStyle, /* useful for read-only file system */ unsupportedLockingStyle /* indicates unsupported file system */ } sqlite3LockingStyle; #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** Helper functions to obtain and relinquish the global mutex. */ static void enterMutex(){ |
︙ | ︙ | |||
577 578 579 580 581 582 583 | ){ #ifdef SQLITE_FIXED_LOCKING_STYLE return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE; #else struct statfs fsInfo; | | | | | | | | | | | | | | | | | | | | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 | ){ #ifdef SQLITE_FIXED_LOCKING_STYLE return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE; #else struct statfs fsInfo; if( statfs(filePath, &fsInfo) == -1 ){ return sqlite3TestLockingStyle(filePath, fd); } if( fsInfo.f_flags & MNT_RDONLY ){ return noLockingStyle; } if( strcmp(fsInfo.f_fstypename, "hfs")==0 || strcmp(fsInfo.f_fstypename, "ufs")==0 ){ return posixLockingStyle; } if( strcmp(fsInfo.f_fstypename, "afpfs")==0 ){ return afpLockingStyle; } if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ return sqlite3TestLockingStyle(filePath, fd); } if( strcmp(fsInfo.f_fstypename, "smbfs")==0 ){ return flockLockingStyle; } if( strcmp(fsInfo.f_fstypename, "msdos")==0 ){ return dotlockLockingStyle; } if( strcmp(fsInfo.f_fstypename, "webdav")==0 ){ return unsupportedLockingStyle; } return sqlite3TestLockingStyle(filePath, fd); #endif /* SQLITE_FIXED_LOCKING_STYLE */ } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* |
︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 | #pragma mark AFP Support /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { | | | | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 | #pragma mark AFP Support /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { unsigned long long sharedLockByte; /* Byte offset of shared lock byte */ const char *filePath; /* Name of the file */ }; struct ByteRangeLockPB2 { unsigned long long offset; /* offset to first byte to lock */ unsigned long long length; /* nbr of bytes to lock */ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ |
︙ | ︙ | |||
1538 1539 1540 1541 1542 1543 1544 | OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } /* AFP-style locking following the behavior of unixLock, see the unixLock ** function comments for details of lock management. */ | | < | > | | | | | | | | | | | | | | | 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 | OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } /* AFP-style locking following the behavior of unixLock, see the unixLock ** function comments for details of lock management. */ static int afpUnixLock(sqlite3_file *id, int locktype){ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int gotPendingLock = 0; assert( pFile ); OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), getpid()); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as ** enterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, locktypeName(locktype)); return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* This mutex is needed because pFile->pLock is shared across threads */ enterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ leaveMutex(); return rc; } /* A PENDING lock is needed before acquiring a SHARED lock and before ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ if( locktype==SHARED_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) ){ int failed; failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1); if (failed) { rc = SQLITE_BUSY; goto afp_end_lock; } } /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( locktype==SHARED_LOCK ){ int lk, failed; int tries = 0; /* Now get the read-lock */ /* note that the quality of the randomness doesn't matter that much */ lk = random(); |
︙ | ︙ | |||
1659 1660 1661 1662 1663 1664 1665 | if( rc==SQLITE_OK ){ pFile->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ pFile->locktype = PENDING_LOCK; } afp_end_lock: | | | | | | | | | 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | if( rc==SQLITE_OK ){ pFile->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ pFile->locktype = PENDING_LOCK; } afp_end_lock: leaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); 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. */ static int afpUnixUnlock(sqlite3_file *id, int locktype) { struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; assert( pFile ); |
︙ | ︙ | |||
1738 1739 1740 1741 1742 1743 1744 | if (rc == SQLITE_OK) pFile->locktype = locktype; leaveMutex(); return rc; } /* | | | < < < < | < < < < | | | | 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 | if (rc == SQLITE_OK) pFile->locktype = locktype; leaveMutex(); return rc; } /* ** Close a file & cleanup AFP specific locking context */ static int afpUnixClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; if( !pFile ) return SQLITE_OK; afpUnixUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; close(pFile->h); OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } #pragma mark flock() style locking /* ** The flockLockingContext is not used */ typedef void flockLockingContext; static int flockUnixCheckReservedLock(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; if (pFile->locktype == RESERVED_LOCK) { return 1; /* already have a reserved lock */ } else { /* attempt to get the lock */ int rc = flock(pFile->h, LOCK_EX | LOCK_NB); |
︙ | ︙ | |||
1837 1838 1839 1840 1841 1842 1843 | else { pFile->locktype = NO_LOCK; return SQLITE_OK; } } /* | | | < < < | | | | < | > | | > | > > | | | | > | | 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 | else { pFile->locktype = NO_LOCK; return SQLITE_OK; } } /* ** Close a file. */ static int flockUnixClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; if( !pFile ) return SQLITE_OK; flockUnixUnlock(id, NO_LOCK); if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; close(pFile->h); OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } #pragma mark Old-School .lock file based locking /* ** The dotlockLockingContext structure contains all dotlock (.lock) lock ** specific state */ typedef struct dotlockLockingContext dotlockLockingContext; struct dotlockLockingContext { char *lockPath; }; static int dotlockUnixCheckReservedLock(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; dotlockLockingContext *context; context = (dotlockLockingContext*)pFile->lockingContext; if (pFile->locktype == RESERVED_LOCK) { return 1; /* already have a reserved lock */ } else { struct stat statBuf; if (lstat(context->lockPath,&statBuf) == 0){ /* file exists, someone else has the lock */ return 1; }else{ /* file does not exist, we could have it if we want it */ return 0; } } } static int dotlockUnixLock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; dotlockLockingContext *context; int fd; context = (dotlockLockingContext*)pFile->lockingContext; /* if we already have a lock, it is exclusive. ** Just adjust level and punt on outta here. */ if (pFile->locktype > NO_LOCK) { pFile->locktype = locktype; /* Always update the timestamp on the old file */ utimes(context->lockPath,NULL); return SQLITE_OK; } /* check to see if lock file already exists */ struct stat statBuf; if (lstat(context->lockPath,&statBuf) == 0){ return SQLITE_BUSY; /* it does, busy */ } /* grab an exclusive lock */ fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600); if( fd<0 ){ /* failed to open/create the file, someone else may have stolen the lock */ return SQLITE_BUSY; } close(fd); /* got it, set the type and return ok */ pFile->locktype = locktype; return SQLITE_OK; } static int dotlockUnixUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; dotlockLockingContext *context; context = (dotlockLockingContext*)pFile->lockingContext; assert( locktype<=SHARED_LOCK ); /* no-op if possible */ if( pFile->locktype==locktype ){ return SQLITE_OK; } |
︙ | ︙ | |||
1953 1954 1955 1956 1957 1958 1959 | ** Close a file. */ static int dotlockUnixClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; if( !pFile ) return SQLITE_OK; dotlockUnixUnlock(id, NO_LOCK); | < < < < < | < < < < | | | | < < | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 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 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 | ** Close a file. */ static int dotlockUnixClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; if( !pFile ) return SQLITE_OK; dotlockUnixUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; close(pFile->h); OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } #pragma mark No locking /* ** The nolockLockingContext is void */ typedef void nolockLockingContext; static int nolockUnixCheckReservedLock(sqlite3_file *id) { return 0; } static int nolockUnixLock(sqlite3_file *id, int locktype) { return SQLITE_OK; } static int nolockUnixUnlock(sqlite3_file *id, int locktype) { return SQLITE_OK; } /* ** Close a file. */ static int nolockUnixClose(sqlite3_file *id) { unixFile *pFile = (unixFile*)id; if( !pFile ) return SQLITE_OK; if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; close(pFile->h); OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
︙ | ︙ | |||
2130 2131 2132 2133 2134 2135 2136 | unixFileControl, unixSectorSize, unixDeviceCharacteristics }; /* ** This vector defines all the methods that can operate on an sqlite3_file | | | 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 | unixFileControl, unixSectorSize, unixDeviceCharacteristics }; /* ** This vector defines all the methods that can operate on an sqlite3_file ** for unix with nolock style file locking. */ static const sqlite3_io_methods sqlite3NolockLockingUnixIoMethod = { 1, /* iVersion */ nolockUnixClose, unixRead, unixWrite, unixTruncate, |
︙ | ︙ | |||
2177 2178 2179 2180 2181 2182 2183 | int rc; #ifdef FD_CLOEXEC fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); #endif lockingStyle = sqlite3DetectLockingStyle(zFilename, h); | | < | 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 | int rc; #ifdef FD_CLOEXEC fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); #endif lockingStyle = sqlite3DetectLockingStyle(zFilename, h); if ( lockingStyle==posixLockingStyle ){ enterMutex(); rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); leaveMutex(); if( rc ){ if( dirfd>=0 ) close(dirfd); close(h); return SQLITE_NOMEM; |
︙ | ︙ | |||
2203 2204 2205 2206 2207 2208 2209 | pNew->dirfd = dirfd; SET_THREADID(pNew); switch(lockingStyle) { case afpLockingStyle: { /* afp locking uses the file path so it needs to be included in ** the afpLockingContext */ | | | | | > > > | > > | < | | > > | < < < | > > > > > > | < | | 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 | pNew->dirfd = dirfd; SET_THREADID(pNew); switch(lockingStyle) { case afpLockingStyle: { /* afp locking uses the file path so it needs to be included in ** the afpLockingContext */ afpLockingContext *context; pNew->pMethod = &sqlite3AFPLockingUnixIoMethod; pNew->lockingContext = context = sqlite3_malloc( sizeof(*context) ); if( context==0 ){ close(h); if( dirfd>=0 ) close(dirfd); return SQLITE_NOMEM; } /* NB: zFilename exists and remains valid until the file is closed ** according to requirement F11141. So we do not need to make a ** copy of the filename. */ context->filePath = zFilename; srandomdev(); break; } case flockLockingStyle: /* flock locking doesn't need additional lockingContext information */ pNew->pMethod = &sqlite3FlockLockingUnixIoMethod; break; case dotlockLockingStyle: { /* dotlock locking uses the file path so it needs to be included in ** the dotlockLockingContext */ dotlockLockingContext *context; int nFilename; nFilename = strlen(zFilename); pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod; pNew->lockingContext = context = sqlite3_malloc( sizeof(*context) + nFilename + 6 ); if( context==0 ){ close(h); if( dirfd>=0 ) close(dirfd); return SQLITE_NOMEM; } context->lockPath = (char*)&context[1]; sqlite3_snprintf(nFilename, context->lockPath, "%s.lock", zFilename); break; } case posixLockingStyle: /* posix locking doesn't need additional lockingContext information */ pNew->pMethod = &sqlite3UnixIoMethod; break; case noLockingStyle: |
︙ | ︙ |