/ Check-in [db5b7b77]
Login

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

Overview
Comment:Merging in cherry picked diffs for persist wal, alloc padding, wal-safe vacuum and sqlite3_file_control based lockstate checking
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx-377
Files: files | file ages | folders
SHA1: db5b7b778c09c57501cb8266895a0ea4f2de7649
User & Date: adam 2011-10-10 22:11:44
References
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
Context
2011-10-11
00:09
Patches to the apple-osx-377 branch so that it will compile and run on non-Mac unix platforms. Leaf check-in: b431a634 user: drh tags: apple-osx-377
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
18:59
Cherrypick the sqlite_data_count() changes from [d4f95b3b6e] and [9913996e7b] into the apple-osx branch for version 3.7.7. check-in: aef7945c user: drh tags: apple-osx-377
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

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

Changes to src/btree.c.

  8165   8165   ** "write version" (single byte at byte offset 19) fields in the database
  8166   8166   ** header to iVersion.
  8167   8167   */
  8168   8168   int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
  8169   8169     BtShared *pBt = pBtree->pBt;
  8170   8170     int rc;                         /* Return code */
  8171   8171    
  8172         -  assert( pBtree->inTrans==TRANS_NONE );
  8173   8172     assert( iVersion==1 || iVersion==2 );
  8174   8173   
  8175   8174     /* If setting the version fields to 1, do not automatically open the
  8176   8175     ** WAL connection, even if the version fields are currently set to 2.
  8177   8176     */
  8178   8177     pBt->doNotUseWAL = (u8)(iVersion==1);
  8179   8178   

Changes to src/main.c.

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

Changes to src/mem1.c.

    41     41   #include <libkern/OSAtomic.h>
    42     42   
    43     43   static malloc_zone_t* _sqliteZone_;
    44     44   
    45     45   #define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
    46     46   #define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
    47     47   #define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
           48  +#define SQLITE_MALLOCSIZE(x) (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
    48     49   
    49     50   #endif
    50     51   
    51     52   /*
    52     53   ** Like malloc(), but remember the size of the allocation
    53     54   ** so that we can find it later using sqlite3MemSize().
    54     55   **
................................................................................
    56     57   ** cases of nByte<=0 will be intercepted and dealt with by higher level
    57     58   ** routines.
    58     59   */
    59     60   static void *sqlite3MemMalloc(int nByte){
    60     61     sqlite3_int64 *p;
    61     62     assert( nByte>0 );
    62     63     nByte = ROUND8(nByte);
    63         -  p = SQLITE_MALLOC( nByte+8 );
    64         -  if( p ){
    65         -    p[0] = nByte;
    66         -    p++;
    67         -  }else{
           64  +  p = SQLITE_MALLOC( nByte );
           65  +  if( !p ){
    68     66       testcase( sqlite3GlobalConfig.xLog!=0 );
    69     67       sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
    70     68     }
    71     69     return (void *)p;
    72     70   }
    73     71   
    74     72   /*
................................................................................
    78     76   ** For this low-level routine, we already know that pPrior!=0 since
    79     77   ** cases where pPrior==0 will have been intecepted and dealt with
    80     78   ** by higher-level routines.
    81     79   */
    82     80   static void sqlite3MemFree(void *pPrior){
    83     81     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    84     82     assert( pPrior!=0 );
    85         -  p--;
    86     83     SQLITE_FREE(p);
    87     84   }
    88     85   
    89     86   /*
    90     87   ** Report the allocated size of a prior return from xMalloc()
    91     88   ** or xRealloc().
    92     89   */
    93     90   static int sqlite3MemSize(void *pPrior){
    94     91     sqlite3_int64 *p;
    95     92     if( pPrior==0 ) return 0;
    96         -  p = (sqlite3_int64*)pPrior;
    97         -  p--;
    98         -  return (int)p[0];
           93  +  return (int)SQLITE_MALLOCSIZE(pPrior);
    99     94   }
   100     95   
   101     96   /*
   102     97   ** Like realloc().  Resize an allocation previously obtained from
   103     98   ** sqlite3MemMalloc().
   104     99   **
   105    100   ** For this low-level interface, we know that pPrior!=0.  Cases where
................................................................................
   108    103   ** cases where nByte<=0 will have been intercepted by higher-level
   109    104   ** routines and redirected to xFree.
   110    105   */
   111    106   static void *sqlite3MemRealloc(void *pPrior, int nByte){
   112    107     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
   113    108     assert( pPrior!=0 && nByte>0 );
   114    109     assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
   115         -  p--;
   116         -  p = SQLITE_REALLOC(p, nByte+8 );
   117         -  if( p ){
   118         -    p[0] = nByte;
   119         -    p++;
   120         -  }else{
          110  +  p = SQLITE_REALLOC(p, nByte );
          111  +  if( !p ){
   121    112       testcase( sqlite3GlobalConfig.xLog!=0 );
   122    113       sqlite3_log(SQLITE_NOMEM,
   123    114         "failed memory resize %u to %u bytes",
   124    115         sqlite3MemSize(pPrior), nByte);
   125    116     }
   126    117     return (void*)p;
   127    118   }

Changes to src/os_unix.c.

   254    254     char aPadding[32];
   255    255   #endif
   256    256   };
   257    257   
   258    258   /*
   259    259   ** Allowed values for the unixFile.ctrlFlags bitmask:
   260    260   */
   261         -#define UNIXFILE_EXCL   0x01     /* Connections from one process only */
   262         -#define UNIXFILE_RDONLY 0x02     /* Connection is read only */
          261  +#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
          262  +#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
          263  +#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
   263    264   
   264    265   /*
   265    266   ** Include code that is common to all os_*.c files
   266    267   */
   267    268   #include "os_common.h"
   268    269   
   269    270   /*
................................................................................
  1535   1536     unixLeaveMutex();
  1536   1537     OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
  1537   1538   
  1538   1539     *pResOut = reserved;
  1539   1540     return rc;
  1540   1541   }
  1541   1542   
         1543  +static int _unixFileLock(unixFile *pFile, struct flock *pLock, int retry);
         1544  +
  1542   1545   /*
  1543   1546   ** Attempt to set a system-lock on the file pFile.  The lock is 
  1544   1547   ** described by pLock.
  1545   1548   **
  1546   1549   ** If the pFile was opened read/write from unix-excl, then the only lock
  1547   1550   ** ever obtained is an exclusive lock, and it is obtained exactly once
  1548   1551   ** the first time any lock is attempted.  All subsequent system locking
................................................................................
  1555   1558   ** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
  1556   1559   ** and is read-only.
  1557   1560   **
  1558   1561   ** Zero is returned if the call completes successfully, or -1 if a call
  1559   1562   ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
  1560   1563   */
  1561   1564   static int unixFileLock(unixFile *pFile, struct flock *pLock){
  1562         -  int rc;
         1565  +  return _unixFileLock(pFile, pLock, 0);
         1566  +}
         1567  +
         1568  +static int unixFileLock2(unixFile *pFile, struct flock *pLock){
         1569  +  return _unixFileLock(pFile, pLock, 10);
         1570  +}
         1571  +
         1572  +static int _unixFileLock(unixFile *pFile, struct flock *pLock, int retry) {
         1573  +  int rc = 0;
  1563   1574     unixInodeInfo *pInode = pFile->pInode;
  1564   1575     assert( unixMutexHeld() );
  1565   1576     assert( pInode!=0 );
  1566   1577     if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
  1567   1578      && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
  1568   1579     ){
  1569   1580       if( pInode->bProcessLock==0 ){
................................................................................
  1577   1588         if( rc<0 ) return rc;
  1578   1589         pInode->bProcessLock = 1;
  1579   1590         pInode->nLock++;
  1580   1591       }else{
  1581   1592         rc = 0;
  1582   1593       }
  1583   1594     }else{
  1584         -    rc = osFcntl(pFile->h, F_SETLK, pLock);
         1595  +    int i = 0;                      
         1596  +    do {
         1597  +      rc = osFcntl(pFile->h, F_SETLK, pLock);
         1598  +      if (rc && retry) {
         1599  +        usleep(100 * (++i));
         1600  +      }
         1601  +    } while (!rc && retry--);
  1585   1602     }
  1586   1603     return rc;
  1587   1604   }
  1588   1605   
  1589   1606   /*
  1590   1607   ** Lock the file with the lock specified by parameter eFileLock - one
  1591   1608   ** of the following:
................................................................................
  1748   1765         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1749   1766       }
  1750   1767   
  1751   1768       /* Drop the temporary PENDING lock */
  1752   1769       lock.l_start = PENDING_BYTE;
  1753   1770       lock.l_len = 1L;
  1754   1771       lock.l_type = F_UNLCK;
  1755         -    if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
         1772  +    if( unixFileLock2(pFile, &lock) && rc==SQLITE_OK ){
  1756   1773         /* This could happen with a network mount */
  1757   1774         tErrno = errno;
  1758   1775   #if OSLOCKING_CHECK_BUSY_IOERR
  1759   1776         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
  1760   1777   #else
  1761   1778         rc = SQLITE_IOERR_UNLOCK; 
  1762   1779   #endif
................................................................................
  1916   1933       if( eFileLock==SHARED_LOCK ){
  1917   1934   
  1918   1935   #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
  1919   1936         (void)handleNFSUnlock;
  1920   1937         assert( handleNFSUnlock==0 );
  1921   1938   #endif
  1922   1939   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
         1940  +      int tErrno;               /* Error code from system call errors */
  1923   1941         if( handleNFSUnlock ){
  1924         -        int tErrno;               /* Error code from system call errors */
  1925   1942           off_t divSize = SHARED_SIZE - 1;
  1926   1943           
  1927   1944           lock.l_type = F_UNLCK;
  1928   1945           lock.l_whence = SEEK_SET;
  1929   1946           lock.l_start = SHARED_FIRST;
  1930   1947           lock.l_len = divSize;
  1931         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1948  +        if( unixFileLock2(pFile, &lock)==(-1) ){
  1932   1949             tErrno = errno;
  1933   1950   #if OSLOCKING_CHECK_BUSY_IOERR
  1934   1951             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1935   1952   #else
  1936   1953             rc = SQLITE_IOERR_UNLOCK;
  1937   1954   #endif
  1938   1955             if( IS_LOCK_ERROR(rc) ){
................................................................................
  1940   1957             }
  1941   1958             goto end_unlock;
  1942   1959           }
  1943   1960           lock.l_type = F_RDLCK;
  1944   1961           lock.l_whence = SEEK_SET;
  1945   1962           lock.l_start = SHARED_FIRST;
  1946   1963           lock.l_len = divSize;
  1947         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1964  +        if( unixFileLock2(pFile, &lock)==(-1) ){
  1948   1965             tErrno = errno;
         1966  +#if OSLOCKING_CHECK_BUSY_IOERR
  1949   1967             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
         1968  +#else
         1969  +          rc = SQLITE_IOERR_UNLOCK;
         1970  +#endif
  1950   1971             if( IS_LOCK_ERROR(rc) ){
  1951   1972               pFile->lastErrno = tErrno;
  1952   1973             }
  1953   1974             goto end_unlock;
  1954   1975           }
  1955   1976           lock.l_type = F_UNLCK;
  1956   1977           lock.l_whence = SEEK_SET;
  1957   1978           lock.l_start = SHARED_FIRST+divSize;
  1958   1979           lock.l_len = SHARED_SIZE-divSize;
  1959         -        if( unixFileLock(pFile, &lock)==(-1) ){
         1980  +        if( unixFileLock2(pFile, &lock)==(-1) ){
  1960   1981             tErrno = errno;
  1961   1982   #if OSLOCKING_CHECK_BUSY_IOERR
  1962   1983             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1963   1984   #else
  1964   1985             rc = SQLITE_IOERR_UNLOCK;
  1965   1986   #endif
  1966   1987             if( IS_LOCK_ERROR(rc) ){
................................................................................
  1971   1992         }else
  1972   1993   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  1973   1994         {
  1974   1995           lock.l_type = F_RDLCK;
  1975   1996           lock.l_whence = SEEK_SET;
  1976   1997           lock.l_start = SHARED_FIRST;
  1977   1998           lock.l_len = SHARED_SIZE;
  1978         -        if( unixFileLock(pFile, &lock) ){
  1979         -#if OSLOCKING_CHECK_BUSY_IOERR
         1999  +        if( unixFileLock2(pFile, &lock) ){
  1980   2000             tErrno = errno;
         2001  +#if OSLOCKING_CHECK_BUSY_IOERR
  1981   2002             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1982         -          if( IS_LOCK_ERROR(rc) ){
  1983         -            pFile->lastErrno = tErrno;
  1984         -          }
  1985   2003   #else
  1986   2004             /* In theory, the call to unixFileLock() cannot fail because another
  1987   2005             ** process is holding an incompatible lock. If it does, this 
  1988   2006             ** indicates that the other process is not following the locking
  1989   2007             ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
  1990   2008             ** SQLITE_BUSY would confuse the upper layer (in practice it causes 
  1991   2009             ** an assert to fail). */ 
  1992   2010             rc = SQLITE_IOERR_RDLOCK;
  1993         -          pFile->lastErrno = errno;
         2011  +          pFile->lastErrno = tErrno;
  1994   2012   #endif
         2013  +          if( IS_LOCK_ERROR(rc) ){
         2014  +            pFile->lastErrno = tErrno;
         2015  +          }
  1995   2016             goto end_unlock;
  1996   2017           }
  1997   2018         }
  1998   2019       }
  1999   2020       lock.l_type = F_UNLCK;
  2000   2021       lock.l_whence = SEEK_SET;
  2001   2022       lock.l_start = PENDING_BYTE;
  2002   2023       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  2003         -    if( unixFileLock(pFile, &lock)==0 ){
         2024  +    if( unixFileLock2(pFile, &lock)==0 ){
  2004   2025         pInode->eFileLock = SHARED_LOCK;
  2005   2026       }else{
  2006   2027   #if OSLOCKING_CHECK_BUSY_IOERR
  2007   2028         tErrno = errno;
  2008   2029         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  2009   2030         if( IS_LOCK_ERROR(rc) ){
  2010   2031           pFile->lastErrno = tErrno;
................................................................................
  2025   2046       if( pInode->nShared==0 ){
  2026   2047         lock.l_type = F_UNLCK;
  2027   2048         lock.l_whence = SEEK_SET;
  2028   2049         lock.l_start = lock.l_len = 0L;
  2029   2050         SimulateIOErrorBenign(1);
  2030   2051         SimulateIOError( h=(-1) )
  2031   2052         SimulateIOErrorBenign(0);
  2032         -      if( unixFileLock(pFile, &lock)==0 ){
         2053  +      if( unixFileLock2(pFile, &lock)==0 ){
  2033   2054           pInode->eFileLock = NO_LOCK;
  2034   2055         }else{
  2035   2056   #if OSLOCKING_CHECK_BUSY_IOERR
  2036   2057           tErrno = errno;
  2037   2058           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  2038   2059           if( IS_LOCK_ERROR(rc) ){
  2039   2060             pFile->lastErrno = tErrno;
................................................................................
  3841   3862   #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
  3842   3863   #include "sqlite3_private.h"
  3843   3864   #include <copyfile.h>
  3844   3865   static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
  3845   3866   #endif
  3846   3867   static int isProxyLockingMode(unixFile *);
  3847   3868   
         3869  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
         3870  +static int unixTruncateDatabase(unixFile *, int);
         3871  +
         3872  +static int unixInvalidateSupportFiles(unixFile *, int);
         3873  +
         3874  +static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
         3875  +  sqlite3_file *id = (sqlite3_file *)pFile;
         3876  +  Btree *pSrcBtree = NULL;
         3877  +  sqlite3_file *src_file = NULL;
         3878  +  unixFile *pSrcFile = NULL;
         3879  +  char srcWalPath[MAXPATHLEN+5];
         3880  +  int srcWalFD = -1;
         3881  +  int rc = SQLITE_OK;
         3882  +  void *pLock = NULL;
         3883  +  int flags = 0;
         3884  +  sqlite3 *srcdb2 = NULL;
         3885  +  copyfile_state_t s;
         3886  +  int corruptSrcFileLock = 0;
         3887  +  int corruptDstFileLock = 0;
         3888  +  int isSrcCorrupt = 0;
         3889  +  int isDstCorrupt = 0;
         3890  +  
         3891  +  if( !sqlite3SafetyCheckOk(srcdb) ){
         3892  +    return SQLITE_MISUSE;
         3893  +  }
         3894  +    
         3895  +#if SQLITE_ENABLE_DATA_PROTECTION
         3896  +  flags |= pFile->protFlags;
         3897  +#endif
         3898  +#if SQLITE_ENABLE_LOCKING_STYLE
         3899  +  if( isProxyLockingMode(pFile) ){
         3900  +    flags |= SQLITE_OPEN_AUTOPROXY;
         3901  +  }
         3902  +#endif
         3903  +  
         3904  +  rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
         3905  +  if( rc ){
         3906  +    if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         3907  +      isDstCorrupt = 1;
         3908  +      rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
         3909  +    }
         3910  +    if( rc ){
         3911  +      return rc;
         3912  +    }
         3913  +  }
         3914  +  /* get the src file descriptor adhering to the db struct access rules 
         3915  +   ** this code is modeled after sqlite3_file_control() in main.c
         3916  +   */ 
         3917  +  sqlite3_mutex_enter(srcdb->mutex);
         3918  +  if( srcdb->nDb>0 ){
         3919  +    pSrcBtree = srcdb->aDb[0].pBt;
         3920  +  }
         3921  +  if( pSrcBtree ){
         3922  +    Pager *pSrcPager;
         3923  +    sqlite3BtreeEnter(pSrcBtree);
         3924  +    pSrcPager = sqlite3BtreePager(pSrcBtree);
         3925  +    assert( pSrcPager!=0 );
         3926  +    src_file = sqlite3PagerFile(pSrcPager);
         3927  +    assert( src_file!=0 );
         3928  +    if( src_file->pMethods ){
         3929  +      int srcFlags = 0;
         3930  +      pSrcFile = (unixFile *)src_file;
         3931  +      /* wal mode db cannot be opened readonly */
         3932  +      if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
         3933  +        srcFlags = SQLITE_OPEN_READWRITE;
         3934  +      } else {
         3935  +        srcFlags = SQLITE_OPEN_READONLY;
         3936  +      }
         3937  +#if SQLITE_ENABLE_DATA_PROTECTION
         3938  +      srcFlags |= pSrcFile->protFlags;
         3939  +#endif
         3940  +#if SQLITE_ENABLE_LOCKING_STYLE
         3941  +      if( isProxyLockingMode(pSrcFile) ){
         3942  +        srcFlags |= SQLITE_OPEN_AUTOPROXY;
         3943  +      }
         3944  +#endif
         3945  +      rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
         3946  +      if( rc==SQLITE_OK ){
         3947  +        /* start a deferred transaction and read to establish a read lock */
         3948  +        rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
         3949  +        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         3950  +          isSrcCorrupt = 1;
         3951  +          rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
         3952  +        }
         3953  +      }
         3954  +    }
         3955  +  }
         3956  +  if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
         3957  +    rc = SQLITE_INTERNAL;
         3958  +  }
         3959  +  if( rc!=SQLITE_OK ){
         3960  +    goto end_replace_database;
         3961  +  }
         3962  +  /* both databases are locked appropriately, copy the src wal journal if 
         3963  +   ** one exists and then the actual database file
         3964  +   */
         3965  +  strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
         3966  +  strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
         3967  +  srcWalFD = open(srcWalPath, O_RDONLY);
         3968  +  if( !(srcWalFD<0) ){
         3969  +    char dstWalPath[MAXPATHLEN+5];
         3970  +    int dstWalFD = -1;
         3971  +    strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
         3972  +    strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
         3973  +    dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
         3974  +    if( !(dstWalFD<0) ){
         3975  +      s = copyfile_state_alloc();
         3976  +      lseek(srcWalFD, 0, SEEK_SET);
         3977  +      lseek(dstWalFD, 0, SEEK_SET);
         3978  +      if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
         3979  +        int err=errno;
         3980  +        switch(err) {
         3981  +          case ENOMEM:
         3982  +            rc = SQLITE_NOMEM;
         3983  +            break;
         3984  +          default:
         3985  +            pFile->lastErrno = err;
         3986  +            rc = SQLITE_IOERR;
         3987  +        }
         3988  +      }
         3989  +      copyfile_state_free(s);
         3990  +      close(dstWalFD);
         3991  +    }
         3992  +    close(srcWalFD);
         3993  +  }
         3994  +  if( rc==SQLITE_OK ){
         3995  +    /* before we copy, ensure that the file change counter will be modified */
         3996  +    uint32_t srcChange = 0;
         3997  +    uint32_t dstChange = 0;
         3998  +    pread(pSrcFile->h, &srcChange, 4, 24);
         3999  +    pread(pFile->h, &dstChange, 4, 24);
         4000  +    
         4001  +    /* copy the actual database */
         4002  +    s = copyfile_state_alloc();
         4003  +    lseek(pSrcFile->h, 0, SEEK_SET);
         4004  +    lseek(pFile->h, 0, SEEK_SET);
         4005  +    if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
         4006  +      int err=errno;
         4007  +      switch(err) {
         4008  +        case ENOMEM:
         4009  +          rc = SQLITE_NOMEM;
         4010  +          break;
         4011  +        default:
         4012  +          pFile->lastErrno = err;
         4013  +          rc = SQLITE_IOERR;
         4014  +      }
         4015  +    }
         4016  +    copyfile_state_free(s);
         4017  +    
         4018  +    if (srcChange == dstChange) {
         4019  +      /* modify the change counter to force page zero to be reloaded */
         4020  +      dstChange ++;
         4021  +      pwrite(pFile->h, &dstChange, 4, 24);
         4022  +    }
         4023  +  }
         4024  +  if( isSrcCorrupt ){
         4025  +    sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
         4026  +  }else{
         4027  +    /* done with the source db so end the transaction */
         4028  +    sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
         4029  +  }
         4030  +  /* zero out any old journal clutter */
         4031  +  if( rc==SQLITE_OK ){
         4032  +    int skipWAL = (srcWalFD<0)?0:1;
         4033  +    unixInvalidateSupportFiles(pFile, skipWAL);
         4034  +  }
         4035  +  
         4036  +end_replace_database:
         4037  +  if( pSrcBtree ){
         4038  +    sqlite3_close(srcdb2);
         4039  +    sqlite3BtreeLeave(pSrcBtree);
         4040  +  }
         4041  +  sqlite3_mutex_leave(srcdb->mutex);
         4042  +  if( isDstCorrupt ){
         4043  +    sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
         4044  +  }else{
         4045  +    sqlite3demo_superunlock(pLock);
         4046  +  }
         4047  +  return rc;
         4048  +}
         4049  +
         4050  +#define SQLITE_FILE_HEADER_LEN 16
         4051  +#include "btreeInt.h"
         4052  +/* Check for a conflicting lock.  If one is found, print an this
         4053  + ** on standard output using the format string given and return 1.
         4054  + ** If there are no conflicting locks, return 0.
         4055  + */
         4056  +static int unixIsLocked(
         4057  +  pid_t pid,            /* PID to test for lock owner */
         4058  +  int h,                /* File descriptor to check */
         4059  +  int type,             /* F_RDLCK or F_WRLCK */
         4060  +  unsigned int iOfst,   /* First byte of the lock */
         4061  +  unsigned int iCnt,    /* Number of bytes in the lock range */
         4062  +  const char *zType     /* Type of lock */
         4063  +){
         4064  +  struct flock lk;
         4065  +  int err;
         4066  +  
         4067  +  memset(&lk, 0, sizeof(lk));
         4068  +  lk.l_type = type;
         4069  +  lk.l_whence = SEEK_SET;
         4070  +  lk.l_start = iOfst;
         4071  +  lk.l_len = iCnt;
         4072  +  
         4073  +  if( pid!=SQLITE_LOCKSTATE_ANYPID ){
         4074  +#ifndef F_GETLKPID
         4075  +# warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK
         4076  +    err = fcntl(h, F_GETLK, &lk);
         4077  +#else
         4078  +    lk.l_pid = pid;
         4079  +    err = fcntl(h, F_GETLKPID, &lk);
         4080  +#endif
         4081  +  }else{
         4082  +    err = fcntl(h, F_GETLK, &lk);
         4083  +  }
         4084  +  
         4085  +  if( err==(-1) ){
         4086  +    fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
         4087  +    return -1;
         4088  +  }
         4089  +  
         4090  +  if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){
         4091  +#ifdef SQLITE_DEBUG
         4092  +    fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid);
         4093  +#endif
         4094  +    return 1;
         4095  +  } 
         4096  +  return 0;
         4097  +}
         4098  +
         4099  +static int unixLockstatePid(unixFile *, pid_t, int *);
         4100  +
         4101  +#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
         4102  +                               
  3848   4103   /*
  3849   4104   ** Information and control of an open file handle.
  3850   4105   */
  3851   4106   static int unixFileControl(sqlite3_file *id, int op, void *pArg){
         4107  +  unixFile *pFile = (unixFile*)id;
  3852   4108     switch( op ){
  3853   4109       case SQLITE_FCNTL_LOCKSTATE: {
  3854         -      *(int*)pArg = ((unixFile*)id)->eFileLock;
         4110  +      *(int*)pArg = pFile->eFileLock;
  3855   4111         return SQLITE_OK;
  3856   4112       }
  3857         -    case SQLITE_LAST_ERRNO: {
  3858         -      *(int*)pArg = ((unixFile*)id)->lastErrno;
         4113  +    case SQLITE_FCNTL_LAST_ERRNO: {
         4114  +      *(int*)pArg = pFile->lastErrno;
  3859   4115         return SQLITE_OK;
  3860   4116       }
  3861   4117       case SQLITE_FCNTL_CHUNK_SIZE: {
  3862         -      ((unixFile*)id)->szChunk = *(int *)pArg;
         4118  +      pFile->szChunk = *(int *)pArg;
  3863   4119         return SQLITE_OK;
  3864   4120       }
  3865   4121       case SQLITE_FCNTL_SIZE_HINT: {
  3866         -      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
         4122  +      return fcntlSizeHint(pFile, *(i64 *)pArg);
         4123  +    }
         4124  +    case SQLITE_FCNTL_PERSIST_WAL: {
         4125  +      int bPersist = *(int*)pArg;
         4126  +      if( bPersist<0 ){
         4127  +        *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
         4128  +      }else if( bPersist==0 ){
         4129  +        pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
         4130  +      }else{
         4131  +        pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
         4132  +      }
         4133  +      return SQLITE_OK;
  3867   4134       }
  3868   4135   #ifndef NDEBUG
  3869   4136       /* The pager calls this method to signal that it has done
  3870   4137       ** a rollback and that the database is therefore unchanged and
  3871   4138       ** it hence it is OK for the transaction change counter to be
  3872   4139       ** unchanged.
  3873   4140       */
  3874   4141       case SQLITE_FCNTL_DB_UNCHANGED: {
  3875   4142         ((unixFile*)id)->dbUpdate = 0;
  3876   4143         return SQLITE_OK;
  3877   4144       }
  3878   4145   #endif
  3879   4146   #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  3880         -    case SQLITE_SET_LOCKPROXYFILE:
  3881         -    case SQLITE_GET_LOCKPROXYFILE: {
         4147  +    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
         4148  +    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
  3882   4149         return proxyFileControl(id,op,pArg);
  3883   4150       }
  3884   4151   #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
  3885   4152   #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
  3886         -    case SQLITE_TRUNCATE_DATABASE: {
  3887         -      unixFile *pFile = (unixFile*)id;
  3888         -      int rc = SQLITE_OK;
  3889         -      void *pLock = NULL;
  3890         -      int flags = 0;
  3891         -      int corruptFileLock = 0;
  3892         -      int isCorrupt = 0;
  3893         -
  3894         -#if SQLITE_ENABLE_DATA_PROTECTION
  3895         -      flags |= pFile->protFlags;
  3896         -#endif
  3897         -#if SQLITE_ENABLE_LOCKING_STYLE
  3898         -      if( isProxyLockingMode(pFile) ){
  3899         -        flags |= SQLITE_OPEN_AUTOPROXY;
  3900         -      }
  3901         -#endif
  3902         -      
  3903         -      rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
  3904         -      if( rc ){
  3905         -        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  3906         -          isCorrupt = 1;
  3907         -          rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
  3908         -        }
  3909         -        if( rc ){
  3910         -          return rc;
  3911         -        }
  3912         -      }
  3913         -      rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
  3914         -
  3915         -      if( rc==SQLITE_OK ){
  3916         -        char jPath[MAXPATHLEN+9];
  3917         -        int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
  3918         -        if( zLen<MAXPATHLEN ){
  3919         -          size_t jLen;
  3920         -          const char extensions[2][9] = { "-wal", "-journal" /*, "-shm" */ };
  3921         -          int j = 0;
  3922         -          for( j=0; j<2; j++ ){
  3923         -            jLen = strlcpy(&jPath[zLen], extensions[j], 9);
  3924         -            if( jLen < 9 ){
  3925         -              int jfd = open(jPath, O_TRUNC);
  3926         -              if( jfd==(-1) ){
  3927         -                if ( errno!=ENOENT ){
  3928         -                  perror(jPath);
  3929         -                }
  3930         -              } else {
  3931         -                fsync(jfd);
  3932         -                close(jfd);
  3933         -              }
  3934         -            }
  3935         -          }
  3936         -        }
  3937         -        pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
  3938         -      }
  3939         -      if( isCorrupt ){
  3940         -        sqlite3demo_superunlock_corrupt(id, corruptFileLock);
  3941         -      }else{
  3942         -        sqlite3demo_superunlock(pLock);
  3943         -      }
  3944         -      return rc;
  3945         -    }
  3946         -      
  3947         -    case SQLITE_REPLACE_DATABASE: {
  3948         -      unixFile *pFile = (unixFile*)id;
  3949         -      sqlite3 *srcdb = (sqlite3 *)pArg;
  3950         -      Btree *pSrcBtree = NULL;
  3951         -      sqlite3_file *src_file = NULL;
  3952         -      unixFile *pSrcFile = NULL;
  3953         -      char srcWalPath[MAXPATHLEN+5];
  3954         -      int srcWalFD = -1;
  3955         -      int rc = SQLITE_OK;
  3956         -      void *pLock = NULL;
  3957         -      int flags = 0;
  3958         -      sqlite3 *srcdb2 = NULL;
  3959         -      copyfile_state_t s;
  3960         -      int corruptSrcFileLock = 0;
  3961         -      int corruptDstFileLock = 0;
  3962         -      int isSrcCorrupt = 0;
  3963         -      int isDstCorrupt = 0;
  3964         -
  3965         -      if( !sqlite3SafetyCheckOk(srcdb) ){
         4153  +    case SQLITE_FCNTL_TRUNCATE_DATABASE: {
         4154  +      return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0));
         4155  +    }
         4156  +    case SQLITE_FCNTL_REPLACE_DATABASE: {
         4157  +      return unixReplaceDatabase(pFile, (sqlite3 *)pArg);
         4158  +    }
         4159  +    case SQLITE_FCNTL_LOCKSTATE_PID: {
         4160  +      LockstatePID *pLockstate;
         4161  +      int rc;
         4162  +      
         4163  +      if( pArg==NULL ){
  3966   4164           return SQLITE_MISUSE;
  3967   4165         }
  3968         -      
  3969         -#if SQLITE_ENABLE_DATA_PROTECTION
  3970         -      flags |= pFile->protFlags;
  3971         -#endif
  3972         -#if SQLITE_ENABLE_LOCKING_STYLE
  3973         -      if( isProxyLockingMode(pFile) ){
  3974         -        flags |= SQLITE_OPEN_AUTOPROXY;
  3975         -      }
  3976         -#endif
  3977         -      
  3978         -      rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
  3979         -      if( rc ){
  3980         -        if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  3981         -          isDstCorrupt = 1;
  3982         -          rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
  3983         -        }
  3984         -        if( rc ){
  3985         -          return rc;
  3986         -        }
  3987         -      }
  3988         -      /* get the src file descriptor adhering to the db struct access rules 
  3989         -       ** this code is modeled after sqlite3_file_control() in main.c
  3990         -       */ 
  3991         -      sqlite3_mutex_enter(srcdb->mutex);
  3992         -      if( srcdb->nDb>0 ){
  3993         -        pSrcBtree = srcdb->aDb[0].pBt;
  3994         -      }
  3995         -      if( pSrcBtree ){
  3996         -        Pager *pSrcPager;
  3997         -        sqlite3BtreeEnter(pSrcBtree);
  3998         -        pSrcPager = sqlite3BtreePager(pSrcBtree);
  3999         -        assert( pSrcPager!=0 );
  4000         -        src_file = sqlite3PagerFile(pSrcPager);
  4001         -        assert( src_file!=0 );
  4002         -        if( src_file->pMethods ){
  4003         -          int srcFlags = 0;
  4004         -          pSrcFile = (unixFile *)src_file;
  4005         -          /* wal mode db cannot be opened readonly */
  4006         -          if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
  4007         -            srcFlags = SQLITE_OPEN_READWRITE;
  4008         -          } else {
  4009         -            srcFlags = SQLITE_OPEN_READONLY;
  4010         -          }
  4011         -#if SQLITE_ENABLE_DATA_PROTECTION
  4012         -          srcFlags |= pSrcFile->protFlags;
  4013         -#endif
  4014         -#if SQLITE_ENABLE_LOCKING_STYLE
  4015         -          if( isProxyLockingMode(pSrcFile) ){
  4016         -            srcFlags |= SQLITE_OPEN_AUTOPROXY;
  4017         -          }
  4018         -#endif
  4019         -          rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
  4020         -          if( rc==SQLITE_OK ){
  4021         -            /* start a deferred transaction and read to establish a read lock */
  4022         -            rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
  4023         -            if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
  4024         -              isSrcCorrupt = 1;
  4025         -              rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
  4026         -            }
  4027         -          }
  4028         -        }
  4029         -      }
  4030         -      if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
  4031         -        rc = SQLITE_INTERNAL;
  4032         -      }
  4033         -      if( rc!=SQLITE_OK ){
  4034         -        goto end_replace_database;
  4035         -      }
  4036         -      /* both databases are locked appropriately, copy the src wal journal if 
  4037         -      ** one exists and then the actual database file
  4038         -      */
  4039         -      strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
  4040         -      strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
  4041         -      srcWalFD = open(srcWalPath, O_RDONLY);
  4042         -      if( !(srcWalFD<0) ){
  4043         -        char dstWalPath[MAXPATHLEN+5];
  4044         -        int dstWalFD = -1;
  4045         -        strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
  4046         -        strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
  4047         -        dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
  4048         -        if( !(dstWalFD<0) ){
  4049         -          s = copyfile_state_alloc();
  4050         -          lseek(srcWalFD, 0, SEEK_SET);
  4051         -          lseek(dstWalFD, 0, SEEK_SET);
  4052         -          if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
  4053         -            int err=errno;
  4054         -            switch(err) {
  4055         -              case ENOMEM:
  4056         -                rc = SQLITE_NOMEM;
  4057         -                break;
  4058         -              default:
  4059         -                pFile->lastErrno = err;
  4060         -                rc = SQLITE_IOERR;
  4061         -            }
  4062         -          }
  4063         -          copyfile_state_free(s);
  4064         -          close(dstWalFD);
  4065         -        }
  4066         -        close(srcWalFD);
  4067         -      }
  4068         -      if( rc==SQLITE_OK ){
  4069         -        /* before we copy, ensure that the file change counter will be modified */
  4070         -        uint32_t srcChange = 0;
  4071         -        uint32_t dstChange = 0;
  4072         -        pread(pSrcFile->h, &srcChange, 4, 24);
  4073         -        pread(pFile->h, &dstChange, 4, 24);
  4074         -        
  4075         -        /* copy the actual database */
  4076         -        s = copyfile_state_alloc();
  4077         -        lseek(pSrcFile->h, 0, SEEK_SET);
  4078         -        lseek(pFile->h, 0, SEEK_SET);
  4079         -        if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
  4080         -          int err=errno;
  4081         -          switch(err) {
  4082         -            case ENOMEM:
  4083         -              rc = SQLITE_NOMEM;
  4084         -              break;
  4085         -            default:
  4086         -              pFile->lastErrno = err;
  4087         -              rc = SQLITE_IOERR;
  4088         -          }
  4089         -        }
  4090         -        copyfile_state_free(s);
  4091         -        
  4092         -        if (srcChange == dstChange) {
  4093         -          /* modify the change counter to force page zero to be reloaded */
  4094         -          dstChange ++;
  4095         -          pwrite(pFile->h, &dstChange, 4, 24);
  4096         -        }
  4097         -      }
  4098         -      if( isSrcCorrupt ){
  4099         -        sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
  4100         -      }else{
  4101         -        /* done with the source db so end the transaction */
  4102         -        sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
  4103         -      }
  4104         -      /* zero out any old journal clutter */
  4105         -      if( rc==SQLITE_OK ){
  4106         -        char jPath[MAXPATHLEN+9];
  4107         -        int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
  4108         -        if( zLen<MAXPATHLEN ){
  4109         -          size_t jLen;
  4110         -          const char extensions[2][9] = { "-wal", "-journal" /* "-shm" */ };
  4111         -          int j = (srcWalFD<0)?0:1; /* skip the wal if we replaced it */
  4112         -          for( ; j<2; j++ ){
  4113         -            jLen = strlcpy(&jPath[zLen], extensions[j], 9);
  4114         -            if( jLen < 9 ){
  4115         -              int jfd = open(jPath, O_TRUNC);
  4116         -              if( jfd==(-1) ){
  4117         -                if ( errno!=ENOENT ){
  4118         -                  perror(jPath);
  4119         -                }
  4120         -              } else {
  4121         -                fsync(jfd);
  4122         -                close(jfd);
  4123         -              }
  4124         -            }
  4125         -          }
  4126         -        }
  4127         -        pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
  4128         -      }
  4129         -      
  4130         -    end_replace_database:
  4131         -      if( pSrcBtree ){
  4132         -        sqlite3_close(srcdb2);
  4133         -        sqlite3BtreeLeave(pSrcBtree);
  4134         -      }
  4135         -      sqlite3_mutex_leave(srcdb->mutex);
  4136         -      if( isDstCorrupt ){
  4137         -        sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
  4138         -      }else{
  4139         -        sqlite3demo_superunlock(pLock);
  4140         -      }
         4166  +      pLockstate = (LockstatePID *)pArg;
         4167  +      rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state));
  4141   4168         return rc;
  4142   4169       }
  4143   4170   #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
  4144   4171       case SQLITE_FCNTL_SYNC_OMITTED: {
  4145   4172         return SQLITE_OK;  /* A no-op */
  4146   4173       }
  4147   4174     }
................................................................................
  4466   4493       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  4467   4494       if( pShmNode->mutex==0 ){
  4468   4495         rc = SQLITE_NOMEM;
  4469   4496         goto shm_open_err;
  4470   4497       }
  4471   4498   
  4472   4499       if( pInode->bProcessLock==0 ){
  4473         -      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
         4500  +      const char *zRO;
         4501  +      zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
         4502  +      if( zRO && sqlite3GetBoolean(zRO) ){
         4503  +        pShmNode->h = robust_open(zShmFilename, O_RDONLY,
         4504  +                                  (sStat.st_mode & 0777));
         4505  +        pShmNode->isReadonly = 1;
         4506  +      }else{
         4507  +        pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
  4474   4508                                  (sStat.st_mode & 0777));
         4509  +      }
  4475   4510         if( pShmNode->h<0 ){
  4476   4511           const char *zRO;
  4477   4512           zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
  4478   4513           if( zRO && sqlite3GetBoolean(zRO) ){
  4479   4514             pShmNode->h = robust_open(zShmFilename, O_RDONLY,
  4480   4515                                       (sStat.st_mode & 0777));
  4481   4516             pShmNode->isReadonly = 1;
................................................................................
  4842   4877   
  4843   4878   #else
  4844   4879   # define unixShmMap     0
  4845   4880   # define unixShmLock    0
  4846   4881   # define unixShmBarrier 0
  4847   4882   # define unixShmUnmap   0
  4848   4883   #endif /* #ifndef SQLITE_OMIT_WAL */
         4884  +
         4885  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
         4886  +static const char *unixTempFileDir(void);
         4887  +
         4888  +static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) {
         4889  +  char jPath[MAXPATHLEN+9];
         4890  +  int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
         4891  +  if( zLen<MAXPATHLEN ){
         4892  +    size_t jLen;
         4893  +    const char extensions[3][9] = { "-wal", "-journal", "-shm" };
         4894  +    int j = (skipWAL ? 1 : 0);
         4895  +    for( ; j<3; j++ ){
         4896  +      
         4897  +      /* Check to see if the shm file is already opened for this pFile */
         4898  +      if( j==2 ){
         4899  +        unixEnterMutex(); /* Because pFile->pInode is shared across threads */
         4900  +        unixShmNode *pShmNode = pFile->pInode->pShmNode;
         4901  +        if( pShmNode && !pShmNode->isReadonly ){
         4902  +          struct stat sStat;
         4903  +          sqlite3_mutex_enter(pShmNode->mutex);
         4904  +          
         4905  +          if( pShmNode->h>=0 && !osFstat(pShmNode->h, &sStat) ){
         4906  +            unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
         4907  +            if( size>0 ){
         4908  +              bzero(pShmNode->apRegion[0], size);
         4909  +              sqlite3_mutex_leave(pShmNode->mutex);
         4910  +              unixLeaveMutex();
         4911  +              continue;
         4912  +            }
         4913  +          }
         4914  +          sqlite3_mutex_leave(pShmNode->mutex);
         4915  +        }
         4916  +        unixLeaveMutex();
         4917  +      }
         4918  +      jLen = strlcpy(&jPath[zLen], extensions[j], 9);
         4919  +      if( jLen < 9 ){
         4920  +        int jflags = (j<2) ? O_TRUNC : O_RDWR;
         4921  +        int jfd = open(jPath, jflags);
         4922  +        if( jfd==(-1) ){
         4923  +          if( errno!=ENOENT ){
         4924  +            perror(jPath);
         4925  +          }
         4926  +        } else {
         4927  +          if( j==2 ){
         4928  +            struct stat sStat;
         4929  +            if( !osFstat(jfd, &sStat) ){
         4930  +              unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
         4931  +              if( size>0 ){
         4932  +                uint32_t zero = 0;
         4933  +                pwrite(jfd, &zero, (size_t)size, 0);
         4934  +              }
         4935  +            }
         4936  +          }
         4937  +          fsync(jfd);
         4938  +          close(jfd);
         4939  +        }
         4940  +      }
         4941  +    }
         4942  +  }
         4943  +  return SQLITE_OK;
         4944  +}
         4945  +
         4946  +static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
         4947  +  sqlite3_file *id = (sqlite3_file *)pFile;
         4948  +  int rc = SQLITE_OK;
         4949  +  void *pLock = NULL;
         4950  +  int flags = 0;
         4951  +  int corruptFileLock = 0;
         4952  +  int isCorrupt = 0;
         4953  +    
         4954  +#if SQLITE_ENABLE_DATA_PROTECTION
         4955  +  flags |= pFile->protFlags;
         4956  +#endif
         4957  +#if SQLITE_ENABLE_LOCKING_STYLE
         4958  +  if( isProxyLockingMode(pFile) ){
         4959  +    flags |= SQLITE_OPEN_AUTOPROXY;
         4960  +  }
         4961  +#endif
         4962  +  
         4963  +  rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
         4964  +  if( rc ){
         4965  +    if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
         4966  +      isCorrupt = 1;
         4967  +      rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
         4968  +    }
         4969  +    if( rc ){
         4970  +      return rc;
         4971  +    }
         4972  +  }
         4973  +  rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
         4974  +  if( rc==SQLITE_OK ){
         4975  +    unixInvalidateSupportFiles(pFile, 0);
         4976  +  }
         4977  +  pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
         4978  +
         4979  +
         4980  +  if( isCorrupt ){
         4981  +    sqlite3demo_superunlock_corrupt(id, corruptFileLock);
         4982  +  }else{
         4983  +    sqlite3demo_superunlock(pLock);
         4984  +  }
         4985  +  return rc;
         4986  +}
         4987  +
         4988  +/*
         4989  + ** Lock locations for shared-memory locks used by WAL mode.
         4990  + */
         4991  +#ifndef SHM_BASE
         4992  +# define SHM_BASE          120
         4993  +# define SHM_WRITE         SHM_BASE
         4994  +# define SHM_CHECKPOINT    (SHM_BASE+1)
         4995  +# define SHM_RECOVER       (SHM_BASE+2)
         4996  +# define SHM_READ_FIRST    (SHM_BASE+3)
         4997  +# define SHM_READ_SIZE     5
         4998  +#endif /* SHM_BASE */
         4999  +
         5000  +/*
         5001  +** This test only works for lock testing on unix/posix VFS.
         5002  +** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
         5003  +*/
         5004  +static int unixLockstatePid(unixFile *pFile, pid_t pid, int *pLockstate){
         5005  +  int hDb;        /* File descriptor for the open database file */
         5006  +  int hShm = -1;  /* File descriptor for WAL shared-memory file */
         5007  +  ssize_t got;    /* Bytes read from header */
         5008  +  int isWal;                 /* True if in WAL mode */
         5009  +  int nLock = 0;             /* Number of locks held */
         5010  +  unsigned char aHdr[100];   /* Database header */
         5011  +  
         5012  +  assert(pLockstate);
         5013  +  
         5014  +  /* make sure we are dealing with a database file */
         5015  +  hDb = pFile->h;
         5016  +  if( hDb<0 ){
         5017  +    *pLockstate = SQLITE_LOCKSTATE_ERROR;
         5018  +    return SQLITE_ERROR;
         5019  +  }
         5020  +  assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN );
         5021  +  got = pread(hDb, aHdr, 100, 0);
         5022  +  if( got<0 ){
         5023  +    *pLockstate = SQLITE_LOCKSTATE_ERROR;
         5024  +    return SQLITE_ERROR;
         5025  +  }
         5026  +  if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){
         5027  +    *pLockstate = SQLITE_LOCKSTATE_NOTADB;
         5028  +    return SQLITE_NOTADB;
         5029  +  }
         5030  +  
         5031  +  /* First check for an exclusive lock */
         5032  +  nLock += unixIsLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE");
         5033  +  isWal = aHdr[18]==2;
         5034  +  if( nLock==0 && isWal==0 ){
         5035  +    /* Rollback mode */
         5036  +    nLock += unixIsLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED");
         5037  +  }
         5038  +  if( nLock==0 && isWal!=0 ){
         5039  +    /* lookup the file descriptor for the shared memory file if we have it open in this process */
         5040  +    unixEnterMutex(); /* Because pFile->pInode is shared across threads */
         5041  +    unixShmNode *pShmNode = pFile->pInode->pShmNode;
         5042  +    if( pShmNode ){
         5043  +      sqlite3_mutex_enter(pShmNode->mutex);
         5044  +      
         5045  +      hShm = pShmNode->h;
         5046  +      if( hShm >= 0){
         5047  +        if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
         5048  +           unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
         5049  +          nLock = 1;
         5050  +        }
         5051  +      }
         5052  +      
         5053  +      sqlite3_mutex_leave(pShmNode->mutex);
         5054  +    } 
         5055  +    
         5056  +    if( hShm<0 ){
         5057  +      /* the shared memory file isn't open in this process space, open our own FD */
         5058  +      char zShm[MAXPATHLEN];
         5059  +      
         5060  +      /* WAL mode */
         5061  +      strlcpy(zShm, pFile->zPath, MAXPATHLEN);
         5062  +      strlcat(zShm, "-shm", MAXPATHLEN);
         5063  +      hShm = open(zShm, O_RDONLY, 0);
         5064  +      if( hShm<0 ){
         5065  +        *pLockstate = SQLITE_LOCKSTATE_OFF;
         5066  +        unixLeaveMutex();
         5067  +        return SQLITE_OK;
         5068  +      }
         5069  +      if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
         5070  +         unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
         5071  +        nLock = 1;
         5072  +      }
         5073  +      close(hShm);
         5074  +    }
         5075  +    unixLeaveMutex();
         5076  +  }
         5077  +  if( nLock>0 ){
         5078  +    *pLockstate = SQLITE_LOCKSTATE_ON;
         5079  +  } else {
         5080  +    *pLockstate = SQLITE_LOCKSTATE_OFF;
         5081  +  }
         5082  +  return SQLITE_OK;
         5083  +}
         5084  +
         5085  +#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
         5086  +
         5087  +
  4849   5088   
  4850   5089   /*
  4851   5090   ** Here ends the implementation of all sqlite3_file methods.
  4852   5091   **
  4853   5092   ********************** End sqlite3_file Methods *******************************
  4854   5093   ******************************************************************************/
  4855   5094   

Changes to src/os_win.c.

    98     98   ** portability layer.
    99     99   */
   100    100   typedef struct winFile winFile;
   101    101   struct winFile {
   102    102     const sqlite3_io_methods *pMethod; /*** Must be first ***/
   103    103     sqlite3_vfs *pVfs;      /* The VFS used to open this file */
   104    104     HANDLE h;               /* Handle for accessing the file */
   105         -  unsigned char locktype; /* Type of lock currently held on this file */
          105  +  u8 locktype;            /* Type of lock currently held on this file */
   106    106     short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
          107  +  u8 bPersistWal;         /* True to persist WAL files */
   107    108     DWORD lastErrno;        /* The Windows errno from the last I/O error */
   108    109     DWORD sectorSize;       /* Sector size of the device file is on */
   109    110     winShm *pShm;           /* Instance of shared memory on this file */
   110    111     const char *zPath;      /* Full pathname of this file */
   111    112     int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
   112    113   #if SQLITE_OS_WINCE
   113    114     WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
................................................................................
  1272   1273     return rc;
  1273   1274   }
  1274   1275   
  1275   1276   /*
  1276   1277   ** Control and query of the open file handle.
  1277   1278   */
  1278   1279   static int winFileControl(sqlite3_file *id, int op, void *pArg){
         1280  +  winFile *pFile = (winFile*)id;
  1279   1281     switch( op ){
  1280   1282       case SQLITE_FCNTL_LOCKSTATE: {
  1281         -      *(int*)pArg = ((winFile*)id)->locktype;
         1283  +      *(int*)pArg = pFile->locktype;
  1282   1284         return SQLITE_OK;
  1283   1285       }
  1284   1286       case SQLITE_LAST_ERRNO: {
  1285         -      *(int*)pArg = (int)((winFile*)id)->lastErrno;
         1287  +      *(int*)pArg = (int)pFile->lastErrno;
  1286   1288         return SQLITE_OK;
  1287   1289       }
  1288   1290       case SQLITE_FCNTL_CHUNK_SIZE: {
  1289         -      ((winFile*)id)->szChunk = *(int *)pArg;
         1291  +      pFile->szChunk = *(int *)pArg;
  1290   1292         return SQLITE_OK;
  1291   1293       }
  1292   1294       case SQLITE_FCNTL_SIZE_HINT: {
  1293   1295         sqlite3_int64 sz = *(sqlite3_int64*)pArg;
  1294   1296         SimulateIOErrorBenign(1);
  1295   1297         winTruncate(id, sz);
  1296   1298         SimulateIOErrorBenign(0);
  1297   1299         return SQLITE_OK;
         1300  +    }
         1301  +    case SQLITE_FCNTL_PERSIST_WAL: {
         1302  +      int bPersist = *(int*)pArg;
         1303  +      if( bPersist<0 ){
         1304  +        *(int*)pArg = pFile->bPersistWal;
         1305  +      }else{
         1306  +        pFile->bPersistWal = bPersist!=0;
         1307  +      }
         1308  +      return SQLITE_OK;
  1298   1309       }
  1299   1310       case SQLITE_FCNTL_SYNC_OMITTED: {
  1300   1311         return SQLITE_OK;
  1301   1312       }
  1302   1313     }
  1303   1314     return SQLITE_NOTFOUND;
  1304   1315   }

Changes to src/pager.c.

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

Changes to src/sqlite.h.in.

   733    733   ** when the database connection has [PRAGMA synchronous] set to OFF.)^
   734    734   ** Some specialized VFSes need this signal in order to operate correctly
   735    735   ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
   736    736   ** VFSes do not need this signal and should silently ignore this opcode.
   737    737   ** Applications should not call [sqlite3_file_control()] with this
   738    738   ** opcode as doing so may disrupt the operation of the specialized VFSes
   739    739   ** that do require it.  
          740  +**
          741  +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
          742  +** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
          743  +** write ahead log and shared memory files used for transaction control
          744  +** are automatically deleted when the latest connection to the database
          745  +** closes.  Setting persistent WAL mode causes those files to persist after
          746  +** close.  Persisting the files is useful when other processes that do not
          747  +** have write permission on the directory containing the database file want
          748  +** to read the database file, as the WAL and shared memory files must exist
          749  +** in order for the database to be readable.  The fourth parameter to
          750  +** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
          751  +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
          752  +** WAL mode.  If the integer is -1, then it is overwritten with the current
          753  +** WAL persistence setting.
          754  +**
   740    755   */
   741         -#define SQLITE_FCNTL_LOCKSTATE        1
   742         -#define SQLITE_GET_LOCKPROXYFILE      2
   743         -#define SQLITE_SET_LOCKPROXYFILE      3
   744         -#define SQLITE_LAST_ERRNO             4
   745         -#define SQLITE_FCNTL_SIZE_HINT        5
   746         -#define SQLITE_FCNTL_CHUNK_SIZE       6
   747         -#define SQLITE_FCNTL_FILE_POINTER     7
   748         -#define SQLITE_FCNTL_SYNC_OMITTED     8
   749         -
          756  +#define SQLITE_FCNTL_LOCKSTATE          1
          757  +#define SQLITE_FCNTL_GET_LOCKPROXYFILE  2
          758  +#define SQLITE_FCNTL_SET_LOCKPROXYFILE  3
          759  +#define SQLITE_FCNTL_LAST_ERRNO         4
          760  +#define SQLITE_FCNTL_SIZE_HINT          5
          761  +#define SQLITE_FCNTL_CHUNK_SIZE         6
          762  +#define SQLITE_FCNTL_FILE_POINTER       7
          763  +#define SQLITE_FCNTL_SYNC_OMITTED       8
          764  +#define SQLITE_FCNTL_PERSIST_WAL       10
          765  +/* deprecated names */
          766  +#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
          767  +#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
          768  +#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
   750    769   
   751    770   /*
   752    771   ** CAPI3REF: Mutex Handle
   753    772   **
   754    773   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   755    774   ** abstract type for a mutex object.  The SQLite core never looks
   756    775   ** at the internal representation of an [sqlite3_mutex].  It only

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.

  3246   3246   #endif
  3247   3247   #define MEMTYPE_HEAP       0x01  /* General heap allocations */
  3248   3248   #define MEMTYPE_LOOKASIDE  0x02  /* Might have been lookaside memory */
  3249   3249   #define MEMTYPE_SCRATCH    0x04  /* Scratch allocations */
  3250   3250   #define MEMTYPE_PCACHE     0x08  /* Page cache allocations */
  3251   3251   #define MEMTYPE_DB         0x10  /* Uses sqlite3DbMalloc, not sqlite_malloc */
  3252   3252   
         3253  +
         3254  +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
         3255  +
         3256  +/*
         3257  +** An instance of the following structure is used to hold the process ID
         3258  +** and return-by-reference lockstate value.  The SQLITE_FCNTL_LOCKSTATE_PID
         3259  +** requires the 4th argument to sqlite3_file_control to be a pointer to an
         3260  +** instance of LockstatePID initialized with a LockstatePID.pid value equal
         3261  +** to a process ID to be tested, or the special value SQLITE_LOCKSTATE_ANYPID
         3262  +** The Lockstate.state value is always set to one of the following values
         3263  +** when sqlite3_file_control returns:
         3264  +** 
         3265  +**   SQLITE_LOCKSTATE_OFF    no active sqlite file locks match the specified pid
         3266  +**   SQLITE_LOCKSTATE_ON     active sqlite file locks match the specified pid
         3267  +**   SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file
         3268  +**   SQLITE_LOCKSTATE_ERROR  path was not vaild or was unreadable
         3269  +*/
         3270  +typedef struct LockstatePID LockstatePID;
         3271  +struct LockstatePID {
         3272  +  pid_t pid;                 /* Process ID to test */
         3273  +  int state;                 /* The state of the lock (return value) */
         3274  +};
         3275  +
         3276  +#endif
         3277  +
  3253   3278   #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   
................................................................................
  5278   5282     }
  5279   5283   #else
  5280   5284     Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
  5281   5285   #endif
  5282   5286     
  5283   5287     return TCL_OK;  
  5284   5288   }
         5289  +
         5290  +/*
         5291  +** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
         5292  +**
         5293  +** This TCL command runs the sqlite3_file_control interface with
         5294  +** the SQLITE_FCNTL_PERSIST_WAL opcode.
         5295  +*/
         5296  +static int file_control_persist_wal(
         5297  +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
         5298  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         5299  +  int objc,              /* Number of arguments */
         5300  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         5301  +){
         5302  +  sqlite3 *db;
         5303  +  int rc;
         5304  +  int bPersist;
         5305  +  char z[100];
         5306  +  
         5307  +  if( objc!=3 ){
         5308  +    Tcl_AppendResult(interp, "wrong # args: should be \"",
         5309  +                     Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
         5310  +    return TCL_ERROR;
         5311  +  }
         5312  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         5313  +    return TCL_ERROR;
         5314  +  }
         5315  +  if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
         5316  +  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
         5317  +  sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
         5318  +  Tcl_AppendResult(interp, z, (char*)0);
         5319  +  return TCL_OK;  
         5320  +}
         5321  +
  5285   5322   
  5286   5323   /*
  5287   5324   ** tclcmd:   sqlite3_vfs_list
  5288   5325   **
  5289   5326   **   Return a tcl list containing the names of all registered vfs's.
  5290   5327   */
  5291   5328   static int vfs_list(
................................................................................
  5990   6027        { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
  5991   6028   #ifdef __APPLE__
  5992   6029        { "file_control_truncate_test", file_control_truncate_test,  0   },
  5993   6030        { "file_control_replace_test", file_control_replace_test,  0   },
  5994   6031   #endif 
  5995   6032        { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  5996   6033        { "file_control_sizehint_test", file_control_sizehint_test,  0   },
         6034  +     { "file_control_persist_wal",    file_control_persist_wal,     0   },
  5997   6035        { "sqlite3_vfs_list",           vfs_list,     0   },
  5998   6036        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  5999   6037        { "path_is_local",              path_is_local,  0   },
  6000   6038        { "path_is_dos",                path_is_dos,  0   },
  6001   6039   
  6002   6040        /* Functions from os.h */
  6003   6041   #ifndef SQLITE_OMIT_UTF16

Changes to src/vdbeaux.c.

  1504   1504     if( pParse->explain && nMem<10 ){
  1505   1505       nMem = 10;
  1506   1506     }
  1507   1507     memset(zCsr, 0, zEnd-zCsr);
  1508   1508     zCsr += (zCsr - (u8*)0)&7;
  1509   1509     assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
  1510   1510   
         1511  +  p->expired = 0;
         1512  +  
  1511   1513     /* Memory for registers, parameters, cursor, etc, is allocated in two
  1512   1514     ** passes.  On the first pass, we try to reuse unused space at the 
  1513   1515     ** end of the opcode array.  If we are unable to satisfy all memory
  1514   1516     ** requirements by reusing the opcode array tail, then the second
  1515   1517     ** pass will fill in the rest using a fresh allocation.  
  1516   1518     **
  1517   1519     ** 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);
................................................................................
  1801   1805       ** the database. In this case checkpoint the database and unlink both
  1802   1806       ** the wal and wal-index files.
  1803   1807       **
  1804   1808       ** The EXCLUSIVE lock is not released before returning.
  1805   1809       */
  1806   1810       rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
  1807   1811       if( rc==SQLITE_OK ){
         1812  +      int bPersistWal = -1;
  1808   1813         if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
  1809   1814           pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
  1810   1815         }
  1811   1816         rc = sqlite3WalCheckpoint(
  1812   1817             pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
  1813   1818         );
  1814         -      if( rc==SQLITE_OK ){
         1819  +      sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
         1820  +      if( rc==SQLITE_OK && bPersistWal!=1 ){
  1815   1821           isDelete = 1;
  1816   1822         }
  1817   1823       }
  1818   1824   
  1819   1825       walIndexClose(pWal, isDelete);
  1820   1826       sqlite3OsClose(pWal->pWalFd);
  1821   1827       if( isDelete ){
................................................................................
  1860   1866     **
  1861   1867     ** There are two copies of the header at the beginning of the wal-index.
  1862   1868     ** When reading, read [0] first then [1].  Writes are in the reverse order.
  1863   1869     ** Memory barriers are used to prevent the compiler or the hardware from
  1864   1870     ** reordering the reads and writes.
  1865   1871     */
  1866   1872     aHdr = walIndexHdr(pWal);
         1873  +  if( aHdr==NULL ){
         1874  +    return 1; /* Shouldn't be getting NULL from walIndexHdr, but we are */
         1875  +  }
  1867   1876     memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
  1868   1877     walShmBarrier(pWal);
  1869   1878     memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
  1870   1879   
  1871   1880     if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
  1872   1881       return 1;   /* Dirty read */
  1873   1882     }  
................................................................................
  2044   2053     ** is more of a scheduler yield than an actual delay.  But on the 10th
  2045   2054     ** an subsequent retries, the delays start becoming longer and longer, 
  2046   2055     ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
  2047   2056     ** The total delay time before giving up is less than 1 second.
  2048   2057     */
  2049   2058     if( cnt>5 ){
  2050   2059       int nDelay = 1;                      /* Pause time in microseconds */
  2051         -    if( cnt>100 ){
         2060  +    if( cnt>500 ){
  2052   2061         VVA_ONLY( pWal->lockError = 1; )
  2053   2062         return SQLITE_PROTOCOL;
  2054   2063       }
  2055   2064       if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
  2056   2065       sqlite3OsSleep(pWal->pVfs, nDelay);
  2057   2066     }
  2058   2067   

Added test/walpersist.test.

            1  +# 2011 July 26
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# This file contains tests for using WAL with persistent WAL file mode.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +source $testdir/lock_common.tcl
           18  +set ::testprefix walpersist
           19  +
           20  +do_test walpersist-1.0 {
           21  +  db eval {
           22  +    PRAGMA journal_mode=WAL;
           23  +    CREATE TABLE t1(a);
           24  +    INSERT INTO t1 VALUES(randomblob(5000));
           25  +  }
           26  +  file exists test.db-wal
           27  +} {1}
           28  +do_test walpersist-1.1 {
           29  +  file exists test.db-shm
           30  +} {1}
           31  +do_test walpersist-1.2 {
           32  +  db close
           33  +  list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
           34  +} {1 0 0}
           35  +do_test walpersist-1.3 {
           36  +  sqlite3 db test.db
           37  +  db eval {SELECT length(a) FROM t1}
           38  +} {5000}
           39  +do_test walpersist-1.4 {
           40  +  list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
           41  +} {1 1 1}
           42  +do_test walpersist-1.5 {
           43  +  file_control_persist_wal db -1
           44  +} {0 0}
           45  +do_test walpersist-1.6 {
           46  +  file_control_persist_wal db 1
           47  +} {0 1}
           48  +do_test walpersist-1.7 {
           49  +  file_control_persist_wal db -1
           50  +} {0 1}
           51  +do_test walpersist-1.8 {
           52  +  file_control_persist_wal db 0
           53  +} {0 0}
           54  +do_test walpersist-1.9 {
           55  +  file_control_persist_wal db -1
           56  +} {0 0}
           57  +do_test walpersist-1.10 {
           58  +  file_control_persist_wal db 1
           59  +} {0 1}
           60  +do_test walpersist-1.11 {
           61  +  db close
           62  +  list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
           63  +} {1 1 1}
           64  +
           65  +  
           66  +
           67  +
           68  +finish_test