]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix reporting on locks from external processes. Various other fixes.
authordan <dan@noemail.net>
Wed, 2 Sep 2020 15:26:28 +0000 (15:26 +0000)
committerdan <dan@noemail.net>
Wed, 2 Sep 2020 15:26:28 +0000 (15:26 +0000)
FossilOrigin-Name: 459de23e869c79357221100e81d2c8e0b812ed3260e58d7d7acb3419876f41a3

ext/misc/shmlockvtab.c
manifest
manifest.uuid
src/os_unix.c
src/sqlite.h.in

index f45e395108c5becd0dc9448f9ec9a63df45526f0..9d0e16a06d6cfb21b7eae23a51c99094930946f9 100644 (file)
@@ -10,6 +10,9 @@
 **
 *************************************************************************
 **
+** This file contains the implementation of the "shmlock" eponymous 
+** virtual table module. The schema of which is effectively:
+**
 **   CREATE TABLE shmlock(
 **       connid TEXT, 
 **       lock TEXT, 
 **       mxFrame INTEGER,
 **       dbname HIDDEN
 **   );
+**
+** This virtual table may be used to query for the locks held on the main or
+** any attached database that is in wal mode. If the database is not in
+** wal mode, zero rows are returned. Otherwise, one row is returned for
+** each lock held on the database by a connection in either the current 
+** process, as well as - to the extent possible - one row for each lock held 
+** by another process. On unix, "to the extent possible" means that if
+** two or more external processes hold a SHARED wal-mode lock on the same
+** locking-slot, only one of them is reported on.
+**
+** To query for locks on the main database, either of:
+**
+**     SELECT * FROM shmlock;
+**     SELECT * FROM shmlock('main');
+**
+** To query for locks on the attached database named 'aux':
+**
+**     SELECT * FROM shmlock('aux');
+**
+** The non-HIDDEN columns of each row may be interpreted as follows:
+**
+** connid:
+**   String identifying the connection. For a local connection lock, this is
+**   either the string representation of an internal pointer value, or else a
+**   string configured using the file-control SQLITE_FCNTL_SHMLOCK_NAME.
+**   For a lock from an external process, the id takes the form "pid.123",
+**   where 123 is the process-id of the lock holder.
+**
+** lock:
+**   A text value representing the particular wal mode lock held. One of
+**   "WRITE", "CHECKPOINT", "RECOVER" or "READ(n)", where n is between 0 and
+**   4, inclusive.
+**
+** locktype:
+**   'R' for a shared (reader) lock, or 'W' for an exclusive (writer) lock.
+**
+** mxframe:
+**   When the lock is a shared lock held on a READ(n) slot, the integer value
+**   of the corresponding read-mark slot in shared-memory.
+**
+** This module currently only works with the "unix" VFS.
+**
 */
 #if !defined(SQLITEINT_H)
 #include "sqlite3ext.h"
@@ -43,9 +88,9 @@ struct shmlock_cursor {
   sqlite3_vtab_cursor base;  /* Base class - must be first */
   char *zFcntl;
   int iFcntl;
+  char *aSpace;              /* Space to use for dequoted strings */
 
   const char *azCol[4];
-  int anCol[4];
   sqlite3_int64 iRowid;
 };
 
@@ -108,6 +153,7 @@ static int shmlockOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
 static int shmlockClose(sqlite3_vtab_cursor *cur){
   shmlock_cursor *pCur = (shmlock_cursor*)cur;
   sqlite3_free(pCur->zFcntl);
+  sqlite3_free(pCur->aSpace);
   sqlite3_free(pCur);
   return SQLITE_OK;
 }
@@ -120,17 +166,30 @@ static int shmlockNext(sqlite3_vtab_cursor *cur){
   shmlock_cursor *pCur = (shmlock_cursor*)cur;
   int ii = pCur->iFcntl;
   const char *z = pCur->zFcntl;
+  char *a = pCur->aSpace;
   int iCol;
 
   memset(pCur->azCol, 0, sizeof(char*)*4);
-  memset(pCur->anCol, 0, sizeof(int)*4);
+  if( z[ii]=='\0' ) return SQLITE_OK;;
   for(iCol=0; iCol<4; iCol++){
-    pCur->azCol[iCol] = &z[ii];
-    while( z[ii]!=' ' && z[ii]!='\n' && z[ii]!='\0' ) ii++;
-    pCur->anCol[iCol] = &z[ii] - pCur->azCol[iCol];
-    if( z[ii]=='\0' ) break;
+    if( z[ii]!='\'' ) return SQLITE_ERROR;
+
+    pCur->azCol[iCol] = a;
     ii++;
-    if( z[ii-1]=='\n' ) break;
+    while( z[ii] ){
+      if( z[ii]=='\'' ){
+        ii++;
+        if( z[ii]!='\'' ) break;
+      }
+      *a++ = z[ii++];
+    }
+    *a++ = '\0';
+    while( z[ii]==' ' ) ii++;
+    if( z[ii]=='\0' ) break;
+    if( z[ii]=='\n' ){
+      ii++;
+      break;
+    }
   }
 
   pCur->iFcntl = ii;
@@ -149,7 +208,7 @@ static int shmlockColumn(
 ){
   shmlock_cursor *pCur = (shmlock_cursor*)cur;
   if( i<=3 && pCur->azCol[i] ){
-    sqlite3_result_text(ctx, pCur->azCol[i], pCur->anCol[i], SQLITE_TRANSIENT);
+    sqlite3_result_text(ctx, pCur->azCol[i], -1, SQLITE_TRANSIENT);
   }
   return SQLITE_OK;
 }
@@ -193,8 +252,9 @@ static int shmlockFilter(
     assert( argc==1 );
     zDb = (const char*)sqlite3_value_text(argv[0]);
   }
-  sqlite3_free(pCur->zFcntl);
+  sqlite3_free(pCur->aSpace);
   pCur->zFcntl = 0;
+  pCur->aSpace = 0;
   rc = sqlite3_file_control(
       pTab->db, zDb, SQLITE_FCNTL_SHMLOCK_GET, (void*)&pCur->zFcntl
   );
@@ -204,7 +264,13 @@ static int shmlockFilter(
     rc = SQLITE_OK;
   }
   if( pCur->zFcntl ){
-    rc = shmlockNext(pVtabCursor);
+    int n = strlen(pCur->zFcntl);
+    pCur->aSpace = sqlite3_malloc(n);
+    if( pCur->aSpace==0 ){
+      rc = SQLITE_NOMEM;
+    }else{
+      rc = shmlockNext(pVtabCursor);
+    }
   }
   return rc;
 }
index 1090c254291d90d003a78ffb3253556895a435d1..e625218eb44f42fd076b15e0e9f9012b315794d4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sfile-controls\sand\sa\svtab\sfrontend\sfor\squerying\sthe\sunix\sVFS\sfor\sthe\scurrently\sheld\sshm-locks.\sStill\ssome\sissues.
-D 2020-09-01T20:56:28.962
+C Fix\sreporting\son\slocks\sfrom\sexternal\sprocesses.\sVarious\sother\sfixes.
+D 2020-09-02T15:26:28.763
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -317,7 +317,7 @@ F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a
 F ext/misc/series.c 4057dda3579b38ff88b2d3b13b4dd92dbd9d6f90dac2b55c19b0a8ed87ee4959
 F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
 F ext/misc/shathree.c 135b7c145db4a09b1650c3e7aff9cb538763a9a361e834c015dd1aaf8d5c9a00
-F ext/misc/shmlockvtab.c 2cf63c9c57c47e551a92fe1f126f718a67a2de7d3714a6183b548ef3585a3639 w ext/misc/shmlocksvtab.c
+F ext/misc/shmlockvtab.c d218fd9eeacd8406b72cb12d4b80409734415350d3c1dfc3b504ce10cb01f072
 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
 F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
 F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
@@ -520,7 +520,7 @@ F src/os.c 80e4cf3e5da06be03ca641661e331ce60eeeeabf0d7354dbb1c0e166d0eedbbe
 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 1f65273dc9635f4aeab61c4893d3cb809008c9658c5fce56bc069618f0cfa6eb
+F src/os_unix.c 695560d6427b8d45d1bb0595c4ec9ce944d0b1cbb8bc97d9345141301abf28d2
 F src/os_win.c a2149ff0a85c1c3f9cc102a46c673ce87e992396ba3411bfb53db66813b32f1d
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 3700a1c55427a3d4168ad1f1b8a8b0cb9ace1d107e4506e30a8f1e66d8a1195e
@@ -538,7 +538,7 @@ F src/resolve.c 97b91fb25d86881ff20c9ad2ad98412c6c1bb5f7d6c9bb044db250cbc9cfcd4b
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 233e884d7da6601486c7b93aedb97fd29302ae5c03742d0e0eccb4790638bb77
 F src/shell.c.in 9bae0c8397e7b592fb404678c4c1fc7944d9dc798a928d1eb40bcd608c33d21b
-F src/sqlite.h.in 67c266c9e0893f8959ccba1de14b21df9c284315a60f2bb040adbbf82868389c
+F src/sqlite.h.in 7c248cbaedb64e39071cda07e7ff7ab47a4bbebc279ccb1676f47b353a89360d
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
 F src/sqliteInt.h d8d69318b1ba3906d4860da1cd1c6b3650b81c9595e5bc360c6469a1e54e09e1
@@ -1880,10 +1880,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d34caf3bb63d0512ea116a8c8c8343b76aa39441bd4b3e98231747a705b91d54
-R 70d4b88230a783c0d9a1569eb690c6e9
-T *branch * shmlock-vtab
-T *sym-shmlock-vtab *
-T -sym-trunk *
+P ef10e1b386d7a9028eab64e1f4802e3d6b2df11c6723130a29e5effc8dcb2e80
+R 1fe025e21af9295b836249b2ab87a4c4
 U dan
-Z 051d13975a42f6e641461833c8ed92f1
+Z 312afa0e4b2458b1639f92694294c2f3
index f1ab915fa5dc31f07706b84aec442b018626bff5..22bd28ae64246172604bd3256f12fb11c39a1d9d 100644 (file)
@@ -1 +1 @@
-ef10e1b386d7a9028eab64e1f4802e3d6b2df11c6723130a29e5effc8dcb2e80
\ No newline at end of file
+459de23e869c79357221100e81d2c8e0b812ed3260e58d7d7acb3419876f41a3
\ No newline at end of file
index 4ad408ea004c3f6c7fc43efecfaa0cc52e65e2d1..5136772965e862fcab5ee7237e3aa6184c9ea6fb 100644 (file)
@@ -4297,7 +4297,7 @@ struct unixShm {
   u8 id;                     /* Id of this connection within its unixShmNode */
   u16 sharedMask;            /* Mask of shared locks held */
   u16 exclMask;              /* Mask of exclusive locks held */
-  const char *zShmlockName;
+  const char *zShmlockName;  /* Name to use for FCNTL_SHMLOCK_GET */
 };
 
 /*
@@ -4306,23 +4306,30 @@ struct unixShm {
 #define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
 #define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
 
+/*
+** This is the implementation of the SQLITE_FCNTL_SHMLOCK_NAME file-control.
+*/
 static int unixFcntlShmlockName(unixFile *pFile, const char *zName){
   int rc = SQLITE_OK;
   assert( !pFile->pShm || pFile->pShm->zShmlockName==pFile->zShmlockName );
+  if( pFile->pShm ){
+    sqlite3_mutex_enter(pFile->pShm->pShmNode->pShmMutex);
+  }
   sqlite3_free(pFile->zShmlockName);
   pFile->zShmlockName = sqlite3_mprintf("%s", zName);
   if( pFile->zShmlockName==0 ){
     rc = SQLITE_NOMEM;
   }
-  if( pFile->pShm){
-    unixShmNode *pShmNode = pFile->pShm->pShmNode;
-    sqlite3_mutex_enter(pShmNode->pShmMutex);
+  if( pFile->pShm ){
     pFile->pShm->zShmlockName = pFile->zShmlockName;
-    sqlite3_mutex_leave(pShmNode->pShmMutex);
+    sqlite3_mutex_leave(pFile->pShm->pShmNode->pShmMutex);
   }
   return rc;
 }
 
+/*
+** This is the implementation of the SQLITE_FCNTL_SHMLOCK_GET file-control.
+*/
 static int unixFcntlShmlockGet(unixFile *pFile, char **pzOut){
   int rc = SQLITE_OK;
   unixShm *p = pFile->pShm;
@@ -4357,11 +4364,11 @@ static int unixFcntlShmlockGet(unixFile *pFile, char **pzOut){
             if( (1<<i) & (pX->exclMask|pX->sharedMask) ){
               int bWrite = (1<<i) & pX->exclMask;
               if( bWrite==0 && i>=3 ){
-                sqlite3_str_appendf(pStr, "%s %s R %d\n", 
+                sqlite3_str_appendf(pStr, "%Q %Q 'R' '%d'\n", 
                     zName, aLockName[i], aReadMark[i-3]
                 );
               }else{
-                sqlite3_str_appendf(pStr, "%s %s %s\n", 
+                sqlite3_str_appendf(pStr, "%Q %Q %Q\n", 
                     zName, aLockName[i], bWrite ? "W" : "R"
                 );
               }
@@ -4371,21 +4378,21 @@ static int unixFcntlShmlockGet(unixFile *pFile, char **pzOut){
         }
       }
       for(i=0; i<SQLITE_SHM_NLOCK; i++){
-        if( pShmNode->aLock[i]==0 ){
+        if( pShmNode->aLock[i]>=0 ){
           struct flock lock;
           lock.l_whence = SEEK_SET;
           lock.l_start = UNIX_SHM_BASE+i;
           lock.l_len = 1;
           lock.l_type = F_WRLCK;
-          if( osFcntl(pFile->h, F_GETLK, &lock) ){
+          if( osFcntl(pShmNode->hShm, F_GETLK, &lock) ){
             rc = SQLITE_IOERR_LOCK;
           }else if( lock.l_type!=F_UNLCK ){
             if( lock.l_type==F_RDLCK && i>=3 ){
-              sqlite3_str_appendf(pStr, "pid.%d %s R %d\n", 
-                  lock.l_pid, aLockName[i], aReadMark[i]
+              sqlite3_str_appendf(pStr, "'pid.%d' %Q 'R' '%d'\n", 
+                  lock.l_pid, aLockName[i], aReadMark[i-3]
               );
             }else{
-              sqlite3_str_appendf(pStr, "pid.%d %s %s\n", 
+              sqlite3_str_appendf(pStr, "'pid.%d' %Q %Q\n", 
                   lock.l_pid, aLockName[i], lock.l_type==F_WRLCK ? "W" : "R"
               );
             }
index d8c738d7162216740b22e0565cc189eca7af275a..b71915f0a3b0c1815e98350ea11b6fb17722430f 100644 (file)
@@ -1126,6 +1126,24 @@ struct sqlite3_io_methods {
 ** in wal mode after the client has finished copying pages from the wal
 ** file to the database file, but before the *-shm file is updated to
 ** record the fact that the pages have been checkpointed.
+**
+** <li>[[SQLITE_FCNTL_SHMLOCK_GET]]
+** This file-control is currently only supported by the "unix" VFS. The
+** (void*) argument passed with this file-control must actually be
+** a (char**) pointer. If the database is in wal-mode, the target of the
+** pointer is set to point to a human readable description of all the
+** wal-mode locks held on the database, by the current and external 
+** processes. It is the responsibility of the caller to eventually free 
+** this string using sqlite3_free(). See also the virtual table module in 
+** file "shmlockvtab.c" of the source distribution.
+** </ul>
+**
+** <li>[[SQLITE_FCNTL_SHMLOCK_NAME]]
+** This file-control is currently only supported by the "unix" VFS. The
+** (void*) argument passed with this file-control should point to a
+** nul-terminated string. A copy of this string will be used in reports
+** returned by future calls to SQLITE_FCNTL_SHMLOCK_GET within the current
+** process to identify this connection.
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -1168,7 +1186,7 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_CKPT_START             39
 
 #define SQLITE_FCNTL_SHMLOCK_GET            40
-#define SQLITE_FCNTL_SHMLOCK_NAME           42
+#define SQLITE_FCNTL_SHMLOCK_NAME           41
 
 /* deprecated names */
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE