diff --git a/doc/testrunner.md b/doc/testrunner.md
index d828fd76d8..d420076c4f 100644
--- a/doc/testrunner.md
+++ b/doc/testrunner.md
@@ -2,6 +2,26 @@
# The testrunner.tcl Script
+
+
+
# 1. Overview
testrunner.tcl is a Tcl script used to run multiple SQLite tests using
@@ -44,6 +64,7 @@ Sometimes testrunner.tcl uses the [testfixture] binary that it is run with
to run tests (see "Binary Tests" below). Sometimes it builds testfixture and
other binaries in specific configurations to test (see "Source Tests").
+
# 2. Binary Tests
The commands described in this section all run various combinations of the Tcl
@@ -61,6 +82,7 @@ these tests is therefore:
The following sub-sections describe the various options that can be
passed to testrunner.tcl to test binary testfixture builds.
+
## 2.1. Organization of Tcl Tests
Tcl tests are stored in files that match the pattern *\*.test*. They are
@@ -91,6 +113,7 @@ Running **all** tests is to run all tests in the full test set, plus a dozen
or so permutations. The specific permutations that are run as part of "all"
are defined in file *testrunner_data.tcl*.
+
## 2.2. Commands to Run Tests
To run the "veryquick" test set, use either of the following:
@@ -114,6 +137,12 @@ a specified pattern (e.g. all tests that start with "fts5"), either of:
./testfixture $TESTDIR/testrunner.tcl 'fts5*'
```
+Strictly speaking, for a test to be run the pattern must match the script
+filename, not including the directory, using the rules of Tcl's
+\[string match\] command. Except that before the matching is done, any "%"
+characters specified as part of the pattern are transformed to "\*".
+
+
To run "all" tests (full + permutations):
```
@@ -141,6 +170,7 @@ Or, if the failure occured as part of a permutation:
TODO: An example instead of "$PERMUTATION" and $PATH\_TO\_SCRIPT?
+
# 3. Source Code Tests
The commands described in this section invoke the C compiler to build
@@ -159,7 +189,8 @@ shell that supports SQLite 3.31.1 or newer via "package require sqlite3".
TODO: ./configure + Makefile.msc build systems.
-## Commands to Run SQLite Tests
+
+## 3.1. Commands to Run SQLite Tests
The **mdevtest** command is equivalent to running the veryquick tests and
the [make fuzztest] target once for each of two --enable-all builds - one
@@ -201,7 +232,18 @@ of the specific tests run.
tclsh $TESTDIR/testrunner.tcl release
```
-## Running ZipVFS Tests
+As with source code tests, one or more patterns
+may be appended to any of the above commands (mdevtest, sdevtest or release).
+In that case only Tcl tests (no fuzz or other tests) that match the specified
+pattern are run. For example, to run the just the Tcl rtree tests in all
+builds and configurations supported by "release":
+
+```
+ tclsh $TESTDIR/testrunner.tcl release rtree%
+```
+
+
+## 3.2. Running ZipVFS Tests
testrunner.tcl can build a zipvfs-enabled testfixture and use it to run
tests from the Zipvfs project with the following command:
@@ -217,7 +259,8 @@ test both SQLite and Zipvfs with a single command:
tclsh $TESTDIR/testrunner.tcl --zipvfs $PATH_TO_ZIPVFS mdevtest
```
-## Investigating Source Code Test Failures
+
+## 3.3. Investigating Source Code Test Failures
Investigating a test failure that occurs during source code testing is a
two step process:
@@ -244,9 +287,31 @@ target to build. This may be used either to run a [make] command test directly,
or else to build a testfixture (or testfixture.exe) binary with which to
run a Tcl test script, as described above.
+
+# 4. Extra testrunner.tcl Options
+The testrunner.tcl script options in this section may be used with both source
+code and binary tests.
-# 4. Controlling CPU Core Utilization
+The **--buildonly** option instructs testrunner.tcl just to build the binaries
+required by a test, not to run any actual tests. For example:
+
+```
+ # Build binaries required by release test.
+ tclsh $TESTDIR/testrunner.tcl --buildonly release"
+```
+
+The **--dryrun** option prevents testrunner.tcl from building any binaries
+or running any tests. Instead, it just writes the shell commands that it
+would normally execute into the testrunner.log file. Example:
+
+```
+ # Log the shell commmands that make up the mdevtest test.
+ tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest"
+```
+
+
+# 5. Controlling CPU Core Utilization
When running either binary or source code tests, testrunner.tcl reports the
number of jobs it intends to use to stdout. e.g.
@@ -277,8 +342,3 @@ testrunner.log and testrunner.db files:
-
-
-
-
-
diff --git a/manifest b/manifest
index 0134cc2e4a..275eb80263 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Convert\sthe\sjson_array_length()\sfunction\sto\suse\sJSONB\sinstead\sof\sJsonNodes.
-D 2023-11-29T01:38:15.043
+C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\sjsonb\sbranch.
+D 2023-11-29T12:18:02.265
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -41,7 +41,7 @@ F doc/compile-for-windows.md 50b27d77be96195c66031a3181cb8684ed822327ea834e07f9c
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/lemon.html 44a53a1d2b42d7751f7b2f478efb23c978e258d794bfd172442307a755b9fa44
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
-F doc/testrunner.md 2434864be2219d4f0b6ffc99d0a2172d531c4ca4345340776f67ad4edd90dc90
+F doc/testrunner.md 8d36ec692cf4994bb66d84a4645b9afa1ce9d47dc12cbf8d437c5a5fb6ddeedb
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
@@ -712,7 +712,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
-F src/os_unix.c dc5404b56da7fb13cf272ddb94c3753cf9e82d32a65cba35dbb6aadcb849419c
+F src/os_unix.c 97bdcd43315da7aaec9fea2da1ff7c9de458f93dd363e073f2742403a7f2e011
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 987ab3a2cd9065d62e9955474470ff733445e2357432a67e3d0f5a8f9313e334
@@ -721,7 +721,7 @@ F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
-F src/pragma.c b3b4ad9c0298d63098a067acca613c21a5f56b4d176d5842922bcd0b07b7164e
+F src/pragma.c b5b4cff830575e6188cd56a295a57448d2b9dbc53f0dae58e22b97354cda3781
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
F src/printf.c 9da63b9ae1c14789bcae12840f5d800fd9302500cd2d62733fac77f0041b4750
@@ -729,7 +729,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 85857bedd2913d888aa571755b48c54cd2e6e7fcb0087e19b226ee0368cfda1e
-F src/shell.c.in a492f9209fe62ce3d1048802d59cd6e38e8444f88573fe1aebaadcd22e04156b
+F src/shell.c.in 7bb83293775e1a5586d65212997442bc7acc70a2f1b781745da64ec3c2e4ea97
F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
@@ -798,11 +798,11 @@ F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c b22cc9f203a8c0b9ee5338a67f8860347d14845864c10248bebe84518a781677
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
-F src/vdbe.c a5bf636ef502cfac538418fbf537a5e0cf825c7ce9ff784cddee2eb813dfe7a7
-F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
+F src/vdbe.c f73bead140670fac1aa4227188827ada52387a5fe0ccff0dd5af2a906754d904
+F src/vdbe.h 88e19a982df9027ec1c177c793d1a5d34dc23d8f06e3b2d997f43688b05ee0eb
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
-F src/vdbeaux.c b34dfbc09403ccb676608da16ff0780d23d466470563d24fdf6350b8d2271d5e
+F src/vdbeaux.c c5a471b34e9c4cfc0295a3e10734fd197670ffaebcb742f284c8e17e8026ceea
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
F src/vdbemem.c 0012d5f01cc866833847c2f3ae4c318ac53a1cb3d28acad9c35e688039464cf0
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
@@ -810,7 +810,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
F src/vtab.c 154725ebecd3bc02f7fbd7ad3974334f73fff76e02a964e828e48a7c5fb7efff
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 69aa3ce60b2862a24cd86bb528e653e2137388ead258ef64db49ec9038807f5f
+F src/wal.c e5247a3406531b705b44630e9ccf9ca0e5c74955ef19c06fbb146d765c500c20
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 1fdc69ce1333e9bd6d7d3df9fa5af1373a3f5bfdd52108d1dbc0ca85a55f777e
@@ -1655,7 +1655,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 68454ef88508c196d19e8694daa27bff7107a91857799eaa12f417188ae53ede
-F test/testrunner.tcl 8a6721213bce1cfd3b33e1588cc6431143d96b98819206bf91f5a205fbb150d4
+F test/testrunner.tcl e18d71f2e797da808ba6d31335e504ed6b2791581b89287a72b697a2f31b1ea1
F test/testrunner_data.tcl e4d5017290a6d5c11785e36cc94c67d8bb950c8cdc2dbe4c1db2a3a583812560
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
@@ -2145,8 +2145,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d5f48c57e975ac468cf29a43a5d0b56ef6d06cf35a8b0bddf87ec1c0fc7ae028
-R 4f247130b18247c9fbdce9034c7ad3a3
+P 5ab790736d943e08f097efcee5cfbf0d83c65b0a53f273060330ba719affa5e5 cad269d5e274443c39203a56603b991accc0399135d436996fc039d1d28ec9db
+R e74b99bb550123c4a0166b07666ffd15
U drh
-Z 81615ca9c91f916f71f930ae045acac7
+Z 2ea38ce368a7d99793b6d4f302fe78c3
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 539a333b70..2b29025123 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-5ab790736d943e08f097efcee5cfbf0d83c65b0a53f273060330ba719affa5e5
\ No newline at end of file
+1a59fcab2179cc3b52ecd3de7d2018db96ac149aaff521959773a517b8d9ac3e
\ No newline at end of file
diff --git a/src/os_unix.c b/src/os_unix.c
index dab03c97fb..7362a13206 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4595,7 +4595,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* Do not use a blocking lock here. If the lock cannot be obtained
+ ** immediately, it means some other connection is truncating the
+ ** *-shm file. And after it has done so, it will not release its
+ ** lock, but only downgrade it to a shared lock. So no point in
+ ** blocking here. The call below to obtain the shared DMS lock may
+ ** use a blocking lock. */
+ int iSaveTimeout = pDbFd->iBusyTimeout;
+ pDbFd->iBusyTimeout = 0;
+#endif
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ pDbFd->iBusyTimeout = iSaveTimeout;
+#endif
/* The first connection to attach must truncate the -shm file. We
** truncate to 3 bytes (an arbitrary small number, less than the
** -shm header size) rather than 0 as a system debugging aid, to
diff --git a/src/pragma.c b/src/pragma.c
index 90076b0c26..4c90574182 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1779,7 +1779,8 @@ void sqlite3Pragma(
if( pVTab->pModule->iVersion<4 ) continue;
if( pVTab->pModule->xIntegrity==0 ) continue;
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
- sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
+ pTab->nTabRef++;
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, a1);
diff --git a/src/shell.c.in b/src/shell.c.in
index 0ffd2b8d78..4a4a0e1fef 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -439,7 +439,7 @@ static void endTimer(void){
FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
sqlite3_int64 ftWallEnd = timeOfDay();
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
- oputf("Run Time: real %.3f user %f sys %f\n",
+ sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
(ftWallEnd - ftWallBegin)*0.001,
timeDiff(&ftUserBegin, &ftUserEnd),
timeDiff(&ftKernelBegin, &ftKernelEnd));
@@ -11860,14 +11860,14 @@ static void printBold(const char *zText){
FOREGROUND_RED|FOREGROUND_INTENSITY
);
#endif
- oputz(zText);
+ sputz(stdout, zText);
#if !SQLITE_OS_WINRT
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
#endif
}
#else
static void printBold(const char *zText){
- oputf("\033[1m%s\033[0m", zText);
+ sputf(stdout, "\033[1m%s\033[0m", zText);
}
#endif
@@ -12334,8 +12334,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}else if( cli_strcmp(z,"-bail")==0 ){
/* No-op. The bail_on_error flag should already be set. */
}else if( cli_strcmp(z,"-version")==0 ){
- oputf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(),
- 8*(int)sizeof(char*));
+ sputf(stdout, "%s %s (%d-bit)\n",
+ sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
return 0;
}else if( cli_strcmp(z,"-interactive")==0 ){
/* already handled */
@@ -12467,13 +12467,13 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#else
# define SHELL_CIO_CHAR_SET ""
#endif
- oputf("SQLite version %s %.19s%s\n" /*extra-version-info*/
+ sputf(stdout, "SQLite version %s %.19s%s\n" /*extra-version-info*/
"Enter \".help\" for usage hints.\n",
sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);
if( warnInmemoryDb ){
- oputz("Connected to a ");
+ sputz(stdout, "Connected to a ");
printBold("transient in-memory database");
- oputz(".\nUse \".open FILENAME\" to reopen on a"
+ sputz(stdout, ".\nUse \".open FILENAME\" to reopen on a"
" persistent database.\n");
}
zHistory = getenv("SQLITE_HISTORY");
diff --git a/src/vdbe.c b/src/vdbe.c
index 8f6ba02826..4f710d9a20 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -8180,9 +8180,10 @@ case OP_VCheck: { /* out2 */
pOut = &aMem[pOp->p2];
sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */
- assert( pOp->p4type==P4_TABLE );
+ assert( pOp->p4type==P4_TABLEREF );
pTab = pOp->p4.pTab;
assert( pTab!=0 );
+ assert( pTab->nTabRef>0 );
assert( IsVirtual(pTab) );
if( pTab->u.vtab.p==0 ) break;
pVtab = pTab->u.vtab.p->pVtab;
@@ -8191,13 +8192,11 @@ case OP_VCheck: { /* out2 */
assert( pModule!=0 );
assert( pModule->iVersion>=4 );
assert( pModule->xIntegrity!=0 );
- pTab->nTabRef++;
sqlite3VtabLock(pTab->u.vtab.p);
assert( pOp->p1>=0 && pOp->p1nDb );
rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName,
pOp->p3, &zErr);
sqlite3VtabUnlock(pTab->u.vtab.p);
- sqlite3DeleteTable(db, pTab);
if( rc ){
sqlite3_free(zErr);
goto abort_due_to_error;
diff --git a/src/vdbe.h b/src/vdbe.h
index f44f24f93e..25bda6be7a 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -126,6 +126,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
+#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 114a759c9a..420365e930 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1400,6 +1400,10 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
+ case P4_TABLEREF: {
+ if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
+ break;
+ }
}
}
diff --git a/src/wal.c b/src/wal.c
index d83f361d64..fa22e64c84 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -2004,6 +2004,19 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+
+
+/*
+** Attempt to enable blocking locks that block for nMs ms. Return 1 if
+** blocking locks are successfully enabled, or 0 otherwise.
+*/
+static int walEnableBlockingMs(Wal *pWal, int nMs){
+ int rc = sqlite3OsFileControl(
+ pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs
+ );
+ return (rc==SQLITE_OK);
+}
+
/*
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
** they are supported by the VFS, and (b) the database handle is configured
@@ -2015,11 +2028,7 @@ static int walEnableBlocking(Wal *pWal){
if( pWal->db ){
int tmout = pWal->db->busyTimeout;
if( tmout ){
- int rc;
- rc = sqlite3OsFileControl(
- pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
- );
- res = (rc==SQLITE_OK);
+ res = walEnableBlockingMs(pWal, tmout);
}
}
return res;
@@ -2068,20 +2077,10 @@ void sqlite3WalDb(Wal *pWal, sqlite3 *db){
pWal->db = db;
}
-/*
-** Take an exclusive WRITE lock. Blocking if so configured.
-*/
-static int walLockWriter(Wal *pWal){
- int rc;
- walEnableBlocking(pWal);
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
- walDisableBlocking(pWal);
- return rc;
-}
#else
# define walEnableBlocking(x) 0
# define walDisableBlocking(x)
-# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
+# define walEnableBlockingMs(pWal, ms) 0
# define sqlite3WalDb(pWal, db)
#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
@@ -2682,7 +2681,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
}
}else{
int bWriteLock = pWal->writeLock;
- if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
+ if( bWriteLock
+ || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
+ ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
@@ -2690,7 +2691,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
- */
+ ** Disable blocking locks first. */
+ walDisableBlocking(pWal);
rc = walIndexRecover(pWal);
*pChanged = 1;
}
@@ -2957,6 +2959,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
u32 mxFrame; /* Wal frame to lock to */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int nBlockTmout = 0;
+#endif
assert( pWal->readLock<0 ); /* Not currently locked */
@@ -2987,6 +2992,19 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return SQLITE_PROTOCOL;
}
if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor
+ ** to block for locks for approximately nDelay us. This affects three
+ ** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if
+ ** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the
+ ** first attempted read fails, and (c) the shared lock taken on the DMS
+ ** slot in os_unix.c. All three of these locks are attempted from within
+ ** the call to walIndexReadHdr() below. */
+ nBlockTmout = (nDelay+998) / 1000;
+ if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){
+ nDelay = 1;
+ }
+#endif
sqlite3OsSleep(pWal->pVfs, nDelay);
}
@@ -2995,6 +3013,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
if( pWal->bShmUnreliable==0 ){
rc = walIndexReadHdr(pWal, pChanged);
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ walDisableBlocking(pWal);
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
+#endif
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
** then convert BUSY errors to WAL_RETRY. If recovery is known to
@@ -3109,9 +3131,12 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
}
+ (void)walEnableBlockingMs(pWal, nBlockTmout);
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ walDisableBlocking(pWal);
if( rc ){
- return rc==SQLITE_BUSY ? WAL_RETRY : rc;
+ assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
+ return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
}
/* Now that the read-lock has been obtained, check that neither the
** value in the aReadMark[] array or the contents of the wal-index
diff --git a/test/testrunner.tcl b/test/testrunner.tcl
index 025f2ecdb4..edefdcd156 100644
--- a/test/testrunner.tcl
+++ b/test/testrunner.tcl
@@ -148,6 +148,8 @@ set TRG(cmdline) $argv
set TRG(reporttime) 2000
set TRG(fuzztest) 0 ;# is the fuzztest option present.
set TRG(zipvfs) "" ;# -zipvfs option, if any
+set TRG(buildonly) 0 ;# True if --buildonly option
+set TRG(dryrun) 0 ;# True if --dryrun option
switch -nocase -glob -- $tcl_platform(os) {
*darwin* {
@@ -427,6 +429,10 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
incr ii
set TRG(zipvfs) [file normalize [lindex $argv $ii]]
if {$isLast} { usage }
+ } elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} {
+ set TRG(buildonly) 1
+ } elseif {($n>2 && [string match "$a*" --dryrun]) || $a=="-d"} {
+ set TRG(dryrun) 1
} else {
usage
}
@@ -752,6 +758,20 @@ proc add_zipvfs_jobs {} {
set ::env(SQLITE_TEST_DIR) $::testdir
}
+# Used to add jobs for "mdevtest" and "sdevtest".
+#
+proc add_devtest_jobs {lBld patternlist} {
+ global TRG
+
+ foreach b $lBld {
+ set bld [add_build_job $b $TRG(testfixture)]
+ add_tcl_jobs $bld veryquick $patternlist
+ if {$patternlist==""} {
+ add_fuzztest_jobs $b
+ }
+ }
+}
+
proc add_jobs_from_cmdline {patternlist} {
global TRG
@@ -775,33 +795,28 @@ proc add_jobs_from_cmdline {patternlist} {
}
mdevtest {
- foreach b [list All-O0 All-Debug] {
- set bld [add_build_job $b $TRG(testfixture)]
- add_tcl_jobs $bld veryquick ""
- add_fuzztest_jobs $b
- }
+ add_devtest_jobs {All-O0 All-Debug} [lrange $patternlist 1 end]
}
sdevtest {
- foreach b [list All-Sanitize All-Debug] {
- set bld [add_build_job $b $TRG(testfixture)]
- add_tcl_jobs $bld veryquick ""
- add_fuzztest_jobs $b
- }
+ add_devtest_jobs {All-Sanitize All-Debug} [lrange $patternlist 1 end]
}
release {
+ set patternlist [lrange $patternlist 1 end]
foreach b [trd_builds $TRG(platform)] {
set bld [add_build_job $b $TRG(testfixture)]
foreach c [trd_configs $TRG(platform) $b] {
- add_tcl_jobs $bld $c ""
+ add_tcl_jobs $bld $c $patternlist
}
- foreach e [trd_extras $TRG(platform) $b] {
- if {$e=="fuzztest"} {
- add_fuzztest_jobs $b
- } else {
- add_make_job $bld $e
+ if {$patternlist==""} {
+ foreach e [trd_extras $TRG(platform) $b] {
+ if {$e=="fuzztest"} {
+ add_fuzztest_jobs $b
+ } else {
+ add_make_job $bld $e
+ }
}
}
}
@@ -834,6 +849,17 @@ proc make_new_testset {} {
}
+proc mark_job_as_finished {jobid output state endtm} {
+ r_write_db {
+ trdb eval {
+ UPDATE jobs
+ SET output=$output, state=$state, endtime=$endtm
+ WHERE jobid=$jobid;
+ UPDATE jobs SET state='ready' WHERE depid=$jobid;
+ }
+ }
+}
+
proc script_input_ready {fd iJob jobid} {
global TRG
global O
@@ -868,15 +894,7 @@ proc script_input_ready {fd iJob jobid} {
puts $TRG(log) "### $job(displayname) ${jobtm}ms ($state)"
puts $TRG(log) [string trim $O($iJob)]
- r_write_db {
- set output $O($iJob)
- trdb eval {
- UPDATE jobs
- SET output=$output, state=$state, endtime=$tm
- WHERE jobid=$jobid;
- UPDATE jobs SET state='ready' WHERE depid=$jobid;
- }
- }
+ mark_job_as_finished $jobid $O($iJob) $state $tm
dirs_freeDir $iJob
launch_some_jobs
@@ -928,16 +946,28 @@ proc launch_another_job {iJob} {
close $fd
}
- set pwd [pwd]
- cd $dir
- set fd [open $TRG(run) w]
- puts $fd $job(cmd)
- close $fd
- set fd [open "|$TRG(runcmd) 2>@1" r]
- cd $pwd
+ if { $TRG(dryrun) } {
- fconfigure $fd -blocking false
- fileevent $fd readable [list script_input_ready $fd $iJob $job(jobid)]
+ mark_job_as_finished $job(jobid) "" done 0
+ dirs_freeDir $iJob
+ if {$job(build)!=""} {
+ puts $TRG(log) "(cd $dir ; $job(cmd) )"
+ } else {
+ puts $TRG(log) "$job(cmd)"
+ }
+
+ } else {
+ set pwd [pwd]
+ cd $dir
+ set fd [open $TRG(run) w]
+ puts $fd $job(cmd)
+ close $fd
+ set fd [open "|$TRG(runcmd) 2>@1" r]
+ cd $pwd
+
+ fconfigure $fd -blocking false
+ fileevent $fd readable [list script_input_ready $fd $iJob $job(jobid)]
+ }
return 1
}
@@ -1035,6 +1065,16 @@ proc run_testset {} {
puts "Test log is $TRG(logname)"
}
+# Handle the --buildonly option, if it was specified.
+#
+proc handle_buildonly {} {
+ global TRG
+ if {$TRG(buildonly)} {
+ r_write_db {
+ trdb eval { DELETE FROM jobs WHERE displaytype!='bld' }
+ }
+ }
+}
sqlite3 trdb $TRG(dbname)
trdb timeout $TRG(timeout)
@@ -1043,6 +1083,8 @@ if {$TRG(nJob)>1} {
puts "splitting work across $TRG(nJob) jobs"
}
puts "built testset in [expr $tm/1000]ms.."
+
+handle_buildonly
run_testset
trdb close
#puts [pwd]