/ Check-in [3934b004]
Login

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

Overview
Comment:Merge the unix-excl VFS into the trunk. This merge also adds the -vfs option to the command-line shell.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3934b004e93852c89b937ec20431de96a2e99440
User & Date: drh 2011-03-14 13:54:01
Context
2011-03-15
02:55
Fix cut-and-paste typo in debugging print statement in winMutexTry(). check-in: def98fd2 user: shaneh tags: trunk
2011-03-14
13:54
Merge the unix-excl VFS into the trunk. This merge also adds the -vfs option to the command-line shell. check-in: 3934b004 user: drh tags: trunk
2011-03-12
18:10
In the "unix-excl" VFS, use the heap for shared memory, since only a single process is able to read or write the database. Closed-Leaf check-in: a05a6d40 user: drh tags: unix-excl
04:58
More tests for SQLITE_OMIT_UNIQUE_ENFORCEMENT and minor change to implementation. check-in: b8699943 user: shaneh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

   202    202   typedef struct unixFile unixFile;
   203    203   struct unixFile {
   204    204     sqlite3_io_methods const *pMethod;  /* Always the first entry */
   205    205     unixInodeInfo *pInode;              /* Info about locks on this inode */
   206    206     int h;                              /* The file descriptor */
   207    207     int dirfd;                          /* File descriptor for the directory */
   208    208     unsigned char eFileLock;            /* The type of lock held on this fd */
          209  +  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
   209    210     int lastErrno;                      /* The unix errno from last I/O error */
   210    211     void *lockingContext;               /* Locking style specific state */
   211    212     UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
   212    213     const char *zPath;                  /* Name of the file */
   213    214     unixShm *pShm;                      /* Shared memory segment information */
   214    215     int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
   215    216   #if SQLITE_ENABLE_LOCKING_STYLE
................................................................................
   238    239     /* In test mode, increase the size of this structure a bit so that 
   239    240     ** it is larger than the struct CrashFile defined in test6.c.
   240    241     */
   241    242     char aPadding[32];
   242    243   #endif
   243    244   };
   244    245   
          246  +/*
          247  +** Allowed values for the unixFile.ctrlFlags bitmask:
          248  +*/
          249  +#define UNIXFILE_EXCL   0x01     /* Connections from one process only */
          250  +
   245    251   /*
   246    252   ** Include code that is common to all os_*.c files
   247    253   */
   248    254   #include "os_common.h"
   249    255   
   250    256   /*
   251    257   ** Define various macros that are missing from some systems.
................................................................................
   883    889   ** A single inode can have multiple file descriptors, so each unixFile
   884    890   ** structure contains a pointer to an instance of this object and this
   885    891   ** object keeps a count of the number of unixFile pointing to it.
   886    892   */
   887    893   struct unixInodeInfo {
   888    894     struct unixFileId fileId;       /* The lookup key */
   889    895     int nShared;                    /* Number of SHARED locks held */
   890         -  int eFileLock;                  /* One of SHARED_LOCK, RESERVED_LOCK etc. */
          896  +  unsigned char eFileLock;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
          897  +  unsigned char bProcessLock;     /* An exclusive process lock is held */
   891    898     int nRef;                       /* Number of pointers to this structure */
   892    899     unixShmNode *pShmNode;          /* Shared memory associated with this inode */
   893    900     int nLock;                      /* Number of outstanding file locks */
   894    901     UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
   895    902     unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
   896    903     unixInodeInfo *pPrev;           /*    .... doubly linked */
   897    904   #if defined(SQLITE_ENABLE_LOCKING_STYLE)
................................................................................
  1154   1161     if( pFile->pInode->eFileLock>SHARED_LOCK ){
  1155   1162       reserved = 1;
  1156   1163     }
  1157   1164   
  1158   1165     /* Otherwise see if some other process holds it.
  1159   1166     */
  1160   1167   #ifndef __DJGPP__
  1161         -  if( !reserved ){
         1168  +  if( !reserved && !pFile->pInode->bProcessLock ){
  1162   1169       struct flock lock;
  1163   1170       lock.l_whence = SEEK_SET;
  1164   1171       lock.l_start = RESERVED_BYTE;
  1165   1172       lock.l_len = 1;
  1166   1173       lock.l_type = F_WRLCK;
  1167   1174       if (-1 == osFcntl(pFile->h, F_GETLK, &lock)) {
  1168   1175         int tErrno = errno;
................................................................................
  1176   1183     
  1177   1184     unixLeaveMutex();
  1178   1185     OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
  1179   1186   
  1180   1187     *pResOut = reserved;
  1181   1188     return rc;
  1182   1189   }
         1190  +
         1191  +/*
         1192  +** Attempt to set a system-lock on the file pFile.  The lock is 
         1193  +** described by pLock.
         1194  +**
         1195  +** If the pFile was opened from unix-excl, then the only lock ever
         1196  +** obtained is an exclusive lock, and it is obtained exactly once
         1197  +** the first time any lock is attempted.  All subsequent system locking
         1198  +** operations become no-ops.  Locking operations still happen internally,
         1199  +** in order to coordinate access between separate database connections
         1200  +** within this process, but all of that is handled in memory and the
         1201  +** operating system does not participate.
         1202  +*/
         1203  +static int unixFileLock(unixFile *pFile, struct flock *pLock){
         1204  +  int rc;
         1205  +  unixInodeInfo *pInode = pFile->pInode;
         1206  +  assert( unixMutexHeld() );
         1207  +  assert( pInode!=0 );
         1208  +  if( (pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock ){
         1209  +    if( pInode->bProcessLock==0 ){
         1210  +      struct flock lock;
         1211  +      assert( pInode->nLock==0 );
         1212  +      lock.l_whence = SEEK_SET;
         1213  +      lock.l_start = SHARED_FIRST;
         1214  +      lock.l_len = SHARED_SIZE;
         1215  +      lock.l_type = F_WRLCK;
         1216  +      rc = osFcntl(pFile->h, F_SETLK, &lock);
         1217  +      if( rc<0 ) return rc;
         1218  +      pInode->bProcessLock = 1;
         1219  +      pInode->nLock++;
         1220  +    }else{
         1221  +      rc = 0;
         1222  +    }
         1223  +  }else{
         1224  +    rc = osFcntl(pFile->h, F_SETLK, pLock);
         1225  +  }
         1226  +  return rc;
         1227  +}
  1183   1228   
  1184   1229   /*
  1185   1230   ** Lock the file with the lock specified by parameter eFileLock - one
  1186   1231   ** of the following:
  1187   1232   **
  1188   1233   **     (1) SHARED_LOCK
  1189   1234   **     (2) RESERVED_LOCK
................................................................................
  1313   1358     lock.l_len = 1L;
  1314   1359     lock.l_whence = SEEK_SET;
  1315   1360     if( eFileLock==SHARED_LOCK 
  1316   1361         || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  1317   1362     ){
  1318   1363       lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
  1319   1364       lock.l_start = PENDING_BYTE;
  1320         -    s = osFcntl(pFile->h, F_SETLK, &lock);
         1365  +    s = unixFileLock(pFile, &lock);
  1321   1366       if( s==(-1) ){
  1322   1367         tErrno = errno;
  1323   1368         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1324   1369         if( IS_LOCK_ERROR(rc) ){
  1325   1370           pFile->lastErrno = tErrno;
  1326   1371         }
  1327   1372         goto end_lock;
................................................................................
  1335   1380     if( eFileLock==SHARED_LOCK ){
  1336   1381       assert( pInode->nShared==0 );
  1337   1382       assert( pInode->eFileLock==0 );
  1338   1383   
  1339   1384       /* Now get the read-lock */
  1340   1385       lock.l_start = SHARED_FIRST;
  1341   1386       lock.l_len = SHARED_SIZE;
  1342         -    if( (s = osFcntl(pFile->h, F_SETLK, &lock))==(-1) ){
         1387  +    if( (s = unixFileLock(pFile, &lock))==(-1) ){
  1343   1388         tErrno = errno;
  1344   1389       }
  1345   1390       /* Drop the temporary PENDING lock */
  1346   1391       lock.l_start = PENDING_BYTE;
  1347   1392       lock.l_len = 1L;
  1348   1393       lock.l_type = F_UNLCK;
  1349         -    if( osFcntl(pFile->h, F_SETLK, &lock)!=0 ){
         1394  +    if( unixFileLock(pFile, &lock)!=0 ){
  1350   1395         if( s != -1 ){
  1351   1396           /* This could happen with a network mount */
  1352   1397           tErrno = errno; 
  1353   1398           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
  1354   1399           if( IS_LOCK_ERROR(rc) ){
  1355   1400             pFile->lastErrno = tErrno;
  1356   1401           }
................................................................................
  1385   1430         case EXCLUSIVE_LOCK:
  1386   1431           lock.l_start = SHARED_FIRST;
  1387   1432           lock.l_len = SHARED_SIZE;
  1388   1433           break;
  1389   1434         default:
  1390   1435           assert(0);
  1391   1436       }
  1392         -    s = osFcntl(pFile->h, F_SETLK, &lock);
         1437  +    s = unixFileLock(pFile, &lock);
  1393   1438       if( s==(-1) ){
  1394   1439         tErrno = errno;
  1395   1440         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1396   1441         if( IS_LOCK_ERROR(rc) ){
  1397   1442           pFile->lastErrno = tErrno;
  1398   1443         }
  1399   1444       }
................................................................................
  1454   1499   ** 
  1455   1500   ** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
  1456   1501   ** the byte range is divided into 2 parts and the first part is unlocked then
  1457   1502   ** set to a read lock, then the other part is simply unlocked.  This works 
  1458   1503   ** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to 
  1459   1504   ** remove the write lock on a region when a read lock is set.
  1460   1505   */
  1461         -static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
         1506  +static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
  1462   1507     unixFile *pFile = (unixFile*)id;
  1463   1508     unixInodeInfo *pInode;
  1464   1509     struct flock lock;
  1465   1510     int rc = SQLITE_OK;
  1466   1511     int h;
  1467   1512     int tErrno;                      /* Error code from system call errors */
  1468   1513   
................................................................................
  1521   1566         if( handleNFSUnlock ){
  1522   1567           off_t divSize = SHARED_SIZE - 1;
  1523   1568           
  1524   1569           lock.l_type = F_UNLCK;
  1525   1570           lock.l_whence = SEEK_SET;
  1526   1571           lock.l_start = SHARED_FIRST;
  1527   1572           lock.l_len = divSize;
  1528         -        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
         1573  +        if( unixFileLock(pFile,, &lock)==(-1) ){
  1529   1574             tErrno = errno;
  1530   1575             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1531   1576             if( IS_LOCK_ERROR(rc) ){
  1532   1577               pFile->lastErrno = tErrno;
  1533   1578             }
  1534   1579             goto end_unlock;
  1535   1580           }
  1536   1581           lock.l_type = F_RDLCK;
  1537   1582           lock.l_whence = SEEK_SET;
  1538   1583           lock.l_start = SHARED_FIRST;
  1539   1584           lock.l_len = divSize;
  1540         -        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
         1585  +        if( unixFileLock(pFile, &lock)==(-1) ){
  1541   1586             tErrno = errno;
  1542   1587             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1543   1588             if( IS_LOCK_ERROR(rc) ){
  1544   1589               pFile->lastErrno = tErrno;
  1545   1590             }
  1546   1591             goto end_unlock;
  1547   1592           }
  1548   1593           lock.l_type = F_UNLCK;
  1549   1594           lock.l_whence = SEEK_SET;
  1550   1595           lock.l_start = SHARED_FIRST+divSize;
  1551   1596           lock.l_len = SHARED_SIZE-divSize;
  1552         -        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
         1597  +        if( unixFileLock(pFile, &lock)==(-1) ){
  1553   1598             tErrno = errno;
  1554   1599             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1555   1600             if( IS_LOCK_ERROR(rc) ){
  1556   1601               pFile->lastErrno = tErrno;
  1557   1602             }
  1558   1603             goto end_unlock;
  1559   1604           }
................................................................................
  1560   1605         }else
  1561   1606   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  1562   1607         {
  1563   1608           lock.l_type = F_RDLCK;
  1564   1609           lock.l_whence = SEEK_SET;
  1565   1610           lock.l_start = SHARED_FIRST;
  1566   1611           lock.l_len = SHARED_SIZE;
  1567         -        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
         1612  +        if( unixFileLock(pFile, &lock)==(-1) ){
  1568   1613             tErrno = errno;
  1569   1614             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1570   1615             if( IS_LOCK_ERROR(rc) ){
  1571   1616               pFile->lastErrno = tErrno;
  1572   1617             }
  1573   1618             goto end_unlock;
  1574   1619           }
  1575   1620         }
  1576   1621       }
  1577   1622       lock.l_type = F_UNLCK;
  1578   1623       lock.l_whence = SEEK_SET;
  1579   1624       lock.l_start = PENDING_BYTE;
  1580   1625       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  1581         -    if( osFcntl(h, F_SETLK, &lock)!=(-1) ){
         1626  +    if( unixFileLock(pFile, &lock)!=(-1) ){
  1582   1627         pInode->eFileLock = SHARED_LOCK;
  1583   1628       }else{
  1584   1629         tErrno = errno;
  1585   1630         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1586   1631         if( IS_LOCK_ERROR(rc) ){
  1587   1632           pFile->lastErrno = tErrno;
  1588   1633         }
................................................................................
  1598   1643       if( pInode->nShared==0 ){
  1599   1644         lock.l_type = F_UNLCK;
  1600   1645         lock.l_whence = SEEK_SET;
  1601   1646         lock.l_start = lock.l_len = 0L;
  1602   1647         SimulateIOErrorBenign(1);
  1603   1648         SimulateIOError( h=(-1) )
  1604   1649         SimulateIOErrorBenign(0);
  1605         -      if( osFcntl(h, F_SETLK, &lock)!=(-1) ){
         1650  +      if( unixFileLock(pFile, &lock)!=(-1) ){
  1606   1651           pInode->eFileLock = NO_LOCK;
  1607   1652         }else{
  1608   1653           tErrno = errno;
  1609   1654           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1610   1655           if( IS_LOCK_ERROR(rc) ){
  1611   1656             pFile->lastErrno = tErrno;
  1612   1657           }
................................................................................
  1636   1681   ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  1637   1682   ** must be either NO_LOCK or SHARED_LOCK.
  1638   1683   **
  1639   1684   ** If the locking level of the file descriptor is already at or below
  1640   1685   ** the requested locking level, this routine is a no-op.
  1641   1686   */
  1642   1687   static int unixUnlock(sqlite3_file *id, int eFileLock){
  1643         -  return _posixUnlock(id, eFileLock, 0);
         1688  +  return posixUnlock(id, eFileLock, 0);
  1644   1689   }
  1645   1690   
  1646   1691   /*
  1647   1692   ** This function performs the parts of the "close file" operation 
  1648   1693   ** common to all locking schemes. It closes the directory and file
  1649   1694   ** handles, if they are valid, and sets all fields of the unixFile
  1650   1695   ** structure to 0.
................................................................................
  1686   1731   */
  1687   1732   static int unixClose(sqlite3_file *id){
  1688   1733     int rc = SQLITE_OK;
  1689   1734     if( id ){
  1690   1735       unixFile *pFile = (unixFile *)id;
  1691   1736       unixUnlock(id, NO_LOCK);
  1692   1737       unixEnterMutex();
         1738  +    assert( pFile->pInode==0 || pFile->pInode->nLock>0
         1739  +            || pFile->pInode->bProcessLock==0 );
  1693   1740       if( pFile->pInode && pFile->pInode->nLock ){
  1694   1741         /* If there are outstanding locks, do not actually close the file just
  1695   1742         ** yet because that would clear those locks.  Instead, add the file
  1696   1743         ** descriptor to pInode->pUnused list.  It will be automatically closed 
  1697   1744         ** when the last lock is cleared.
  1698   1745         */
  1699   1746         setPendingFd(pFile);
................................................................................
  2817   2864    ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  2818   2865    ** must be either NO_LOCK or SHARED_LOCK.
  2819   2866    **
  2820   2867    ** If the locking level of the file descriptor is already at or below
  2821   2868    ** the requested locking level, this routine is a no-op.
  2822   2869    */
  2823   2870   static int nfsUnlock(sqlite3_file *id, int eFileLock){
  2824         -  return _posixUnlock(id, eFileLock, 1);
         2871  +  return posixUnlock(id, eFileLock, 1);
  2825   2872   }
  2826   2873   
  2827   2874   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  2828   2875   /*
  2829   2876   ** The code above is the NFS lock implementation.  The code is specific
  2830   2877   ** to MacOSX and does not work on other unix platforms.  No alternative
  2831   2878   ** is available.  
................................................................................
  3514   3561   
  3515   3562     /* Shared locks never span more than one byte */
  3516   3563     assert( n==1 || lockType!=F_RDLCK );
  3517   3564   
  3518   3565     /* Locks are within range */
  3519   3566     assert( n>=1 && n<SQLITE_SHM_NLOCK );
  3520   3567   
  3521         -  /* Initialize the locking parameters */
  3522         -  memset(&f, 0, sizeof(f));
  3523         -  f.l_type = lockType;
  3524         -  f.l_whence = SEEK_SET;
  3525         -  f.l_start = ofst;
  3526         -  f.l_len = n;
         3568  +  if( pShmNode->h>=0 ){
         3569  +    /* Initialize the locking parameters */
         3570  +    memset(&f, 0, sizeof(f));
         3571  +    f.l_type = lockType;
         3572  +    f.l_whence = SEEK_SET;
         3573  +    f.l_start = ofst;
         3574  +    f.l_len = n;
  3527   3575   
  3528         -  rc = osFcntl(pShmNode->h, F_SETLK, &f);
  3529         -  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
         3576  +    rc = osFcntl(pShmNode->h, F_SETLK, &f);
         3577  +    rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
         3578  +  }
  3530   3579   
  3531   3580     /* Update the global lock state and do debug tracing */
  3532   3581   #ifdef SQLITE_DEBUG
  3533   3582     { u16 mask;
  3534   3583     OSTRACE(("SHM-LOCK "));
  3535   3584     mask = (1<<(ofst+n)) - (1<<ofst);
  3536   3585     if( rc==SQLITE_OK ){
................................................................................
  3577   3626     unixShmNode *p = pFd->pInode->pShmNode;
  3578   3627     assert( unixMutexHeld() );
  3579   3628     if( p && p->nRef==0 ){
  3580   3629       int i;
  3581   3630       assert( p->pInode==pFd->pInode );
  3582   3631       if( p->mutex ) sqlite3_mutex_free(p->mutex);
  3583   3632       for(i=0; i<p->nRegion; i++){
  3584         -      munmap(p->apRegion[i], p->szRegion);
         3633  +      if( p->h>=0 ){
         3634  +        munmap(p->apRegion[i], p->szRegion);
         3635  +      }else{
         3636  +        sqlite3_free(p->apRegion[i]);
         3637  +      }
  3585   3638       }
  3586   3639       sqlite3_free(p->apRegion);
  3587   3640       if( p->h>=0 ){
  3588   3641         robust_close(pFd, p->h, __LINE__);
  3589   3642         p->h = -1;
  3590   3643       }
  3591   3644       p->pInode->pShmNode = 0;
................................................................................
  3617   3670   ** same database file at the same time, database corruption will likely
  3618   3671   ** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
  3619   3672   ** "unsupported" and may go away in a future SQLite release.
  3620   3673   **
  3621   3674   ** When opening a new shared-memory file, if no other instances of that
  3622   3675   ** file are currently open, in this process or in other processes, then
  3623   3676   ** the file must be truncated to zero length or have its header cleared.
         3677  +**
         3678  +** If the original database file (pDbFd) is using the "unix-excl" VFS
         3679  +** that means that an exclusive lock is held on the database file and
         3680  +** that no other processes are able to read or write the database.  In
         3681  +** that case, we do not really need shared memory.  No shared memory
         3682  +** file is created.  The shared memory will be simulated with heap memory.
  3624   3683   */
  3625   3684   static int unixOpenSharedMemory(unixFile *pDbFd){
  3626   3685     struct unixShm *p = 0;          /* The connection to be opened */
  3627   3686     struct unixShmNode *pShmNode;   /* The underlying mmapped file */
  3628   3687     int rc;                         /* Result code */
  3629   3688     unixInodeInfo *pInode;          /* The inode of fd */
  3630   3689     char *zShmFilename;             /* Name of the file used for SHM */
................................................................................
  3646   3705       struct stat sStat;                 /* fstat() info for database file */
  3647   3706   
  3648   3707       /* Call fstat() to figure out the permissions on the database file. If
  3649   3708       ** a new *-shm file is created, an attempt will be made to create it
  3650   3709       ** with the same permissions. The actual permissions the file is created
  3651   3710       ** with are subject to the current umask setting.
  3652   3711       */
  3653         -    if( osFstat(pDbFd->h, &sStat) ){
         3712  +    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
  3654   3713         rc = SQLITE_IOERR_FSTAT;
  3655   3714         goto shm_open_err;
  3656   3715       }
  3657   3716   
  3658   3717   #ifdef SQLITE_SHM_DIRECTORY
  3659   3718       nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 30;
  3660   3719   #else
................................................................................
  3679   3738       pShmNode->pInode = pDbFd->pInode;
  3680   3739       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  3681   3740       if( pShmNode->mutex==0 ){
  3682   3741         rc = SQLITE_NOMEM;
  3683   3742         goto shm_open_err;
  3684   3743       }
  3685   3744   
  3686         -    pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
  3687         -                             (sStat.st_mode & 0777));
  3688         -    if( pShmNode->h<0 ){
  3689         -      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
  3690         -      goto shm_open_err;
  3691         -    }
  3692         -
  3693         -    /* Check to see if another process is holding the dead-man switch.
  3694         -    ** If not, truncate the file to zero length. 
  3695         -    */
  3696         -    rc = SQLITE_OK;
  3697         -    if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
  3698         -      if( robust_ftruncate(pShmNode->h, 0) ){
  3699         -        rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
  3700         -      }
  3701         -    }
  3702         -    if( rc==SQLITE_OK ){
  3703         -      rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
  3704         -    }
  3705         -    if( rc ) goto shm_open_err;
         3745  +    if( pInode->bProcessLock==0 ){
         3746  +      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
         3747  +                               (sStat.st_mode & 0777));
         3748  +      if( pShmNode->h<0 ){
         3749  +        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
         3750  +        goto shm_open_err;
         3751  +      }
         3752  +  
         3753  +      /* Check to see if another process is holding the dead-man switch.
         3754  +      ** If not, truncate the file to zero length. 
         3755  +      */
         3756  +      rc = SQLITE_OK;
         3757  +      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
         3758  +        if( robust_ftruncate(pShmNode->h, 0) ){
         3759  +          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
         3760  +        }
         3761  +      }
         3762  +      if( rc==SQLITE_OK ){
         3763  +        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
         3764  +      }
         3765  +      if( rc ) goto shm_open_err;
         3766  +    }
  3706   3767     }
  3707   3768   
  3708   3769     /* Make the new connection a child of the unixShmNode */
  3709   3770     p->pShmNode = pShmNode;
  3710   3771   #ifdef SQLITE_DEBUG
  3711   3772     p->id = pShmNode->nextShmId++;
  3712   3773   #endif
................................................................................
  3772   3833       if( rc!=SQLITE_OK ) return rc;
  3773   3834     }
  3774   3835   
  3775   3836     p = pDbFd->pShm;
  3776   3837     pShmNode = p->pShmNode;
  3777   3838     sqlite3_mutex_enter(pShmNode->mutex);
  3778   3839     assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
         3840  +  assert( pShmNode->pInode==pDbFd->pInode );
         3841  +  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
         3842  +  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
  3779   3843   
  3780   3844     if( pShmNode->nRegion<=iRegion ){
  3781   3845       char **apNew;                      /* New apRegion[] array */
  3782   3846       int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
  3783   3847       struct stat sStat;                 /* Used by fstat() */
  3784   3848   
  3785   3849       pShmNode->szRegion = szRegion;
  3786   3850   
  3787         -    /* The requested region is not mapped into this processes address space.
  3788         -    ** Check to see if it has been allocated (i.e. if the wal-index file is
  3789         -    ** large enough to contain the requested region).
  3790         -    */
  3791         -    if( osFstat(pShmNode->h, &sStat) ){
  3792         -      rc = SQLITE_IOERR_SHMSIZE;
  3793         -      goto shmpage_out;
  3794         -    }
  3795         -
  3796         -    if( sStat.st_size<nByte ){
  3797         -      /* The requested memory region does not exist. If bExtend is set to
  3798         -      ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
  3799         -      **
  3800         -      ** Alternatively, if bExtend is true, use ftruncate() to allocate
  3801         -      ** the requested memory region.
         3851  +    if( pShmNode->h>=0 ){
         3852  +      /* The requested region is not mapped into this processes address space.
         3853  +      ** Check to see if it has been allocated (i.e. if the wal-index file is
         3854  +      ** large enough to contain the requested region).
  3802   3855         */
  3803         -      if( !bExtend ) goto shmpage_out;
  3804         -      if( robust_ftruncate(pShmNode->h, nByte) ){
  3805         -        rc = unixLogError(SQLITE_IOERR_SHMSIZE,"ftruncate",pShmNode->zFilename);
         3856  +      if( osFstat(pShmNode->h, &sStat) ){
         3857  +        rc = SQLITE_IOERR_SHMSIZE;
  3806   3858           goto shmpage_out;
  3807   3859         }
         3860  +  
         3861  +      if( sStat.st_size<nByte ){
         3862  +        /* The requested memory region does not exist. If bExtend is set to
         3863  +        ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
         3864  +        **
         3865  +        ** Alternatively, if bExtend is true, use ftruncate() to allocate
         3866  +        ** the requested memory region.
         3867  +        */
         3868  +        if( !bExtend ) goto shmpage_out;
         3869  +        if( robust_ftruncate(pShmNode->h, nByte) ){
         3870  +          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
         3871  +                            pShmNode->zFilename);
         3872  +          goto shmpage_out;
         3873  +        }
         3874  +      }
  3808   3875       }
  3809   3876   
  3810   3877       /* Map the requested memory region into this processes address space. */
  3811   3878       apNew = (char **)sqlite3_realloc(
  3812   3879           pShmNode->apRegion, (iRegion+1)*sizeof(char *)
  3813   3880       );
  3814   3881       if( !apNew ){
  3815   3882         rc = SQLITE_IOERR_NOMEM;
  3816   3883         goto shmpage_out;
  3817   3884       }
  3818   3885       pShmNode->apRegion = apNew;
  3819   3886       while(pShmNode->nRegion<=iRegion){
  3820         -      void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
  3821         -          MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
  3822         -      );
  3823         -      if( pMem==MAP_FAILED ){
  3824         -        rc = SQLITE_IOERR;
  3825         -        goto shmpage_out;
         3887  +      void *pMem;
         3888  +      if( pShmNode->h>=0 ){
         3889  +        pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
         3890  +            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
         3891  +        );
         3892  +        if( pMem==MAP_FAILED ){
         3893  +          rc = SQLITE_IOERR;
         3894  +          goto shmpage_out;
         3895  +        }
         3896  +      }else{
         3897  +        pMem = sqlite3_malloc(szRegion);
         3898  +        if( pMem==0 ){
         3899  +          rc = SQLITE_NOMEM;
         3900  +          goto shmpage_out;
         3901  +        }
         3902  +        memset(pMem, 0, szRegion);
  3826   3903         }
  3827   3904         pShmNode->apRegion[pShmNode->nRegion] = pMem;
  3828   3905         pShmNode->nRegion++;
  3829   3906       }
  3830   3907     }
  3831   3908   
  3832   3909   shmpage_out:
................................................................................
  3865   3942     assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
  3866   3943     assert( n>=1 );
  3867   3944     assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
  3868   3945          || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
  3869   3946          || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
  3870   3947          || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
  3871   3948     assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
         3949  +  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
         3950  +  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
  3872   3951   
  3873   3952     mask = (1<<(ofst+n)) - (1<<ofst);
  3874   3953     assert( n>1 || mask==(1<<ofst) );
  3875   3954     sqlite3_mutex_enter(pShmNode->mutex);
  3876   3955     if( flags & SQLITE_SHM_UNLOCK ){
  3877   3956       u16 allMask = 0; /* Mask of locks held by siblings */
  3878   3957   
................................................................................
  4002   4081   
  4003   4082     /* If pShmNode->nRef has reached 0, then close the underlying
  4004   4083     ** shared-memory file, too */
  4005   4084     unixEnterMutex();
  4006   4085     assert( pShmNode->nRef>0 );
  4007   4086     pShmNode->nRef--;
  4008   4087     if( pShmNode->nRef==0 ){
  4009         -    if( deleteFlag ) unlink(pShmNode->zFilename);
         4088  +    if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
  4010   4089       unixShmPurge(pDbFd);
  4011   4090     }
  4012   4091     unixLeaveMutex();
  4013   4092   
  4014   4093     return SQLITE_OK;
  4015   4094   }
  4016   4095   
................................................................................
  4347   4426     assert( zFilename==0 || zFilename[0]=='/' );
  4348   4427   #endif
  4349   4428   
  4350   4429     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  4351   4430     pNew->h = h;
  4352   4431     pNew->dirfd = dirfd;
  4353   4432     pNew->zPath = zFilename;
         4433  +  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
         4434  +    pNew->ctrlFlags = UNIXFILE_EXCL;
         4435  +  }else{
         4436  +    pNew->ctrlFlags = 0;
         4437  +  }
  4354   4438   
  4355   4439   #if OS_VXWORKS
  4356   4440     pNew->pId = vxworksFindFileId(zFilename);
  4357   4441     if( pNew->pId==0 ){
  4358   4442       noLock = 1;
  4359   4443       rc = SQLITE_NOMEM;
  4360   4444     }
................................................................................
  6546   6630   #if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
  6547   6631       UNIXVFS("unix",          autolockIoFinder ),
  6548   6632   #else
  6549   6633       UNIXVFS("unix",          posixIoFinder ),
  6550   6634   #endif
  6551   6635       UNIXVFS("unix-none",     nolockIoFinder ),
  6552   6636       UNIXVFS("unix-dotfile",  dotlockIoFinder ),
         6637  +    UNIXVFS("unix-excl",     posixIoFinder ),
  6553   6638   #if OS_VXWORKS
  6554   6639       UNIXVFS("unix-namedsem", semIoFinder ),
  6555   6640   #endif
  6556   6641   #if SQLITE_ENABLE_LOCKING_STYLE
  6557   6642       UNIXVFS("unix-posix",    posixIoFinder ),
  6558   6643   #if !OS_VXWORKS
  6559   6644       UNIXVFS("unix-flock",    flockIoFinder ),

Changes to src/shell.c.

   415    415     char nullvalue[20];    /* The text to print when a NULL comes back from
   416    416                            ** the database */
   417    417     struct previous_mode_data explainPrev;
   418    418                            /* Holds the mode information just before
   419    419                            ** .explain ON */
   420    420     char outfile[FILENAME_MAX]; /* Filename for *out */
   421    421     const char *zDbFilename;    /* name of the database file */
          422  +  const char *zVfs;           /* Name of VFS to use */
   422    423     sqlite3_stmt *pStmt;   /* Current statement if any. */
   423    424     FILE *pLog;            /* Write log output here */
   424    425   };
   425    426   
   426    427   /*
   427    428   ** These are the allowed modes.
   428    429   */
................................................................................
  2596   2597     "   -html                set output mode to HTML\n"
  2597   2598     "   -line                set output mode to 'line'\n"
  2598   2599     "   -list                set output mode to 'list'\n"
  2599   2600     "   -separator 'x'       set output field separator (|)\n"
  2600   2601     "   -stats               print memory stats before each finalize\n"
  2601   2602     "   -nullvalue 'text'    set text string for NULL values\n"
  2602   2603     "   -version             show SQLite version\n"
         2604  +  "   -vfs NAME            use NAME as the default VFS\n"
  2603   2605   ;
  2604   2606   static void usage(int showDetail){
  2605   2607     fprintf(stderr,
  2606   2608         "Usage: %s [OPTIONS] FILENAME [SQL]\n"  
  2607   2609         "FILENAME is the name of an SQLite database. A new database is created\n"
  2608   2610         "if the file does not previously exist.\n", Argv0);
  2609   2611     if( showDetail ){
................................................................................
  2680   2682           if( c=='K' ){ szHeap *= 1000; break; }
  2681   2683           if( c=='G' ){ szHeap *= 1000000000; break; }
  2682   2684         }
  2683   2685         if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
  2684   2686   #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  2685   2687         sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
  2686   2688   #endif
         2689  +    }else if( strcmp(argv[i],"-vfs")==0 ){
         2690  +      i++;
         2691  +      sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[i]);
         2692  +      if( pVfs ){
         2693  +        sqlite3_vfs_register(pVfs, 1);
         2694  +      }else{
         2695  +        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
         2696  +        exit(1);
         2697  +      }
  2687   2698       }
  2688   2699     }
  2689   2700     if( i<argc ){
  2690   2701   #if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2
  2691   2702       data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] );
  2692   2703   #else
  2693   2704       data.zDbFilename = argv[i++];
................................................................................
  2787   2798         printf("%s\n", sqlite3_libversion());
  2788   2799         return 0;
  2789   2800       }else if( strcmp(z,"-interactive")==0 ){
  2790   2801         stdin_is_interactive = 1;
  2791   2802       }else if( strcmp(z,"-batch")==0 ){
  2792   2803         stdin_is_interactive = 0;
  2793   2804       }else if( strcmp(z,"-heap")==0 ){
         2805  +      i++;
         2806  +    }else if( strcmp(z,"-vfs")==0 ){
  2794   2807         i++;
  2795   2808       }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
  2796   2809         usage(1);
  2797   2810       }else{
  2798   2811         fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
  2799   2812         fprintf(stderr,"Use -help for a list of options.\n");
  2800   2813         return 1;