/ Check-in [864349de]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:More changes prior to release 2.0.2. Mostly comment changes. But there was also a minor change to temptable.test so that it would work under Windows. (CVS 282)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:864349de6fba5b38a3fbf7ab502922937b1b61e5
User & Date: drh 2001-10-09 12:39:24
Context
2001-10-09
12:44
Remove files before rebuilding. (CVS 283) check-in: 6307641d user: drh tags: trunk
12:39
More changes prior to release 2.0.2. Mostly comment changes. But there was also a minor change to temptable.test so that it would work under Windows. (CVS 282) check-in: 864349de user: drh tags: trunk
04:21
Version 2.0.2 (CVS 281) check-in: 765359c7 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os.c.

    35     35   #endif
    36     36   #if OS_WIN
    37     37   # include <winbase.h>
    38     38   #endif
    39     39   
    40     40   
    41     41   #if OS_UNIX
           42  +/*
           43  +** Here is the dirt on POSIX advisory locks:  ANSI STD 1003.1 (1996)
           44  +** section 6.5.2.2 lines 483 through 490 specify that when a process
           45  +** sets or clears a lock, that operation overrides any prior locks set
           46  +** by the same process.  It does not explicitly say so, but this implies
           47  +** that it overrides locks set by the same process using a different
           48  +** file descriptor.  Consider this test case:
           49  +**
           50  +**       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
           51  +**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
           52  +**
           53  +** Suppose ./file1 and ./file2 are really be the same file (because
           54  +** one is a hard or symbolic link to the other) then if you set
           55  +** an exclusive lock on fd1, then try to get an exclusive lock
           56  +** on fd2, it works.  I would have expected the second lock to
           57  +** fail since there was already a lock on the file due to fd1.
           58  +** But not so.  Since both locks came from the same process, the
           59  +** second overrides the first, even though they were on different
           60  +** file descriptors opened on different file names.
           61  +**
           62  +** Bummer.  If you ask me, this is broken.  Badly broken.  It means
           63  +** that we cannot use POSIX locks to synchronize file access among
           64  +** competing threads of the same process.  POSIX locks will work fine
           65  +** to synchronize access for threads in separate processes, but not
           66  +** threads within the same process.
           67  +**
           68  +** To work around the problem, SQLite has to manage file locks internally
           69  +** on its own.  Whenever a new database is opened, we have to find the
           70  +** specific inode of the database file (the inode is determined by the
           71  +** st_dev and st_ino fields of the stat structure the stat() fills in)
           72  +** and check for locks already existing on that inode.  When locks are
           73  +** created or removed, we have to look at our own internal record of the
           74  +** locks to see if another thread has previously set a lock on that same
           75  +** inode.
           76  +**
           77  +** The OsFile structure for POSIX is no longer just an integer file
           78  +** descriptor.  It is now a structure that holds the integer file
           79  +** descriptor and a pointer to a structure that describes the internal
           80  +** locks on the corresponding inode.  There is one locking structure
           81  +** per inode, so if the same inode is opened twice, both OsFile structures
           82  +** point to the same locking structure.  The locking structure keeps
           83  +** a reference count (so we will know when to delete it) and a "cnt"
           84  +** field that tells us its internal lock status.  cnt==0 means the
           85  +** file is unlocked.  cnt==-1 means the file has an exclusive lock.
           86  +** cnt>0 means there are cnt shared locks on the file.
           87  +**
           88  +** Any attempt to lock or unlock a file first checks the locking
           89  +** structure.  The fcntl() system call is only invoked to set a 
           90  +** POSIX lock if the internal lock structure transitions between
           91  +** a locked and an unlocked state.
           92  +*/
           93  +
    42     94   /*
    43     95   ** An instance of the following structure serves as the key used
    44     96   ** to locate a particular lockInfo structure given its inode. 
    45     97   */
    46     98   struct inodeKey {
    47     99     dev_t dev;   /* Device number */
    48    100     ino_t ino;   /* Inode number */
    49    101   };
    50    102   
    51    103   /*
    52    104   ** An instance of the following structure is allocated for each inode.
    53         -** A single inode can have multiple file descriptors, so each OsFile structure
    54         -** contains a pointer to an instance of this object.
          105  +** A single inode can have multiple file descriptors, so each OsFile
          106  +** structure contains a pointer to an instance of this object and this
          107  +** object keeps a count of the number of OsFiles pointing to it.
    55    108   */
    56    109   struct lockInfo {
    57    110     struct inodeKey key;  /* The lookup key */
    58    111     int cnt;              /* 0: unlocked.  -1: write lock.  >=1: read lock */
    59    112     int nRef;             /* Number of pointers to this structure */
    60    113   };
    61    114   
................................................................................
    63    116   ** This hash table maps inodes (in the form of inodeKey structures) into
    64    117   ** pointers to lockInfo structures.
    65    118   */
    66    119   static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
    67    120   
    68    121   /*
    69    122   ** Given a file descriptor, locate a lockInfo structure that describes
    70         -** that file descriptor.  Create a new one if necessary.
          123  +** that file descriptor.  Create a new one if necessary.  NULL might
          124  +** be returned if malloc() fails.
    71    125   */
    72    126   static struct lockInfo *findLockInfo(int fd){
    73    127     int rc;
    74    128     struct inodeKey key;
    75    129     struct stat statbuf;
    76    130     struct lockInfo *pInfo;
    77    131     rc = fstat(fd, &statbuf);
    78    132     if( rc!=0 ) return 0;
    79    133     key.dev = statbuf.st_dev;
    80    134     key.ino = statbuf.st_ino;
    81    135     pInfo = (struct lockInfo*)sqliteHashFind(&lockHash, &key, sizeof(key));
    82    136     if( pInfo==0 ){
    83    137       pInfo = sqliteMalloc( sizeof(*pInfo) );
          138  +    if( pInfo==0 ) return 0;
    84    139       pInfo->key = key;
    85    140       pInfo->nRef = 1;
    86    141       pInfo->cnt = 0;
    87    142       sqliteHashInsert(&lockHash, &pInfo->key, sizeof(key), pInfo);
    88    143     }else{
    89    144       pInfo->nRef++;
    90    145     }
................................................................................
    97    152   static void releaseLockInfo(struct lockInfo *pInfo){
    98    153     pInfo->nRef--;
    99    154     if( pInfo->nRef==0 ){
   100    155       sqliteHashInsert(&lockHash, &pInfo->key, sizeof(pInfo->key), 0);
   101    156       sqliteFree(pInfo);
   102    157     }
   103    158   }
   104         -#endif
          159  +#endif  /** POSIX advisory lock work-around **/
   105    160   
   106    161   
   107    162   /*
   108    163   ** Delete the named file
   109    164   */
   110    165   int sqliteOsDelete(const char *zFilename){
   111    166   #if OS_UNIX

Changes to test/temptable.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for temporary tables and indices.
    14     14   #
    15         -# $Id: temptable.test,v 1.2 2001/10/09 04:19:47 drh Exp $
           15  +# $Id: temptable.test,v 1.3 2001/10/09 12:39:24 drh Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Create an alternative connection to the database
    21     21   #
    22     22   do_test temptable-1.0 {
................................................................................
   220    220     execsql {
   221    221       SELECT y FROM t2 WHERE x=1;
   222    222     }
   223    223   } {2}
   224    224   do_test temptable-5.9 {
   225    225     execsql {SELECT y FROM t2 WHERE x=9}
   226    226   } {8}
          227  +
          228  +db2 close
   227    229   
   228    230   finish_test

Changes to www/changes.tcl.

    14     14   
    15     15   proc chng {date desc} {
    16     16     puts "<DT><B>$date</B></DT>"
    17     17     puts "<DD><P><UL>$desc</UL></P></DD>"
    18     18   }
    19     19   
    20     20   chng {2001 Oct 9 (2.0.2)} {
    21         -<li>Fix a bugs in the locking protocol.</li>
           21  +<li>Fix two bugs in the locking protocol.  (One was masking the other.)</li>
    22     22   <li>Removed some unused "#include <unistd.h>" that were causing problems
    23     23       for VC++.</li>
    24     24   <li>Fixed <b>sqlite.h</b> so that it is usable from C++</li>
    25     25   <li>Added the FULL_COLUMN_NAMES pragma.  When set to "ON", the names of
    26     26       columns are reported back as TABLE.COLUMN instead of just COLUMN.</li>
    27     27   <li>Added the TABLE_INFO() and INDEX_INFO() pragmas to help support the
    28     28       ODBC interface.</li>