From: dan Date: Tue, 1 Sep 2020 20:56:28 +0000 (+0000) Subject: Add file-controls and a vtab frontend for querying the unix VFS for the currently... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b7ae3b541c41a247d2faba380004eba1bec21b50;p=thirdparty%2Fsqlite.git Add file-controls and a vtab frontend for querying the unix VFS for the currently held shm-locks. Still some issues. FossilOrigin-Name: ef10e1b386d7a9028eab64e1f4802e3d6b2df11c6723130a29e5effc8dcb2e80 --- diff --git a/ext/misc/shmlockvtab.c b/ext/misc/shmlockvtab.c new file mode 100644 index 0000000000..f45e395108 --- /dev/null +++ b/ext/misc/shmlockvtab.c @@ -0,0 +1,286 @@ +/* +** 2020-09-02 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** CREATE TABLE shmlock( +** connid TEXT, +** lock TEXT, +** locktype TEXT, +** mxFrame INTEGER, +** dbname HIDDEN +** ); +*/ +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include +#include + +/* shmlock_vtab is a subclass of sqlite3_vtab which is +** underlying representation of the virtual table +*/ +typedef struct shmlock_vtab shmlock_vtab; +struct shmlock_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; +}; + +/* shmlock_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result +*/ +typedef struct shmlock_cursor shmlock_cursor; +struct shmlock_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + char *zFcntl; + int iFcntl; + + const char *azCol[4]; + int anCol[4]; + sqlite3_int64 iRowid; +}; + +/* +** Create a new shmlock_vtab object. +*/ +static int shmlockConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + shmlock_vtab *pNew; + int rc; + + rc = sqlite3_declare_vtab(db, + "CREATE TABLE shmlock(" + "connid TEXT, " + "lock TEXT, " + "locktype TEXT, " + "mxFrame INTEGER," + "dbname HIDDEN" + ");" + ); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for shmlock_vtab objects. +*/ +static int shmlockDisconnect(sqlite3_vtab *pVtab){ + shmlock_vtab *p = (shmlock_vtab*)pVtab; + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Constructor for a new shmlock_cursor object. +*/ +static int shmlockOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + shmlock_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a shmlock_cursor. +*/ +static int shmlockClose(sqlite3_vtab_cursor *cur){ + shmlock_cursor *pCur = (shmlock_cursor*)cur; + sqlite3_free(pCur->zFcntl); + sqlite3_free(pCur); + return SQLITE_OK; +} + + +/* +** Advance a shmlock_cursor to its next row of output. +*/ +static int shmlockNext(sqlite3_vtab_cursor *cur){ + shmlock_cursor *pCur = (shmlock_cursor*)cur; + int ii = pCur->iFcntl; + const char *z = pCur->zFcntl; + int iCol; + + memset(pCur->azCol, 0, sizeof(char*)*4); + memset(pCur->anCol, 0, sizeof(int)*4); + 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; + ii++; + if( z[ii-1]=='\n' ) break; + } + + pCur->iFcntl = ii; + pCur->iRowid++; + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the shmlock_cursor +** is currently pointing. +*/ +static int shmlockColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + shmlock_cursor *pCur = (shmlock_cursor*)cur; + if( i<=3 && pCur->azCol[i] ){ + sqlite3_result_text(ctx, pCur->azCol[i], pCur->anCol[i], SQLITE_TRANSIENT); + } + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int shmlockRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + shmlock_cursor *pCur = (shmlock_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int shmlockEof(sqlite3_vtab_cursor *cur){ + shmlock_cursor *pCur = (shmlock_cursor*)cur; + return pCur->azCol[1]==0; +} + +/* +** This method is called to "rewind" the shmlock_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to shmlockColumn() or shmlockRowid() or +** shmlockEof(). +*/ +static int shmlockFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + int rc; + shmlock_cursor *pCur = (shmlock_cursor *)pVtabCursor; + shmlock_vtab *pTab = (shmlock_vtab*)pVtabCursor->pVtab; + const char *zDb = "main"; + + if( idxNum==1 ){ + assert( argc==1 ); + zDb = (const char*)sqlite3_value_text(argv[0]); + } + sqlite3_free(pCur->zFcntl); + pCur->zFcntl = 0; + rc = sqlite3_file_control( + pTab->db, zDb, SQLITE_FCNTL_SHMLOCK_GET, (void*)&pCur->zFcntl + ); + pCur->iRowid = 1; + pCur->iFcntl = 0; + if( rc==SQLITE_NOTFOUND ){ + rc = SQLITE_OK; + } + if( pCur->zFcntl ){ + rc = shmlockNext(pVtabCursor); + } + return rc; +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int shmlockBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int ii; + + /* Search for a dbname=? constraint. If one is found, set idxNum=1 and + ** pass the ? as the only argument to xFilter. Otherwise, leave idxNum=0 + ** and pass no arguments to xFilter. */ + for(ii=0; iinConstraint; ii++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; + if( p->usable && p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==4 ){ + pIdxInfo->aConstraintUsage[ii].argvIndex = 1; + pIdxInfo->aConstraintUsage[ii].omit = 1; + pIdxInfo->idxNum = 1; + break; + } + } + + pIdxInfo->estimatedCost = (double)10; + pIdxInfo->estimatedRows = 10; + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** virtual table. +*/ +static sqlite3_module shmlockModule = { + /* iVersion */ 0, + /* xCreate */ 0, + /* xConnect */ shmlockConnect, + /* xBestIndex */ shmlockBestIndex, + /* xDisconnect */ shmlockDisconnect, + /* xDestroy */ 0, + /* xOpen */ shmlockOpen, + /* xClose */ shmlockClose, + /* xFilter */ shmlockFilter, + /* xNext */ shmlockNext, + /* xEof */ shmlockEof, + /* xColumn */ shmlockColumn, + /* xRowid */ shmlockRowid, + /* xUpdate */ 0, + /* xBegin */ 0, + /* xSync */ 0, + /* xCommit */ 0, + /* xRollback */ 0, + /* xFindMethod */ 0, + /* xRename */ 0, + /* xSavepoint */ 0, + /* xRelease */ 0, + /* xRollbackTo */ 0, + /* xShadowName */ 0 +}; + + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_shmlockvtab_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + rc = sqlite3_create_module(db, "shmlock", &shmlockModule, 0); + return rc; +} diff --git a/main.mk b/main.mk index 693887bd66..a99f08dbc7 100644 --- a/main.mk +++ b/main.mk @@ -377,6 +377,7 @@ TESTSRC += \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/remember.c \ $(TOP)/ext/misc/series.c \ + $(TOP)/ext/misc/shmlockvtab.c \ $(TOP)/ext/misc/spellfix.c \ $(TOP)/ext/misc/totype.c \ $(TOP)/ext/misc/unionvtab.c \ diff --git a/manifest b/manifest index c80c5cffe6..1090c25429 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sLemon\soutput,\sadd\sa\sprefix\scomment\sthat\sexplains\sthat\sthe\soutput\sfile\nis\sautomatically\sgenerated\sand\sshows\sthe\sname\sof\sthe\ssource\sfile. -D 2020-09-01T12:26:55.781 +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 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -317,6 +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/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6 @@ -457,7 +458,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk b1cd0bc6aedad7ebb667b7f74f835f932f60ee33be2a5c3051fd93eb465f5c75 +F main.mk 9702e0f4d4c530f3516fc062255c0874e5044000bfb81a5210507399ca2054ac F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -519,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 d707ed2867a2fb32101469327acf3274165d9935e9ab9e27bdab0c1a7d661be7 +F src/os_unix.c 1f65273dc9635f4aeab61c4893d3cb809008c9658c5fce56bc069618f0cfa6eb F src/os_win.c a2149ff0a85c1c3f9cc102a46c673ce87e992396ba3411bfb53db66813b32f1d F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 3700a1c55427a3d4168ad1f1b8a8b0cb9ace1d107e4506e30a8f1e66d8a1195e @@ -537,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 473a79ff2c5c6d54a09af88206ea4d02c4b74558f7d29315a4ede05da8eb8732 +F src/sqlite.h.in 67c266c9e0893f8959ccba1de14b21df9c284315a60f2bb040adbbf82868389c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197 F src/sqliteInt.h d8d69318b1ba3906d4860da1cd1c6b3650b81c9595e5bc360c6469a1e54e09e1 @@ -545,7 +546,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71 -F src/test1.c 9e52fb797bf74fa327295df38881aa3ade0824bfb0c14abd0719e555b169fd55 +F src/test1.c 1cfa55932b81c8f3980f6983b3f77a7836c2f8e53da1d39d7e831444e714f8a3 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -1879,7 +1880,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 84d54eb35716174195ee7e5ac846f47308e5dbb0056e8ff568daa133860bab74 -R 7f45e5b59f1c52d29dee23ebb0c2337a -U drh -Z 0e6fd8fbc683d31bd259b25e22ecc736 +P d34caf3bb63d0512ea116a8c8c8343b76aa39441bd4b3e98231747a705b91d54 +R 70d4b88230a783c0d9a1569eb690c6e9 +T *branch * shmlock-vtab +T *sym-shmlock-vtab * +T -sym-trunk * +U dan +Z 051d13975a42f6e641461833c8ed92f1 diff --git a/manifest.uuid b/manifest.uuid index 12efad1e94..f1ab915fa5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d34caf3bb63d0512ea116a8c8c8343b76aa39441bd4b3e98231747a705b91d54 \ No newline at end of file +ef10e1b386d7a9028eab64e1f4802e3d6b2df11c6723130a29e5effc8dcb2e80 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 5419a042a6..4ad408ea00 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -229,6 +229,7 @@ struct unixFile { const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ + char *zShmlockName; #if SQLITE_MAX_MMAP_SIZE>0 int nFetchOut; /* Number of outstanding xFetch refs */ sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ @@ -2112,6 +2113,7 @@ static int closeUnixFile(sqlite3_file *id){ OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); sqlite3_free(pFile->pPreallocatedUnused); + sqlite3_free(pFile->zShmlockName); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } @@ -3928,8 +3930,10 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){ } } -/* Forward declaration */ +/* Forward declarations used by file-control implementations */ static int unixGetTempname(int nBuf, char *zBuf); +static int unixFcntlShmlockGet(unixFile *pFile, char **pzOut); +static int unixFcntlShmlockName(unixFile *pFile, const char *zName); /* ** Information and control of an open file handle. @@ -4046,6 +4050,16 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ +#ifndef SQLITE_OMIT_WAL + case SQLITE_FCNTL_SHMLOCK_GET: { + char **pzOut = (char**)pArg; + return unixFcntlShmlockGet((unixFile*)id, pzOut); + } + case SQLITE_FCNTL_SHMLOCK_NAME: { + char *zName = (char*)pArg; + return unixFcntlShmlockName((unixFile*)id, zName); + } +#endif } return SQLITE_NOTFOUND; } @@ -4283,6 +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; }; /* @@ -4291,6 +4306,106 @@ 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 */ +static int unixFcntlShmlockName(unixFile *pFile, const char *zName){ + int rc = SQLITE_OK; + assert( !pFile->pShm || pFile->pShm->zShmlockName==pFile->zShmlockName ); + 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); + pFile->pShm->zShmlockName = pFile->zShmlockName; + sqlite3_mutex_leave(pShmNode->pShmMutex); + } + return rc; +} + +static int unixFcntlShmlockGet(unixFile *pFile, char **pzOut){ + int rc = SQLITE_OK; + unixShm *p = pFile->pShm; + const char *aLockName[] = { + "WRITE", "CHECKPOINT", "RECOVER", + "READ(0)", "READ(1)", "READ(2)", "READ(3)", "READ(4)" + }; + assert( ArraySize(aLockName)==SQLITE_SHM_NLOCK ); + if( p ){ + sqlite3_str *pStr = sqlite3_str_new(0); + if( pStr==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + int nRow; + int i; + u32 aReadMark[5]; + char *zOut = 0; + unixShm *pX = 0; + unixShmNode *pShmNode = p->pShmNode; + sqlite3_mutex_enter(pShmNode->pShmMutex); + memcpy(aReadMark, &(pShmNode->apRegion[0])[100], sizeof(aReadMark)); + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( pX->exclMask|pX->sharedMask ){ + char zBuf[32]; + const char *zName = pX->zShmlockName; + if( zName==0 ){ + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", (void*)pX); + zName = zBuf; + } + assert( (pX->exclMask & pX->sharedMask)==0 ); + for(i=0; iexclMask|pX->sharedMask) ){ + int bWrite = (1<exclMask; + if( bWrite==0 && i>=3 ){ + sqlite3_str_appendf(pStr, "%s %s R %d\n", + zName, aLockName[i], aReadMark[i-3] + ); + }else{ + sqlite3_str_appendf(pStr, "%s %s %s\n", + zName, aLockName[i], bWrite ? "W" : "R" + ); + } + nRow++; + } + } + } + } + for(i=0; iaLock[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) ){ + 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] + ); + }else{ + sqlite3_str_appendf(pStr, "pid.%d %s %s\n", + lock.l_pid, aLockName[i], lock.l_type==F_WRLCK ? "W" : "R" + ); + } + nRow++; + } + } + } + sqlite3_mutex_leave(pShmNode->pShmMutex); + if( rc!=SQLITE_OK ){ + sqlite3_free(sqlite3_str_finish(pStr)); + }else{ + rc = sqlite3_str_errcode(pStr); + zOut = sqlite3_str_finish(pStr); + } + *pzOut = zOut; + } + } + return rc; +} + /* ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. ** @@ -4629,6 +4744,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ ** pShmNode->pShmMutex. */ sqlite3_mutex_enter(pShmNode->pShmMutex); + p->zShmlockName = pDbFd->zShmlockName; p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; sqlite3_mutex_leave(pShmNode->pShmMutex); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 2a8ad56ce9..d8c738d716 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1167,6 +1167,9 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_CKPT_START 39 +#define SQLITE_FCNTL_SHMLOCK_GET 40 +#define SQLITE_FCNTL_SHMLOCK_NAME 42 + /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE diff --git a/src/test1.c b/src/test1.c index 04b9f7a011..36c30462f4 100644 --- a/src/test1.c +++ b/src/test1.c @@ -6271,6 +6271,35 @@ static int SQLITE_TCLAPI file_control_tempfilename( return TCL_OK; } +/* +** tclcmd: file_control_shmlock_name DB DBNAME SHMLOCKNAME +** +** Return a string that is a temporary filename +*/ +static int SQLITE_TCLAPI file_control_shmlock_name( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + const char *zDbName = "main"; + char *zName = 0; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SHMLOCKNAME"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ + return TCL_ERROR; + } + zDbName = Tcl_GetString(objv[2]); + zName = Tcl_GetString(objv[3]); + + sqlite3_file_control(db, zDbName, SQLITE_FCNTL_SHMLOCK_NAME, (void*)zName); + return TCL_OK; +} + /* ** tclcmd: sqlite3_vfs_list @@ -7292,6 +7321,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*); + extern int sqlite3_shmlockvtab_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); @@ -7321,6 +7351,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( { "regexp", sqlite3_regexp_init }, { "remember", sqlite3_remember_init }, { "series", sqlite3_series_init }, + { "shmlockvtab", sqlite3_shmlockvtab_init }, { "spellfix", sqlite3_spellfix_init }, { "totype", sqlite3_totype_init }, { "unionvtab", sqlite3_unionvtab_init }, @@ -8161,6 +8192,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, { "file_control_vfsname", file_control_vfsname, 0 }, { "file_control_tempfilename", file_control_tempfilename, 0 }, + { "file_control_shmlock_name", file_control_shmlock_name, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 },