/ Check-in [148f8dec]
Login

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

Overview
Comment:Initial attempt to get SQLite working with OFD locks on Linux. The code here does not function correctly. This is an incremental check-in for a work in progress.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ofd-locks
Files: files | file ages | folders
SHA3-256: 148f8dec9a26f11d343bfeb558fd12ba18d7f5d4d69da58fc8aa22f88e13c408
User & Date: drh 2018-06-19 13:45:48
Context
2018-06-19
17:19
Miscellaneous cleanup of OFD logic. Add an #if 0 to disable the use of OFD logic, temporarily, until I can get it to actually work. check-in: d849ade3 user: drh tags: ofd-locks
13:45
Initial attempt to get SQLite working with OFD locks on Linux. The code here does not function correctly. This is an incremental check-in for a work in progress. check-in: 148f8dec user: drh tags: ofd-locks
11:15
Minor change to the input grammar to make the parser tables slightly smaller. check-in: 320fa69e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/os_unix.c.

   174    174   
   175    175   /*
   176    176   ** Only set the lastErrno if the error code is a real error and not 
   177    177   ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
   178    178   */
   179    179   #define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
   180    180   
          181  +/*
          182  +** Are OFD locks supported?
          183  +*/
          184  +#if defined(F_OFD_SETLK) && defined(F_OFD_GETLK)
          185  +# define HAVE_OFD_LOCKS 1
          186  +#else
          187  +# define HAVE_OFD_LOCKS 0
          188  +# define F_OFD_SETLK 0    /* Fake value so we can use the identifier */
          189  +# define F_OFD_GETLK 0    /* Fake value so we can use the identifier */
          190  +#endif
          191  +
   181    192   /* Forward references */
   182    193   typedef struct unixShm unixShm;               /* Connection shared memory */
   183    194   typedef struct unixShmNode unixShmNode;       /* Shared memory instance */
   184    195   typedef struct unixInodeInfo unixInodeInfo;   /* An i-node */
   185    196   typedef struct UnixUnusedFd UnixUnusedFd;     /* An unused file descriptor */
   186    197   
   187    198   /*
................................................................................
   210    221     unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
   211    222     int lastErrno;                      /* The unix errno from last I/O error */
   212    223     void *lockingContext;               /* Locking style specific state */
   213    224     UnixUnusedFd *pPreallocatedUnused;  /* Pre-allocated UnixUnusedFd */
   214    225     const char *zPath;                  /* Name of the file */
   215    226     unixShm *pShm;                      /* Shared memory segment information */
   216    227     int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
          228  +  int eGetLk, eSetLk;
   217    229   #if SQLITE_MAX_MMAP_SIZE>0
   218    230     int nFetchOut;                      /* Number of outstanding xFetch refs */
   219    231     sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
   220    232     sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
   221    233     sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
   222    234     void *pMapRegion;                   /* Memory mapped region */
   223    235   #endif
................................................................................
   744    756   ** command-line option on the compiler.  This code is normally
   745    757   ** turned off.
   746    758   */
   747    759   static int lockTrace(int fd, int op, struct flock *p){
   748    760     char *zOpName, *zType;
   749    761     int s;
   750    762     int savedErrno;
   751         -  if( op==F_GETLK ){
          763  +  if( op==F_GETLK || op==F_OFD_GETLK ){
   752    764       zOpName = "GETLK";
   753         -  }else if( op==F_SETLK ){
          765  +  }else if( op==F_SETLK || op==F_OFD_SETLK ){
   754    766       zOpName = "SETLK";
   755    767     }else{
   756    768       s = osFcntl(fd, op, p);
   757    769       sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
   758    770       return s;
   759    771     }
   760    772     if( p->l_type==F_RDLCK ){
................................................................................
   768    780     }
   769    781     assert( p->l_whence==SEEK_SET );
   770    782     s = osFcntl(fd, op, p);
   771    783     savedErrno = errno;
   772    784     sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
   773    785        threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
   774    786        (int)p->l_pid, s);
   775         -  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
          787  +  if( s==(-1)
          788  +   && (op==F_SETLK || op==F_OFD_SETLK)
          789  +   && (p->l_type==F_RDLCK || p->l_type==F_WRLCK)
          790  +  ){
   776    791       struct flock l2;
   777    792       l2 = *p;
   778    793       osFcntl(fd, F_GETLK, &l2);
   779    794       if( l2.l_type==F_RDLCK ){
   780    795         zType = "RDLCK";
   781    796       }else if( l2.l_type==F_WRLCK ){
   782    797         zType = "WRLCK";
................................................................................
   990   1005   ******************************************************************************/
   991   1006   
   992   1007   
   993   1008   /******************************************************************************
   994   1009   *************************** Posix Advisory Locking ****************************
   995   1010   **
   996   1011   ** POSIX advisory locks are broken by design.  ANSI STD 1003.1 (1996)
   997         -** section 6.5.2.2 lines 483 through 490 specify that when a process
         1012  +** section 6.5.2.2 lines 483 through 490 says that when a process
   998   1013   ** sets or clears a lock, that operation overrides any prior locks set
   999         -** by the same process.  It does not explicitly say so, but this implies
  1000         -** that it overrides locks set by the same process using a different
  1001         -** file descriptor.  Consider this test case:
         1014  +** by the *same process*.  That means that if two different threads
         1015  +** open the same file using different file descriptors, then POSIX
         1016  +** advisory locking will not work to coordinate access between those two
         1017  +** threads.  Consider this test case:
  1002   1018   **
  1003   1019   **       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
  1004   1020   **       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
  1005   1021   **
  1006   1022   ** Suppose ./file1 and ./file2 are really the same file (because
  1007   1023   ** one is a hard or symbolic link to the other) then if you set
  1008   1024   ** an exclusive lock on fd1, then try to get an exclusive lock
  1009         -** on fd2, it works.  I would have expected the second lock to
         1025  +** on fd2, it works.  In a reasonable system,  the second lock would
  1010   1026   ** fail since there was already a lock on the file due to fd1.
  1011         -** But not so.  Since both locks came from the same process, the
  1012         -** second overrides the first, even though they were on different
  1013         -** file descriptors opened on different file names.
         1027  +** But this is not the case in POSIX advisory locking.  Since both
         1028  +** locks came from the same process, the second overrides the first,
         1029  +** even though they were on different file descriptors opened on
         1030  +** different file names.
  1014   1031   **
  1015   1032   ** This means that we cannot use POSIX locks to synchronize file access
  1016   1033   ** among competing threads of the same process.  POSIX locks will work fine
  1017   1034   ** to synchronize access for threads in separate processes, but not
  1018   1035   ** threads within the same process.
  1019   1036   **
  1020   1037   ** To work around the problem, SQLite has to manage file locks internally
................................................................................
  1026   1043   ** locks to see if another thread has previously set a lock on that same
  1027   1044   ** inode.
  1028   1045   **
  1029   1046   ** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
  1030   1047   ** For VxWorks, we have to use the alternative unique ID system based on
  1031   1048   ** canonical filename and implemented in the previous division.)
  1032   1049   **
  1033         -** The sqlite3_file structure for POSIX is no longer just an integer file
  1034         -** descriptor.  It is now a structure that holds the integer file
  1035         -** descriptor and a pointer to a structure that describes the internal
  1036         -** locks on the corresponding inode.  There is one locking structure
  1037         -** per inode, so if the same inode is opened twice, both unixFile structures
  1038         -** point to the same locking structure.  The locking structure keeps
  1039         -** a reference count (so we will know when to delete it) and a "cnt"
  1040         -** field that tells us its internal lock status.  cnt==0 means the
  1041         -** file is unlocked.  cnt==-1 means the file has an exclusive lock.
  1042         -** cnt>0 means there are cnt shared locks on the file.
         1050  +** The sqlite3_file object for POSIX (a.k.a. the unixFile object) is more
         1051  +** than just an integer file descriptor.  It also holds  a pointer
         1052  +** a pointer to another object (unixInodeInfo) that describes the
         1053  +** internal locks on the corresponding inode.  There is one
         1054  +** unixInodeInfo object per inode, so if the same inode is opened twice,
         1055  +** both unixFile objects point to the same lunixInodeInfo. The unixInodeInfo
         1056  +** keeps a reference count (nRef) so we will know when to delete it.
  1043   1057   **
  1044         -** Any attempt to lock or unlock a file first checks the locking
  1045         -** structure.  The fcntl() system call is only invoked to set a 
  1046         -** POSIX lock if the internal lock structure transitions between
  1047         -** a locked and an unlocked state.
         1058  +** Any attempt to lock or unlock a unixFile first checks the unixInodeInfo.
         1059  +** The fcntl() system call is only invoked to set a POSIX lock if the
         1060  +** unixInodeInfo transitions between a locked and an unlocked state.
  1048   1061   **
  1049   1062   ** But wait:  there are yet more problems with POSIX advisory locks.
  1050   1063   **
  1051   1064   ** If you close a file descriptor that points to a file that has locks,
  1052   1065   ** all locks on that file that are owned by the current process are
  1053   1066   ** released.  To work around this problem, each unixInodeInfo object
  1054   1067   ** maintains a count of the number of pending locks on tha inode.
  1055         -** When an attempt is made to close an unixFile, if there are
  1056         -** other unixFile open on the same inode that are holding locks, the call
         1068  +** When an attempt is made to close an unixFile, if there are other
         1069  +** unixFile objcts open on the same inode that are holding locks, the call
  1057   1070   ** to close() the file descriptor is deferred until all of the locks clear.
  1058   1071   ** The unixInodeInfo structure keeps a list of file descriptors that need to
  1059   1072   ** be closed and that list is walked (and cleared) when the last lock
  1060   1073   ** clears.
  1061   1074   **
  1062         -** Yet another problem:  LinuxThreads do not play well with posix locks.
         1075  +** LinuxThreads:
  1063   1076   **
  1064   1077   ** Many older versions of linux use the LinuxThreads library which is
  1065   1078   ** not posix compliant.  Under LinuxThreads, a lock created by thread
  1066   1079   ** A cannot be modified or overridden by a different thread B.
  1067   1080   ** Only thread A can modify the lock.  Locking behavior is correct
  1068   1081   ** if the appliation uses the newer Native Posix Thread Library (NPTL)
  1069   1082   ** on linux - with NPTL a lock created by thread A can override locks
................................................................................
  1074   1087   ** current process.
  1075   1088   **
  1076   1089   ** SQLite used to support LinuxThreads.  But support for LinuxThreads
  1077   1090   ** was dropped beginning with version 3.7.0.  SQLite will still work with
  1078   1091   ** LinuxThreads provided that (1) there is no more than one connection 
  1079   1092   ** per database file in the same process and (2) database connections
  1080   1093   ** do not move across threads.
         1094  +**
         1095  +** OFD Locks:
         1096  +**
         1097  +** Recent unix-like OSes have added support for Open File Description or "OFD"
         1098  +** locks.  (This is not a typo: the name is "Open File Description" not
         1099  +** "Open File Descriptor".  "-ion" not "-or".  There is a subtle difference
         1100  +** between "Discription" and "Descriptor" which is described on the Linux
         1101  +** fcntl manpage and will not be repeated here.)  The main difference
         1102  +** between OFD locks and POSIX locks is that OFD locks are associated
         1103  +** with a single open() system call and do not interfere with with file
         1104  +** descriptors obtained from different open() system calls in the same
         1105  +** process.  In other words, OFD locks fix the brokenness of POSIX locks.
         1106  +**
         1107  +** As of 2018-06-19, SQLite will use OFD locks if they are available.
         1108  +** But the older work-arounds for POSIX locks are still here in the code
         1109  +** since SQLite also needs to work on systems that do not support
         1110  +** OFD locks.  Someday, perhaps, all unix systems will have reliable
         1111  +** support for OFD locks, and at that time we can omit the unixInodeInfo
         1112  +** object and all of its associated complication.  But for now we still
         1113  +** have to support the older POSIX lock work-around hack.
  1081   1114   */
  1082   1115   
  1083   1116   /*
  1084   1117   ** An instance of the following structure serves as the key used
  1085   1118   ** to locate a particular unixInodeInfo object.
  1086   1119   */
  1087   1120   struct unixFileId {
................................................................................
  1448   1481   #ifndef __DJGPP__
  1449   1482     if( !reserved && !pFile->pInode->bProcessLock ){
  1450   1483       struct flock lock;
  1451   1484       lock.l_whence = SEEK_SET;
  1452   1485       lock.l_start = RESERVED_BYTE;
  1453   1486       lock.l_len = 1;
  1454   1487       lock.l_type = F_WRLCK;
  1455         -    if( osFcntl(pFile->h, F_GETLK, &lock) ){
         1488  +    lock.l_pid = 0;
         1489  +    if( osFcntl(pFile->h, pFile->eGetLk, &lock) ){
  1456   1490         rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
  1457   1491         storeLastErrno(pFile, errno);
  1458   1492       } else if( lock.l_type!=F_UNLCK ){
  1459   1493         reserved = 1;
  1460   1494       }
  1461   1495     }
  1462   1496   #endif
................................................................................
  1478   1512   ** failing the lock.  The iBusyTimeout value is always reset back to
  1479   1513   ** zero on each call.
  1480   1514   **
  1481   1515   ** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
  1482   1516   ** attempt to set the lock.
  1483   1517   */
  1484   1518   #ifndef SQLITE_ENABLE_SETLK_TIMEOUT
  1485         -# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
         1519  +# define osSetAdvisoryLock(h,e,x,t) osFcntl(h,e,x)
  1486   1520   #else
  1487         -static int osSetPosixAdvisoryLock(
         1521  +static int osSetAdvisoryLock(
  1488   1522     int h,                /* The file descriptor on which to take the lock */
         1523  +  int eSetLk,           /* ioctl verb for setting the lock */
  1489   1524     struct flock *pLock,  /* The description of the lock */
  1490   1525     unixFile *pFile       /* Structure holding timeout value */
  1491   1526   ){
  1492         -  int rc = osFcntl(h,F_SETLK,pLock);
         1527  +  int rc = osFcntl(h,eSetLk,pLock);
  1493   1528     while( rc<0 && pFile->iBusyTimeout>0 ){
  1494   1529       /* On systems that support some kind of blocking file lock with a timeout,
  1495   1530       ** make appropriate changes here to invoke that blocking file lock.  On
  1496   1531       ** generic posix, however, there is no such API.  So we simply try the
  1497   1532       ** lock once every millisecond until either the timeout expires, or until
  1498   1533       ** the lock is obtained. */
  1499   1534       usleep(1000);
  1500         -    rc = osFcntl(h,F_SETLK,pLock);
         1535  +    rc = osFcntl(h,eSetLk,pLock);
  1501   1536       pFile->iBusyTimeout--;
  1502   1537     }
  1503   1538     return rc;
  1504   1539   }
  1505   1540   #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
  1506   1541   
  1507   1542   
................................................................................
  1533   1568       if( pInode->bProcessLock==0 ){
  1534   1569         struct flock lock;
  1535   1570         assert( pInode->nLock==0 );
  1536   1571         lock.l_whence = SEEK_SET;
  1537   1572         lock.l_start = SHARED_FIRST;
  1538   1573         lock.l_len = SHARED_SIZE;
  1539   1574         lock.l_type = F_WRLCK;
  1540         -      rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
         1575  +      lock.l_pid = 0;
         1576  +      rc = osSetAdvisoryLock(pFile->h, pFile->eSetLk, &lock, pFile);
  1541   1577         if( rc<0 ) return rc;
  1542   1578         pInode->bProcessLock = 1;
  1543   1579         pInode->nLock++;
  1544   1580       }else{
  1545   1581         rc = 0;
  1546   1582       }
  1547   1583     }else{
  1548         -    rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
         1584  +    pLock->l_pid = 0;
         1585  +    rc = osSetAdvisoryLock(pFile->h, pFile->eSetLk, pLock, pFile);
  1549   1586     }
  1550   1587     return rc;
  1551   1588   }
  1552   1589   
  1553   1590   /*
  1554   1591   ** Lock the file with the lock specified by parameter eFileLock - one
  1555   1592   ** of the following:
................................................................................
  1660   1697       goto end_lock;
  1661   1698     }
  1662   1699   
  1663   1700     /* If a SHARED lock is requested, and some thread using this PID already
  1664   1701     ** has a SHARED or RESERVED lock, then increment reference counts and
  1665   1702     ** return SQLITE_OK.
  1666   1703     */
  1667         -  if( eFileLock==SHARED_LOCK && 
  1668         -      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
         1704  +  if( eFileLock==SHARED_LOCK
         1705  +   && pFile->eGetLk==F_GETLK
         1706  +   && (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK)
         1707  +  ){
  1669   1708       assert( eFileLock==SHARED_LOCK );
  1670   1709       assert( pFile->eFileLock==0 );
  1671   1710       assert( pInode->nShared>0 );
  1672   1711       pFile->eFileLock = SHARED_LOCK;
  1673   1712       pInode->nShared++;
  1674   1713       pInode->nLock++;
  1675   1714       goto end_lock;
................................................................................
  3907   3946       }
  3908   3947   #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  3909   3948       case SQLITE_FCNTL_LOCK_TIMEOUT: {
  3910   3949         pFile->iBusyTimeout = *(int*)pArg;
  3911   3950         return SQLITE_OK;
  3912   3951       }
  3913   3952   #endif
         3953  +    case SQLITE_FCNTL_OFD_LOCKS: {
         3954  +      int x = *(int*)pArg;
         3955  +      if( x==0 ){
         3956  +        pFile->eSetLk = F_SETLK;
         3957  +        pFile->eGetLk = F_GETLK;
         3958  +      }
         3959  +      *(int*)pArg = pFile->eSetLk==F_OFD_SETLK;
         3960  +      return SQLITE_OK;
         3961  +    }
  3914   3962   #if SQLITE_MAX_MMAP_SIZE>0
  3915   3963       case SQLITE_FCNTL_MMAP_SIZE: {
  3916   3964         i64 newLimit = *(i64*)pArg;
  3917   3965         int rc = SQLITE_OK;
  3918   3966         if( newLimit>sqlite3GlobalConfig.mxMmap ){
  3919   3967           newLimit = sqlite3GlobalConfig.mxMmap;
  3920   3968         }
................................................................................
  4226   4274   
  4227   4275     if( pShmNode->h>=0 ){
  4228   4276       /* Initialize the locking parameters */
  4229   4277       f.l_type = lockType;
  4230   4278       f.l_whence = SEEK_SET;
  4231   4279       f.l_start = ofst;
  4232   4280       f.l_len = n;
  4233         -    rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
         4281  +    f.l_pid = 0;
         4282  +    rc = osSetAdvisoryLock(pShmNode->h, pFile->eSetLk, &f, pFile);
  4234   4283       rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
  4235   4284     }
  4236   4285   
  4237   4286     /* Update the global lock state and do debug tracing */
  4238   4287   #ifdef SQLITE_DEBUG
  4239   4288     { u16 mask;
  4240   4289     OSTRACE(("SHM-LOCK "));
................................................................................
  4351   4400     ** process might open and use the *-shm file without truncating it.
  4352   4401     ** And if the *-shm file has been corrupted by a power failure or
  4353   4402     ** system crash, the database itself may also become corrupt.  */
  4354   4403     lock.l_whence = SEEK_SET;
  4355   4404     lock.l_start = UNIX_SHM_DMS;
  4356   4405     lock.l_len = 1;
  4357   4406     lock.l_type = F_WRLCK;
  4358         -  if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
         4407  +  if( osFcntl(pShmNode->h, pDbFd->eGetLk, &lock)!=0 ) {
  4359   4408       rc = SQLITE_IOERR_LOCK;
  4360   4409     }else if( lock.l_type==F_UNLCK ){
  4361   4410       if( pShmNode->isReadonly ){
  4362   4411         pShmNode->isUnlocked = 1;
  4363   4412         rc = SQLITE_READONLY_CANTINIT;
  4364   4413       }else{
  4365   4414         rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
................................................................................
  5408   5457     assert( pNew->pInode==NULL );
  5409   5458   
  5410   5459     /* No locking occurs in temporary files */
  5411   5460     assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
  5412   5461   
  5413   5462     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  5414   5463     pNew->h = h;
         5464  +  pNew->eSetLk = F_SETLK;
         5465  +  pNew->eGetLk = F_GETLK;
         5466  +#if HAVE_OFD_LOCKS
         5467  +  {
         5468  +    struct flock lock;
         5469  +    lock.l_whence = SEEK_SET;
         5470  +    lock.l_start = RESERVED_BYTE;
         5471  +    lock.l_len = 1;
         5472  +    lock.l_type = F_WRLCK;
         5473  +    lock.l_pid = 0;
         5474  +    if( osFcntl(h, F_OFD_GETLK, &lock)==0 ){
         5475  +      pNew->eSetLk = F_OFD_SETLK;
         5476  +      pNew->eGetLk = F_OFD_GETLK;
         5477  +    }
         5478  +  }
         5479  +#endif
  5415   5480     pNew->pVfs = pVfs;
  5416   5481     pNew->zPath = zFilename;
  5417   5482     pNew->ctrlFlags = (u8)ctrlFlags;
  5418   5483   #if SQLITE_MAX_MMAP_SIZE>0
  5419   5484     pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
  5420   5485   #endif
  5421   5486     if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),

Changes to src/sqlite.h.in.

  1069   1069   ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
  1070   1070   **
  1071   1071   ** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
  1072   1072   ** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
  1073   1073   ** a file lock using the xLock or xShmLock methods of the VFS to wait
  1074   1074   ** for up to M milliseconds before failing, where M is the single 
  1075   1075   ** unsigned integer parameter.
         1076  +**
         1077  +** <li>[[SQLITE_FCNTL_OFD_LOCKS]]
         1078  +** The [SQLITE_FCNTL_OFD_LOCKS] opcode will query whether or not OFD
         1079  +** locking is currently being used for an open file, or disable the use
         1080  +** of OFD locking on the file.  The argument is a pointer to an integer
         1081  +** in the callers context.  If that integer is initially -1, then it is
         1082  +** set to 1 or 0 if the system is or is not using OFD locks for the file.
         1083  +** If the integer is initially 0, then OFD locks are disabled for the file.
         1084  +** This file-control is intended for testing and validation use only.
         1085  +** Applications that strive for correctness and error-free operation should
         1086  +** not mess with this file-control.
  1076   1087   ** </ul>
  1077   1088   */
  1078   1089   #define SQLITE_FCNTL_LOCKSTATE               1
  1079   1090   #define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
  1080   1091   #define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
  1081   1092   #define SQLITE_FCNTL_LAST_ERRNO              4
  1082   1093   #define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
  1104   1115   #define SQLITE_FCNTL_JOURNAL_POINTER        28
  1105   1116   #define SQLITE_FCNTL_WIN32_GET_HANDLE       29
  1106   1117   #define SQLITE_FCNTL_PDB                    30
  1107   1118   #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
  1108   1119   #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
  1109   1120   #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
  1110   1121   #define SQLITE_FCNTL_LOCK_TIMEOUT           34
         1122  +#define SQLITE_FCNTL_OFD_LOCKS              35
  1111   1123   
  1112   1124   /* deprecated names */
  1113   1125   #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
  1114   1126   #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
  1115   1127   #define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
  1116   1128   
  1117   1129   

Changes to src/test1.c.

  5958   5958     }
  5959   5959     if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
  5960   5960     rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
  5961   5961     sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
  5962   5962     Tcl_AppendResult(interp, z, (char*)0);
  5963   5963     return TCL_OK;  
  5964   5964   }
         5965  +
         5966  +/*
         5967  +** tclcmd:   file_control_ofd_locks DB ?DISABLE?
         5968  +**
         5969  +** Run sqlite3_file_control() to query the OFD lock capability.  Return
         5970  +** true if OFD locks are available and false if not.
         5971  +**
         5972  +** If the DISABLE argument is true, then disable OFD locking, if it is
         5973  +** enabled.  The returned value will show that OFD locks are disabled.
         5974  +*/
         5975  +static int SQLITE_TCLAPI file_control_ofd_locks(
         5976  +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
         5977  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         5978  +  int objc,              /* Number of arguments */
         5979  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         5980  +){
         5981  +  sqlite3 *db;
         5982  +  int rc;
         5983  +  int b = 0;
         5984  +
         5985  +  if( objc!=2 && objc!=3 ){
         5986  +    Tcl_AppendResult(interp, "wrong # args: should be \"",
         5987  +        Tcl_GetStringFromObj(objv[0], 0), " DB ?DISABLE?", 0);
         5988  +    return TCL_ERROR;
         5989  +  }
         5990  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         5991  +    return TCL_ERROR;
         5992  +  }
         5993  +  if( objc==3 && Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
         5994  +  b = b ? 0 : -1;
         5995  +  rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_OFD_LOCKS,(void*)&b);
         5996  +  Tcl_AppendResult(interp, (rc==SQLITE_OK && b) ? "1" : "0", (char*)0);
         5997  +  return TCL_OK;  
         5998  +}
  5965   5999   
  5966   6000   /*
  5967   6001   ** tclcmd:   file_control_powersafe_overwrite DB PSOW-FLAG
  5968   6002   **
  5969   6003   ** This TCL command runs the sqlite3_file_control interface with
  5970   6004   ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
  5971   6005   */
................................................................................
  5990   6024     }
  5991   6025     if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
  5992   6026     rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
  5993   6027     sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
  5994   6028     Tcl_AppendResult(interp, z, (char*)0);
  5995   6029     return TCL_OK;  
  5996   6030   }
  5997         -
  5998   6031   
  5999   6032   /*
  6000   6033   ** tclcmd:   file_control_vfsname DB ?AUXDB?
  6001   6034   **
  6002   6035   ** Return a string that describes the stack of VFSes.
  6003   6036   */
  6004   6037   static int SQLITE_TCLAPI file_control_vfsname(
................................................................................
  7701   7734        { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  7702   7735   #if SQLITE_OS_WIN
  7703   7736        { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
  7704   7737        { "file_control_win32_get_handle", file_control_win32_get_handle, 0  },
  7705   7738        { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
  7706   7739   #endif
  7707   7740        { "file_control_persist_wal",    file_control_persist_wal,     0   },
         7741  +     { "file_control_ofd_locks",      file_control_ofd_locks,       0   },
  7708   7742        { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
  7709   7743        { "file_control_vfsname",        file_control_vfsname,         0   },
  7710   7744        { "file_control_tempfilename",   file_control_tempfilename,    0   },
  7711   7745        { "sqlite3_vfs_list",           vfs_list,     0   },
  7712   7746        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  7713   7747   
  7714   7748        /* Functions from os.h */