/ Check-in [6cb43f6c]
Login

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

Overview
Comment:Forward port the Apple-specific changes from [db5b7b778c] in the apple-osx-377 branch. Fix this up so that it will compile and run on Linux.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1: 6cb43f6c6e9d8054e00acab378b8af0d82d3084c
User & Date: drh 2011-10-10 23:53:48
Context
2011-10-11
14:19
Merge the latest trunk changes into the apple-osx branch. check-in: 7e2c4898 user: drh tags: apple-osx
2011-10-10
23:53
Forward port the Apple-specific changes from [db5b7b778c] in the apple-osx-377 branch. Fix this up so that it will compile and run on Linux. check-in: 6cb43f6c user: drh tags: apple-osx
22:11
Merging in cherry picked diffs for persist wal, alloc padding, wal-safe vacuum and sqlite3_file_control based lockstate checking check-in: db5b7b77 user: adam tags: apple-osx-377
2011-09-19
20:32
Merge in all trunk changes through the 3.7.8 release. check-in: ade72b18 user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

   415    415         if( rc==SQLITE_OK ){
   416    416           if( p->pDestDb ){
   417    417             sqlite3ResetInternalSchema(p->pDestDb, -1);
   418    418           }
   419    419           if( destMode==PAGER_JOURNALMODE_WAL ){
   420    420             rc = sqlite3BtreeSetVersion(p->pDest, 2);
   421    421           }
          422  +        }
          423  +      
          424  +      if( destMode==PAGER_JOURNALMODE_WAL ){
          425  +          /* This call cannot fail. The success of the BtreeUpdateMeta()
          426  +          ** method above indicates that a write transaction has been opened
          427  +          ** and page 1 is already dirty. Therefore this always succeeds.
          428  +          */
          429  +          TESTONLY(int rc2 =) sqlite3BtreeSetVersion(p->pDest, 2);
          430  +          assert( rc2==SQLITE_OK );
   422    431         }
   423    432         if( rc==SQLITE_OK ){
   424    433           int nDestTruncate;
   425    434           /* Set nDestTruncate to the final number of pages in the destination
   426    435           ** database. The complication here is that the destination page
   427    436           ** size may be different to the source page size. 
   428    437           **

Changes to src/main.c.

  2985   2985       zFilename += sqlite3Strlen30(zFilename) + 1;
  2986   2986       if( x==0 ) return zFilename;
  2987   2987       zFilename += sqlite3Strlen30(zFilename) + 1;
  2988   2988     }
  2989   2989     return 0;
  2990   2990   }
  2991   2991   
  2992         -#if (SQLITE_ENABLE_APPLE_SPI>0)
  2993         -#define SQLITE_FILE_HEADER_LEN 16
  2994         -#include <fcntl.h>
  2995         -#include "sqlite3_private.h"
  2996         -#include "btreeInt.h"
  2997         -#include <errno.h>
  2998         -#include <sys/param.h>
         2992  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
  2999   2993   
  3000         -/* Check for a conflicting lock.  If one is found, print an this
  3001         - ** on standard output using the format string given and return 1.
  3002         - ** If there are no conflicting locks, return 0.
  3003         - */
  3004         -static int isLocked(
  3005         -  pid_t pid,            /* PID to test for lock owner */
  3006         -  int h,                /* File descriptor to check */
  3007         -  int type,             /* F_RDLCK or F_WRLCK */
  3008         -  unsigned int iOfst,   /* First byte of the lock */
  3009         -  unsigned int iCnt,    /* Number of bytes in the lock range */
  3010         -  const char *zType     /* Type of lock */
  3011         -){
  3012         -  struct flock lk;
  3013         -  int err;
  3014         -  
  3015         -  memset(&lk, 0, sizeof(lk));
  3016         -  lk.l_type = type;
  3017         -  lk.l_whence = SEEK_SET;
  3018         -  lk.l_start = iOfst;
  3019         -  lk.l_len = iCnt;
  3020         -
  3021         -  if( pid!=SQLITE_LOCKSTATE_ANYPID ){
  3022         -#ifndef F_GETLKPID
  3023         -# warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK
  3024         -    err = fcntl(h, F_GETLK, &lk);
  3025         -#else
  3026         -    lk.l_pid = pid;
  3027         -    err = fcntl(h, F_GETLKPID, &lk);
  3028         -#endif
  3029         -  }else{
  3030         -    err = fcntl(h, F_GETLK, &lk);
  3031         -  }
  3032         -
  3033         -  if( err==(-1) ){
  3034         -    fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
  3035         -    return -1;
  3036         -  }
  3037         -  
  3038         -  if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){
  3039         -#ifdef SQLITE_DEBUG
  3040         -    fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid);
  3041         -#endif
  3042         -    return 1;
  3043         -  } 
  3044         -  return 0;
  3045         -}
  3046         -
  3047         -/*
  3048         - ** Location of locking bytes in the database file
  3049         - */
  3050         -#ifndef PENDING_BYTE
  3051         -# define PENDING_BYTE      (0x40000000)
  3052         -# define RESERVED_BYTE     (PENDING_BYTE+1)
  3053         -# define SHARED_FIRST      (PENDING_BYTE+2)
  3054         -# define SHARED_SIZE       510
  3055         -#endif /* PENDING_BYTE */
  3056         -
  3057         -/*
  3058         - ** Lock locations for shared-memory locks used by WAL mode.
  3059         - */
  3060         -#ifndef SHM_BASE
  3061         -# define SHM_BASE          120
  3062         -# define SHM_WRITE         SHM_BASE
  3063         -# define SHM_CHECKPOINT    (SHM_BASE+1)
  3064         -# define SHM_RECOVER       (SHM_BASE+2)
  3065         -# define SHM_READ_FIRST    (SHM_BASE+3)
  3066         -# define SHM_READ_SIZE     5
  3067         -#endif /* SHM_BASE */
         2994  +#include "sqlite3_private.h"
  3068   2995   
  3069   2996   /* 
  3070   2997   ** Testing a file path for sqlite locks held by a process ID. 
  3071   2998   ** Returns SQLITE_LOCKSTATE_ON if locks are present on path
  3072   2999   ** that would prevent writing to the database.
  3073         -**
  3074         -** This test only works for lock testing on unix/posix VFS.
  3075         -** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
  3076   3000   */
  3077   3001   int _sqlite3_lockstate(const char *path, pid_t pid){
  3078         -  int hDb;        /* File descriptor for the open database file */
  3079         -  int hShm;       /* File descriptor for WAL shared-memory file */
  3080         -  ssize_t got;    /* Bytes read from header */
  3081         -  int isWal;                 /* True if in WAL mode */
  3082         -  int nLock = 0;             /* Number of locks held */
  3083         -  unsigned char aHdr[100];   /* Database header */
         3002  +  sqlite3 *db = NULL;
  3084   3003     
  3085         -  /* Open the file at path and make sure we are dealing with a database file */
  3086         -  hDb = open(path, O_RDONLY | O_NOCTTY);
  3087         -  if( hDb<0 ){
  3088         -    return SQLITE_LOCKSTATE_ERROR;
         3004  +  if( sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK ){
         3005  +    LockstatePID lockstate = {pid, -1};
         3006  +    sqlite3_file_control(db, NULL, SQLITE_FCNTL_LOCKSTATE_PID, &lockstate);
         3007  +    sqlite3_close(db);
         3008  +    int state = lockstate.state;
         3009  +    return state;
  3089   3010     }
  3090         -  assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN );
  3091         -  got = pread(hDb, aHdr, 100, 0);
  3092         -  if( got<0 ){
  3093         -    close(hDb);
  3094         -    return SQLITE_LOCKSTATE_ERROR;
  3095         -  }
  3096         -  if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){
  3097         -    close(hDb);
  3098         -    return SQLITE_LOCKSTATE_NOTADB;
  3099         -  }
  3100         -  
  3101         -  /* First check for an exclusive lock */
  3102         -  nLock += isLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE");
  3103         -  isWal = aHdr[18]==2;
  3104         -  if( nLock==0 && isWal==0 ){
  3105         -    /* Rollback mode */
  3106         -    nLock += isLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED");
  3107         -  }
  3108         -  close(hDb);
  3109         -  if( nLock==0 && isWal!=0 ){
  3110         -    char zShm[MAXPATHLEN];
  3111         -    
  3112         -    close(hDb);
  3113         -    /* WAL mode */
  3114         -    strlcpy(zShm, path, MAXPATHLEN);
  3115         -    strlcat(zShm, "-shm", MAXPATHLEN);
  3116         -    hShm = open(zShm, O_RDONLY, 0);
  3117         -    if( hShm<0 ){
  3118         -      return SQLITE_LOCKSTATE_OFF;
  3119         -    }
  3120         -    if( isLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
  3121         -       isLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
  3122         -      nLock = 1;
  3123         -    }
  3124         -    close(hShm);
  3125         -  }
  3126         -  if( nLock>0 ){
  3127         -    return SQLITE_LOCKSTATE_ON;
  3128         -  }
  3129         -  return SQLITE_LOCKSTATE_OFF;
         3011  +  return SQLITE_LOCKSTATE_ERROR;
  3130   3012   }
  3131   3013   
  3132   3014   #endif /* SQLITE_ENABLE_APPLE_SPI */

Changes to src/mem1.c.

    28     28   
    29     29   #if (!defined(__APPLE__))
    30     30   
    31     31   #define SQLITE_MALLOC(x) malloc(x)
    32     32   #define SQLITE_FREE(x) free(x)
    33     33   #define SQLITE_REALLOC(x,y) realloc((x),(y))
    34     34   
    35         -
    36     35   #else
    37     36   
    38     37   
    39     38   #include <sys/sysctl.h>
    40     39   #include <malloc/malloc.h>
    41     40   #include <libkern/OSAtomic.h>
    42     41   
    43     42   static malloc_zone_t* _sqliteZone_;
    44     43   
    45     44   #define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
    46     45   #define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
    47     46   #define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
           47  +#define SQLITE_MALLOCSIZE(x) (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
    48     48   
    49     49   #endif
    50     50   
    51     51   /*
    52     52   ** Like malloc(), but remember the size of the allocation
    53     53   ** so that we can find it later using sqlite3MemSize().
    54     54   **
................................................................................
    56     56   ** cases of nByte<=0 will be intercepted and dealt with by higher level
    57     57   ** routines.
    58     58   */
    59     59   static void *sqlite3MemMalloc(int nByte){
    60     60     sqlite3_int64 *p;
    61     61     assert( nByte>0 );
    62     62     nByte = ROUND8(nByte);
    63         -  p = SQLITE_MALLOC( nByte+8 );
           63  +#ifndef SQLITE_MALLOCSIZE
           64  +  p = SQLITE_MALLOC( nByte + 8 );
    64     65     if( p ){
    65     66       p[0] = nByte;
    66     67       p++;
    67     68     }else{
    68     69       testcase( sqlite3GlobalConfig.xLog!=0 );
    69     70       sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
    70     71     }
           72  +#else
           73  +  p = SQLITE_MALLOC( nByte );
           74  +  if( !p ){
           75  +    testcase( sqlite3GlobalConfig.xLog!=0 );
           76  +    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
           77  +  }
           78  +#endif
    71     79     return (void *)p;
    72     80   }
    73     81   
    74     82   /*
    75     83   ** Like free() but works for allocations obtained from sqlite3MemMalloc()
    76     84   ** or sqlite3MemRealloc().
    77     85   **
................................................................................
    78     86   ** For this low-level routine, we already know that pPrior!=0 since
    79     87   ** cases where pPrior==0 will have been intecepted and dealt with
    80     88   ** by higher-level routines.
    81     89   */
    82     90   static void sqlite3MemFree(void *pPrior){
    83     91     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    84     92     assert( pPrior!=0 );
           93  +#ifndef SQLITE_MALLOCSIZE
    85     94     p--;
           95  +#endif
    86     96     SQLITE_FREE(p);
    87     97   }
    88     98   
    89     99   /*
    90    100   ** Report the allocated size of a prior return from xMalloc()
    91    101   ** or xRealloc().
    92    102   */
    93    103   static int sqlite3MemSize(void *pPrior){
          104  +#ifndef SQLITE_MALLOCSIZE
    94    105     sqlite3_int64 *p;
    95    106     if( pPrior==0 ) return 0;
    96    107     p = (sqlite3_int64*)pPrior;
    97    108     p--;
    98    109     return (int)p[0];
          110  +#else
          111  +  return (int)SQLITE_MALLOCSIZE(pPrior);
          112  +#endif
    99    113   }
   100    114   
   101    115   /*
   102    116   ** Like realloc().  Resize an allocation previously obtained from
   103    117   ** sqlite3MemMalloc().
   104    118   **
   105    119   ** For this low-level interface, we know that pPrior!=0.  Cases where
................................................................................
   108    122   ** cases where nByte<=0 will have been intercepted by higher-level
   109    123   ** routines and redirected to xFree.
   110    124   */
   111    125   static void *sqlite3MemRealloc(void *pPrior, int nByte){
   112    126     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
   113    127     assert( pPrior!=0 && nByte>0 );
   114    128     assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
          129  +#ifndef SQLITE_MALLOCSIZE
   115    130     p--;
   116    131     p = SQLITE_REALLOC(p, nByte+8 );
   117    132     if( p ){
   118    133       p[0] = nByte;
   119    134       p++;
   120    135     }else{
          136  +     testcase( sqlite3GlobalConfig.xLog!=0 );
          137  +     sqlite3_log(SQLITE_NOMEM,
          138  +       "failed memory resize %u to %u bytes",
          139  +       sqlite3MemSize(pPrior), nByte);
          140  +  }
          141  +#else
          142  +  p = SQLITE_REALLOC(p, nByte );
          143  +  if( !p ){
   121    144       testcase( sqlite3GlobalConfig.xLog!=0 );
   122    145       sqlite3_log(SQLITE_NOMEM,
   123    146         "failed memory resize %u to %u bytes",
   124    147         sqlite3MemSize(pPrior), nByte);
   125    148     }
          149  +#endif
   126    150     return (void*)p;
   127    151   }
   128    152   
   129    153   /*
   130    154   ** Round up a request size to the next valid allocation size.
   131    155   */
   132    156   static int sqlite3MemRoundup(int n){

Changes to src/os_unix.c.

  1570   1570   ** This function is a pass-through to fcntl(F_SETLK) if pFile is using
  1571   1571   ** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
  1572   1572   ** and is read-only.
  1573   1573   **
  1574   1574   ** Zero is returned if the call completes successfully, or -1 if a call
  1575   1575   ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
  1576   1576   */
  1577         -static int unixFileLock(unixFile *pFile, struct flock *pLock){
         1577  +static int unixFileLock(unixFile *pFile, struct flock *pLock, int nRetry){
  1578   1578     int rc;
  1579   1579     unixInodeInfo *pInode = pFile->pInode;
  1580   1580     assert( unixMutexHeld() );
  1581   1581     assert( pInode!=0 );
  1582   1582     if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
  1583   1583      && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
  1584   1584     ){
................................................................................
  1590   1590         lock.l_len = SHARED_SIZE;
  1591   1591         lock.l_type = F_WRLCK;
  1592   1592         rc = osFcntl(pFile->h, F_SETLK, &lock);
  1593   1593         if( rc<0 ) return rc;
  1594   1594         pInode->bProcessLock = 1;
  1595   1595         pInode->nLock++;
  1596   1596       }else{
         1597  +      int i = 0;                      
         1598  +      do {
         1599  +        rc = osFcntl(pFile->h, F_SETLK, pLock);
         1600  +        if( rc && nRetry ){
         1601  +           usleep(100 * (++i));
         1602  +        }
         1603  +      }while( !rc && nRetry-- );
  1597   1604         rc = 0;
  1598   1605       }
  1599   1606     }else{
  1600   1607       rc = osFcntl(pFile->h, F_SETLK, pLock);
  1601   1608     }
  1602   1609     return rc;
  1603   1610   }
................................................................................
  1733   1740     lock.l_len = 1L;
  1734   1741     lock.l_whence = SEEK_SET;
  1735   1742     if( eFileLock==SHARED_LOCK 
  1736   1743         || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  1737   1744     ){
  1738   1745       lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
  1739   1746       lock.l_start = PENDING_BYTE;
  1740         -    if( unixFileLock(pFile, &lock) ){
         1747  +    if( unixFileLock(pFile, &lock, 0) ){
  1741   1748         tErrno = errno;
  1742   1749         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1743   1750         if( IS_LOCK_ERROR(rc) ){
  1744   1751           pFile->lastErrno = tErrno;
  1745   1752         }
  1746   1753         goto end_lock;
  1747   1754       }
................................................................................
  1755   1762       assert( pInode->nShared==0 );
  1756   1763       assert( pInode->eFileLock==0 );
  1757   1764       assert( rc==SQLITE_OK );
  1758   1765   
  1759   1766       /* Now get the read-lock */
  1760   1767       lock.l_start = SHARED_FIRST;
  1761   1768       lock.l_len = SHARED_SIZE;
  1762         -    if( unixFileLock(pFile, &lock) ){
         1769  +    if( unixFileLock(pFile, &lock, 0) ){
  1763   1770         tErrno = errno;
  1764   1771         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1765   1772       }
  1766   1773   
  1767   1774       /* Drop the temporary PENDING lock */
  1768   1775       lock.l_start = PENDING_BYTE;
  1769   1776       lock.l_len = 1L;
  1770   1777       lock.l_type = F_UNLCK;
  1771         -    if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
         1778  +    if( unixFileLock(pFile, &lock, 10) && rc==SQLITE_OK ){
  1772   1779         /* This could happen with a network mount */
  1773   1780         tErrno = errno;
  1774   1781   #if OSLOCKING_CHECK_BUSY_IOERR
  1775   1782         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
  1776   1783   #else
  1777   1784         rc = SQLITE_IOERR_UNLOCK; 
  1778   1785   #endif
................................................................................
  1805   1812         lock.l_start = RESERVED_BYTE;
  1806   1813         lock.l_len = 1L;
  1807   1814       }else{
  1808   1815         lock.l_start = SHARED_FIRST;
  1809   1816         lock.l_len = SHARED_SIZE;
  1810   1817       }
  1811   1818   
  1812         -    if( unixFileLock(pFile, &lock) ){
         1819  +    if( unixFileLock(pFile, &lock, 0) ){
  1813   1820         tErrno = errno;
  1814   1821         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1815   1822         if( rc!=SQLITE_BUSY ){
  1816   1823           pFile->lastErrno = tErrno;
  1817   1824         }
  1818   1825       }
  1819   1826     }
................................................................................
  1926   1933       ** write lock until the rest is covered by a read lock:
  1927   1934       **  1:   [WWWWW]
  1928   1935       **  2:   [....W]
  1929   1936       **  3:   [RRRRW]
  1930   1937       **  4:   [RRRR.]
  1931   1938       */
  1932   1939       if( eFileLock==SHARED_LOCK ){
         1940  +      int tErrno;               /* Error code from system call errors */
  1933   1941   
  1934   1942   #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
  1935   1943         (void)handleNFSUnlock;
  1936   1944         assert( handleNFSUnlock==0 );
  1937   1945   #endif
  1938   1946   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  1939   1947         if( handleNFSUnlock ){
  1940         -        int tErrno;               /* Error code from system call errors */
  1941   1948           off_t divSize = SHARED_SIZE - 1;
  1942   1949           
  1943   1950           lock.l_type = F_UNLCK;
  1944   1951           lock.l_whence = SEEK_SET;
  1945   1952           lock.l_start = SHARED_FIRST;
  1946   1953           lock.l_len = divSize;
  1947         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1954  +        if( unixFileLock(pFile, &lock, 10)==(-1) ){
  1948   1955             tErrno = errno;
  1949   1956   #if OSLOCKING_CHECK_BUSY_IOERR
  1950   1957             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1951   1958   #else
  1952   1959             rc = SQLITE_IOERR_UNLOCK;
  1953   1960   #endif
  1954   1961             if( IS_LOCK_ERROR(rc) ){
................................................................................
  1956   1963             }
  1957   1964             goto end_unlock;
  1958   1965           }
  1959   1966           lock.l_type = F_RDLCK;
  1960   1967           lock.l_whence = SEEK_SET;
  1961   1968           lock.l_start = SHARED_FIRST;
  1962   1969           lock.l_len = divSize;
  1963         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1970  +        if( unixFileLock(pFile, &lock, 10)==(-1) ){
  1964   1971             tErrno = errno;
  1965   1972             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1966   1973             if( IS_LOCK_ERROR(rc) ){
  1967   1974               pFile->lastErrno = tErrno;
  1968   1975             }
  1969   1976             goto end_unlock;
  1970   1977           }
  1971   1978           lock.l_type = F_UNLCK;
  1972   1979           lock.l_whence = SEEK_SET;
  1973   1980           lock.l_start = SHARED_FIRST+divSize;
  1974   1981           lock.l_len = SHARED_SIZE-divSize;
  1975         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1982  +        if( unixFileLock(pFile, &lock, 10)==(-1) ){
  1976   1983             tErrno = errno;
  1977   1984   #if OSLOCKING_CHECK_BUSY_IOERR
  1978   1985             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1979   1986   #else
  1980   1987             rc = SQLITE_IOERR_UNLOCK;
  1981   1988   #endif
  1982   1989             if( IS_LOCK_ERROR(rc) ){
................................................................................
  1987   1994         }else
  1988   1995   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  1989   1996         {
  1990   1997           lock.l_type = F_RDLCK;
  1991   1998           lock.l_whence = SEEK_SET;
  1992   1999           lock.l_start = SHARED_FIRST;
  1993   2000           lock.l_len = SHARED_SIZE;
  1994         -        if( unixFileLock(pFile, &lock) ){
  1995         -#if OSLOCKING_CHECK_BUSY_IOERR
         2001  +        if( unixFileLock(pFile, &lock, 10) ){
  1996   2002             tErrno = errno;
         2003  +#if OSLOCKING_CHECK_BUSY_IOERR
  1997   2004             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1998         -          if( IS_LOCK_ERROR(rc) ){
  1999         -            pFile->lastErrno = tErrno;
  2000         -          }
  2001   2005   #else
  2002   2006             /* In theory, the call to unixFileLock() cannot fail because another
  2003   2007             ** process is holding an incompatible lock. If it does, this 
  2004   2008             ** indicates that the other process is not following the locking
  2005   2009             ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
  2006   2010             ** SQLITE_BUSY would confuse the upper layer (in practice it causes 
  2007   2011             ** an assert to fail). */ 
  2008   2012             rc = SQLITE_IOERR_RDLOCK;
  2009         -          pFile->lastErrno = errno;
         2013  +          pFile->lastErrno = tErrno;
  2010   2014   #endif
         2015  +          if( IS_LOCK_ERROR(rc) ){
         2016  +            pFile->lastErrno = tErrno;
         2017  +          }
  2011   2018             goto end_unlock;
  2012   2019           }
  2013   2020         }
  2014   2021       }
  2015   2022       lock.l_type = F_UNLCK;
  2016   2023       lock.l_whence = SEEK_SET;
  2017   2024       lock.l_start = PENDING_BYTE;
  2018   2025       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  2019         -    if( unixFileLock(pFile, &lock)==0 ){
         2026  +    if( unixFileLock(pFile, &lock, 10)==0 ){
  2020   2027         pInode->eFileLock = SHARED_LOCK;
  2021   2028       }else{
  2022   2029   #if OSLOCKING_CHECK_BUSY_IOERR
  2023   2030         tErrno = errno;
  2024   2031         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  2025   2032         if( IS_LOCK_ERROR(rc) ){
  2026   2033           pFile->lastErrno = tErrno;
................................................................................
  2041   2048       if( pInode->nShared==0 ){
  2042   2049         lock.l_type = F_UNLCK;
  2043   2050         lock.l_whence = SEEK_SET;
  2044   2051         lock.l_start = lock.l_len = 0L;
  2045   2052         SimulateIOErrorBenign(1);
  2046   2053         SimulateIOError( h=(-1) )
  2047   2054         SimulateIOErrorBenign(0);
  2048         -      if( unixFileLock(pFile, &lock)==0 ){
         2055  +      if( unixFileLock(pFile, &lock, 10)==0 ){
  2049   2056           pInode->eFileLock = NO_LOCK;
  2050   2057         }else{
  2051   2058   #if OSLOCKING_CHECK_BUSY_IOERR
  2052   2059           tErrno = errno;
  2053   2060           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  2054   2061           if( IS_LOCK_ERROR(rc) ){
  2055   2062             pFile->lastErrno = tErrno;
................................................................................
  3882   3889   
  3883   3890   #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
  3884   3891   #include "sqlite3_private.h"
  3885   3892   #include <copyfile.h>
  3886   3893   static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
  3887   3894   #endif
  3888   3895   static int isProxyLockingMode(unixFile *);
         3896  +
         3897  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
         3898  +static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
         3899  +  sqlite3_file *id = (sqlite3_file *)pFile;
         3900  +  int rc = SQLITE_OK;
         3901  +  void *pLock = NULL;
         3902  +  int flags = 0;
         3903  +  int corruptFileLock = 0;
         3904  +  int isCorrupt = 0;
         3905  +    
         3906  +#if SQLITE_ENABLE_DATA_PROTECTION
         3907  +  flags |= pFile->protFlags;
         3908  +#endif
         3909  +#if SQLITE_ENABLE_LOCKING_STYLE
         3910  +  if( isProxyLockingMode(pFile) ){
         3911  +    flags |= SQLITE_OPEN_AUTOPROXY;
         3912  +  }
         3913  +#endif
         3914  +  
         3915  +  rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
         3916  +  if( rc ){
         3917  +    if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         3918  +      isCorrupt = 1;
         3919  +      rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
         3920  +    }
         3921  +    if( rc ){
         3922  +      return rc;
         3923  +    }
         3924  +  }
         3925  +  rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
         3926  +  if( rc==SQLITE_OK ){
         3927  +    unixInvalidateSupportFiles(pFile, 0);
         3928  +  }
         3929  +  pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
         3930  +
         3931  +
         3932  +  if( isCorrupt ){
         3933  +    sqlite3demo_superunlock_corrupt(id, corruptFileLock);
         3934  +  }else{
         3935  +    sqlite3demo_superunlock(pLock);
         3936  +  }
         3937  +  return rc;
         3938  +}
         3939  +
         3940  +static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) {
         3941  +  char jPath[MAXPATHLEN+9];
         3942  +  int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
         3943  +  if( zLen<MAXPATHLEN ){
         3944  +    size_t jLen;
         3945  +    const char extensions[3][9] = { "-wal", "-journal", "-shm" };
         3946  +    int j = (skipWAL ? 1 : 0);
         3947  +    for( ; j<3; j++ ){
         3948  +      
         3949  +      /* Check to see if the shm file is already opened for this pFile */
         3950  +      if( j==2 ){
         3951  +        unixEnterMutex(); /* Because pFile->pInode is shared across threads */
         3952  +        unixShmNode *pShmNode = pFile->pInode->pShmNode;
         3953  +        if( pShmNode && !pShmNode->isReadonly ){
         3954  +          struct stat sStat;
         3955  +          sqlite3_mutex_enter(pShmNode->mutex);
         3956  +          
         3957  +          if( pShmNode->h>=0 && !osFstat(pShmNode->h, &sStat) ){
         3958  +            unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
         3959  +            if( size>0 ){
         3960  +              bzero(pShmNode->apRegion[0], size);
         3961  +              sqlite3_mutex_leave(pShmNode->mutex);
         3962  +              unixLeaveMutex();
         3963  +              continue;
         3964  +            }
         3965  +          }
         3966  +          sqlite3_mutex_leave(pShmNode->mutex);
         3967  +        }
         3968  +        unixLeaveMutex();
         3969  +      }
         3970  +      jLen = strlcpy(&jPath[zLen], extensions[j], 9);
         3971  +      if( jLen < 9 ){
         3972  +        int jflags = (j<2) ? O_TRUNC : O_RDWR;
         3973  +        int jfd = open(jPath, jflags);
         3974  +        if( jfd==(-1) ){
         3975  +          if( errno!=ENOENT ){
         3976  +            perror(jPath);
         3977  +          }
         3978  +        } else {
         3979  +          if( j==2 ){
         3980  +            struct stat sStat;
         3981  +            if( !osFstat(jfd, &sStat) ){
         3982  +              unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
         3983  +              if( size>0 ){
         3984  +                uint32_t zero = 0;
         3985  +                pwrite(jfd, &zero, (size_t)size, 0);
         3986  +              }
         3987  +            }
         3988  +          }
         3989  +          fsync(jfd);
         3990  +          close(jfd);
         3991  +        }
         3992  +      }
         3993  +    }
         3994  +  }
         3995  +  return SQLITE_OK;
         3996  +}
         3997  +
         3998  +static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
         3999  +  sqlite3_file *id = (sqlite3_file *)pFile;
         4000  +  Btree *pSrcBtree = NULL;
         4001  +  sqlite3_file *src_file = NULL;
         4002  +  unixFile *pSrcFile = NULL;
         4003  +  char srcWalPath[MAXPATHLEN+5];
         4004  +  int srcWalFD = -1;
         4005  +  int rc = SQLITE_OK;
         4006  +  void *pLock = NULL;
         4007  +  int flags = 0;
         4008  +  sqlite3 *srcdb2 = NULL;
         4009  +  copyfile_state_t s;
         4010  +  int corruptSrcFileLock = 0;
         4011  +  int corruptDstFileLock = 0;
         4012  +  int isSrcCorrupt = 0;
         4013  +  int isDstCorrupt = 0;
         4014  +  
         4015  +  if( !sqlite3SafetyCheckOk(srcdb) ){
         4016  +    return SQLITE_MISUSE;
         4017  +  }
         4018  +    
         4019  +#if SQLITE_ENABLE_DATA_PROTECTION
         4020  +  flags |= pFile->protFlags;
         4021  +#endif
         4022  +#if SQLITE_ENABLE_LOCKING_STYLE
         4023  +  if( isProxyLockingMode(pFile) ){
         4024  +    flags |= SQLITE_OPEN_AUTOPROXY;
         4025  +  }
         4026  +#endif
         4027  +  
         4028  +  rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
         4029  +  if( rc ){
         4030  +    if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         4031  +      isDstCorrupt = 1;
         4032  +      rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
         4033  +    }
         4034  +    if( rc ){
         4035  +      return rc;
         4036  +    }
         4037  +  }
         4038  +  /* get the src file descriptor adhering to the db struct access rules 
         4039  +   ** this code is modeled after sqlite3_file_control() in main.c
         4040  +   */ 
         4041  +  sqlite3_mutex_enter(srcdb->mutex);
         4042  +  if( srcdb->nDb>0 ){
         4043  +    pSrcBtree = srcdb->aDb[0].pBt;
         4044  +  }
         4045  +  if( pSrcBtree ){
         4046  +    Pager *pSrcPager;
         4047  +    sqlite3BtreeEnter(pSrcBtree);
         4048  +    pSrcPager = sqlite3BtreePager(pSrcBtree);
         4049  +    assert( pSrcPager!=0 );
         4050  +    src_file = sqlite3PagerFile(pSrcPager);
         4051  +    assert( src_file!=0 );
         4052  +    if( src_file->pMethods ){
         4053  +      int srcFlags = 0;
         4054  +      pSrcFile = (unixFile *)src_file;
         4055  +      /* wal mode db cannot be opened readonly */
         4056  +      if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
         4057  +        srcFlags = SQLITE_OPEN_READWRITE;
         4058  +      } else {
         4059  +        srcFlags = SQLITE_OPEN_READONLY;
         4060  +      }
         4061  +#if SQLITE_ENABLE_DATA_PROTECTION
         4062  +      srcFlags |= pSrcFile->protFlags;
         4063  +#endif
         4064  +#if SQLITE_ENABLE_LOCKING_STYLE
         4065  +      if( isProxyLockingMode(pSrcFile) ){
         4066  +        srcFlags |= SQLITE_OPEN_AUTOPROXY;
         4067  +      }
         4068  +#endif
         4069  +      rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
         4070  +      if( rc==SQLITE_OK ){
         4071  +        /* start a deferred transaction and read to establish a read lock */
         4072  +        rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
         4073  +        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         4074  +          isSrcCorrupt = 1;
         4075  +          rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
         4076  +        }
         4077  +      }
         4078  +    }
         4079  +  }
         4080  +  if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
         4081  +    rc = SQLITE_INTERNAL;
         4082  +  }
         4083  +  if( rc!=SQLITE_OK ){
         4084  +    goto end_replace_database;
         4085  +  }
         4086  +  /* both databases are locked appropriately, copy the src wal journal if 
         4087  +   ** one exists and then the actual database file
         4088  +   */
         4089  +  strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
         4090  +  strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
         4091  +  srcWalFD = open(srcWalPath, O_RDONLY);
         4092  +  if( !(srcWalFD<0) ){
         4093  +    char dstWalPath[MAXPATHLEN+5];
         4094  +    int dstWalFD = -1;
         4095  +    strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
         4096  +    strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
         4097  +    dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
         4098  +    if( !(dstWalFD<0) ){
         4099  +      s = copyfile_state_alloc();
         4100  +      lseek(srcWalFD, 0, SEEK_SET);
         4101  +      lseek(dstWalFD, 0, SEEK_SET);
         4102  +      if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
         4103  +        int err=errno;
         4104  +        switch(err) {
         4105  +          case ENOMEM:
         4106  +            rc = SQLITE_NOMEM;
         4107  +            break;
         4108  +          default:
         4109  +            pFile->lastErrno = err;
         4110  +            rc = SQLITE_IOERR;
         4111  +        }
         4112  +      }
         4113  +      copyfile_state_free(s);
         4114  +      close(dstWalFD);
         4115  +    }
         4116  +    close(srcWalFD);
         4117  +  }
         4118  +  if( rc==SQLITE_OK ){
         4119  +    /* before we copy, ensure that the file change counter will be modified */
         4120  +    uint32_t srcChange = 0;
         4121  +    uint32_t dstChange = 0;
         4122  +    pread(pSrcFile->h, &srcChange, 4, 24);
         4123  +    pread(pFile->h, &dstChange, 4, 24);
         4124  +    
         4125  +    /* copy the actual database */
         4126  +    s = copyfile_state_alloc();
         4127  +    lseek(pSrcFile->h, 0, SEEK_SET);
         4128  +    lseek(pFile->h, 0, SEEK_SET);
         4129  +    if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
         4130  +      int err=errno;
         4131  +      switch(err) {
         4132  +        case ENOMEM:
         4133  +          rc = SQLITE_NOMEM;
         4134  +          break;
         4135  +        default:
         4136  +          pFile->lastErrno = err;
         4137  +          rc = SQLITE_IOERR;
         4138  +      }
         4139  +    }
         4140  +    copyfile_state_free(s);
         4141  +    
         4142  +    if (srcChange == dstChange) {
         4143  +      /* modify the change counter to force page zero to be reloaded */
         4144  +      dstChange ++;
         4145  +      pwrite(pFile->h, &dstChange, 4, 24);
         4146  +    }
         4147  +  }
         4148  +  if( isSrcCorrupt ){
         4149  +    sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
         4150  +  }else{
         4151  +    /* done with the source db so end the transaction */
         4152  +    sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
         4153  +  }
         4154  +  /* zero out any old journal clutter */
         4155  +  if( rc==SQLITE_OK ){
         4156  +    int skipWAL = (srcWalFD<0)?0:1;
         4157  +    unixInvalidateSupportFiles(pFile, skipWAL);
         4158  +  }
         4159  +  
         4160  +end_replace_database:
         4161  +  if( pSrcBtree ){
         4162  +    sqlite3_close(srcdb2);
         4163  +    sqlite3BtreeLeave(pSrcBtree);
         4164  +  }
         4165  +  sqlite3_mutex_leave(srcdb->mutex);
         4166  +  if( isDstCorrupt ){
         4167  +    sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
         4168  +  }else{
         4169  +    sqlite3demo_superunlock(pLock);
         4170  +  }
         4171  +  return rc;
         4172  +}
         4173  +#define SQLITE_FILE_HEADER_LEN 16
         4174  +#include "btreeInt.h"
         4175  +/* Check for a conflicting lock.  If one is found, print an this
         4176  + ** on standard output using the format string given and return 1.
         4177  + ** If there are no conflicting locks, return 0.
         4178  + */
         4179  +static int unixIsLocked(
         4180  +  pid_t pid,            /* PID to test for lock owner */
         4181  +  int h,                /* File descriptor to check */
         4182  +  int type,             /* F_RDLCK or F_WRLCK */
         4183  +  unsigned int iOfst,   /* First byte of the lock */
         4184  +  unsigned int iCnt,    /* Number of bytes in the lock range */
         4185  +  const char *zType     /* Type of lock */
         4186  +){
         4187  +  struct flock lk;
         4188  +  int err;
         4189  +  
         4190  +  memset(&lk, 0, sizeof(lk));
         4191  +  lk.l_type = type;
         4192  +  lk.l_whence = SEEK_SET;
         4193  +  lk.l_start = iOfst;
         4194  +  lk.l_len = iCnt;
         4195  +  
         4196  +  if( pid!=SQLITE_LOCKSTATE_ANYPID ){
         4197  +#ifndef F_GETLKPID
         4198  +# warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK
         4199  +    err = fcntl(h, F_GETLK, &lk);
         4200  +#else
         4201  +    lk.l_pid = pid;
         4202  +    err = fcntl(h, F_GETLKPID, &lk);
         4203  +#endif
         4204  +  }else{
         4205  +    err = fcntl(h, F_GETLK, &lk);
         4206  +  }
         4207  +  
         4208  +  if( err==(-1) ){
         4209  +    fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
         4210  +    return -1;
         4211  +  }
         4212  +  
         4213  +  if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){
         4214  +#ifdef SQLITE_DEBUG
         4215  +    fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid);
         4216  +#endif
         4217  +    return 1;
         4218  +  } 
         4219  +  return 0;
         4220  +}
         4221  +
         4222  +/*
         4223  +** This test only works for lock testing on unix/posix VFS.
         4224  +** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
         4225  +*/
         4226  +static int unixLockstatePid(unixFile *pFile, pid_t pid, int *pLockstate){
         4227  +  int hDb;        /* File descriptor for the open database file */
         4228  +  int hShm = -1;  /* File descriptor for WAL shared-memory file */
         4229  +  ssize_t got;    /* Bytes read from header */
         4230  +  int isWal;                 /* True if in WAL mode */
         4231  +  int nLock = 0;             /* Number of locks held */
         4232  +  unsigned char aHdr[100];   /* Database header */
         4233  +  
         4234  +  assert(pLockstate);
         4235  +  
         4236  +  /* make sure we are dealing with a database file */
         4237  +  hDb = pFile->h;
         4238  +  if( hDb<0 ){
         4239  +    *pLockstate = SQLITE_LOCKSTATE_ERROR;
         4240  +    return SQLITE_ERROR;
         4241  +  }
         4242  +  assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN );
         4243  +  got = pread(hDb, aHdr, 100, 0);
         4244  +  if( got<0 ){
         4245  +    *pLockstate = SQLITE_LOCKSTATE_ERROR;
         4246  +    return SQLITE_ERROR;
         4247  +  }
         4248  +  if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){
         4249  +    *pLockstate = SQLITE_LOCKSTATE_NOTADB;
         4250  +    return SQLITE_NOTADB;
         4251  +  }
         4252  +  
         4253  +  /* First check for an exclusive lock */
         4254  +  nLock += unixIsLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE");
         4255  +  isWal = aHdr[18]==2;
         4256  +  if( nLock==0 && isWal==0 ){
         4257  +    /* Rollback mode */
         4258  +    nLock += unixIsLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED");
         4259  +  }
         4260  +  if( nLock==0 && isWal!=0 ){
         4261  +    /* lookup the file descriptor for the shared memory file if we have it open in this process */
         4262  +    unixEnterMutex(); /* Because pFile->pInode is shared across threads */
         4263  +    unixShmNode *pShmNode = pFile->pInode->pShmNode;
         4264  +    if( pShmNode ){
         4265  +      sqlite3_mutex_enter(pShmNode->mutex);
         4266  +      
         4267  +      hShm = pShmNode->h;
         4268  +      if( hShm >= 0){
         4269  +        if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
         4270  +           unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
         4271  +          nLock = 1;
         4272  +        }
         4273  +      }
         4274  +      
         4275  +      sqlite3_mutex_leave(pShmNode->mutex);
         4276  +    } 
         4277  +    
         4278  +    if( hShm<0 ){
         4279  +      /* the shared memory file isn't open in this process space, open our own FD */
         4280  +      char zShm[MAXPATHLEN];
         4281  +      
         4282  +      /* WAL mode */
         4283  +      strlcpy(zShm, pFile->zPath, MAXPATHLEN);
         4284  +      strlcat(zShm, "-shm", MAXPATHLEN);
         4285  +      hShm = open(zShm, O_RDONLY, 0);
         4286  +      if( hShm<0 ){
         4287  +        *pLockstate = SQLITE_LOCKSTATE_OFF;
         4288  +        unixLeaveMutex();
         4289  +        return SQLITE_OK;
         4290  +      }
         4291  +      if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
         4292  +         unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
         4293  +        nLock = 1;
         4294  +      }
         4295  +      close(hShm);
         4296  +    }
         4297  +    unixLeaveMutex();
         4298  +  }
         4299  +  if( nLock>0 ){
         4300  +    *pLockstate = SQLITE_LOCKSTATE_ON;
         4301  +  } else {
         4302  +    *pLockstate = SQLITE_LOCKSTATE_OFF;
         4303  +  }
         4304  +  return SQLITE_OK;
         4305  +}
         4306  +
         4307  +#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
         4308  +
  3889   4309   
  3890   4310   /*
  3891   4311   ** Information and control of an open file handle.
  3892   4312   */
  3893   4313   static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  3894   4314     unixFile *pFile = (unixFile*)id;
  3895   4315     switch( op ){
................................................................................
  3931   4351       */
  3932   4352       case SQLITE_FCNTL_DB_UNCHANGED: {
  3933   4353         ((unixFile*)id)->dbUpdate = 0;
  3934   4354         return SQLITE_OK;
  3935   4355       }
  3936   4356   #endif
  3937   4357   #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  3938         -    case SQLITE_SET_LOCKPROXYFILE:
  3939         -    case SQLITE_GET_LOCKPROXYFILE: {
         4358  +    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
         4359  +    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
  3940   4360         return proxyFileControl(id,op,pArg);
  3941   4361       }
  3942   4362   #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
  3943   4363   #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
  3944         -    case SQLITE_TRUNCATE_DATABASE: {
  3945         -      unixFile *pFile = (unixFile*)id;
  3946         -      int rc = SQLITE_OK;
  3947         -      void *pLock = NULL;
  3948         -      int flags = 0;
  3949         -      int corruptFileLock = 0;
  3950         -      int isCorrupt = 0;
  3951         -
  3952         -#if SQLITE_ENABLE_DATA_PROTECTION
  3953         -      flags |= pFile->protFlags;
  3954         -#endif
  3955         -#if SQLITE_ENABLE_LOCKING_STYLE
  3956         -      if( isProxyLockingMode(pFile) ){
  3957         -        flags |= SQLITE_OPEN_AUTOPROXY;
  3958         -      }
  3959         -#endif
         4364  +    case SQLITE_FCNTL_TRUNCATE_DATABASE: {
         4365  +      return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0));
         4366  +    }
         4367  +    case SQLITE_FCNTL_REPLACE_DATABASE: {
         4368  +      return unixReplaceDatabase(pFile, (sqlite3 *)pArg);
         4369  +    }
         4370  +    case SQLITE_FCNTL_LOCKSTATE_PID: {
         4371  +      LockstatePID *pLockstate;
         4372  +      int rc;
  3960   4373         
  3961         -      rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
  3962         -      if( rc ){
  3963         -        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  3964         -          isCorrupt = 1;
  3965         -          rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
  3966         -        }
  3967         -        if( rc ){
  3968         -          return rc;
  3969         -        }
         4374  +      if( pArg==NULL ){
         4375  +        return SQLITE_MISUSE;
  3970   4376         }
  3971         -      rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
  3972         -
  3973         -      if( rc==SQLITE_OK ){
  3974         -        char jPath[MAXPATHLEN+9];
  3975         -        int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
  3976         -        if( zLen<MAXPATHLEN ){
  3977         -          size_t jLen;
  3978         -          const char extensions[2][9] = { "-wal", "-journal" /*, "-shm" */ };
  3979         -          int j = 0;
  3980         -          for( j=0; j<2; j++ ){
  3981         -            jLen = strlcpy(&jPath[zLen], extensions[j], 9);
  3982         -            if( jLen < 9 ){
  3983         -              int jfd = open(jPath, O_TRUNC);
  3984         -              if( jfd==(-1) ){
  3985         -                if ( errno!=ENOENT ){
  3986         -                  perror(jPath);
  3987         -                }
  3988         -              } else {
  3989         -                fsync(jfd);
  3990         -                close(jfd);
  3991         -              }
  3992         -            }
  3993         -          }
  3994         -        }
  3995         -        pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
  3996         -      }
  3997         -      if( isCorrupt ){
  3998         -        sqlite3demo_superunlock_corrupt(id, corruptFileLock);
  3999         -      }else{
  4000         -        sqlite3demo_superunlock(pLock);
  4001         -      }
         4377  +      pLockstate = (LockstatePID *)pArg;
         4378  +      rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state));
  4002   4379         return rc;
  4003   4380       }
  4004   4381         
  4005         -    case SQLITE_REPLACE_DATABASE: {
  4006         -      unixFile *pFile = (unixFile*)id;
  4007         -      sqlite3 *srcdb = (sqlite3 *)pArg;
  4008         -      Btree *pSrcBtree = NULL;
  4009         -      sqlite3_file *src_file = NULL;
  4010         -      unixFile *pSrcFile = NULL;
  4011         -      char srcWalPath[MAXPATHLEN+5];
  4012         -      int srcWalFD = -1;
  4013         -      int rc = SQLITE_OK;
  4014         -      void *pLock = NULL;
  4015         -      int flags = 0;
  4016         -      sqlite3 *srcdb2 = NULL;
  4017         -      copyfile_state_t s;
  4018         -      int corruptSrcFileLock = 0;
  4019         -      int corruptDstFileLock = 0;
  4020         -      int isSrcCorrupt = 0;
  4021         -      int isDstCorrupt = 0;
  4022         -
  4023         -      if( !sqlite3SafetyCheckOk(srcdb) ){
  4024         -        return SQLITE_MISUSE;
  4025         -      }
  4026         -      
  4027         -#if SQLITE_ENABLE_DATA_PROTECTION
  4028         -      flags |= pFile->protFlags;
  4029         -#endif
  4030         -#if SQLITE_ENABLE_LOCKING_STYLE
  4031         -      if( isProxyLockingMode(pFile) ){
  4032         -        flags |= SQLITE_OPEN_AUTOPROXY;
  4033         -      }
  4034         -#endif
  4035         -      
  4036         -      rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
  4037         -      if( rc ){
  4038         -        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  4039         -          isDstCorrupt = 1;
  4040         -          rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
  4041         -        }
  4042         -        if( rc ){
  4043         -          return rc;
  4044         -        }
  4045         -      }
  4046         -      /* get the src file descriptor adhering to the db struct access rules 
  4047         -       ** this code is modeled after sqlite3_file_control() in main.c
  4048         -       */ 
  4049         -      sqlite3_mutex_enter(srcdb->mutex);
  4050         -      if( srcdb->nDb>0 ){
  4051         -        pSrcBtree = srcdb->aDb[0].pBt;
  4052         -      }
  4053         -      if( pSrcBtree ){
  4054         -        Pager *pSrcPager;
  4055         -        sqlite3BtreeEnter(pSrcBtree);
  4056         -        pSrcPager = sqlite3BtreePager(pSrcBtree);
  4057         -        assert( pSrcPager!=0 );
  4058         -        src_file = sqlite3PagerFile(pSrcPager);
  4059         -        assert( src_file!=0 );
  4060         -        if( src_file->pMethods ){
  4061         -          int srcFlags = 0;
  4062         -          pSrcFile = (unixFile *)src_file;
  4063         -          /* wal mode db cannot be opened readonly */
  4064         -          if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
  4065         -            srcFlags = SQLITE_OPEN_READWRITE;
  4066         -          } else {
  4067         -            srcFlags = SQLITE_OPEN_READONLY;
  4068         -          }
  4069         -#if SQLITE_ENABLE_DATA_PROTECTION
  4070         -          srcFlags |= pSrcFile->protFlags;
  4071         -#endif
  4072         -#if SQLITE_ENABLE_LOCKING_STYLE
  4073         -          if( isProxyLockingMode(pSrcFile) ){
  4074         -            srcFlags |= SQLITE_OPEN_AUTOPROXY;
  4075         -          }
  4076         -#endif
  4077         -          rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
  4078         -          if( rc==SQLITE_OK ){
  4079         -            /* start a deferred transaction and read to establish a read lock */
  4080         -            rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
  4081         -            if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  4082         -              isSrcCorrupt = 1;
  4083         -              rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
  4084         -            }
  4085         -          }
  4086         -        }
  4087         -      }
  4088         -      if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
  4089         -        rc = SQLITE_INTERNAL;
  4090         -      }
  4091         -      if( rc!=SQLITE_OK ){
  4092         -        goto end_replace_database;
  4093         -      }
  4094         -      /* both databases are locked appropriately, copy the src wal journal if 
  4095         -      ** one exists and then the actual database file
  4096         -      */
  4097         -      strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
  4098         -      strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
  4099         -      srcWalFD = open(srcWalPath, O_RDONLY);
  4100         -      if( !(srcWalFD<0) ){
  4101         -        char dstWalPath[MAXPATHLEN+5];
  4102         -        int dstWalFD = -1;
  4103         -        strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
  4104         -        strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
  4105         -        dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
  4106         -        if( !(dstWalFD<0) ){
  4107         -          s = copyfile_state_alloc();
  4108         -          lseek(srcWalFD, 0, SEEK_SET);
  4109         -          lseek(dstWalFD, 0, SEEK_SET);
  4110         -          if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
  4111         -            int err=errno;
  4112         -            switch(err) {
  4113         -              case ENOMEM:
  4114         -                rc = SQLITE_NOMEM;
  4115         -                break;
  4116         -              default:
  4117         -                pFile->lastErrno = err;
  4118         -                rc = SQLITE_IOERR;
  4119         -            }
  4120         -          }
  4121         -          copyfile_state_free(s);
  4122         -          close(dstWalFD);
  4123         -        }
  4124         -        close(srcWalFD);
  4125         -      }
  4126         -      if( rc==SQLITE_OK ){
  4127         -        /* before we copy, ensure that the file change counter will be modified */
  4128         -        uint32_t srcChange = 0;
  4129         -        uint32_t dstChange = 0;
  4130         -        pread(pSrcFile->h, &srcChange, 4, 24);
  4131         -        pread(pFile->h, &dstChange, 4, 24);
  4132         -        
  4133         -        /* copy the actual database */
  4134         -        s = copyfile_state_alloc();
  4135         -        lseek(pSrcFile->h, 0, SEEK_SET);
  4136         -        lseek(pFile->h, 0, SEEK_SET);
  4137         -        if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
  4138         -          int err=errno;
  4139         -          switch(err) {
  4140         -            case ENOMEM:
  4141         -              rc = SQLITE_NOMEM;
  4142         -              break;
  4143         -            default:
  4144         -              pFile->lastErrno = err;
  4145         -              rc = SQLITE_IOERR;
  4146         -          }
  4147         -        }
  4148         -        copyfile_state_free(s);
  4149         -        
  4150         -        if (srcChange == dstChange) {
  4151         -          /* modify the change counter to force page zero to be reloaded */
  4152         -          dstChange ++;
  4153         -          pwrite(pFile->h, &dstChange, 4, 24);
  4154         -        }
  4155         -      }
  4156         -      if( isSrcCorrupt ){
  4157         -        sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
  4158         -      }else{
  4159         -        /* done with the source db so end the transaction */
  4160         -        sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
  4161         -      }
  4162         -      /* zero out any old journal clutter */
  4163         -      if( rc==SQLITE_OK ){
  4164         -        char jPath[MAXPATHLEN+9];
  4165         -        int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
  4166         -        if( zLen<MAXPATHLEN ){
  4167         -          size_t jLen;
  4168         -          const char extensions[2][9] = { "-wal", "-journal" /* "-shm" */ };
  4169         -          int j = (srcWalFD<0)?0:1; /* skip the wal if we replaced it */
  4170         -          for( ; j<2; j++ ){
  4171         -            jLen = strlcpy(&jPath[zLen], extensions[j], 9);
  4172         -            if( jLen < 9 ){
  4173         -              int jfd = open(jPath, O_TRUNC);
  4174         -              if( jfd==(-1) ){
  4175         -                if ( errno!=ENOENT ){
  4176         -                  perror(jPath);
  4177         -                }
  4178         -              } else {
  4179         -                fsync(jfd);
  4180         -                close(jfd);
  4181         -              }
  4182         -            }
  4183         -          }
  4184         -        }
  4185         -        pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
  4186         -      }
  4187         -      
  4188         -    end_replace_database:
  4189         -      if( pSrcBtree ){
  4190         -        sqlite3_close(srcdb2);
  4191         -        sqlite3BtreeLeave(pSrcBtree);
  4192         -      }
  4193         -      sqlite3_mutex_leave(srcdb->mutex);
  4194         -      if( isDstCorrupt ){
  4195         -        sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
  4196         -      }else{
  4197         -        sqlite3demo_superunlock(pLock);
  4198         -      }
  4199         -      return rc;
  4200         -    }
  4201   4382   #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
  4202   4383       case SQLITE_FCNTL_SYNC_OMITTED: {
  4203   4384         return SQLITE_OK;  /* A no-op */
  4204   4385       }
  4205   4386     }
  4206   4387     return SQLITE_NOTFOUND;
  4207   4388   }
................................................................................
  4522   4703       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  4523   4704       if( pShmNode->mutex==0 ){
  4524   4705         rc = SQLITE_NOMEM;
  4525   4706         goto shm_open_err;
  4526   4707       }
  4527   4708   
  4528   4709       if( pInode->bProcessLock==0 ){
  4529         -      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
         4710  +      const char *zRO;
         4711  +      zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
         4712  +      if( zRO && sqlite3GetBoolean(zRO) ){
         4713  +        pShmNode->h = robust_open(zShmFilename, O_RDONLY,
         4714  +                                  (sStat.st_mode & 0777));
         4715  +        pShmNode->isReadonly = 1;
         4716  +      }else{
         4717  +        pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
  4530   4718                                  (sStat.st_mode & 0777));
         4719  +      }
  4531   4720         if( pShmNode->h<0 ){
  4532   4721           const char *zRO;
  4533   4722           zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
  4534   4723           if( zRO && sqlite3GetBoolean(zRO) ){
  4535   4724             pShmNode->h = robust_open(zShmFilename, O_RDONLY,
  4536   4725                                       (sStat.st_mode & 0777));
  4537   4726             pShmNode->isReadonly = 1;

Changes to src/os_win.c.

  1623   1623               rc = winTruncate(id, newSz);
  1624   1624               SimulateIOErrorBenign(0);
  1625   1625             }
  1626   1626           }
  1627   1627           return rc;
  1628   1628         }
  1629   1629         return SQLITE_OK;
         1630  +    }
         1631  +    case SQLITE_FCNTL_PERSIST_WAL: {
         1632  +      int bPersist = *(int*)pArg;
         1633  +      if( bPersist<0 ){
         1634  +        *(int*)pArg = pFile->bPersistWal;
         1635  +      }else{
         1636  +        pFile->bPersistWal = bPersist!=0;
         1637  +      }
         1638  +      return SQLITE_OK;
  1630   1639       }
  1631   1640       case SQLITE_FCNTL_PERSIST_WAL: {
  1632   1641         int bPersist = *(int*)pArg;
  1633   1642         if( bPersist<0 ){
  1634   1643           *(int*)pArg = pFile->bPersistWal;
  1635   1644         }else{
  1636   1645           pFile->bPersistWal = bPersist!=0;

Changes to src/pager.c.

  6736   6736   
  6737   6737     /* Open the connection to the log file. If this operation fails, 
  6738   6738     ** (e.g. due to malloc() failure), return an error code.
  6739   6739     */
  6740   6740     if( rc==SQLITE_OK ){
  6741   6741   #if SQLITE_ENABLE_DATA_PROTECTION
  6742   6742       rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode,
  6743         -        pPager->journalSizeLimit, (pPager->vfsFlags & SQLITE_OPEN_FILEPROTECTION_MASK), 
         6743  +        pPager->journalSizeLimit, (pPager->vfsFlags & (SQLITE_OPEN_FILEPROTECTION_MASK | SQLITE_OPEN_READONLY)), 
  6744   6744           &pPager->pWal);
  6745   6745   #else
  6746   6746       rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode,
  6747         -        pPager->journalSizeLimit, 0, &pPager->pWal);
         6747  +        pPager->journalSizeLimit, (pPager->vfsFlags & SQLITE_OPEN_READONLY), &pPager->pWal);
  6748   6748   #endif
  6749   6749     }
  6750   6750   
  6751   6751     return rc;
  6752   6752   }
  6753   6753   
  6754   6754   

Changes to src/sqlite.h.in.

   763    763   ** have write permission on the directory containing the database file want
   764    764   ** to read the database file, as the WAL and shared memory files must exist
   765    765   ** in order for the database to be readable.  The fourth parameter to
   766    766   ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
   767    767   ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
   768    768   ** WAL mode.  If the integer is -1, then it is overwritten with the current
   769    769   ** WAL persistence setting.
   770         -** 
   771    770   */
   772         -#define SQLITE_FCNTL_LOCKSTATE        1
   773         -#define SQLITE_GET_LOCKPROXYFILE      2
   774         -#define SQLITE_SET_LOCKPROXYFILE      3
   775         -#define SQLITE_LAST_ERRNO             4
   776         -#define SQLITE_FCNTL_SIZE_HINT        5
   777         -#define SQLITE_FCNTL_CHUNK_SIZE       6
   778         -#define SQLITE_FCNTL_FILE_POINTER     7
   779         -#define SQLITE_FCNTL_SYNC_OMITTED     8
   780         -#define SQLITE_FCNTL_WIN32_AV_RETRY   9
   781         -#define SQLITE_FCNTL_PERSIST_WAL     10
          771  +#define SQLITE_FCNTL_LOCKSTATE           1
          772  +#define SQLITE_FCNTL_GET_LOCKPROXYFILE   2
          773  +#define SQLITE_FCNTL_SET_LOCKPROXYFILE   3
          774  +#define SQLITE_FCNTL_LAST_ERRNO          4
          775  +#define SQLITE_FCNTL_SIZE_HINT           5
          776  +#define SQLITE_FCNTL_CHUNK_SIZE          6
          777  +#define SQLITE_FCNTL_FILE_POINTER        7
          778  +#define SQLITE_FCNTL_SYNC_OMITTED        8
          779  +#define SQLITE_FCNTL_WIN32_AV_RETRY      9
          780  +#define SQLITE_FCNTL_PERSIST_WAL        10
          781  +
          782  +/* deprecated names */
          783  +#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
          784  +#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
          785  +#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
   782    786   
   783    787   /*
   784    788   ** CAPI3REF: Mutex Handle
   785    789   **
   786    790   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   787    791   ** abstract type for a mutex object.  The SQLite core never looks
   788    792   ** at the internal representation of an [sqlite3_mutex].  It only
................................................................................
  3345   3349   **
  3346   3350   ** ^The sqlite3_data_count(P) interface returns the number of columns in the
  3347   3351   ** current row of the result set of [prepared statement] P.
  3348   3352   ** ^If prepared statement P does not have results ready to return
  3349   3353   ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
  3350   3354   ** interfaces) then sqlite3_data_count(P) returns 0.
  3351   3355   ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
         3356  +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
         3357  +** [sqlite3_step](P) returned [SQLITE_DONE].  ^The sqlite3_data_count(P)
         3358  +** will return non-zero if previous call to [sqlite3_step](P) returned
         3359  +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
         3360  +** where it always returns zero since each step of that multi-step
         3361  +** pragma returns 0 columns of data.
  3352   3362   **
  3353   3363   ** See also: [sqlite3_column_count()]
  3354   3364   */
  3355   3365   int sqlite3_data_count(sqlite3_stmt *pStmt);
  3356   3366   
  3357   3367   /*
  3358   3368   ** CAPI3REF: Fundamental Datatypes

Changes to src/sqlite3_private.h.

    23     23   **
    24     24   ** There is no support for identifying db files encrypted via SEE encryption
    25     25   ** currently.  Zero byte files are tested for sqlite locks, but if no sqlite 
    26     26   ** locks are present then SQLITE_LOCKSTATE_NOTADB is returned.
    27     27   */
    28     28   extern int _sqlite3_lockstate(const char *path, pid_t pid);
    29     29   
           30  +/*
           31  +** Test an open database connection for sqlite locks held by a process ID,
           32  +** if a process has an open database connection this will avoid trashing file
           33  +** locks by re-using open file descriptors for the database file and support
           34  +** files (-shm)
           35  +*/
           36  +#define SQLITE_FCNTL_LOCKSTATE_PID          103
           37  +
    30     38   /*
    31     39   ** Pass the SQLITE_TRUNCATE_DATABASE operation code to sqlite3_file_control() 
    32     40   ** to truncate a database and its associated journal file to zero length.
    33     41   */
    34         -#define SQLITE_TRUNCATE_DATABASE      101
           42  +#define SQLITE_FCNTL_TRUNCATE_DATABASE      101
           43  +#define SQLITE_TRUNCATE_DATABASE            SQLITE_FCNTL_TRUNCATE_DATABASE
    35     44   
    36     45   /*
    37     46   ** Pass the SQLITE_REPLACE_DATABASE operation code to sqlite3_file_control() 
    38     47   ** and a sqlite3 pointer to another open database file to safely copy the 
    39     48   ** contents of that database file into the receiving database.
    40     49   */
    41         -#define SQLITE_REPLACE_DATABASE       102
           50  +#define SQLITE_FCNTL_REPLACE_DATABASE       102
           51  +#define SQLITE_REPLACE_DATABASE             SQLITE_FCNTL_REPLACE_DATABASE
    42     52   
    43     53   #endif

Changes to src/sqliteInt.h.

  3261   3261   #endif
  3262   3262   #define MEMTYPE_HEAP       0x01  /* General heap allocations */
  3263   3263   #define MEMTYPE_LOOKASIDE  0x02  /* Might have been lookaside memory */
  3264   3264   #define MEMTYPE_SCRATCH    0x04  /* Scratch allocations */
  3265   3265   #define MEMTYPE_PCACHE     0x08  /* Page cache allocations */
  3266   3266   #define MEMTYPE_DB         0x10  /* Uses sqlite3DbMalloc, not sqlite_malloc */
  3267   3267   
         3268  +
         3269  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
         3270  +
         3271  +/*
         3272  +** An instance of the following structure is used to hold the process ID
         3273  +** and return-by-reference lockstate value.  The SQLITE_FCNTL_LOCKSTATE_PID
         3274  +** requires the 4th argument to sqlite3_file_control to be a pointer to an
         3275  +** instance of LockstatePID initialized with a LockstatePID.pid value equal
         3276  +** to a process ID to be tested, or the special value SQLITE_LOCKSTATE_ANYPID
         3277  +** The Lockstate.state value is always set to one of the following values
         3278  +** when sqlite3_file_control returns:
         3279  +** 
         3280  +**   SQLITE_LOCKSTATE_OFF    no active sqlite file locks match the specified pid
         3281  +**   SQLITE_LOCKSTATE_ON     active sqlite file locks match the specified pid
         3282  +**   SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file
         3283  +**   SQLITE_LOCKSTATE_ERROR  path was not vaild or was unreadable
         3284  +*/
         3285  +typedef struct LockstatePID LockstatePID;
         3286  +struct LockstatePID {
         3287  +  pid_t pid;                 /* Process ID to test */
         3288  +  int state;                 /* The state of the lock (return value) */
         3289  +};
         3290  +
         3291  +#endif
         3292  +
  3268   3293   #endif /* _SQLITEINT_H_ */

Changes to src/test1.c.

  4986   4986   static int file_control_truncate_test(
  4987   4987     ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  4988   4988     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  4989   4989     int objc,              /* Number of arguments */
  4990   4990     Tcl_Obj *CONST objv[]  /* Command arguments */
  4991   4991   ){
  4992   4992     sqlite3 *db;
         4993  +  int flags;
  4993   4994     int rc;
  4994   4995     
  4995         -  if( objc!=2 ){
         4996  +  if( objc!=3 ){
  4996   4997       Tcl_AppendResult(interp, "wrong # args: should be \"",
  4997         -                     Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
         4998  +                     Tcl_GetStringFromObj(objv[0], 0), " DB FLAGS", 0);
  4998   4999       return TCL_ERROR;
  4999   5000     }
  5000   5001     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5001   5002       return TCL_ERROR;
  5002   5003     }
  5003         -  rc = sqlite3_file_control(db, NULL, SQLITE_TRUNCATE_DATABASE, 0);
         5004  +  if( Tcl_GetIntFromObj(interp, objv[2], &flags) ){
         5005  +    return TCL_ERROR;
         5006  +  }
         5007  +  rc = sqlite3_file_control(db, NULL, SQLITE_TRUNCATE_DATABASE, &flags);
  5004   5008     if( rc ){ 
  5005   5009       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 
  5006   5010       return TCL_ERROR; 
  5007   5011     }
  5008   5012     return TCL_OK;  
  5009   5013   }
  5010   5014   
................................................................................
  5201   5205    */
  5202   5206   static int path_is_local(
  5203   5207     ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5204   5208     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5205   5209     int objc,              /* Number of arguments */
  5206   5210     Tcl_Obj *CONST objv[]  /* Command arguments */
  5207   5211   ){
  5208         -  sqlite3 *db;
  5209   5212     const char *zPath;
  5210   5213     int nPath;
  5211   5214     
  5212   5215     if( objc!=2 ){
  5213   5216       Tcl_AppendResult(interp, "wrong # args: should be \"",
  5214   5217                        Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
  5215   5218       return TCL_ERROR;
................................................................................
  5243   5246    */
  5244   5247   static int path_is_dos(
  5245   5248     ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5246   5249     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5247   5250     int objc,              /* Number of arguments */
  5248   5251     Tcl_Obj *CONST objv[]  /* Command arguments */
  5249   5252   ){
  5250         -  sqlite3 *db;
  5251   5253     const char *zPath;
  5252   5254     int nPath;
  5253   5255     
  5254   5256     if( objc!=2 ){
  5255   5257       Tcl_AppendResult(interp, "wrong # args: should be \"",
  5256   5258                        Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
  5257   5259       return TCL_ERROR;
................................................................................
  6168   6170   #ifdef __APPLE__
  6169   6171        { "file_control_truncate_test", file_control_truncate_test,  0   },
  6170   6172        { "file_control_replace_test", file_control_replace_test,  0   },
  6171   6173   #endif 
  6172   6174        { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  6173   6175        { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  6174   6176        { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
         6177  +     { "file_control_persist_wal",    file_control_persist_wal,     0   },
  6175   6178        { "file_control_persist_wal",    file_control_persist_wal,     0   },
  6176   6179        { "sqlite3_vfs_list",           vfs_list,     0   },
  6177   6180        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  6178   6181        { "path_is_local",              path_is_local,  0   },
  6179   6182        { "path_is_dos",                path_is_dos,  0   },
  6180   6183   
  6181   6184        /* Functions from os.h */

Changes to src/vdbeaux.c.

  1138   1138     int nRow;                            /* Stop when row count reaches this */
  1139   1139     int nSub = 0;                        /* Number of sub-vdbes seen so far */
  1140   1140     SubProgram **apSub = 0;              /* Array of sub-vdbes */
  1141   1141     Mem *pSub = 0;                       /* Memory cell hold array of subprogs */
  1142   1142     sqlite3 *db = p->db;                 /* The database connection */
  1143   1143     int i;                               /* Loop counter */
  1144   1144     int rc = SQLITE_OK;                  /* Return code */
  1145         -  Mem *pMem = p->pResultSet = &p->aMem[1];  /* First Mem of result set */
         1145  +  Mem *pMem = &p->aMem[1];             /* First Mem of result set */
  1146   1146   
  1147   1147     assert( p->explain );
  1148   1148     assert( p->magic==VDBE_MAGIC_RUN );
  1149   1149     assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
  1150   1150   
  1151   1151     /* Even though this opcode does not use dynamic strings for
  1152   1152     ** the result, result columns may become dynamic if the user calls
  1153   1153     ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
  1154   1154     */
  1155   1155     releaseMemArray(pMem, 8);
         1156  +  p->pResultSet = 0;
  1156   1157   
  1157   1158     if( p->rc==SQLITE_NOMEM ){
  1158   1159       /* This happens if a malloc() inside a call to sqlite3_column_text() or
  1159   1160       ** sqlite3_column_text16() failed.  */
  1160   1161       db->mallocFailed = 1;
  1161   1162       return SQLITE_ERROR;
  1162   1163     }
................................................................................
  1303   1304         {
  1304   1305           pMem->flags = MEM_Null;                       /* Comment */
  1305   1306           pMem->type = SQLITE_NULL;
  1306   1307         }
  1307   1308       }
  1308   1309   
  1309   1310       p->nResColumn = 8 - 4*(p->explain-1);
         1311  +    p->pResultSet = &p->aMem[1];
  1310   1312       p->rc = SQLITE_OK;
  1311   1313       rc = SQLITE_ROW;
  1312   1314     }
  1313   1315     return rc;
  1314   1316   }
  1315   1317   #endif /* SQLITE_OMIT_EXPLAIN */
  1316   1318   
................................................................................
  1507   1509       nMem = 10;
  1508   1510     }
  1509   1511     memset(zCsr, 0, zEnd-zCsr);
  1510   1512     zCsr += (zCsr - (u8*)0)&7;
  1511   1513     assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
  1512   1514     p->expired = 0;
  1513   1515   
         1516  +  p->expired = 0;
         1517  +  
  1514   1518     /* Memory for registers, parameters, cursor, etc, is allocated in two
  1515   1519     ** passes.  On the first pass, we try to reuse unused space at the 
  1516   1520     ** end of the opcode array.  If we are unable to satisfy all memory
  1517   1521     ** requirements by reusing the opcode array tail, then the second
  1518   1522     ** pass will fill in the rest using a fresh allocation.  
  1519   1523     **
  1520   1524     ** This two-pass approach that reuses as much memory as possible from

Changes to src/wal.c.

  1281   1281     pRet->pDbFd = pDbFd;
  1282   1282     pRet->readLock = -1;
  1283   1283     pRet->mxWalSize = mxWalSize;
  1284   1284     pRet->zWalName = zWalName;
  1285   1285     pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
  1286   1286   
  1287   1287     /* Open file handle on the write-ahead log file. */
  1288         -  vfsFlags = flags | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
         1288  +  if( flags&SQLITE_OPEN_READONLY ){
         1289  +    vfsFlags = flags | SQLITE_OPEN_WAL;
         1290  +  } else {
         1291  +    vfsFlags = flags | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
         1292  +  }
  1289   1293     rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, vfsFlags, &vfsFlags);
  1290   1294     if( rc==SQLITE_OK && vfsFlags&SQLITE_OPEN_READONLY ){
  1291   1295       pRet->readOnly = WAL_RDONLY;
  1292   1296     }
  1293   1297   
  1294   1298     if( rc!=SQLITE_OK ){
  1295   1299       walIndexClose(pRet, 0);
................................................................................
  1862   1866     **
  1863   1867     ** There are two copies of the header at the beginning of the wal-index.
  1864   1868     ** When reading, read [0] first then [1].  Writes are in the reverse order.
  1865   1869     ** Memory barriers are used to prevent the compiler or the hardware from
  1866   1870     ** reordering the reads and writes.
  1867   1871     */
  1868   1872     aHdr = walIndexHdr(pWal);
         1873  +  if( aHdr==NULL ){
         1874  +    return 1; /* Shouldn't be getting NULL from walIndexHdr, but we are */
         1875  +  }
  1869   1876     memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
  1870   1877     walShmBarrier(pWal);
  1871   1878     memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
  1872   1879   
  1873   1880     if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
  1874   1881       return 1;   /* Dirty read */
  1875   1882     }  
................................................................................
  2046   2053     ** is more of a scheduler yield than an actual delay.  But on the 10th
  2047   2054     ** an subsequent retries, the delays start becoming longer and longer, 
  2048   2055     ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
  2049   2056     ** The total delay time before giving up is less than 1 second.
  2050   2057     */
  2051   2058     if( cnt>5 ){
  2052   2059       int nDelay = 1;                      /* Pause time in microseconds */
  2053         -    if( cnt>100 ){
         2060  +    if( cnt>500 ){
  2054   2061         VVA_ONLY( pWal->lockError = 1; )
  2055   2062         return SQLITE_PROTOCOL;
  2056   2063       }
  2057   2064       if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
  2058   2065       sqlite3OsSleep(pWal->pVfs, nDelay);
  2059   2066     }
  2060   2067