/ Check-in [e2f08426]
Login

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

Overview
Comment:Use mkdir() and rmdir() rather than open() and unlink() to create the lock files with the unix-dotlock VFS. The change is backwards compatible and, we are told, works better on some network filesystems.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e2f08426d7a84a2ac6148f485b7af377201a175b
User & Date: drh 2011-11-04 02:24:02
Context
2011-11-04
10:37
Add a missing va_end() macro to fts3.c. check-in: e6f82574 user: dan tags: trunk
02:24
Use mkdir() and rmdir() rather than open() and unlink() to create the lock files with the unix-dotlock VFS. The change is backwards compatible and, we are told, works better on some network filesystems. check-in: e2f08426 user: drh tags: trunk
00:35
Enhance the shell so that the ".schema" command works with case insensitive LIKE patterns even with PRAGMA cache_sensitive_like=ON. check-in: b06bf3b3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/os_unix.c.

   403    403   
   404    404     { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
   405    405   #define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
   406    406   
   407    407     { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
   408    408   #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
   409    409   
          410  +  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
          411  +#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
          412  +
          413  +  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
          414  +#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
          415  +
   410    416   }; /* End of the overrideable system calls */
   411    417   
   412    418   /*
   413    419   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
   414    420   ** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
   415    421   ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
   416    422   ** system call named zName.
................................................................................
  1841   1847   /******************* End of the no-op lock implementation *********************
  1842   1848   ******************************************************************************/
  1843   1849   
  1844   1850   /******************************************************************************
  1845   1851   ************************* Begin dot-file Locking ******************************
  1846   1852   **
  1847   1853   ** The dotfile locking implementation uses the existance of separate lock
  1848         -** files in order to control access to the database.  This works on just
  1849         -** about every filesystem imaginable.  But there are serious downsides:
         1854  +** files (really a directory) to control access to the database.  This works
         1855  +** on just about every filesystem imaginable.  But there are serious downsides:
  1850   1856   **
  1851   1857   **    (1)  There is zero concurrency.  A single reader blocks all other
  1852   1858   **         connections from reading or writing the database.
  1853   1859   **
  1854   1860   **    (2)  An application crash or power loss can leave stale lock files
  1855   1861   **         sitting around that need to be cleared manually.
  1856   1862   **
  1857   1863   ** Nevertheless, a dotlock is an appropriate locking mode for use if no
  1858   1864   ** other locking strategy is available.
  1859   1865   **
  1860         -** Dotfile locking works by creating a file in the same directory as the
  1861         -** database and with the same name but with a ".lock" extension added.
  1862         -** The existance of a lock file implies an EXCLUSIVE lock.  All other lock
  1863         -** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
         1866  +** Dotfile locking works by creating a subdirectory in the same directory as
         1867  +** the database and with the same name but with a ".lock" extension added.
         1868  +** The existance of a lock directory implies an EXCLUSIVE lock.  All other
         1869  +** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
  1864   1870   */
  1865   1871   
  1866   1872   /*
  1867   1873   ** The file suffix added to the data base filename in order to create the
  1868         -** lock file.
         1874  +** lock directory.
  1869   1875   */
  1870   1876   #define DOTLOCK_SUFFIX ".lock"
  1871   1877   
  1872   1878   /*
  1873   1879   ** This routine checks if there is a RESERVED lock held on the specified
  1874   1880   ** file by this or any other process. If such a lock is held, set *pResOut
  1875   1881   ** to a non-zero value otherwise *pResOut is set to zero.  The return value
................................................................................
  1928   1934   ** routine to lower a locking level.
  1929   1935   **
  1930   1936   ** With dotfile locking, we really only support state (4): EXCLUSIVE.
  1931   1937   ** But we track the other locking levels internally.
  1932   1938   */
  1933   1939   static int dotlockLock(sqlite3_file *id, int eFileLock) {
  1934   1940     unixFile *pFile = (unixFile*)id;
  1935         -  int fd;
  1936   1941     char *zLockFile = (char *)pFile->lockingContext;
  1937   1942     int rc = SQLITE_OK;
  1938   1943   
  1939   1944   
  1940   1945     /* If we have any lock, then the lock file already exists.  All we have
  1941   1946     ** to do is adjust our internal record of the lock level.
  1942   1947     */
................................................................................
  1948   1953   #else
  1949   1954       utimes(zLockFile, NULL);
  1950   1955   #endif
  1951   1956       return SQLITE_OK;
  1952   1957     }
  1953   1958     
  1954   1959     /* grab an exclusive lock */
  1955         -  fd = robust_open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
  1956         -  if( fd<0 ){
  1957         -    /* failed to open/create the file, someone else may have stolen the lock */
         1960  +  rc = osMkdir(zLockFile, 0777);
         1961  +  if( rc<0 ){
         1962  +    /* failed to open/create the lock directory */
  1958   1963       int tErrno = errno;
  1959   1964       if( EEXIST == tErrno ){
  1960   1965         rc = SQLITE_BUSY;
  1961   1966       } else {
  1962   1967         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1963   1968         if( IS_LOCK_ERROR(rc) ){
  1964   1969           pFile->lastErrno = tErrno;
  1965   1970         }
  1966   1971       }
  1967   1972       return rc;
  1968   1973     } 
  1969         -  robust_close(pFile, fd, __LINE__);
  1970   1974     
  1971   1975     /* got it, set the type and return ok */
  1972   1976     pFile->eFileLock = eFileLock;
  1973   1977     return rc;
  1974   1978   }
  1975   1979   
  1976   1980   /*
................................................................................
  1981   1985   ** the requested locking level, this routine is a no-op.
  1982   1986   **
  1983   1987   ** When the locking level reaches NO_LOCK, delete the lock file.
  1984   1988   */
  1985   1989   static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
  1986   1990     unixFile *pFile = (unixFile*)id;
  1987   1991     char *zLockFile = (char *)pFile->lockingContext;
         1992  +  int rc;
  1988   1993   
  1989   1994     assert( pFile );
  1990   1995     OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
  1991   1996   	   pFile->eFileLock, getpid()));
  1992   1997     assert( eFileLock<=SHARED_LOCK );
  1993   1998     
  1994   1999     /* no-op if possible */
................................................................................
  2002   2007     if( eFileLock==SHARED_LOCK ){
  2003   2008       pFile->eFileLock = SHARED_LOCK;
  2004   2009       return SQLITE_OK;
  2005   2010     }
  2006   2011     
  2007   2012     /* To fully unlock the database, delete the lock file */
  2008   2013     assert( eFileLock==NO_LOCK );
  2009         -  if( osUnlink(zLockFile) ){
         2014  +  rc = osRmdir(zLockFile);
         2015  +  if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
         2016  +  if( rc<0 ){
  2010   2017       int rc = 0;
  2011   2018       int tErrno = errno;
  2012   2019       if( ENOENT != tErrno ){
  2013   2020         rc = SQLITE_IOERR_UNLOCK;
  2014   2021       }
  2015   2022       if( IS_LOCK_ERROR(rc) ){
  2016   2023         pFile->lastErrno = tErrno;
................................................................................
  5711   5718     buf[0] = lockPath[0];
  5712   5719     for( i=1; i<len; i++ ){
  5713   5720       if( lockPath[i] == '/' && (i - start > 0) ){
  5714   5721         /* only mkdir if leaf dir != "." or "/" or ".." */
  5715   5722         if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') 
  5716   5723            || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
  5717   5724           buf[i]='\0';
  5718         -        if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
         5725  +        if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
  5719   5726             int err=errno;
  5720   5727             if( err!=EEXIST ) {
  5721   5728               OSTRACE(("CREATELOCKPATH  FAILED creating %s, "
  5722   5729                        "'%s' proxy lock path=%s pid=%d\n",
  5723   5730                        buf, strerror(err), lockPath, getpid()));
  5724   5731               return err;
  5725   5732             }
................................................................................
  6747   6754       UNIXVFS("unix-proxy",    proxyIoFinder ),
  6748   6755   #endif
  6749   6756     };
  6750   6757     unsigned int i;          /* Loop counter */
  6751   6758   
  6752   6759     /* Double-check that the aSyscall[] array has been constructed
  6753   6760     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  6754         -  assert( ArraySize(aSyscall)==18 );
         6761  +  assert( ArraySize(aSyscall)==20 );
  6755   6762   
  6756   6763     /* Register all VFSes defined in the aVfs[] array */
  6757   6764     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
  6758   6765       sqlite3_vfs_register(&aVfs[i], i==0);
  6759   6766     }
  6760   6767     return SQLITE_OK; 
  6761   6768   }

Changes to test/syscall.test.

    55     55   
    56     56   #-------------------------------------------------------------------------
    57     57   # Tests for the xNextSystemCall method.
    58     58   #
    59     59   foreach s {
    60     60       open close access getcwd stat fstat ftruncate
    61     61       fcntl read pread write pwrite fchmod fallocate
    62         -    pread64 pwrite64 unlink openDirectory
           62  +    pread64 pwrite64 unlink openDirectory mkdir rmdir
    63     63   } {
    64     64     if {[test_syscall exists $s]} {lappend syscall_list $s}
    65     65   }
    66     66   do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]
    67     67   
    68     68   #-------------------------------------------------------------------------
    69     69   # This test verifies that if a call to open() fails and errno is set to