**
*************************************************************************
**
+** 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"
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;
};
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;
}
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;
){
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;
}
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
);
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;
}
-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
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
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
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
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
-ef10e1b386d7a9028eab64e1f4802e3d6b2df11c6723130a29e5effc8dcb2e80
\ No newline at end of file
+459de23e869c79357221100e81d2c8e0b812ed3260e58d7d7acb3419876f41a3
\ No newline at end of file
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 */
};
/*
#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;
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"
);
}
}
}
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"
);
}
** 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
#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