Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Unix version of sqlite3OsLock(). (CVS 1520) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
023d1760c1a720632b25c98d14bf521a |
User & Date: | danielk1977 2004-06-01 14:09:29.000 |
Context
2004-06-02
| ||
00:08 | Fix another website typo. (CVS 1521) (check-in: 24e2bbd0f2 user: drh tags: trunk) | |
2004-06-01
| ||
14:09 | Unix version of sqlite3OsLock(). (CVS 1520) (check-in: 023d1760c1 user: danielk1977 tags: trunk) | |
12:59 | Fix typo on homepage (CVS 1519) (check-in: a84ece2500 user: drh tags: trunk) | |
Changes
Changes to src/os.h.
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | ** prematurely, old temporary files can be easily identified. This can be done ** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. */ #ifndef TEMP_FILE_PREFIX # define TEMP_FILE_PREFIX "sqlite_" #endif int sqlite3OsDelete(const char*); int sqlite3OsFileExists(const char*); int sqliteOsFileRename(const char*, const char*); int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); int sqlite3OsOpenExclusive(const char*, OsFile*, int); int sqlite3OsOpenReadOnly(const char*, OsFile*); | > > > > > > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | ** prematurely, old temporary files can be easily identified. This can be done ** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. */ #ifndef TEMP_FILE_PREFIX # define TEMP_FILE_PREFIX "sqlite_" #endif /* ** The following values may be passed as the second argument to ** sqlite3OsLock(). */ #define SHARED_LOCK 1 #define RESERVED_LOCK 2 #define PENDING_LOCK 3 #define EXCLUSIVE_LOCK 4 int sqlite3OsDelete(const char*); int sqlite3OsFileExists(const char*); int sqliteOsFileRename(const char*, const char*); int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); int sqlite3OsOpenExclusive(const char*, OsFile*, int); int sqlite3OsOpenReadOnly(const char*, OsFile*); |
︙ | ︙ | |||
101 102 103 104 105 106 107 108 109 | int sqlite3OsUnlock(OsFile*); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); int sqlite3OsCurrentTime(double*); void sqlite3OsEnterMutex(void); void sqlite3OsLeaveMutex(void); char *sqlite3OsFullPathname(const char*); #endif /* _SQLITE_OS_H_ */ | > | 109 110 111 112 113 114 115 116 117 118 | int sqlite3OsUnlock(OsFile*); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); int sqlite3OsCurrentTime(double*); void sqlite3OsEnterMutex(void); void sqlite3OsLeaveMutex(void); char *sqlite3OsFullPathname(const char*); int sqlite3OsLock(OsFile*, int); #endif /* _SQLITE_OS_H_ */ |
Changes to src/os_unix.c.
︙ | ︙ | |||
168 169 170 171 172 173 174 175 176 177 178 179 180 181 | ** A single inode can have multiple file descriptors, so each OsFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of OsFiles pointing to it. */ struct lockInfo { struct lockKey key; /* The lookup key */ int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ 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 process ID is omitted. | > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | ** A single inode can have multiple file descriptors, so each OsFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of OsFiles pointing to it. */ struct lockInfo { struct lockKey key; /* The lookup key */ int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ 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 process ID is omitted. |
︙ | ︙ | |||
261 262 263 264 265 266 267 268 269 270 271 272 273 274 | if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ) return 1; pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); return 1; } }else{ | > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ) return 1; pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); return 1; } }else{ |
︙ | ︙ | |||
644 645 646 647 648 649 650 | ** ** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqlite3OsReadLock(OsFile *id){ int rc; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > | | > > > > > > > > > > > < | | > > > > > > > | > > > > > > > > > > > > > | | > > > | | > > | > > > > | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 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 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | ** ** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqlite3OsReadLock(OsFile *id){ int rc; return sqlite3OsLock(id, SHARED_LOCK); } /* ** Change the lock status to be an exclusive or write lock. Return ** SQLITE_OK on success and SQLITE_BUSY on a failure. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqlite3OsWriteLock(OsFile *id){ int rc; return sqlite3OsLock(id, EXCLUSIVE_LOCK); } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** SHARED_LOCK ** RESERVED_LOCK ** PENDING_LOCK ** EXCLUSIVE_LOCK */ int sqlite3OsLock(OsFile *id, int locktype){ int rc = SQLITE_OK; struct lockInfo *pLock = id->pLock; struct flock lock; int s; /* It is an error to request any kind of lock before a shared lock */ if( locktype>SHARED_LOCK && id->locked==0 ){ rc = sqlite3OsLock(id, SHARED_LOCK); if( rc!=SQLITE_OK ) return rc; } assert( locktype==SHARED_LOCK || id->locked!=0 ); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( id->locked>=locktype ){ return SQLITE_OK; } sqlite3OsEnterMutex(); /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (id->locked!=pLock->locktype && (pLock->locktype>RESERVED_LOCK || locktype!=SHARED_LOCK)) || (locktype>RESERVED_LOCK && pLock->cnt>1) ){ rc = SQLITE_BUSY; goto end_lock; } /* If a SHARED lock is requested, and some thread using this PID already ** has a SHARED or RESERVED lock, then increment reference counts and ** return SQLITE_OK. */ if( locktype==SHARED_LOCK && (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ assert( locktype==SHARED_LOCK ); assert( id->locked==0 ); id->locked = SHARED_LOCK; pLock->cnt++; id->pOpen->nLock++; goto end_lock; } lock.l_len = 1L; lock.l_whence = SEEK_SET; /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( locktype==SHARED_LOCK ){ assert( pLock->cnt==0 ); assert( id->pOpen->nLock==0 ); assert( pLock->locktype==0 ); /* Grab a read-lock on byte 2. This ensures that no other process ** has a PENDING lock. */ lock.l_type = F_RDLCK; lock.l_start = 2; s = fcntl(id->fd, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; } /* Now get a read-lock on byte 0 and renege on the byte 2 lock. */ lock.l_start = 0; s = fcntl(id->fd, F_SETLK, &lock); lock.l_start = 2; lock.l_type = F_UNLCK; fcntl(id->fd, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ id->locked = SHARED_LOCK; id->pOpen->nLock = 1; pLock->cnt = 1; } }else{ /* The request was for a RESERVED, PENDING or EXCLUSIVE lock. It is ** assumed that there is a SHARED or greater lock on the file ** already. */ assert( 0!=id->locked ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: lock.l_start = 1; break; case PENDING_LOCK: lock.l_start = 2; break; case EXCLUSIVE_LOCK: lock.l_start = 0; break; default: assert(0); } s = fcntl(id->fd, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } id->locked = locktype; pLock->locktype = locktype; assert(pLock->locktype==RESERVED_LOCK||(id->pOpen->nLock==1&&pLock->cnt==1)); end_lock: sqlite3OsLeaveMutex(); return rc; } /* ** Unlock the given file descriptor. If the file descriptor was ** not previously locked, then this routine is a no-op. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqlite3OsUnlock(OsFile *id){ int rc; if( !id->locked ) return SQLITE_OK; sqlite3OsEnterMutex(); assert( id->pLock->cnt!=0 ); if( id->pLock->cnt>1 ){ id->locked = 0; id->pLock->cnt--; rc = SQLITE_OK; }else{ struct flock lock; int s; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; s = fcntl(id->fd, F_SETLK, &lock); if( s!=0 ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ rc = SQLITE_OK; id->pLock->cnt = 0; id->pLock->locktype = 0; id->locked = 0; } } if( rc==SQLITE_OK ){ /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ |
︙ | ︙ |
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 the printf() interface to SQLite. 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 the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.69 2004/06/01 14:09:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | ){ if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){ Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); return TCL_ERROR; } return TCL_OK; } /* ** Generate a text representation of a pointer that can be understood ** by the getDbPointer and getVmPointer routines above. ** ** The problem is, on some machines (Solaris) if you do a printf with ** "%p" you cannot turn around and do a scanf with the same "%p" and | > > > > > > > > > > > > > > > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | ){ if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){ Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); return TCL_ERROR; } return TCL_OK; } /* ** Decode a pointer to an sqlite3_stmt object. */ static int getFilePointer( Tcl_Interp *interp, const char *zArg, OsFile **ppFile ){ if( sscanf(zArg, PTR_FMT, (void**)ppFile)!=1 ){ Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); return TCL_ERROR; } return TCL_OK; } /* ** Generate a text representation of a pointer that can be understood ** by the getDbPointer and getVmPointer routines above. ** ** The problem is, on some machines (Solaris) if you do a printf with ** "%p" you cannot turn around and do a scanf with the same "%p" and |
︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 | 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; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_search_count; extern int sqlite3_interrupt_count; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 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 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 | 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: sqlite3OsOpenReadWrite <filename> */ static int test_sqlite3OsOpenReadWrite( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ OsFile * 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; } pFile = sqliteMalloc(sizeof(OsFile)); rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); if( rc!=SQLITE_OK ){ sqliteFree(pFile); Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } makePointerStr(interp, zBuf, pFile); Tcl_SetResult(interp, zBuf, 0); return TCL_ERROR; } /* ** Usage: sqlite3OsClose <file handle> */ static int test_sqlite3OsClose( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ OsFile * 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 *)errorName(rc), TCL_STATIC); return TCL_ERROR; } sqliteFree(pFile); return TCL_OK; } /* ** Usage: sqlite3OsLock <file handle> <locktype> */ static int test_sqlite3OsLock( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ OsFile * 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 *)errorName(rc), TCL_STATIC); return TCL_ERROR; } return TCL_OK; } /* ** Usage: sqlite3OsUnlock <file handle> */ static int test_sqlite3OsUnlock( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ OsFile * 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); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_search_count; extern int sqlite3_interrupt_count; |
︙ | ︙ | |||
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text}, { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype}, { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name}, { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16}, { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ | > > > > > > | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 | { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text}, { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype}, { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name}, { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16}, { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, /* Functions from os.h */ { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, { "sqlite3OsClose", test_sqlite3OsClose, 0 }, { "sqlite3OsLock", test_sqlite3OsLock, 0 }, { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
︙ | ︙ |